~ubuntu-branches/ubuntu/hardy/klibc/hardy-updates

« back to all changes in this revision

Viewing changes to ash/error.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeff Bailey
  • Date: 2006-01-04 20:24:52 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104202452-ec4v3n829rymukuv
Tags: 1.1.15-0ubuntu1
* New upstream version.

* Patch to fix compilation on parisc64 kernels.

Show diffs side-by-side

added added

removed removed

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