xref: /minix3/bin/sh/error.c (revision d90bee97498b3043241050f61aed100786c59df4)
1*d90bee97SLionel Sambuc /*	$NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $	*/
2*d90bee97SLionel Sambuc 
3*d90bee97SLionel Sambuc /*-
4*d90bee97SLionel Sambuc  * Copyright (c) 1991, 1993
5*d90bee97SLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
6*d90bee97SLionel Sambuc  *
7*d90bee97SLionel Sambuc  * This code is derived from software contributed to Berkeley by
8*d90bee97SLionel Sambuc  * Kenneth Almquist.
9*d90bee97SLionel Sambuc  *
10*d90bee97SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
11*d90bee97SLionel Sambuc  * modification, are permitted provided that the following conditions
12*d90bee97SLionel Sambuc  * are met:
13*d90bee97SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
14*d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
15*d90bee97SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16*d90bee97SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17*d90bee97SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18*d90bee97SLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
19*d90bee97SLionel Sambuc  *    may be used to endorse or promote products derived from this software
20*d90bee97SLionel Sambuc  *    without specific prior written permission.
21*d90bee97SLionel Sambuc  *
22*d90bee97SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*d90bee97SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*d90bee97SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*d90bee97SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*d90bee97SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*d90bee97SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*d90bee97SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*d90bee97SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*d90bee97SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*d90bee97SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*d90bee97SLionel Sambuc  * SUCH DAMAGE.
33*d90bee97SLionel Sambuc  */
34*d90bee97SLionel Sambuc 
35*d90bee97SLionel Sambuc #include <sys/cdefs.h>
36*d90bee97SLionel Sambuc #ifndef lint
37*d90bee97SLionel Sambuc #if 0
38*d90bee97SLionel Sambuc static char sccsid[] = "@(#)error.c	8.2 (Berkeley) 5/4/95";
39*d90bee97SLionel Sambuc #else
40*d90bee97SLionel Sambuc __RCSID("$NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $");
41*d90bee97SLionel Sambuc #endif
42*d90bee97SLionel Sambuc #endif /* not lint */
43*d90bee97SLionel Sambuc 
44*d90bee97SLionel Sambuc /*
45*d90bee97SLionel Sambuc  * Errors and exceptions.
46*d90bee97SLionel Sambuc  */
47*d90bee97SLionel Sambuc 
48*d90bee97SLionel Sambuc #include <signal.h>
49*d90bee97SLionel Sambuc #include <stdlib.h>
50*d90bee97SLionel Sambuc #include <unistd.h>
51*d90bee97SLionel Sambuc #include <errno.h>
52*d90bee97SLionel Sambuc #include <stdio.h>
53*d90bee97SLionel Sambuc #include <string.h>
54*d90bee97SLionel Sambuc 
55*d90bee97SLionel Sambuc #include "shell.h"
56*d90bee97SLionel Sambuc #include "eval.h" /* for commandname */
57*d90bee97SLionel Sambuc #include "main.h"
58*d90bee97SLionel Sambuc #include "options.h"
59*d90bee97SLionel Sambuc #include "output.h"
60*d90bee97SLionel Sambuc #include "error.h"
61*d90bee97SLionel Sambuc #include "show.h"
62*d90bee97SLionel Sambuc 
63*d90bee97SLionel Sambuc 
64*d90bee97SLionel Sambuc /*
65*d90bee97SLionel Sambuc  * Code to handle exceptions in C.
66*d90bee97SLionel Sambuc  */
67*d90bee97SLionel Sambuc 
68*d90bee97SLionel Sambuc struct jmploc *handler;
69*d90bee97SLionel Sambuc int exception;
70*d90bee97SLionel Sambuc volatile int suppressint;
71*d90bee97SLionel Sambuc volatile int intpending;
72*d90bee97SLionel Sambuc 
73*d90bee97SLionel Sambuc 
74*d90bee97SLionel Sambuc static void exverror(int, const char *, va_list) __dead;
75*d90bee97SLionel Sambuc 
76*d90bee97SLionel Sambuc /*
77*d90bee97SLionel Sambuc  * Called to raise an exception.  Since C doesn't include exceptions, we
78*d90bee97SLionel Sambuc  * just do a longjmp to the exception handler.  The type of exception is
79*d90bee97SLionel Sambuc  * stored in the global variable "exception".
80*d90bee97SLionel Sambuc  */
81*d90bee97SLionel Sambuc 
82*d90bee97SLionel Sambuc void
exraise(int e)83*d90bee97SLionel Sambuc exraise(int e)
84*d90bee97SLionel Sambuc {
85*d90bee97SLionel Sambuc 	if (handler == NULL)
86*d90bee97SLionel Sambuc 		abort();
87*d90bee97SLionel Sambuc 	exception = e;
88*d90bee97SLionel Sambuc 	longjmp(handler->loc, 1);
89*d90bee97SLionel Sambuc }
90*d90bee97SLionel Sambuc 
91*d90bee97SLionel Sambuc 
92*d90bee97SLionel Sambuc /*
93*d90bee97SLionel Sambuc  * Called from trap.c when a SIGINT is received.  (If the user specifies
94*d90bee97SLionel Sambuc  * that SIGINT is to be trapped or ignored using the trap builtin, then
95*d90bee97SLionel Sambuc  * this routine is not called.)  Suppressint is nonzero when interrupts
96*d90bee97SLionel Sambuc  * are held using the INTOFF macro.  The call to _exit is necessary because
97*d90bee97SLionel Sambuc  * there is a short period after a fork before the signal handlers are
98*d90bee97SLionel Sambuc  * set to the appropriate value for the child.  (The test for iflag is
99*d90bee97SLionel Sambuc  * just defensive programming.)
100*d90bee97SLionel Sambuc  */
101*d90bee97SLionel Sambuc 
102*d90bee97SLionel Sambuc void
onint(void)103*d90bee97SLionel Sambuc onint(void)
104*d90bee97SLionel Sambuc {
105*d90bee97SLionel Sambuc 	sigset_t nsigset;
106*d90bee97SLionel Sambuc 
107*d90bee97SLionel Sambuc 	if (suppressint) {
108*d90bee97SLionel Sambuc 		intpending = 1;
109*d90bee97SLionel Sambuc 		return;
110*d90bee97SLionel Sambuc 	}
111*d90bee97SLionel Sambuc 	intpending = 0;
112*d90bee97SLionel Sambuc 	sigemptyset(&nsigset);
113*d90bee97SLionel Sambuc 	sigprocmask(SIG_SETMASK, &nsigset, NULL);
114*d90bee97SLionel Sambuc 	if (rootshell && iflag)
115*d90bee97SLionel Sambuc 		exraise(EXINT);
116*d90bee97SLionel Sambuc 	else {
117*d90bee97SLionel Sambuc 		signal(SIGINT, SIG_DFL);
118*d90bee97SLionel Sambuc 		raise(SIGINT);
119*d90bee97SLionel Sambuc 	}
120*d90bee97SLionel Sambuc 	/* NOTREACHED */
121*d90bee97SLionel Sambuc }
122*d90bee97SLionel Sambuc 
123*d90bee97SLionel Sambuc static __printflike(2, 0) void
exvwarning(int sv_errno,const char * msg,va_list ap)124*d90bee97SLionel Sambuc exvwarning(int sv_errno, const char *msg, va_list ap)
125*d90bee97SLionel Sambuc {
126*d90bee97SLionel Sambuc 	/* Partially emulate line buffered output so that:
127*d90bee97SLionel Sambuc 	 *	printf '%d\n' 1 a 2
128*d90bee97SLionel Sambuc 	 * and
129*d90bee97SLionel Sambuc 	 *	printf '%d %d %d\n' 1 a 2
130*d90bee97SLionel Sambuc 	 * both generate sensible text when stdout and stderr are merged.
131*d90bee97SLionel Sambuc 	 */
132*d90bee97SLionel Sambuc 	if (output.nextc != output.buf && output.nextc[-1] == '\n')
133*d90bee97SLionel Sambuc 		flushout(&output);
134*d90bee97SLionel Sambuc 	if (commandname)
135*d90bee97SLionel Sambuc 		outfmt(&errout, "%s: ", commandname);
136*d90bee97SLionel Sambuc 	else
137*d90bee97SLionel Sambuc 		outfmt(&errout, "%s: ", getprogname());
138*d90bee97SLionel Sambuc 	if (msg != NULL) {
139*d90bee97SLionel Sambuc 		doformat(&errout, msg, ap);
140*d90bee97SLionel Sambuc 		if (sv_errno >= 0)
141*d90bee97SLionel Sambuc 			outfmt(&errout, ": ");
142*d90bee97SLionel Sambuc 	}
143*d90bee97SLionel Sambuc 	if (sv_errno >= 0)
144*d90bee97SLionel Sambuc 		outfmt(&errout, "%s", strerror(sv_errno));
145*d90bee97SLionel Sambuc 	out2c('\n');
146*d90bee97SLionel Sambuc 	flushout(&errout);
147*d90bee97SLionel Sambuc }
148*d90bee97SLionel Sambuc 
149*d90bee97SLionel Sambuc /*
150*d90bee97SLionel Sambuc  * Exverror is called to raise the error exception.  If the second argument
151*d90bee97SLionel Sambuc  * is not NULL then error prints an error message using printf style
152*d90bee97SLionel Sambuc  * formatting.  It then raises the error exception.
153*d90bee97SLionel Sambuc  */
154*d90bee97SLionel Sambuc static __printflike(2, 0) void
exverror(int cond,const char * msg,va_list ap)155*d90bee97SLionel Sambuc exverror(int cond, const char *msg, va_list ap)
156*d90bee97SLionel Sambuc {
157*d90bee97SLionel Sambuc 	CLEAR_PENDING_INT;
158*d90bee97SLionel Sambuc 	INTOFF;
159*d90bee97SLionel Sambuc 
160*d90bee97SLionel Sambuc #ifdef DEBUG
161*d90bee97SLionel Sambuc 	if (msg) {
162*d90bee97SLionel Sambuc 		TRACE(("exverror(%d, \"", cond));
163*d90bee97SLionel Sambuc 		TRACEV((msg, ap));
164*d90bee97SLionel Sambuc 		TRACE(("\") pid=%d\n", getpid()));
165*d90bee97SLionel Sambuc 	} else
166*d90bee97SLionel Sambuc 		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
167*d90bee97SLionel Sambuc #endif
168*d90bee97SLionel Sambuc 	if (msg)
169*d90bee97SLionel Sambuc 		exvwarning(-1, msg, ap);
170*d90bee97SLionel Sambuc 
171*d90bee97SLionel Sambuc 	flushall();
172*d90bee97SLionel Sambuc 	exraise(cond);
173*d90bee97SLionel Sambuc 	/* NOTREACHED */
174*d90bee97SLionel Sambuc }
175*d90bee97SLionel Sambuc 
176*d90bee97SLionel Sambuc 
177*d90bee97SLionel Sambuc void
error(const char * msg,...)178*d90bee97SLionel Sambuc error(const char *msg, ...)
179*d90bee97SLionel Sambuc {
180*d90bee97SLionel Sambuc 	va_list ap;
181*d90bee97SLionel Sambuc 
182*d90bee97SLionel Sambuc 	va_start(ap, msg);
183*d90bee97SLionel Sambuc 	exverror(EXERROR, msg, ap);
184*d90bee97SLionel Sambuc 	/* NOTREACHED */
185*d90bee97SLionel Sambuc 	va_end(ap);
186*d90bee97SLionel Sambuc }
187*d90bee97SLionel Sambuc 
188*d90bee97SLionel Sambuc 
189*d90bee97SLionel Sambuc void
exerror(int cond,const char * msg,...)190*d90bee97SLionel Sambuc exerror(int cond, const char *msg, ...)
191*d90bee97SLionel Sambuc {
192*d90bee97SLionel Sambuc 	va_list ap;
193*d90bee97SLionel Sambuc 
194*d90bee97SLionel Sambuc 	va_start(ap, msg);
195*d90bee97SLionel Sambuc 	exverror(cond, msg, ap);
196*d90bee97SLionel Sambuc 	/* NOTREACHED */
197*d90bee97SLionel Sambuc 	va_end(ap);
198*d90bee97SLionel Sambuc }
199*d90bee97SLionel Sambuc 
200*d90bee97SLionel Sambuc /*
201*d90bee97SLionel Sambuc  * error/warning routines for external builtins
202*d90bee97SLionel Sambuc  */
203*d90bee97SLionel Sambuc 
204*d90bee97SLionel Sambuc void
sh_exit(int rval)205*d90bee97SLionel Sambuc sh_exit(int rval)
206*d90bee97SLionel Sambuc {
207*d90bee97SLionel Sambuc 	exerrno = rval & 255;
208*d90bee97SLionel Sambuc 	exraise(EXEXEC);
209*d90bee97SLionel Sambuc }
210*d90bee97SLionel Sambuc 
211*d90bee97SLionel Sambuc void
sh_err(int status,const char * fmt,...)212*d90bee97SLionel Sambuc sh_err(int status, const char *fmt, ...)
213*d90bee97SLionel Sambuc {
214*d90bee97SLionel Sambuc 	va_list ap;
215*d90bee97SLionel Sambuc 
216*d90bee97SLionel Sambuc 	va_start(ap, fmt);
217*d90bee97SLionel Sambuc 	exvwarning(errno, fmt, ap);
218*d90bee97SLionel Sambuc 	va_end(ap);
219*d90bee97SLionel Sambuc 	sh_exit(status);
220*d90bee97SLionel Sambuc }
221*d90bee97SLionel Sambuc 
222*d90bee97SLionel Sambuc void
sh_verr(int status,const char * fmt,va_list ap)223*d90bee97SLionel Sambuc sh_verr(int status, const char *fmt, va_list ap)
224*d90bee97SLionel Sambuc {
225*d90bee97SLionel Sambuc 	exvwarning(errno, fmt, ap);
226*d90bee97SLionel Sambuc 	sh_exit(status);
227*d90bee97SLionel Sambuc }
228*d90bee97SLionel Sambuc 
229*d90bee97SLionel Sambuc void
sh_errx(int status,const char * fmt,...)230*d90bee97SLionel Sambuc sh_errx(int status, const char *fmt, ...)
231*d90bee97SLionel Sambuc {
232*d90bee97SLionel Sambuc 	va_list ap;
233*d90bee97SLionel Sambuc 
234*d90bee97SLionel Sambuc 	va_start(ap, fmt);
235*d90bee97SLionel Sambuc 	exvwarning(-1, fmt, ap);
236*d90bee97SLionel Sambuc 	va_end(ap);
237*d90bee97SLionel Sambuc 	sh_exit(status);
238*d90bee97SLionel Sambuc }
239*d90bee97SLionel Sambuc 
240*d90bee97SLionel Sambuc void
sh_verrx(int status,const char * fmt,va_list ap)241*d90bee97SLionel Sambuc sh_verrx(int status, const char *fmt, va_list ap)
242*d90bee97SLionel Sambuc {
243*d90bee97SLionel Sambuc 	exvwarning(-1, fmt, ap);
244*d90bee97SLionel Sambuc 	sh_exit(status);
245*d90bee97SLionel Sambuc }
246*d90bee97SLionel Sambuc 
247*d90bee97SLionel Sambuc void
sh_warn(const char * fmt,...)248*d90bee97SLionel Sambuc sh_warn(const char *fmt, ...)
249*d90bee97SLionel Sambuc {
250*d90bee97SLionel Sambuc 	va_list ap;
251*d90bee97SLionel Sambuc 
252*d90bee97SLionel Sambuc 	va_start(ap, fmt);
253*d90bee97SLionel Sambuc 	exvwarning(errno, fmt, ap);
254*d90bee97SLionel Sambuc 	va_end(ap);
255*d90bee97SLionel Sambuc }
256*d90bee97SLionel Sambuc 
257*d90bee97SLionel Sambuc void
sh_vwarn(const char * fmt,va_list ap)258*d90bee97SLionel Sambuc sh_vwarn(const char *fmt, va_list ap)
259*d90bee97SLionel Sambuc {
260*d90bee97SLionel Sambuc 	exvwarning(errno, fmt, ap);
261*d90bee97SLionel Sambuc }
262*d90bee97SLionel Sambuc 
263*d90bee97SLionel Sambuc void
sh_warnx(const char * fmt,...)264*d90bee97SLionel Sambuc sh_warnx(const char *fmt, ...)
265*d90bee97SLionel Sambuc {
266*d90bee97SLionel Sambuc 	va_list ap;
267*d90bee97SLionel Sambuc 
268*d90bee97SLionel Sambuc 	va_start(ap, fmt);
269*d90bee97SLionel Sambuc 	exvwarning(-1, fmt, ap);
270*d90bee97SLionel Sambuc 	va_end(ap);
271*d90bee97SLionel Sambuc }
272*d90bee97SLionel Sambuc 
273*d90bee97SLionel Sambuc void
sh_vwarnx(const char * fmt,va_list ap)274*d90bee97SLionel Sambuc sh_vwarnx(const char *fmt, va_list ap)
275*d90bee97SLionel Sambuc {
276*d90bee97SLionel Sambuc 	exvwarning(-1, fmt, ap);
277*d90bee97SLionel Sambuc }
278*d90bee97SLionel Sambuc 
279*d90bee97SLionel Sambuc 
280*d90bee97SLionel Sambuc /*
281*d90bee97SLionel Sambuc  * Table of error messages.
282*d90bee97SLionel Sambuc  */
283*d90bee97SLionel Sambuc 
284*d90bee97SLionel Sambuc struct errname {
285*d90bee97SLionel Sambuc 	short errcode;		/* error number */
286*d90bee97SLionel Sambuc 	short action;		/* operation which encountered the error */
287*d90bee97SLionel Sambuc 	const char *msg;	/* text describing the error */
288*d90bee97SLionel Sambuc };
289*d90bee97SLionel Sambuc 
290*d90bee97SLionel Sambuc 
291*d90bee97SLionel Sambuc #define ALL (E_OPEN|E_CREAT|E_EXEC)
292*d90bee97SLionel Sambuc 
293*d90bee97SLionel Sambuc STATIC const struct errname errormsg[] = {
294*d90bee97SLionel Sambuc 	{ EINTR,	ALL,	"interrupted" },
295*d90bee97SLionel Sambuc 	{ EACCES,	ALL,	"permission denied" },
296*d90bee97SLionel Sambuc 	{ EIO,		ALL,	"I/O error" },
297*d90bee97SLionel Sambuc 	{ EEXIST,	ALL,	"file exists" },
298*d90bee97SLionel Sambuc 	{ ENOENT,	E_OPEN,	"no such file" },
299*d90bee97SLionel Sambuc 	{ ENOENT,	E_CREAT,"directory nonexistent" },
300*d90bee97SLionel Sambuc 	{ ENOENT,	E_EXEC,	"not found" },
301*d90bee97SLionel Sambuc 	{ ENOTDIR,	E_OPEN,	"no such file" },
302*d90bee97SLionel Sambuc 	{ ENOTDIR,	E_CREAT,"directory nonexistent" },
303*d90bee97SLionel Sambuc 	{ ENOTDIR,	E_EXEC,	"not found" },
304*d90bee97SLionel Sambuc 	{ EISDIR,	ALL,	"is a directory" },
305*d90bee97SLionel Sambuc #ifdef EMFILE
306*d90bee97SLionel Sambuc 	{ EMFILE,	ALL,	"too many open files" },
307*d90bee97SLionel Sambuc #endif
308*d90bee97SLionel Sambuc 	{ ENFILE,	ALL,	"file table overflow" },
309*d90bee97SLionel Sambuc 	{ ENOSPC,	ALL,	"file system full" },
310*d90bee97SLionel Sambuc #ifdef EDQUOT
311*d90bee97SLionel Sambuc 	{ EDQUOT,	ALL,	"disk quota exceeded" },
312*d90bee97SLionel Sambuc #endif
313*d90bee97SLionel Sambuc #ifdef ENOSR
314*d90bee97SLionel Sambuc 	{ ENOSR,	ALL,	"no streams resources" },
315*d90bee97SLionel Sambuc #endif
316*d90bee97SLionel Sambuc 	{ ENXIO,	ALL,	"no such device or address" },
317*d90bee97SLionel Sambuc 	{ EROFS,	ALL,	"read-only file system" },
318*d90bee97SLionel Sambuc 	{ ETXTBSY,	ALL,	"text busy" },
319*d90bee97SLionel Sambuc #ifdef EAGAIN
320*d90bee97SLionel Sambuc 	{ EAGAIN,	E_EXEC,	"not enough memory" },
321*d90bee97SLionel Sambuc #endif
322*d90bee97SLionel Sambuc 	{ ENOMEM,	ALL,	"not enough memory" },
323*d90bee97SLionel Sambuc #ifdef ENOLINK
324*d90bee97SLionel Sambuc 	{ ENOLINK,	ALL,	"remote access failed" },
325*d90bee97SLionel Sambuc #endif
326*d90bee97SLionel Sambuc #ifdef EMULTIHOP
327*d90bee97SLionel Sambuc 	{ EMULTIHOP,	ALL,	"remote access failed" },
328*d90bee97SLionel Sambuc #endif
329*d90bee97SLionel Sambuc #ifdef ECOMM
330*d90bee97SLionel Sambuc 	{ ECOMM,	ALL,	"remote access failed" },
331*d90bee97SLionel Sambuc #endif
332*d90bee97SLionel Sambuc #ifdef ESTALE
333*d90bee97SLionel Sambuc 	{ ESTALE,	ALL,	"remote access failed" },
334*d90bee97SLionel Sambuc #endif
335*d90bee97SLionel Sambuc #ifdef ETIMEDOUT
336*d90bee97SLionel Sambuc 	{ ETIMEDOUT,	ALL,	"remote access failed" },
337*d90bee97SLionel Sambuc #endif
338*d90bee97SLionel Sambuc #ifdef ELOOP
339*d90bee97SLionel Sambuc 	{ ELOOP,	ALL,	"symbolic link loop" },
340*d90bee97SLionel Sambuc #endif
341*d90bee97SLionel Sambuc #ifdef ENAMETOOLONG
342*d90bee97SLionel Sambuc 	{ ENAMETOOLONG,	ALL,	"file name too long" },
343*d90bee97SLionel Sambuc #endif
344*d90bee97SLionel Sambuc 	{ E2BIG,	E_EXEC,	"argument list too long" },
345*d90bee97SLionel Sambuc #ifdef ELIBACC
346*d90bee97SLionel Sambuc 	{ ELIBACC,	E_EXEC,	"shared library missing" },
347*d90bee97SLionel Sambuc #endif
348*d90bee97SLionel Sambuc 	{ 0,		0,	NULL },
349*d90bee97SLionel Sambuc };
350*d90bee97SLionel Sambuc 
351*d90bee97SLionel Sambuc 
352*d90bee97SLionel Sambuc /*
353*d90bee97SLionel Sambuc  * Return a string describing an error.  The returned string may be a
354*d90bee97SLionel Sambuc  * pointer to a static buffer that will be overwritten on the next call.
355*d90bee97SLionel Sambuc  * Action describes the operation that got the error.
356*d90bee97SLionel Sambuc  */
357*d90bee97SLionel Sambuc 
358*d90bee97SLionel Sambuc const char *
errmsg(int e,int action)359*d90bee97SLionel Sambuc errmsg(int e, int action)
360*d90bee97SLionel Sambuc {
361*d90bee97SLionel Sambuc 	struct errname const *ep;
362*d90bee97SLionel Sambuc 	static char buf[12];
363*d90bee97SLionel Sambuc 
364*d90bee97SLionel Sambuc 	for (ep = errormsg ; ep->errcode ; ep++) {
365*d90bee97SLionel Sambuc 		if (ep->errcode == e && (ep->action & action) != 0)
366*d90bee97SLionel Sambuc 			return ep->msg;
367*d90bee97SLionel Sambuc 	}
368*d90bee97SLionel Sambuc 	fmtstr(buf, sizeof buf, "error %d", e);
369*d90bee97SLionel Sambuc 	return buf;
370*d90bee97SLionel Sambuc }
371