1 /* $NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
40 __RCSID("$NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $");
45 * Errors and exceptions.
56 #include "eval.h" /* for commandname */
65 * Code to handle exceptions in C.
68 struct jmploc
*handler
;
70 volatile int suppressint
;
71 volatile int intpending
;
74 static void exverror(int, const char *, va_list) __dead
;
77 * Called to raise an exception. Since C doesn't include exceptions, we
78 * just do a longjmp to the exception handler. The type of exception is
79 * stored in the global variable "exception".
88 longjmp(handler
->loc
, 1);
93 * Called from trap.c when a SIGINT is received. (If the user specifies
94 * that SIGINT is to be trapped or ignored using the trap builtin, then
95 * this routine is not called.) Suppressint is nonzero when interrupts
96 * are held using the INTOFF macro. The call to _exit is necessary because
97 * there is a short period after a fork before the signal handlers are
98 * set to the appropriate value for the child. (The test for iflag is
99 * just defensive programming.)
112 sigemptyset(&nsigset
);
113 sigprocmask(SIG_SETMASK
, &nsigset
, NULL
);
114 if (rootshell
&& iflag
)
117 signal(SIGINT
, SIG_DFL
);
123 static __printflike(2, 0) void
124 exvwarning(int sv_errno
, const char *msg
, va_list ap
)
126 /* Partially emulate line buffered output so that:
127 * printf '%d\n' 1 a 2
129 * printf '%d %d %d\n' 1 a 2
130 * both generate sensible text when stdout and stderr are merged.
132 if (output
.nextc
!= output
.buf
&& output
.nextc
[-1] == '\n')
135 outfmt(&errout
, "%s: ", commandname
);
137 outfmt(&errout
, "%s: ", getprogname());
139 doformat(&errout
, msg
, ap
);
141 outfmt(&errout
, ": ");
144 outfmt(&errout
, "%s", strerror(sv_errno
));
150 * Exverror is called to raise the error exception. If the second argument
151 * is not NULL then error prints an error message using printf style
152 * formatting. It then raises the error exception.
154 static __printflike(2, 0) void
155 exverror(int cond
, const char *msg
, va_list ap
)
162 TRACE(("exverror(%d, \"", cond
));
164 TRACE(("\") pid=%d\n", getpid()));
166 TRACE(("exverror(%d, NULL) pid=%d\n", cond
, getpid()));
169 exvwarning(-1, msg
, ap
);
178 error(const char *msg
, ...)
183 exverror(EXERROR
, msg
, ap
);
190 exerror(int cond
, const char *msg
, ...)
195 exverror(cond
, msg
, ap
);
201 * error/warning routines for external builtins
207 exerrno
= rval
& 255;
212 sh_err(int status
, const char *fmt
, ...)
217 exvwarning(errno
, fmt
, ap
);
223 sh_verr(int status
, const char *fmt
, va_list ap
)
225 exvwarning(errno
, fmt
, ap
);
230 sh_errx(int status
, const char *fmt
, ...)
235 exvwarning(-1, fmt
, ap
);
241 sh_verrx(int status
, const char *fmt
, va_list ap
)
243 exvwarning(-1, fmt
, ap
);
248 sh_warn(const char *fmt
, ...)
253 exvwarning(errno
, fmt
, ap
);
258 sh_vwarn(const char *fmt
, va_list ap
)
260 exvwarning(errno
, fmt
, ap
);
264 sh_warnx(const char *fmt
, ...)
269 exvwarning(-1, fmt
, ap
);
274 sh_vwarnx(const char *fmt
, va_list ap
)
276 exvwarning(-1, fmt
, ap
);
281 * Table of error messages.
285 short errcode
; /* error number */
286 short action
; /* operation which encountered the error */
287 const char *msg
; /* text describing the error */
291 #define ALL (E_OPEN|E_CREAT|E_EXEC)
293 STATIC
const struct errname errormsg
[] = {
294 { EINTR
, ALL
, "interrupted" },
295 { EACCES
, ALL
, "permission denied" },
296 { EIO
, ALL
, "I/O error" },
297 { EEXIST
, ALL
, "file exists" },
298 { ENOENT
, E_OPEN
, "no such file" },
299 { ENOENT
, E_CREAT
,"directory nonexistent" },
300 { ENOENT
, E_EXEC
, "not found" },
301 { ENOTDIR
, E_OPEN
, "no such file" },
302 { ENOTDIR
, E_CREAT
,"directory nonexistent" },
303 { ENOTDIR
, E_EXEC
, "not found" },
304 { EISDIR
, ALL
, "is a directory" },
306 { EMFILE
, ALL
, "too many open files" },
308 { ENFILE
, ALL
, "file table overflow" },
309 { ENOSPC
, ALL
, "file system full" },
311 { EDQUOT
, ALL
, "disk quota exceeded" },
314 { ENOSR
, ALL
, "no streams resources" },
316 { ENXIO
, ALL
, "no such device or address" },
317 { EROFS
, ALL
, "read-only file system" },
318 { ETXTBSY
, ALL
, "text busy" },
320 { EAGAIN
, E_EXEC
, "not enough memory" },
322 { ENOMEM
, ALL
, "not enough memory" },
324 { ENOLINK
, ALL
, "remote access failed" },
327 { EMULTIHOP
, ALL
, "remote access failed" },
330 { ECOMM
, ALL
, "remote access failed" },
333 { ESTALE
, ALL
, "remote access failed" },
336 { ETIMEDOUT
, ALL
, "remote access failed" },
339 { ELOOP
, ALL
, "symbolic link loop" },
342 { ENAMETOOLONG
, ALL
, "file name too long" },
344 { E2BIG
, E_EXEC
, "argument list too long" },
346 { ELIBACC
, E_EXEC
, "shared library missing" },
353 * Return a string describing an error. The returned string may be a
354 * pointer to a static buffer that will be overwritten on the next call.
355 * Action describes the operation that got the error.
359 errmsg(int e
, int action
)
361 struct errname
const *ep
;
364 for (ep
= errormsg
; ep
->errcode
; ep
++) {
365 if (ep
->errcode
== e
&& (ep
->action
& action
) != 0)
368 fmtstr(buf
, sizeof buf
, "error %d", e
);