1*e83f7ba2SBen Gras /* $NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $ */
2*e83f7ba2SBen Gras
3*e83f7ba2SBen Gras /*
4*e83f7ba2SBen Gras * Copyright 1996 Matt Thomas <matt@3am-software.com>
5*e83f7ba2SBen Gras * All rights reserved.
6*e83f7ba2SBen Gras *
7*e83f7ba2SBen Gras * Redistribution and use in source and binary forms, with or without
8*e83f7ba2SBen Gras * modification, are permitted provided that the following conditions
9*e83f7ba2SBen Gras * are met:
10*e83f7ba2SBen Gras * 1. Redistributions of source code must retain the above copyright
11*e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer.
12*e83f7ba2SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
13*e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer in the
14*e83f7ba2SBen Gras * documentation and/or other materials provided with the distribution.
15*e83f7ba2SBen Gras * 3. The name of the author may not be used to endorse or promote products
16*e83f7ba2SBen Gras * derived from this software without specific prior written permission.
17*e83f7ba2SBen Gras *
18*e83f7ba2SBen Gras * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19*e83f7ba2SBen Gras * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*e83f7ba2SBen Gras * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21*e83f7ba2SBen Gras * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22*e83f7ba2SBen Gras * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23*e83f7ba2SBen Gras * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*e83f7ba2SBen Gras * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*e83f7ba2SBen Gras * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*e83f7ba2SBen Gras * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27*e83f7ba2SBen Gras * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*e83f7ba2SBen Gras */
29*e83f7ba2SBen Gras
30*e83f7ba2SBen Gras #include <sys/cdefs.h>
31*e83f7ba2SBen Gras #ifndef lint
32*e83f7ba2SBen Gras __RCSID("$NetBSD: xprintf.c,v 1.21 2010/12/16 22:52:32 joerg Exp $");
33*e83f7ba2SBen Gras #endif /* not lint */
34*e83f7ba2SBen Gras
35*e83f7ba2SBen Gras #include <string.h>
36*e83f7ba2SBen Gras #include <stdlib.h>
37*e83f7ba2SBen Gras #include <unistd.h>
38*e83f7ba2SBen Gras #include <errno.h>
39*e83f7ba2SBen Gras #include <stdarg.h>
40*e83f7ba2SBen Gras
41*e83f7ba2SBen Gras #include "rtldenv.h"
42*e83f7ba2SBen Gras
43*e83f7ba2SBen Gras #ifdef RTLD_LOADER
44*e83f7ba2SBen Gras #define SZ_LONG 0x01
45*e83f7ba2SBen Gras #define SZ_UNSIGNED 0x02
46*e83f7ba2SBen Gras #define SZ_SIZE_T 0x04
47*e83f7ba2SBen Gras
48*e83f7ba2SBen Gras /*
49*e83f7ba2SBen Gras * Non-mallocing printf, for use by malloc and rtld itself.
50*e83f7ba2SBen Gras * This avoids putting in most of stdio.
51*e83f7ba2SBen Gras *
52*e83f7ba2SBen Gras * deals withs formats %x, %p, %s, and %d.
53*e83f7ba2SBen Gras */
54*e83f7ba2SBen Gras size_t
xvsnprintf(char * buf,size_t buflen,const char * fmt,va_list ap)55*e83f7ba2SBen Gras xvsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap)
56*e83f7ba2SBen Gras {
57*e83f7ba2SBen Gras char *bp = buf;
58*e83f7ba2SBen Gras char *const ep = buf + buflen - 4;
59*e83f7ba2SBen Gras int size, prec;
60*e83f7ba2SBen Gras
61*e83f7ba2SBen Gras while (*fmt != '\0' && bp < ep) {
62*e83f7ba2SBen Gras switch (*fmt) {
63*e83f7ba2SBen Gras case '\\':{
64*e83f7ba2SBen Gras if (fmt[1] != '\0')
65*e83f7ba2SBen Gras *bp++ = *++fmt;
66*e83f7ba2SBen Gras continue;
67*e83f7ba2SBen Gras }
68*e83f7ba2SBen Gras case '%':{
69*e83f7ba2SBen Gras size = 0;
70*e83f7ba2SBen Gras prec = -1;
71*e83f7ba2SBen Gras rflag: switch (fmt[1]) {
72*e83f7ba2SBen Gras case '*':
73*e83f7ba2SBen Gras prec = va_arg(ap, int);
74*e83f7ba2SBen Gras /* FALLTHROUGH */
75*e83f7ba2SBen Gras case '.':
76*e83f7ba2SBen Gras fmt++;
77*e83f7ba2SBen Gras goto rflag;
78*e83f7ba2SBen Gras case 'l':
79*e83f7ba2SBen Gras size |= SZ_LONG;
80*e83f7ba2SBen Gras fmt++;
81*e83f7ba2SBen Gras goto rflag;
82*e83f7ba2SBen Gras case 'z':
83*e83f7ba2SBen Gras size |= SZ_SIZE_T;
84*e83f7ba2SBen Gras fmt++;
85*e83f7ba2SBen Gras goto rflag;
86*e83f7ba2SBen Gras case 'u':
87*e83f7ba2SBen Gras size |= SZ_UNSIGNED;
88*e83f7ba2SBen Gras /* FALLTHROUGH */
89*e83f7ba2SBen Gras case 'd':{
90*e83f7ba2SBen Gras long sval;
91*e83f7ba2SBen Gras unsigned long uval;
92*e83f7ba2SBen Gras char digits[sizeof(int) * 3], *dp = digits;
93*e83f7ba2SBen Gras #define SARG() \
94*e83f7ba2SBen Gras (size & SZ_LONG ? va_arg(ap, long) : \
95*e83f7ba2SBen Gras ((size & SZ_SIZE_T ? (long)va_arg(ap, size_t) : \
96*e83f7ba2SBen Gras va_arg(ap, int))))
97*e83f7ba2SBen Gras #define UARG() \
98*e83f7ba2SBen Gras (size & SZ_LONG ? va_arg(ap, unsigned long) : \
99*e83f7ba2SBen Gras ((size & SZ_SIZE_T ? va_arg(ap, size_t) : \
100*e83f7ba2SBen Gras va_arg(ap, unsigned int))))
101*e83f7ba2SBen Gras
102*e83f7ba2SBen Gras if (fmt[1] == 'd') {
103*e83f7ba2SBen Gras if (size & SZ_UNSIGNED)
104*e83f7ba2SBen Gras sval = UARG();
105*e83f7ba2SBen Gras else
106*e83f7ba2SBen Gras sval = SARG();
107*e83f7ba2SBen Gras if (sval < 0) {
108*e83f7ba2SBen Gras if ((sval << 1) == 0) {
109*e83f7ba2SBen Gras /*
110*e83f7ba2SBen Gras * We can't flip the
111*e83f7ba2SBen Gras * sign of this since
112*e83f7ba2SBen Gras * it can't be
113*e83f7ba2SBen Gras * represented as a
114*e83f7ba2SBen Gras * positive number in
115*e83f7ba2SBen Gras * two complement,
116*e83f7ba2SBen Gras * handle the first
117*e83f7ba2SBen Gras * digit. After that,
118*e83f7ba2SBen Gras * it can be flipped
119*e83f7ba2SBen Gras * since it is now not
120*e83f7ba2SBen Gras * 2^(n-1).
121*e83f7ba2SBen Gras */
122*e83f7ba2SBen Gras *dp++ = '0'-(sval % 10);
123*e83f7ba2SBen Gras sval /= 10;
124*e83f7ba2SBen Gras }
125*e83f7ba2SBen Gras *bp++ = '-';
126*e83f7ba2SBen Gras uval = -sval;
127*e83f7ba2SBen Gras } else {
128*e83f7ba2SBen Gras uval = sval;
129*e83f7ba2SBen Gras }
130*e83f7ba2SBen Gras } else {
131*e83f7ba2SBen Gras if (size & SZ_UNSIGNED)
132*e83f7ba2SBen Gras uval = UARG();
133*e83f7ba2SBen Gras else
134*e83f7ba2SBen Gras uval = SARG();
135*e83f7ba2SBen Gras }
136*e83f7ba2SBen Gras do {
137*e83f7ba2SBen Gras *dp++ = '0' + (uval % 10);
138*e83f7ba2SBen Gras uval /= 10;
139*e83f7ba2SBen Gras } while (uval != 0);
140*e83f7ba2SBen Gras do {
141*e83f7ba2SBen Gras *bp++ = *--dp;
142*e83f7ba2SBen Gras } while (dp != digits && bp < ep);
143*e83f7ba2SBen Gras fmt += 2;
144*e83f7ba2SBen Gras break;
145*e83f7ba2SBen Gras }
146*e83f7ba2SBen Gras case 'x':
147*e83f7ba2SBen Gras case 'p':{
148*e83f7ba2SBen Gras unsigned long val = va_arg(ap, unsigned long);
149*e83f7ba2SBen Gras unsigned long mask = ~(~0UL >> 4);
150*e83f7ba2SBen Gras int bits = sizeof(val) * 8 - 4;
151*e83f7ba2SBen Gras const char hexdigits[] = "0123456789abcdef";
152*e83f7ba2SBen Gras if (fmt[1] == 'p') {
153*e83f7ba2SBen Gras *bp++ = '0';
154*e83f7ba2SBen Gras *bp++ = 'x';
155*e83f7ba2SBen Gras }
156*e83f7ba2SBen Gras /* handle the border case */
157*e83f7ba2SBen Gras if (val == 0) {
158*e83f7ba2SBen Gras *bp++ = '0';
159*e83f7ba2SBen Gras fmt += 2;
160*e83f7ba2SBen Gras break;
161*e83f7ba2SBen Gras }
162*e83f7ba2SBen Gras /* suppress 0s */
163*e83f7ba2SBen Gras while ((val & mask) == 0)
164*e83f7ba2SBen Gras bits -= 4, mask >>= 4;
165*e83f7ba2SBen Gras
166*e83f7ba2SBen Gras /* emit the hex digits */
167*e83f7ba2SBen Gras while (bits >= 0 && bp < ep) {
168*e83f7ba2SBen Gras *bp++ = hexdigits[(val & mask) >> bits];
169*e83f7ba2SBen Gras bits -= 4, mask >>= 4;
170*e83f7ba2SBen Gras }
171*e83f7ba2SBen Gras fmt += 2;
172*e83f7ba2SBen Gras break;
173*e83f7ba2SBen Gras }
174*e83f7ba2SBen Gras case 's':{
175*e83f7ba2SBen Gras const char *str = va_arg(ap, const char *);
176*e83f7ba2SBen Gras int len;
177*e83f7ba2SBen Gras
178*e83f7ba2SBen Gras if (str == NULL)
179*e83f7ba2SBen Gras str = "(null)";
180*e83f7ba2SBen Gras
181*e83f7ba2SBen Gras if (prec < 0)
182*e83f7ba2SBen Gras len = strlen(str);
183*e83f7ba2SBen Gras else
184*e83f7ba2SBen Gras len = prec;
185*e83f7ba2SBen Gras if (ep - bp < len)
186*e83f7ba2SBen Gras len = ep - bp;
187*e83f7ba2SBen Gras memcpy(bp, str, len);
188*e83f7ba2SBen Gras bp += len;
189*e83f7ba2SBen Gras fmt += 2;
190*e83f7ba2SBen Gras break;
191*e83f7ba2SBen Gras }
192*e83f7ba2SBen Gras case 'c':{
193*e83f7ba2SBen Gras int c = va_arg(ap, int);
194*e83f7ba2SBen Gras *bp++ = (char)c;
195*e83f7ba2SBen Gras fmt += 2;
196*e83f7ba2SBen Gras break;
197*e83f7ba2SBen Gras }
198*e83f7ba2SBen Gras default:
199*e83f7ba2SBen Gras *bp++ = *fmt;
200*e83f7ba2SBen Gras break;
201*e83f7ba2SBen Gras }
202*e83f7ba2SBen Gras break;
203*e83f7ba2SBen Gras }
204*e83f7ba2SBen Gras default:
205*e83f7ba2SBen Gras *bp++ = *fmt++;
206*e83f7ba2SBen Gras break;
207*e83f7ba2SBen Gras }
208*e83f7ba2SBen Gras }
209*e83f7ba2SBen Gras
210*e83f7ba2SBen Gras *bp = '\0';
211*e83f7ba2SBen Gras return bp - buf;
212*e83f7ba2SBen Gras }
213*e83f7ba2SBen Gras
214*e83f7ba2SBen Gras void
xvprintf(const char * fmt,va_list ap)215*e83f7ba2SBen Gras xvprintf(const char *fmt, va_list ap)
216*e83f7ba2SBen Gras {
217*e83f7ba2SBen Gras char buf[256];
218*e83f7ba2SBen Gras
219*e83f7ba2SBen Gras (void) write(2, buf, xvsnprintf(buf, sizeof(buf), fmt, ap));
220*e83f7ba2SBen Gras }
221*e83f7ba2SBen Gras
222*e83f7ba2SBen Gras void
xprintf(const char * fmt,...)223*e83f7ba2SBen Gras xprintf(const char *fmt, ...)
224*e83f7ba2SBen Gras {
225*e83f7ba2SBen Gras va_list ap;
226*e83f7ba2SBen Gras
227*e83f7ba2SBen Gras va_start(ap, fmt);
228*e83f7ba2SBen Gras
229*e83f7ba2SBen Gras xvprintf(fmt, ap);
230*e83f7ba2SBen Gras
231*e83f7ba2SBen Gras va_end(ap);
232*e83f7ba2SBen Gras }
233*e83f7ba2SBen Gras
234*e83f7ba2SBen Gras void
xsnprintf(char * buf,size_t buflen,const char * fmt,...)235*e83f7ba2SBen Gras xsnprintf(char *buf, size_t buflen, const char *fmt, ...)
236*e83f7ba2SBen Gras {
237*e83f7ba2SBen Gras va_list ap;
238*e83f7ba2SBen Gras
239*e83f7ba2SBen Gras va_start(ap, fmt);
240*e83f7ba2SBen Gras
241*e83f7ba2SBen Gras xvsnprintf(buf, buflen, fmt, ap);
242*e83f7ba2SBen Gras
243*e83f7ba2SBen Gras va_end(ap);
244*e83f7ba2SBen Gras }
245*e83f7ba2SBen Gras
246*e83f7ba2SBen Gras #include "errlist_concat.h"
247*e83f7ba2SBen Gras
248*e83f7ba2SBen Gras const char *
xstrerror(int error)249*e83f7ba2SBen Gras xstrerror(int error)
250*e83f7ba2SBen Gras {
251*e83f7ba2SBen Gras
252*e83f7ba2SBen Gras if (error >= concat_nerr || error < 0) {
253*e83f7ba2SBen Gras static char buf[128];
254*e83f7ba2SBen Gras xsnprintf(buf, sizeof(buf), "Unknown error: %d", error);
255*e83f7ba2SBen Gras return buf;
256*e83f7ba2SBen Gras }
257*e83f7ba2SBen Gras return concat_errlist + concat_offset[error];
258*e83f7ba2SBen Gras }
259*e83f7ba2SBen Gras
260*e83f7ba2SBen Gras void
xerrx(int eval,const char * fmt,...)261*e83f7ba2SBen Gras xerrx(int eval, const char *fmt, ...)
262*e83f7ba2SBen Gras {
263*e83f7ba2SBen Gras va_list ap;
264*e83f7ba2SBen Gras
265*e83f7ba2SBen Gras va_start(ap, fmt);
266*e83f7ba2SBen Gras xvprintf(fmt, ap);
267*e83f7ba2SBen Gras va_end(ap);
268*e83f7ba2SBen Gras (void) write(2, "\n", 1);
269*e83f7ba2SBen Gras
270*e83f7ba2SBen Gras exit(eval);
271*e83f7ba2SBen Gras }
272*e83f7ba2SBen Gras
273*e83f7ba2SBen Gras void
xerr(int eval,const char * fmt,...)274*e83f7ba2SBen Gras xerr(int eval, const char *fmt, ...)
275*e83f7ba2SBen Gras {
276*e83f7ba2SBen Gras int saved_errno = errno;
277*e83f7ba2SBen Gras va_list ap;
278*e83f7ba2SBen Gras
279*e83f7ba2SBen Gras va_start(ap, fmt);
280*e83f7ba2SBen Gras xvprintf(fmt, ap);
281*e83f7ba2SBen Gras va_end(ap);
282*e83f7ba2SBen Gras
283*e83f7ba2SBen Gras xprintf(": %s\n", xstrerror(saved_errno));
284*e83f7ba2SBen Gras exit(eval);
285*e83f7ba2SBen Gras }
286*e83f7ba2SBen Gras
287*e83f7ba2SBen Gras void
xwarn(const char * fmt,...)288*e83f7ba2SBen Gras xwarn(const char *fmt, ...)
289*e83f7ba2SBen Gras {
290*e83f7ba2SBen Gras int saved_errno = errno;
291*e83f7ba2SBen Gras va_list ap;
292*e83f7ba2SBen Gras
293*e83f7ba2SBen Gras va_start(ap, fmt);
294*e83f7ba2SBen Gras xvprintf(fmt, ap);
295*e83f7ba2SBen Gras va_end(ap);
296*e83f7ba2SBen Gras
297*e83f7ba2SBen Gras xprintf(": %s\n", xstrerror(saved_errno));
298*e83f7ba2SBen Gras errno = saved_errno;
299*e83f7ba2SBen Gras }
300*e83f7ba2SBen Gras
301*e83f7ba2SBen Gras void
xwarnx(const char * fmt,...)302*e83f7ba2SBen Gras xwarnx(const char *fmt, ...)
303*e83f7ba2SBen Gras {
304*e83f7ba2SBen Gras va_list ap;
305*e83f7ba2SBen Gras
306*e83f7ba2SBen Gras va_start(ap, fmt);
307*e83f7ba2SBen Gras xvprintf(fmt, ap);
308*e83f7ba2SBen Gras va_end(ap);
309*e83f7ba2SBen Gras (void) write(2, "\n", 1);
310*e83f7ba2SBen Gras }
311*e83f7ba2SBen Gras
312*e83f7ba2SBen Gras #ifdef DEBUG
313*e83f7ba2SBen Gras void
xassert(const char * file,int line,const char * failedexpr)314*e83f7ba2SBen Gras xassert(const char *file, int line, const char *failedexpr)
315*e83f7ba2SBen Gras {
316*e83f7ba2SBen Gras
317*e83f7ba2SBen Gras xprintf("assertion \"%s\" failed: file \"%s\", line %d\n",
318*e83f7ba2SBen Gras failedexpr, file, line);
319*e83f7ba2SBen Gras abort();
320*e83f7ba2SBen Gras /* NOTREACHED */
321*e83f7ba2SBen Gras }
322*e83f7ba2SBen Gras #endif
323*e83f7ba2SBen Gras #endif
324