err.c revision 1.12 1 /* $NetBSD: err.c,v 1.12 1998/07/28 02:47:19 mycroft Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 5/31/93";
40 #else
41 __RCSID("$NetBSD: err.c,v 1.12 1998/07/28 02:47:19 mycroft Exp $");
42 #endif
43 #endif /* not lint */
44
45 #include <sys/types.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #if __STDC__
49 # include <stdarg.h>
50 #else
51 # include <varargs.h>
52 #endif
53
54 #include "csh.h"
55 #include "extern.h"
56
57 char *seterr = NULL; /* Holds last error if there was one */
58
59 #define ERR_FLAGS 0xf0000000
60 #define ERR_NAME 0x10000000
61 #define ERR_SILENT 0x20000000
62 #define ERR_OLD 0x40000000
63
64 static const char *errorlist[] =
65 {
66 #define ERR_SYNTAX 0
67 "Syntax Error",
68 #define ERR_NOTALLOWED 1
69 "%s is not allowed",
70 #define ERR_WTOOLONG 2
71 "Word too long",
72 #define ERR_LTOOLONG 3
73 "$< line too long",
74 #define ERR_DOLZERO 4
75 "No file for $0",
76 #define ERR_DOLQUEST 5
77 "$? not allowed here",
78 #define ERR_INCBR 6
79 "Incomplete [] modifier",
80 #define ERR_EXPORD 7
81 "$ expansion must end before ]",
82 #define ERR_BADMOD 8
83 "Bad : modifier in $ (%c)",
84 #define ERR_SUBSCRIPT 9
85 "Subscript error",
86 #define ERR_BADNUM 10
87 "Badly formed number",
88 #define ERR_NOMORE 11
89 "No more words",
90 #define ERR_FILENAME 12
91 "Missing file name",
92 #define ERR_GLOB 13
93 "Internal glob error",
94 #define ERR_COMMAND 14
95 "Command not found",
96 #define ERR_TOOFEW 15
97 "Too few arguments",
98 #define ERR_TOOMANY 16
99 "Too many arguments",
100 #define ERR_DANGER 17
101 "Too dangerous to alias that",
102 #define ERR_EMPTYIF 18
103 "Empty if",
104 #define ERR_IMPRTHEN 19
105 "Improper then",
106 #define ERR_NOPAREN 20
107 "Words not parenthesized",
108 #define ERR_NOTFOUND 21
109 "%s not found",
110 #define ERR_MASK 22
111 "Improper mask",
112 #define ERR_LIMIT 23
113 "No such limit",
114 #define ERR_TOOLARGE 24
115 "Argument too large",
116 #define ERR_SCALEF 25
117 "Improper or unknown scale factor",
118 #define ERR_UNDVAR 26
119 "Undefined variable",
120 #define ERR_DEEP 27
121 "Directory stack not that deep",
122 #define ERR_BADSIG 28
123 "Bad signal number",
124 #define ERR_UNKSIG 29
125 "Unknown signal; kill -l lists signals",
126 #define ERR_VARBEGIN 30
127 "Variable name must begin with a letter",
128 #define ERR_VARTOOLONG 31
129 "Variable name too long",
130 #define ERR_VARALNUM 32
131 "Variable name must contain alphanumeric characters",
132 #define ERR_JOBCONTROL 33
133 "No job control in this shell",
134 #define ERR_EXPRESSION 34
135 "Expression Syntax",
136 #define ERR_NOHOMEDIR 35
137 "No home directory",
138 #define ERR_CANTCHANGE 36
139 "Can't change to home directory",
140 #define ERR_NULLCOM 37
141 "Invalid null command",
142 #define ERR_ASSIGN 38
143 "Assignment missing expression",
144 #define ERR_UNKNOWNOP 39
145 "Unknown operator",
146 #define ERR_AMBIG 40
147 "Ambiguous",
148 #define ERR_EXISTS 41
149 "%s: File exists",
150 #define ERR_INTR 42
151 "Interrupted",
152 #define ERR_RANGE 43
153 "Subscript out of range",
154 #define ERR_OVERFLOW 44
155 "Line overflow",
156 #define ERR_VARMOD 45
157 "Unknown variable modifier",
158 #define ERR_NOSUCHJOB 46
159 "No such job",
160 #define ERR_TERMINAL 47
161 "Can't from terminal",
162 #define ERR_NOTWHILE 48
163 "Not in while/foreach",
164 #define ERR_NOPROC 49
165 "No more processes",
166 #define ERR_NOMATCH 50
167 "No match",
168 #define ERR_MISSING 51
169 "Missing %c",
170 #define ERR_UNMATCHED 52
171 "Unmatched %c",
172 #define ERR_NOMEM 53
173 "Out of memory",
174 #define ERR_PIPE 54
175 "Can't make pipe",
176 #define ERR_SYSTEM 55
177 "%s: %s",
178 #define ERR_STRING 56
179 "%s",
180 #define ERR_JOBS 57
181 "Usage: jobs [ -l ]",
182 #define ERR_JOBARGS 58
183 "Arguments should be jobs or process id's",
184 #define ERR_JOBCUR 59
185 "No current job",
186 #define ERR_JOBPREV 60
187 "No previous job",
188 #define ERR_JOBPAT 61
189 "No job matches pattern",
190 #define ERR_NESTING 62
191 "Fork nesting > %d; maybe `...` loop",
192 #define ERR_JOBCTRLSUB 63
193 "No job control in subshells",
194 #define ERR_BADPLPS 64
195 "Badly placed ()'s",
196 #define ERR_STOPPED 65
197 "%sThere are suspended jobs",
198 #define ERR_NODIR 66
199 "No other directory",
200 #define ERR_EMPTY 67
201 "Directory stack empty",
202 #define ERR_BADDIR 68
203 "Bad directory",
204 #define ERR_DIRUS 69
205 "Usage: %s [-lvn]%s",
206 #define ERR_HFLAG 70
207 "No operand for -h flag",
208 #define ERR_NOTLOGIN 71
209 "Not a login shell",
210 #define ERR_DIV0 72
211 "Division by 0",
212 #define ERR_MOD0 73
213 "Mod by 0",
214 #define ERR_BADSCALE 74
215 "Bad scaling; did you mean \"%s\"?",
216 #define ERR_SUSPLOG 75
217 "Can't suspend a login shell (yet)",
218 #define ERR_UNKUSER 76
219 "Unknown user: %s",
220 #define ERR_NOHOME 77
221 "No $home variable set",
222 #define ERR_HISTUS 78
223 "Usage: history [-rh] [# number of events]",
224 #define ERR_SPDOLLT 79
225 "$, ! or < not allowed with $# or $?",
226 #define ERR_NEWLINE 80
227 "Newline in variable name",
228 #define ERR_SPSTAR 81
229 "* not allowed with $# or $?",
230 #define ERR_DIGIT 82
231 "$?<digit> or $#<digit> not allowed",
232 #define ERR_VARILL 83
233 "Illegal variable name",
234 #define ERR_NLINDEX 84
235 "Newline in variable index",
236 #define ERR_EXPOVFL 85
237 "Expansion buffer overflow",
238 #define ERR_VARSYN 86
239 "Variable syntax",
240 #define ERR_BADBANG 87
241 "Bad ! form",
242 #define ERR_NOSUBST 88
243 "No previous substitute",
244 #define ERR_BADSUBST 89
245 "Bad substitute",
246 #define ERR_LHS 90
247 "No previous left hand side",
248 #define ERR_RHSLONG 91
249 "Right hand side too long",
250 #define ERR_BADBANGMOD 92
251 "Bad ! modifier: %c",
252 #define ERR_MODFAIL 93
253 "Modifier failed",
254 #define ERR_SUBOVFL 94
255 "Substitution buffer overflow",
256 #define ERR_BADBANGARG 95
257 "Bad ! arg selector",
258 #define ERR_NOSEARCH 96
259 "No prev search",
260 #define ERR_NOEVENT 97
261 "%s: Event not found",
262 #define ERR_TOOMANYRP 98
263 "Too many )'s",
264 #define ERR_TOOMANYLP 99
265 "Too many ('s",
266 #define ERR_BADPLP 100
267 "Badly placed (",
268 #define ERR_MISRED 101
269 "Missing name for redirect",
270 #define ERR_OUTRED 102
271 "Ambiguous output redirect",
272 #define ERR_REDPAR 103
273 "Can't << within ()'s",
274 #define ERR_INRED 104
275 "Ambiguous input redirect",
276 #define ERR_ALIASLOOP 105
277 "Alias loop",
278 #define ERR_HISTLOOP 106
279 "!# History loop",
280 #define ERR_ARCH 107
281 "%s: %s. Wrong Architecture",
282 #define ERR_FILEINQ 108
283 "Malformed file inquiry",
284 #define ERR_SELOVFL 109
285 "Selector overflow",
286 #define ERR_INVALID 110
287 "Invalid Error"
288 };
289
290 /*
291 * The parser and scanner set up errors for later by calling seterr,
292 * which sets the variable err as a side effect; later to be tested,
293 * e.g. in process.
294 */
295 void
296 #if __STDC__
297 seterror(int id, ...)
298 #else
299 seterror(id, va_alist)
300 int id;
301 va_dcl
302 #endif
303 {
304 if (seterr == 0) {
305 char berr[BUFSIZ];
306 va_list va;
307
308 #if __STDC__
309 va_start(va, id);
310 #else
311 va_start(va);
312 #endif
313 if (id < 0 || id > sizeof(errorlist) / sizeof(errorlist[0]))
314 id = ERR_INVALID;
315 (void) vsnprintf(berr, sizeof(berr), errorlist[id], va);
316 va_end(va);
317
318 seterr = strsave(berr);
319 }
320 }
321
322 /*
323 * Print the error with the given id.
324 *
325 * Special ids:
326 * ERR_SILENT: Print nothing.
327 * ERR_OLD: Print the previously set error if one was there.
328 * otherwise return.
329 * ERR_NAME: If this bit is set, print the name of the function
330 * in bname
331 *
332 * This routine always resets or exits. The flag haderr
333 * is set so the routine who catches the unwind can propogate
334 * it if they want.
335 *
336 * Note that any open files at the point of error will eventually
337 * be closed in the routine process in sh.c which is the only
338 * place error unwinds are ever caught.
339 */
340 void
341 #if __STDC__
342 stderror(int id, ...)
343 #else
344 stderror(id, va_alist)
345 int id;
346 va_dcl
347 #endif
348 {
349 va_list va;
350 Char **v;
351 int flags = id & ERR_FLAGS;
352
353 id &= ~ERR_FLAGS;
354
355 if ((flags & ERR_OLD) && seterr == NULL)
356 abort();
357
358 if (id < 0 || id > sizeof(errorlist) / sizeof(errorlist[0]))
359 id = ERR_INVALID;
360
361 (void) fflush(cshout);
362 (void) fflush(csherr);
363 haderr = 1; /* Now to diagnostic output */
364 timflg = 0; /* This isn't otherwise reset */
365
366
367 if (!(flags & ERR_SILENT)) {
368 if (flags & ERR_NAME)
369 (void) fprintf(csherr, "%s: ", bname);
370 if ((flags & ERR_OLD))
371 /* Old error. */
372 (void) fprintf(csherr, "%s.\n", seterr);
373 else {
374 #if __STDC__
375 va_start(va, id);
376 #else
377 va_start(va);
378 #endif
379 (void) vfprintf(csherr, errorlist[id], va);
380 va_end(va);
381 (void) fprintf(csherr, ".\n");
382 }
383 }
384
385 if (seterr) {
386 xfree((ptr_t) seterr);
387 seterr = NULL;
388 }
389
390 if ((v = pargv) != NULL)
391 pargv = 0, blkfree(v);
392 if ((v = gargv) != NULL)
393 gargv = 0, blkfree(v);
394
395 (void) fflush(cshout);
396 (void) fflush(csherr);
397 didfds = 0; /* Forget about 0,1,2 */
398 /*
399 * Go away if -e or we are a child shell
400 */
401 if (exiterr || child) {
402 xexit(1);
403 /* NOTREACHED */
404 }
405
406 /*
407 * Reset the state of the input. This buffered seek to end of file will
408 * also clear the while/foreach stack.
409 */
410 btoeof();
411
412 set(STRstatus, Strsave(STR1));
413 if (tpgrp > 0)
414 (void) tcsetpgrp(FSHTTY, tpgrp);
415 reset(); /* Unwind */
416 }
417