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