1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 #include "sh.h"
16 #include <locale.h>
17 #include <dirent.h>
18 #include <string.h>
19 /*
20 * #include <sys/ioctl.h>
21 * #include <stdlib.h>
22 */
23 #include "sh.tconst.h"
24 /*
25 * C Shell
26 */
27
28 bool child;
29 bool didfds;
30 bool exiterr;
31 bool errspl; /* Argument to error was spliced by seterr2 */
32 bool haderr;
33 jmp_buf reslab;
34 tchar one[2] = { '1', 0 };
35 tchar *onev[2] = { one, NOSTR };
36 short SHDIAG;
37 int tpgrp;
38
39 /*
40 * contains DIR * for last opendir_(), its left open if an error
41 * longjmp (reset) occurs before it gets closed via closedir.
42 * if its not null in the error handler, then closedir it.
43 */
44 DIR *Dirp = NULL;
45
46 /*
47 * Print error string s with optional argument arg.
48 * This routine always resets or exits. The flag haderr
49 * is set so the routine who catches the unwind can propogate
50 * it if they want.
51 *
52 * Note that any open files at the point of error will eventually
53 * be closed in the routine process in sh.c which is the only
54 * place error unwinds are ever caught.
55 */
56 /*VARARGS1*/
57 void
error(s,a1,a2)58 error(s, a1, a2)
59 char *s;
60 {
61 tchar **v;
62 char *ep;
63
64 /*
65 * Must flush before we print as we wish output before the error
66 * to go on (some form of) standard output, while output after
67 * goes on (some form of) diagnostic output.
68 * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG.
69 * See flush in sh.print.c.
70 */
71 flush();
72 haderr = 1; /* Now to diagnostic output */
73 if (v = pargv)
74 pargv = 0, blkfree(v);
75 if (v = gargv)
76 gargv = 0, blkfree(v);
77
78 /*
79 * A zero arguments causes no printing, else print
80 * an error diagnostic here.
81 */
82 if (s) {
83 printf(s, a1, a2), printf("\n");
84 }
85
86
87 didfds = 0; /* Forget about 0,1,2 */
88 if ((ep = err_msg) && errspl) {
89 errspl = 0;
90 xfree(ep);
91 }
92 errspl = 0;
93
94 if ( Dirp ){
95 closedir(Dirp);
96 Dirp = NULL;
97 }
98
99 /*
100 * Go away if -e or we are a child shell
101 */
102 if (exiterr || child) {
103 exit(1);
104 }
105
106 /*
107 * Reset the state of the input.
108 * This buffered seek to end of file will also
109 * clear the while/foreach stack.
110 */
111 btoeof();
112
113 setq(S_status, onev, &shvhed);
114 if (tpgrp > 0)
115 (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp);
116 reset(); /* Unwind */
117 }
118
119 /*
120 * Perror is the shells version of perror which should otherwise
121 * never be called.
122 */
123 void
Perror(tchar * s)124 Perror(tchar *s)
125 {
126 char chbuf[BUFSIZ];
127
128 /*
129 * Perror uses unit 2, thus if we didn't set up the fd's
130 * we must set up unit 2 now else the diagnostic will disappear
131 */
132 if (!didfds) {
133 int oerrno = errno;
134
135 (void) dcopy(SHDIAG, 2);
136 errno = oerrno;
137 }
138 tstostr(chbuf, s);
139 perror(chbuf);
140 error(NULL); /* To exit or unwind */
141 }
142
143 void
bferr(char * cp)144 bferr(char *cp)
145 {
146
147 flush();
148 haderr = 1;
149 if( bname) printf("%t: ", bname);
150 error("%s", gettext(cp));
151 }
152
153 /*
154 * The parser and scanner set up errors for later by calling seterr,
155 * which sets the variable err as a side effect; later to be tested,
156 * e.g. in process.
157 */
158 void
seterr(char * s)159 seterr(char *s)
160 {
161
162 if (err_msg == NULL)
163 err_msg = s, errspl = 0;
164 }
165
166 /* Set err to a splice of cp and dp, to be freed later in error() */
167 void
seterr2(tchar * cp,char * dp)168 seterr2(tchar *cp, char *dp)
169 {
170 char chbuf[BUFSIZ];
171 char *gdp;
172
173 if (err_msg)
174 return;
175
176 /* Concatinate cp and dp in the allocated space. */
177 tstostr(chbuf, cp);
178 gdp = gettext(dp);
179 err_msg = (char *)xalloc(strlen(chbuf)+strlen(gdp)+1);
180 strcpy(err_msg, chbuf);
181 strcat(err_msg, gdp);
182
183 errspl++;/* Remember to xfree(err_msg). */
184 }
185
186 /* Set err to a splice of cp with a string form of character d */
187 void
seterrc(char * cp,tchar d)188 seterrc(char *cp, tchar d)
189 {
190 char chbuf[MB_LEN_MAX+1];
191
192 /* don't overwrite an existing error message */
193 if (err_msg)
194 return;
195
196 #ifdef MBCHAR
197 {
198 wchar_t wcd=(wchar_t)(d&TRIM);
199 int i;
200
201 i = wctomb(chbuf, wcd); /* chbuf holds d in multibyte representation. */
202 chbuf[(i>0)?i:0] = (char) 0;
203 }
204 #else
205 chbuf[0]=(char)(d&TRIM); chbuf[1]=(char)0;
206 #endif
207
208
209 /* Concatinate cp and d in the allocated space. */
210 err_msg = (char *)xalloc(strlen(cp)+strlen(chbuf)+1);
211 strcpy(err_msg, cp);
212 strcat(err_msg, chbuf);
213
214 errspl++; /* Remember to xfree(err_msg). */
215 }
216