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