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