Subversion Repositories HelenOS

Rev

Rev 2714 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2714 cejka 1
/*  $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt 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. All advertising materials mentioning features or use of this software
19
 *    must display the following acknowledgement:
20
 *  This product includes software developed by the University of
21
 *  California, Berkeley and its contributors.
22
 * 4. Neither the name of the University nor the names of its contributors
23
 *    may be used to endorse or promote products derived from this software
24
 *    without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
 * SUCH DAMAGE.
37
 */
38
 
39
#include <sys/cdefs.h>
40
#ifndef lint
41
#if 0
42
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
43
#else
44
__RCSID("$NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $");
45
#endif
46
#endif /* not lint */
47
 
48
/*
49
 * Errors and exceptions.
50
 */
51
 
52
#include <signal.h>
53
#include <stdlib.h>
54
#include <unistd.h>
55
#include <errno.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
 
69
struct jmploc *handler;
70
int exception;
71
volatile int suppressint;
72
volatile int intpending;
73
char *commandname;
74
 
75
 
76
static 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
 
85
void
86
exraise(e)
87
    int e;
88
{
89
    if (handler == NULL)
90
        abort();
91
    exception = e;
92
    longjmp(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
 
106
void
107
onint() {
108
    sigset_t sigset;
109
 
110
    if (suppressint) {
111
        intpending++;
112
        return;
113
    }
114
    intpending = 0;
115
    sigemptyset(&sigset);
116
    sigprocmask(SIG_SETMASK, &sigset, NULL);
117
    if (rootshell && iflag)
118
        exraise(EXINT);
119
    else {
120
        signal(SIGINT, SIG_DFL);
121
        raise(SIGINT);
122
    }
123
    /* NOTREACHED */
124
}
125
 
126
 
127
/*
128
 * Exverror is called to raise the error exception.  If the first argument
129
 * is not NULL then error prints an error message using printf style
130
 * formatting.  It then raises the error exception.
131
 */
132
static void
133
exverror(cond, msg, ap)
134
    int cond;
135
    const char *msg;
136
    va_list ap;
137
{
138
    CLEAR_PENDING_INT;
139
    INTOFF;
140
 
141
#ifdef DEBUG
142
    if (msg)
143
        TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
144
    else
145
        TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
146
#endif
147
    if (msg) {
148
        if (commandname)
149
            outfmt(&errout, "%s: ", commandname);
150
        doformat(&errout, msg, ap);
151
        out2c('\n');
152
    }
153
    flushall();
154
    exraise(cond);
155
    /* NOTREACHED */
156
}
157
 
158
 
159
#ifdef __STDC__
160
void
161
error(const char *msg, ...)
162
#else
163
void
164
error(va_alist)
165
    va_dcl
166
#endif
167
{
168
#ifndef __STDC__
169
    const char *msg;
170
#endif
171
    va_list ap;
172
#ifdef __STDC__
173
    va_start(ap, msg);
174
#else
175
    va_start(ap);
176
    msg = va_arg(ap, const char *);
177
#endif
178
    exverror(EXERROR, msg, ap);
179
    /* NOTREACHED */
180
    va_end(ap);
181
}
182
 
183
 
184
#ifdef __STDC__
185
void
186
exerror(int cond, const char *msg, ...)
187
#else
188
void
189
exerror(va_alist)
190
    va_dcl
191
#endif
192
{
193
#ifndef __STDC__
194
    int cond;
195
    const char *msg;
196
#endif
197
    va_list ap;
198
#ifdef __STDC__
199
    va_start(ap, msg);
200
#else
201
    va_start(ap);
202
    cond = va_arg(ap, int);
203
    msg = va_arg(ap, const char *);
204
#endif
205
    exverror(cond, msg, ap);
206
    /* NOTREACHED */
207
    va_end(ap);
208
}
209
 
210
 
211
 
212
/*
213
 * Table of error messages.
214
 */
215
 
216
struct errname {
217
    short errcode;      /* error number */
218
    short action;       /* operation which encountered the error */
219
    const char *msg;    /* text describing the error */
220
};
221
 
222
 
223
#define ALL (E_OPEN|E_CREAT|E_EXEC)
224
 
225
STATIC const struct errname errormsg[] = {
226
    { EINTR,    ALL,    "interrupted" },
227
    { EACCES,   ALL,    "permission denied" },
228
    { EIO,      ALL,    "I/O error" },
229
    { ENOENT,   E_OPEN, "no such file" },
230
    { ENOENT,   E_CREAT,"directory nonexistent" },
231
    { ENOENT,   E_EXEC, "not found" },
232
    { ENOTDIR,  E_OPEN, "no such file" },
233
    { ENOTDIR,  E_CREAT,"directory nonexistent" },
234
    { ENOTDIR,  E_EXEC, "not found" },
235
    { EISDIR,   ALL,    "is a directory" },
236
    { EEXIST,   E_CREAT,"file exists" },
237
#ifdef notdef
238
    { EMFILE,   ALL,    "too many open files" },
239
#endif
240
    { ENFILE,   ALL,    "file table overflow" },
241
    { ENOSPC,   ALL,    "file system full" },
242
#ifdef EDQUOT
243
    { EDQUOT,   ALL,    "disk quota exceeded" },
244
#endif
245
#ifdef ENOSR
246
    { ENOSR,    ALL,    "no streams resources" },
247
#endif
248
    { ENXIO,    ALL,    "no such device or address" },
249
    { EROFS,    ALL,    "read-only file system" },
250
    { ETXTBSY,  ALL,    "text busy" },
251
#ifdef SYSV
252
    { EAGAIN,   E_EXEC, "not enough memory" },
253
#endif
254
    { ENOMEM,   ALL,    "not enough memory" },
255
#ifdef ENOLINK
256
    { ENOLINK,  ALL,    "remote access failed" },
257
#endif
258
#ifdef EMULTIHOP
259
    { EMULTIHOP,    ALL,    "remote access failed" },
260
#endif
261
#ifdef ECOMM
262
    { ECOMM,    ALL,    "remote access failed" },
263
#endif
264
#ifdef ESTALE
265
    { ESTALE,   ALL,    "remote access failed" },
266
#endif
267
#ifdef ETIMEDOUT
268
    { ETIMEDOUT,    ALL,    "remote access failed" },
269
#endif
270
#ifdef ELOOP
271
    { ELOOP,    ALL,    "symbolic link loop" },
272
#endif
273
    { E2BIG,    E_EXEC, "argument list too long" },
274
#ifdef ELIBACC
275
    { ELIBACC,  E_EXEC, "shared library missing" },
276
#endif
277
    { 0,        0,  NULL },
278
};
279
 
280
 
281
/*
282
 * Return a string describing an error.  The returned string may be a
283
 * pointer to a static buffer that will be overwritten on the next call.
284
 * Action describes the operation that got the error.
285
 */
286
 
287
const char *
288
errmsg(e, action)
289
    int e;
290
    int action;
291
{
292
    struct errname const *ep;
293
    static char buf[12];
294
 
295
    for (ep = errormsg ; ep->errcode ; ep++) {
296
        if (ep->errcode == e && (ep->action & action) != 0)
297
            return ep->msg;
298
    }
299
    fmtstr(buf, sizeof buf, "error %d", e);
300
    return buf;
301
}