VirtualBox

source: kBuild/trunk/src/ash/error.c@ 1158

Last change on this file since 1158 was 809, checked in by bird, 18 years ago

Solaris + cleanup.

  • Property svn:eol-style set to native
File size: 8.0 KB
Line 
1/* $NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $ */
2
3/*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Kenneth Almquist.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
21 *
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
32 * SUCH DAMAGE.
33 */
34
35#ifdef HAVE_SYS_CDEFS_H
36#include <sys/cdefs.h>
37#endif
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
41#else
42__RCSID("$NetBSD: error.c,v 1.31 2003/08/07 09:05:30 agc Exp $");
43#endif
44#endif /* not lint */
45
46/*
47 * Errors and exceptions.
48 */
49
50#include <signal.h>
51#include <stdlib.h>
52#include <unistd.h>
53#include <errno.h>
54#include <stdio.h>
55#include <string.h>
56
57#include "shell.h"
58#include "main.h"
59#include "options.h"
60#include "output.h"
61#include "error.h"
62#include "show.h"
63
64
65/*
66 * Code to handle exceptions in C.
67 */
68
69struct jmploc *handler;
70int exception;
71volatile int suppressint;
72volatile int intpending;
73char *commandname;
74
75
76static void exverror(int, const char *, va_list)
77 __attribute__((__noreturn__));
78
79/*
80 * Called to raise an exception. Since C doesn't include exceptions, we
81 * just do a longjmp to the exception handler. The type of exception is
82 * stored in the global variable "exception".
83 */
84
85void
86exraise(int e)
87{
88 if (handler == NULL)
89 abort();
90 exception = e;
91 longjmp(handler->loc, 1);
92}
93
94
95/*
96 * Called from trap.c when a SIGINT is received. (If the user specifies
97 * that SIGINT is to be trapped or ignored using the trap builtin, then
98 * this routine is not called.) Suppressint is nonzero when interrupts
99 * are held using the INTOFF macro. The call to _exit is necessary because
100 * there is a short period after a fork before the signal handlers are
101 * set to the appropriate value for the child. (The test for iflag is
102 * just defensive programming.)
103 */
104
105void
106onint(void)
107{
108 sigset_t nsigset;
109
110 if (suppressint) {
111 intpending = 1;
112 return;
113 }
114 intpending = 0;
115 sigemptyset(&nsigset);
116 sigprocmask(SIG_SETMASK, &nsigset, NULL);
117 if (rootshell && iflag)
118 exraise(EXINT);
119 else {
120 signal(SIGINT, SIG_DFL);
121 raise(SIGINT);
122 }
123 /* NOTREACHED */
124}
125
126static void
127exvwarning(int sv_errno, const char *msg, va_list ap)
128{
129 /* Partially emulate line buffered output so that:
130 * printf '%d\n' 1 a 2
131 * and
132 * printf '%d %d %d\n' 1 a 2
133 * both generate sensible text when stdout and stderr are merged.
134 */
135 if (output.nextc != output.buf && output.nextc[-1] == '\n')
136 flushout(&output);
137 if (commandname)
138 outfmt(&errout, "%s: ", commandname);
139 if (msg != NULL) {
140 doformat(&errout, msg, ap);
141 if (sv_errno >= 0)
142 outfmt(&errout, ": ");
143 }
144 if (sv_errno >= 0)
145 outfmt(&errout, "%s", strerror(sv_errno));
146 out2c('\n');
147 flushout(&errout);
148}
149
150/*
151 * Exverror is called to raise the error exception. If the second argument
152 * is not NULL then error prints an error message using printf style
153 * formatting. It then raises the error exception.
154 */
155static void
156exverror(int cond, const char *msg, va_list ap)
157{
158 CLEAR_PENDING_INT;
159 INTOFF;
160
161#ifdef DEBUG
162 if (msg) {
163 TRACE(("exverror(%d, \"", cond));
164 TRACEV((msg, ap));
165 TRACE(("\") pid=%d\n", getpid()));
166 } else
167 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
168#endif
169 if (msg)
170 exvwarning(-1, msg, ap);
171
172 output_flushall();
173 exraise(cond);
174 /* NOTREACHED */
175}
176
177
178void
179error(const char *msg, ...)
180{
181 va_list ap;
182
183 va_start(ap, msg);
184 exverror(EXERROR, msg, ap);
185 /* NOTREACHED */
186 va_end(ap);
187}
188
189
190void
191exerror(int cond, const char *msg, ...)
192{
193 va_list ap;
194
195 va_start(ap, msg);
196 exverror(cond, msg, ap);
197 /* NOTREACHED */
198 va_end(ap);
199}
200
201/*
202 * error/warning routines for external builtins
203 */
204
205void
206sh_exit(int rval)
207{
208 exerrno = rval & 255;
209 exraise(EXEXEC);
210}
211
212void
213sh_err(int status, const char *fmt, ...)
214{
215 va_list ap;
216
217 va_start(ap, fmt);
218 exvwarning(errno, fmt, ap);
219 va_end(ap);
220 sh_exit(status);
221}
222
223void
224sh_verr(int status, const char *fmt, va_list ap)
225{
226 exvwarning(errno, fmt, ap);
227 sh_exit(status);
228}
229
230void
231sh_errx(int status, const char *fmt, ...)
232{
233 va_list ap;
234
235 va_start(ap, fmt);
236 exvwarning(-1, fmt, ap);
237 va_end(ap);
238 sh_exit(status);
239}
240
241void
242sh_verrx(int status, const char *fmt, va_list ap)
243{
244 exvwarning(-1, fmt, ap);
245 sh_exit(status);
246}
247
248void
249sh_warn(const char *fmt, ...)
250{
251 va_list ap;
252
253 va_start(ap, fmt);
254 exvwarning(errno, fmt, ap);
255 va_end(ap);
256}
257
258void
259sh_vwarn(const char *fmt, va_list ap)
260{
261 exvwarning(errno, fmt, ap);
262}
263
264void
265sh_warnx(const char *fmt, ...)
266{
267 va_list ap;
268
269 va_start(ap, fmt);
270 exvwarning(-1, fmt, ap);
271 va_end(ap);
272}
273
274void
275sh_vwarnx(const char *fmt, va_list ap)
276{
277 exvwarning(-1, fmt, ap);
278}
279
280
281/*
282 * Table of error messages.
283 */
284
285struct errname {
286 short errcode; /* error number */
287 short action; /* operation which encountered the error */
288 const char *msg; /* text describing the error */
289};
290
291
292#define ALL (E_OPEN|E_CREAT|E_EXEC)
293
294STATIC const struct errname errormsg[] = {
295 { EINTR, ALL, "interrupted" },
296 { EACCES, ALL, "permission denied" },
297 { EIO, ALL, "I/O error" },
298 { EEXIST, ALL, "file exists" },
299 { ENOENT, E_OPEN, "no such file" },
300 { ENOENT, E_CREAT,"directory nonexistent" },
301 { ENOENT, E_EXEC, "not found" },
302 { ENOTDIR, E_OPEN, "no such file" },
303 { ENOTDIR, E_CREAT,"directory nonexistent" },
304 { ENOTDIR, E_EXEC, "not found" },
305 { EISDIR, ALL, "is a directory" },
306#ifdef EMFILE
307 { EMFILE, ALL, "too many open files" },
308#endif
309 { ENFILE, ALL, "file table overflow" },
310 { ENOSPC, ALL, "file system full" },
311#ifdef EDQUOT
312 { EDQUOT, ALL, "disk quota exceeded" },
313#endif
314#ifdef ENOSR
315 { ENOSR, ALL, "no streams resources" },
316#endif
317 { ENXIO, ALL, "no such device or address" },
318 { EROFS, ALL, "read-only file system" },
319#ifdef ETXTBSY
320 { ETXTBSY, ALL, "text busy" },
321#endif
322#ifdef EAGAIN
323 { EAGAIN, E_EXEC, "not enough memory" },
324#endif
325 { ENOMEM, ALL, "not enough memory" },
326#ifdef ENOLINK
327 { ENOLINK, ALL, "remote access failed" },
328#endif
329#ifdef EMULTIHOP
330 { EMULTIHOP, ALL, "remote access failed" },
331#endif
332#ifdef ECOMM
333 { ECOMM, ALL, "remote access failed" },
334#endif
335#ifdef ESTALE
336 { ESTALE, ALL, "remote access failed" },
337#endif
338#ifdef ETIMEDOUT
339 { ETIMEDOUT, ALL, "remote access failed" },
340#endif
341#ifdef ELOOP
342 { ELOOP, ALL, "symbolic link loop" },
343#endif
344 { E2BIG, E_EXEC, "argument list too long" },
345#ifdef ELIBACC
346 { ELIBACC, E_EXEC, "shared library missing" },
347#endif
348 { 0, 0, NULL },
349};
350
351
352/*
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.
356 */
357
358const char *
359errmsg(int e, int action)
360{
361 struct errname const *ep;
362 static char buf[12];
363
364 for (ep = errormsg ; ep->errcode ; ep++) {
365 if (ep->errcode == e && (ep->action & action) != 0)
366 return ep->msg;
367 }
368 fmtstr(buf, sizeof buf, "error %d", e);
369 return buf;
370}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette