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