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