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