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