VirtualBox

source: kBuild/trunk/src/ash-messup/error.c@ 1195

Last change on this file since 1195 was 883, checked in by bird, 18 years ago

hacking...

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