date and time created 91/03/07 20:27:27 by bostic
[unix-history] / usr / src / bin / sh / error.c
CommitLineData
b7bd34f2
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#ifndef lint
12static char sccsid[] = "@(#)error.c 5.1 (Berkeley) %G%";
13#endif /* not lint */
14
15/*
16 * Errors and exceptions.
17 */
18
19#include "shell.h"
20#include "main.h"
21#include "options.h"
22#include "output.h"
23#include "error.h"
24#include <signal.h>
25#ifdef __STDC__
26#include "stdarg.h"
27#else
28#include <varargs.h>
29#endif
30#include <errno.h>
31
32
33/*
34 * Code to handle exceptions in C.
35 */
36
37struct jmploc *handler;
38int exception;
39volatile int suppressint;
40volatile int intpending;
41char *commandname;
42
43
44/*
45 * Called to raise an exception. Since C doesn't include exceptions, we
46 * just do a longjmp to the exception handler. The type of exception is
47 * stored in the global variable "exception".
48 */
49
50void
51exraise(e) {
52 if (handler == NULL)
53 abort();
54 exception = e;
55 longjmp(handler->loc, 1);
56}
57
58
59/*
60 * Called from trap.c when a SIGINT is received. (If the user specifies
61 * that SIGINT is to be trapped or ignored using the trap builtin, then
62 * this routine is not called.) Suppressint is nonzero when interrupts
63 * are held using the INTOFF macro. The call to _exit is necessary because
64 * there is a short period after a fork before the signal handlers are
65 * set to the appropriate value for the child. (The test for iflag is
66 * just defensive programming.)
67 */
68
69void
70onint() {
71 if (suppressint) {
72 intpending++;
73 return;
74 }
75 intpending = 0;
76#ifdef BSD
77 sigsetmask(0);
78#endif
79 if (rootshell && iflag)
80 exraise(EXINT);
81 else
82 _exit(128 + SIGINT);
83}
84
85
86
87void
88error2(a, b)
89 char *a, *b;
90 {
91 error("%s: %s", a, b);
92}
93
94
95/*
96 * Error is called to raise the error exception. If the first argument
97 * is not NULL then error prints an error message using printf style
98 * formatting. It then raises the error exception.
99 */
100
101#ifdef __STDC__
102void
103error(char *msg, ...) {
104#else
105void
106error(va_alist)
107 va_dcl
108 {
109 char *msg;
110#endif
111 va_list ap;
112
113 CLEAR_PENDING_INT;
114 INTOFF;
115#ifdef __STDC__
116 va_start(ap, msg);
117#else
118 va_start(ap);
119 msg = va_arg(ap, char *);
120#endif
121#ifdef DEBUG
122 if (msg)
123 TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
124 else
125 TRACE(("error(NULL) pid=%d\n", getpid()));
126#endif
127 if (msg) {
128 if (commandname)
129 outfmt(&errout, "%s: ", commandname);
130 doformat(&errout, msg, ap);
131 out2c('\n');
132 }
133 va_end(ap);
134 flushall();
135 exraise(EXERROR);
136}
137
138
139
140/*
141 * Table of error messages.
142 */
143
144struct errname {
145 short errcode; /* error number */
146 short action; /* operation which encountered the error */
147 char *msg; /* text describing the error */
148};
149
150
151#define ALL (E_OPEN|E_CREAT|E_EXEC)
152
153STATIC const struct errname errormsg[] = {
154 EINTR, ALL, "interrupted",
155 EACCES, ALL, "permission denied",
156 EIO, ALL, "I/O error",
157 ENOENT, E_OPEN, "no such file",
158 ENOENT, E_CREAT, "directory nonexistent",
159 ENOENT, E_EXEC, "not found",
160 ENOTDIR, E_OPEN, "no such file",
161 ENOTDIR, E_CREAT, "directory nonexistent",
162 ENOTDIR, E_EXEC, "not found",
163 EISDIR, ALL, "is a directory",
164/* EMFILE, ALL, "too many open files", */
165 ENFILE, ALL, "file table overflow",
166 ENOSPC, ALL, "file system full",
167#ifdef EDQUOT
168 EDQUOT, ALL, "disk quota exceeded",
169#endif
170#ifdef ENOSR
171 ENOSR, ALL, "no streams resources",
172#endif
173 ENXIO, ALL, "no such device or address",
174 EROFS, ALL, "read-only file system",
175 ETXTBSY, ALL, "text busy",
176#ifdef SYSV
177 EAGAIN, E_EXEC, "not enough memory",
178#endif
179 ENOMEM, ALL, "not enough memory",
180#ifdef ENOLINK
181 ENOLINK, ALL, "remote access failed"
182#endif
183#ifdef EMULTIHOP
184 EMULTIHOP, ALL, "remote access failed",
185#endif
186#ifdef ECOMM
187 ECOMM, ALL, "remote access failed",
188#endif
189#ifdef ESTALE
190 ESTALE, ALL, "remote access failed",
191#endif
192#ifdef ETIMEDOUT
193 ETIMEDOUT, ALL, "remote access failed",
194#endif
195#ifdef ELOOP
196 ELOOP, ALL, "symbolic link loop",
197#endif
198 E2BIG, E_EXEC, "argument list too long",
199#ifdef ELIBACC
200 ELIBACC, E_EXEC, "shared library missing",
201#endif
202 0, 0, NULL
203};
204
205
206/*
207 * Return a string describing an error. The returned string may be a
208 * pointer to a static buffer that will be overwritten on the next call.
209 * Action describes the operation that got the error.
210 */
211
212char *
213errmsg(e, action) {
214 struct errname const *ep;
215 static char buf[12];
216
217 for (ep = errormsg ; ep->errcode ; ep++) {
218 if (ep->errcode == e && (ep->action & action) != 0)
219 return ep->msg;
220 }
221 fmtstr(buf, sizeof buf, "error %d", e);
222 return buf;
223}