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