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