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