~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to compat/snprintf.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1999-2005, 2008, 2010-2011
 
3
 *      Todd C. Miller <Todd.Miller@courtesan.com>
 
4
 * Copyright (c) 1990, 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
 * Chris Torek.
 
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
 * From: @(#)vfprintf.c 8.1 (Berkeley) 6/4/93
 
35
 */
 
36
 
 
37
/*
 
38
 * v?snprintf/v?asprintf based on 4.4BSD stdio.
 
39
 * NOTE: does not support floating point.
 
40
 */
 
41
 
 
42
#include <config.h>
 
43
 
 
44
#include <sys/types.h>
 
45
#include <sys/param.h>
 
46
 
 
47
#include <stdio.h>
 
48
#ifdef STDC_HEADERS
 
49
# include <stdlib.h>
 
50
# include <stddef.h>
 
51
#else
 
52
# ifdef HAVE_STDLIB_H
 
53
#  include <stdlib.h>
 
54
# endif
 
55
#endif /* STDC_HEADERS */
 
56
#ifdef HAVE_STDINT_H
 
57
# include <stdint.h>
 
58
#endif
 
59
#ifdef HAVE_STRING_H
 
60
# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
 
61
#  include <memory.h>
 
62
# endif
 
63
# include <string.h>
 
64
#endif /* HAVE_STRING_H */
 
65
#ifdef HAVE_STRINGS_H
 
66
# include <strings.h>
 
67
#endif /* HAVE_STRINGS_H */
 
68
#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
 
69
# include <malloc.h>
 
70
#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
 
71
#include <limits.h>
 
72
#include <stdarg.h>
 
73
 
 
74
#include "missing.h"
 
75
 
 
76
static int xxxprintf(char **, size_t, int, const char *, va_list);
 
77
 
 
78
/*
 
79
 * Some systems may not have these defined in <limits.h>
 
80
 */
 
81
#ifndef ULONG_MAX
 
82
# define ULONG_MAX      ((unsigned long)-1)
 
83
#endif
 
84
#ifndef LONG_MAX
 
85
# define LONG_MAX       (ULONG_MAX / 2)
 
86
#endif
 
87
#ifdef HAVE_LONG_LONG_INT
 
88
# ifndef ULLONG_MAX
 
89
#  ifdef UQUAD_MAX
 
90
#   define ULLONG_MAX   UQUAD_MAX
 
91
#  else
 
92
#   define ULLONG_MAX   ((unsigned long long)-1)
 
93
#  endif
 
94
# endif
 
95
# ifndef LLONG_MAX
 
96
#  ifdef QUAD_MAX
 
97
#   define LLONG_MAX    QUAD_MAX
 
98
#  else
 
99
#   define LLONG_MAX    (ULLONG_MAX / 2)
 
100
#  endif
 
101
# endif
 
102
#endif /* HAVE_LONG_LONG_INT */
 
103
 
 
104
/*
 
105
 * Macros for converting digits to letters and vice versa
 
106
 */
 
107
#define to_digit(c)     ((c) - '0')
 
108
#define is_digit(c)     ((unsigned int)to_digit(c) <= 9)
 
109
#define to_char(n)      ((n) + '0')
 
110
 
 
111
/*
 
112
 * Flags used during conversion.
 
113
 */
 
114
#define ALT             0x001           /* alternate form */
 
115
#define HEXPREFIX       0x002           /* add 0x or 0X prefix */
 
116
#define LADJUST         0x004           /* left adjustment */
 
117
#define LONGDBL         0x008           /* long double; unimplemented */
 
118
#define LONGINT         0x010           /* long integer */
 
119
#define QUADINT         0x020           /* quad integer */
 
120
#define SHORTINT        0x040           /* short integer */
 
121
#define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
 
122
 
 
123
#define BUF             68
 
124
 
 
125
/*
 
126
 * Convert an unsigned long to ASCII for printf purposes, returning
 
127
 * a pointer to the first character of the string representation.
 
128
 * Octal numbers can be forced to have a leading zero; hex numbers
 
129
 * use the given digits.
 
130
 */
 
131
static char *
 
132
__ultoa(unsigned long val, char *endp, int base, int octzero, char *xdigs)
 
133
{
 
134
        char *cp = endp;
 
135
        long sval;
 
136
 
 
137
        /*
 
138
         * Handle the three cases separately, in the hope of getting
 
139
         * better/faster code.
 
140
         */
 
141
        switch (base) {
 
142
        case 10:
 
143
                if (val < 10) { /* many numbers are 1 digit */
 
144
                        *--cp = to_char(val);
 
145
                        return cp;
 
146
                }
 
147
                /*
 
148
                 * On many machines, unsigned arithmetic is harder than
 
149
                 * signed arithmetic, so we do at most one unsigned mod and
 
150
                 * divide; this is sufficient to reduce the range of
 
151
                 * the incoming value to where signed arithmetic works.
 
152
                 */
 
153
                if (val > LONG_MAX) {
 
154
                        *--cp = to_char(val % 10);
 
155
                        sval = val / 10;
 
156
                } else
 
157
                        sval = val;
 
158
                do {
 
159
                        *--cp = to_char(sval % 10);
 
160
                        sval /= 10;
 
161
                } while (sval != 0);
 
162
                break;
 
163
 
 
164
        case 8:
 
165
                do {
 
166
                        *--cp = to_char(val & 7);
 
167
                        val >>= 3;
 
168
                } while (val);
 
169
                if (octzero && *cp != '0')
 
170
                        *--cp = '0';
 
171
                break;
 
172
 
 
173
        case 16:
 
174
                do {
 
175
                        *--cp = xdigs[val & 15];
 
176
                        val >>= 4;
 
177
                } while (val);
 
178
                break;
 
179
 
 
180
        default:                        /* oops */
 
181
                abort();
 
182
        }
 
183
        return cp;
 
184
}
 
185
 
 
186
/* Identical to __ultoa, but for quads. */
 
187
#ifdef HAVE_LONG_LONG_INT
 
188
# if SIZEOF_LONG_INT == 8
 
189
#  define __uqtoa(v, e, b, o, x) __ultoa((unsigned long)(v), (e), (b), (o), (x))
 
190
# else
 
191
static char *
 
192
__uqtoa(unsigned long long val, char *endp, int base, int octzero, char *xdigs)
 
193
{
 
194
        char *cp = endp;
 
195
        long long sval;
 
196
 
 
197
        /* quick test for small values; __ultoa is typically much faster */
 
198
        /* (perhaps instead we should run until small, then call __ultoa?) */
 
199
        if (val <= (unsigned long long)ULONG_MAX)
 
200
                return __ultoa((unsigned long)val, endp, base, octzero, xdigs);
 
201
        switch (base) {
 
202
        case 10:
 
203
                if (val < 10) {
 
204
                        *--cp = to_char(val % 10);
 
205
                        return cp;
 
206
                }
 
207
                if (val > LLONG_MAX) {
 
208
                        *--cp = to_char(val % 10);
 
209
                        sval = val / 10;
 
210
                } else
 
211
                        sval = val;
 
212
                do {
 
213
                        *--cp = to_char(sval % 10);
 
214
                        sval /= 10;
 
215
                } while (sval != 0);
 
216
                break;
 
217
 
 
218
        case 8:
 
219
                do {
 
220
                        *--cp = to_char(val & 7);
 
221
                        val >>= 3;
 
222
                } while (val);
 
223
                if (octzero && *cp != '0')
 
224
                        *--cp = '0';
 
225
                break;
 
226
 
 
227
        case 16:
 
228
                do {
 
229
                        *--cp = xdigs[val & 15];
 
230
                        val >>= 4;
 
231
                } while (val);
 
232
                break;
 
233
 
 
234
        default:                        /* oops */
 
235
                abort();
 
236
        }
 
237
        return cp;
 
238
}
 
239
# endif /* !SIZEOF_LONG_INT */
 
240
#endif /* HAVE_LONG_LONG_INT */
 
241
 
 
242
/*
 
243
 * Actual printf innards.
 
244
 */
 
245
static int
 
246
xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap)
 
247
{
 
248
        char *fmt;              /* format string */
 
249
        int ch;                 /* character from fmt */
 
250
        int n;                  /* handy integer (short term usage) */
 
251
        char *cp;               /* handy char pointer (short term usage) */
 
252
        int flags;              /* flags as above */
 
253
        int ret;                /* return value accumulator */
 
254
        int width;              /* width from format (%8d), or 0 */
 
255
        int prec;               /* precision from format (%.3d), or -1 */
 
256
        char sign;              /* sign prefix (' ', '+', '-', or \0) */
 
257
        unsigned long ulval = 0; /* integer arguments %[diouxX] */
 
258
#ifdef HAVE_LONG_LONG_INT
 
259
        unsigned long long uqval = 0; /* %q (quad) integers */
 
260
#endif
 
261
        int base;               /* base for [diouxX] conversion */
 
262
        int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
 
263
        int fieldsz;            /* field size expanded by sign, etc */
 
264
        int realsz;             /* field size expanded by dprec */
 
265
        int size;               /* size of converted field or string */
 
266
        char *xdigs = "";       /* digits for [xX] conversion */
 
267
        char buf[BUF];          /* space for %c, %[diouxX], %[eEfgG] */
 
268
        char ox[2];             /* space for 0x hex-prefix */
 
269
        char *str;              /* pointer to string to fill */
 
270
        char *estr;             /* pointer to last char in str */
 
271
 
 
272
        /*
 
273
         * Choose PADSIZE to trade efficiency vs. size.  If larger printf
 
274
         * fields occur frequently, increase PADSIZE and make the initialisers
 
275
         * below longer.
 
276
         */
 
277
#define PADSIZE 16              /* pad chunk size */
 
278
        static char blanks[PADSIZE] =
 
279
         {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
 
280
        static char zeroes[PADSIZE] =
 
281
         {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
 
282
 
 
283
        /* Print chars to "str", (allocate as needed if alloc is set). */
 
284
#define PRINT(ptr, len) do { \
 
285
        const char *p = ptr; \
 
286
        const char *endp = ptr + len; \
 
287
        while (p < endp && (str < estr || alloc)) { \
 
288
                if (alloc && str >= estr) { \
 
289
                        char *t; \
 
290
                        strsize = (strsize << 1) + 1; \
 
291
                        if (!(t = (char *)realloc(*strp, strsize))) { \
 
292
                                free(str); \
 
293
                                *strp = NULL; \
 
294
                                ret = -1; \
 
295
                                goto done; \
 
296
                        } \
 
297
                        str = t + (str - *strp); \
 
298
                        estr = t + strsize - 1; \
 
299
                        *strp = t; \
 
300
                } \
 
301
                *str++ = *p++; \
 
302
        } \
 
303
} while (0)
 
304
 
 
305
        /* BEWARE, PAD uses `n'. */
 
306
#define PAD(plen, pstr) do { \
 
307
        if ((n = (plen)) > 0) { \
 
308
                while (n > PADSIZE) { \
 
309
                        PRINT(pstr, PADSIZE); \
 
310
                        n -= PADSIZE; \
 
311
                } \
 
312
                PRINT(pstr, n); \
 
313
        } \
 
314
} while (0)
 
315
 
 
316
        /*
 
317
         * To extend shorts properly, we need both signed and unsigned
 
318
         * argument extraction methods.
 
319
         */
 
320
#define SARG() \
 
321
        (flags&LONGINT ? va_arg(ap, long) : \
 
322
            flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
 
323
            (long)va_arg(ap, int))
 
324
#define UARG() \
 
325
        (flags&LONGINT ? va_arg(ap, unsigned long) : \
 
326
            flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
 
327
            (unsigned long)va_arg(ap, unsigned int))
 
328
 
 
329
        fmt = (char *)fmt0;
 
330
        ret = 0;
 
331
 
 
332
        if (alloc) {
 
333
                strsize = 128;
 
334
                *strp = str = (char *)malloc(strsize);
 
335
                if (str == NULL) {
 
336
                        ret = -1;
 
337
                        goto done;
 
338
                }
 
339
                estr = str + 127;
 
340
        } else {
 
341
                str = *strp;
 
342
                if (strsize)
 
343
                        estr = str + strsize - 1;
 
344
                else
 
345
                        estr = NULL;
 
346
        }
 
347
 
 
348
        /*
 
349
         * Scan the format for conversions (`%' character).
 
350
         */
 
351
        for (;;) {
 
352
                for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
 
353
                        /* void */;
 
354
                if ((n = fmt - cp) != 0) {
 
355
                        PRINT(cp, n);
 
356
                        ret += n;
 
357
                }
 
358
                if (ch == '\0')
 
359
                        goto done;
 
360
                fmt++;          /* skip over '%' */
 
361
 
 
362
                flags = 0;
 
363
                dprec = 0;
 
364
                width = 0;
 
365
                prec = -1;
 
366
                sign = '\0';
 
367
 
 
368
rflag:          ch = *fmt++;
 
369
reswitch:       switch (ch) {
 
370
                case ' ':
 
371
                        /*
 
372
                         * ``If the space and + flags both appear, the space
 
373
                         * flag will be ignored.''
 
374
                         *      -- ANSI X3J11
 
375
                         */
 
376
                        if (!sign)
 
377
                                sign = ' ';
 
378
                        goto rflag;
 
379
                case '#':
 
380
                        flags |= ALT;
 
381
                        goto rflag;
 
382
                case '*':
 
383
                        /*
 
384
                         * ``A negative field width argument is taken as a
 
385
                         * - flag followed by a positive field width.''
 
386
                         *      -- ANSI X3J11
 
387
                         * They don't exclude field widths read from args.
 
388
                         */
 
389
                        if ((width = va_arg(ap, int)) >= 0)
 
390
                                goto rflag;
 
391
                        width = -width;
 
392
                        /* FALLTHROUGH */
 
393
                case '-':
 
394
                        flags |= LADJUST;
 
395
                        goto rflag;
 
396
                case '+':
 
397
                        sign = '+';
 
398
                        goto rflag;
 
399
                case '.':
 
400
                        if ((ch = *fmt++) == '*') {
 
401
                                n = va_arg(ap, int);
 
402
                                prec = n < 0 ? -1 : n;
 
403
                                goto rflag;
 
404
                        }
 
405
                        n = 0;
 
406
                        while (is_digit(ch)) {
 
407
                                n = 10 * n + to_digit(ch);
 
408
                                ch = *fmt++;
 
409
                        }
 
410
                        prec = n < 0 ? -1 : n;
 
411
                        goto reswitch;
 
412
                case '0':
 
413
                        /*
 
414
                         * ``Note that 0 is taken as a flag, not as the
 
415
                         * beginning of a field width.''
 
416
                         *      -- ANSI X3J11
 
417
                         */
 
418
                        flags |= ZEROPAD;
 
419
                        goto rflag;
 
420
                case '1': case '2': case '3': case '4':
 
421
                case '5': case '6': case '7': case '8': case '9':
 
422
                        n = 0;
 
423
                        do {
 
424
                                n = 10 * n + to_digit(ch);
 
425
                                ch = *fmt++;
 
426
                        } while (is_digit(ch));
 
427
                        width = n;
 
428
                        goto reswitch;
 
429
                case 'h':
 
430
                        flags |= SHORTINT;
 
431
                        goto rflag;
 
432
                case 'l':
 
433
                        flags |= LONGINT;
 
434
                        goto rflag;
 
435
#ifdef HAVE_LONG_LONG_INT
 
436
                case 'q':
 
437
                        flags |= QUADINT;
 
438
                        goto rflag;
 
439
#endif /* HAVE_LONG_LONG_INT */
 
440
                case 'c':
 
441
                        *(cp = buf) = va_arg(ap, int);
 
442
                        size = 1;
 
443
                        sign = '\0';
 
444
                        break;
 
445
                case 'D':
 
446
                        flags |= LONGINT;
 
447
                        /*FALLTHROUGH*/
 
448
                case 'd':
 
449
                case 'i':
 
450
#ifdef HAVE_LONG_LONG_INT
 
451
                        if (flags & QUADINT) {
 
452
                                uqval = va_arg(ap, long long);
 
453
                                if ((long long)uqval < 0) {
 
454
                                        uqval = -uqval;
 
455
                                        sign = '-';
 
456
                                }
 
457
                        }
 
458
                        else
 
459
#endif /* HAVE_LONG_LONG_INT */
 
460
                        {
 
461
                                ulval = SARG();
 
462
                                if ((long)ulval < 0) {
 
463
                                        ulval = -ulval;
 
464
                                        sign = '-';
 
465
                                }
 
466
                        }
 
467
                        base = 10;
 
468
                        goto number;
 
469
                case 'n':
 
470
#ifdef HAVE_LONG_LONG_INT
 
471
                        if (flags & QUADINT)
 
472
                                *va_arg(ap, long long *) = ret;
 
473
                        else
 
474
#endif /* HAVE_LONG_LONG_INT */
 
475
                        if (flags & LONGINT)
 
476
                                *va_arg(ap, long *) = ret;
 
477
                        else if (flags & SHORTINT)
 
478
                                *va_arg(ap, short *) = ret;
 
479
                        else
 
480
                                *va_arg(ap, int *) = ret;
 
481
                        continue;       /* no output */
 
482
                case 'O':
 
483
                        flags |= LONGINT;
 
484
                        /*FALLTHROUGH*/
 
485
                case 'o':
 
486
#ifdef HAVE_LONG_LONG_INT
 
487
                        if (flags & QUADINT)
 
488
                                uqval = va_arg(ap, unsigned long long);
 
489
                        else
 
490
#endif /* HAVE_LONG_LONG_INT */
 
491
                                ulval = UARG();
 
492
                        base = 8;
 
493
                        goto nosign;
 
494
                case 'p':
 
495
                        /*
 
496
                         * ``The argument shall be a pointer to void.  The
 
497
                         * value of the pointer is converted to a sequence
 
498
                         * of printable characters, in an implementation-
 
499
                         * defined manner.''
 
500
                         *      -- ANSI X3J11
 
501
                         */
 
502
                        ulval = (unsigned long)va_arg(ap, void *);
 
503
                        base = 16;
 
504
                        xdigs = "0123456789abcdef";
 
505
                        flags = (flags & ~QUADINT) | HEXPREFIX;
 
506
                        ch = 'x';
 
507
                        goto nosign;
 
508
                case 's':
 
509
                        if ((cp = va_arg(ap, char *)) == NULL)
 
510
                                cp = "(null)";
 
511
                        if (prec >= 0) {
 
512
                                /*
 
513
                                 * can't use strlen; can only look for the
 
514
                                 * NUL in the first `prec' characters, and
 
515
                                 * strlen() will go further.
 
516
                                 */
 
517
                                char *p = memchr(cp, 0, prec);
 
518
 
 
519
                                if (p != NULL) {
 
520
                                        size = p - cp;
 
521
                                        if (size > prec)
 
522
                                                size = prec;
 
523
                                } else
 
524
                                        size = prec;
 
525
                        } else
 
526
                                size = strlen(cp);
 
527
                        sign = '\0';
 
528
                        break;
 
529
                case 'U':
 
530
                        flags |= LONGINT;
 
531
                        /*FALLTHROUGH*/
 
532
                case 'u':
 
533
#ifdef HAVE_LONG_LONG_INT
 
534
                        if (flags & QUADINT)
 
535
                                uqval = va_arg(ap, unsigned long long);
 
536
                        else
 
537
#endif /* HAVE_LONG_LONG_INT */
 
538
                                ulval = UARG();
 
539
                        base = 10;
 
540
                        goto nosign;
 
541
                case 'X':
 
542
                        xdigs = "0123456789ABCDEF";
 
543
                        goto hex;
 
544
                case 'x':
 
545
                        xdigs = "0123456789abcdef";
 
546
hex:
 
547
#ifdef HAVE_LONG_LONG_INT
 
548
                        if (flags & QUADINT)
 
549
                                uqval = va_arg(ap, unsigned long long);
 
550
                        else
 
551
#endif /* HAVE_LONG_LONG_INT */
 
552
                                ulval = UARG();
 
553
                        base = 16;
 
554
                        /* leading 0x/X only if non-zero */
 
555
                        if (flags & ALT &&
 
556
#ifdef HAVE_LONG_LONG_INT
 
557
                            (flags & QUADINT ? uqval != 0 : ulval != 0))
 
558
#else
 
559
                            ulval != 0)
 
560
#endif /* HAVE_LONG_LONG_INT */
 
561
                                flags |= HEXPREFIX;
 
562
 
 
563
                        /* unsigned conversions */
 
564
nosign:                 sign = '\0';
 
565
                        /*
 
566
                         * ``... diouXx conversions ... if a precision is
 
567
                         * specified, the 0 flag will be ignored.''
 
568
                         *      -- ANSI X3J11
 
569
                         */
 
570
number:                 if ((dprec = prec) >= 0)
 
571
                                flags &= ~ZEROPAD;
 
572
 
 
573
                        /*
 
574
                         * ``The result of converting a zero value with an
 
575
                         * explicit precision of zero is no characters.''
 
576
                         *      -- ANSI X3J11
 
577
                         */
 
578
                        cp = buf + BUF;
 
579
#ifdef HAVE_LONG_LONG_INT
 
580
                        if (flags & QUADINT) {
 
581
                                if (uqval != 0 || prec != 0)
 
582
                                        cp = __uqtoa(uqval, cp, base,
 
583
                                            flags & ALT, xdigs);
 
584
                        }
 
585
                        else
 
586
#endif /* HAVE_LONG_LONG_INT */
 
587
                        {
 
588
                                if (ulval != 0 || prec != 0)
 
589
                                        cp = __ultoa(ulval, cp, base,
 
590
                                            flags & ALT, xdigs);
 
591
                        }
 
592
                        size = buf + BUF - cp;
 
593
                        break;
 
594
                default:        /* "%?" prints ?, unless ? is NUL */
 
595
                        if (ch == '\0')
 
596
                                goto done;
 
597
                        /* pretend it was %c with argument ch */
 
598
                        cp = buf;
 
599
                        *cp = ch;
 
600
                        size = 1;
 
601
                        sign = '\0';
 
602
                        break;
 
603
                }
 
604
 
 
605
                /*
 
606
                 * All reasonable formats wind up here.  At this point, `cp'
 
607
                 * points to a string which (if not flags&LADJUST) should be
 
608
                 * padded out to `width' places.  If flags&ZEROPAD, it should
 
609
                 * first be prefixed by any sign or other prefix; otherwise,
 
610
                 * it should be blank padded before the prefix is emitted.
 
611
                 * After any left-hand padding and prefixing, emit zeroes
 
612
                 * required by a decimal [diouxX] precision, then print the
 
613
                 * string proper, then emit zeroes required by any leftover
 
614
                 * floating precision; finally, if LADJUST, pad with blanks.
 
615
                 *
 
616
                 * Compute actual size, so we know how much to pad.
 
617
                 * fieldsz excludes decimal prec; realsz includes it.
 
618
                 */
 
619
                fieldsz = size;
 
620
                if (sign)
 
621
                        fieldsz++;
 
622
                else if (flags & HEXPREFIX)
 
623
                        fieldsz += 2;
 
624
                realsz = dprec > fieldsz ? dprec : fieldsz;
 
625
 
 
626
                /* right-adjusting blank padding */
 
627
                if ((flags & (LADJUST|ZEROPAD)) == 0)
 
628
                        PAD(width - realsz, blanks);
 
629
 
 
630
                /* prefix */
 
631
                if (sign) {
 
632
                        PRINT(&sign, 1);
 
633
                } else if (flags & HEXPREFIX) {
 
634
                        ox[0] = '0';
 
635
                        ox[1] = ch;
 
636
                        PRINT(ox, 2);
 
637
                }
 
638
 
 
639
                /* right-adjusting zero padding */
 
640
                if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
 
641
                        PAD(width - realsz, zeroes);
 
642
 
 
643
                /* leading zeroes from decimal precision */
 
644
                PAD(dprec - fieldsz, zeroes);
 
645
 
 
646
                /* the string or number proper */
 
647
                PRINT(cp, size);
 
648
 
 
649
                /* left-adjusting padding (always blank) */
 
650
                if (flags & LADJUST)
 
651
                        PAD(width - realsz, blanks);
 
652
 
 
653
                /* finally, adjust ret */
 
654
                ret += width > realsz ? width : realsz;
 
655
        }
 
656
done:
 
657
        if (strsize)
 
658
                *str = '\0';
 
659
        return ret;
 
660
        /* NOTREACHED */
 
661
}
 
662
 
 
663
#ifndef HAVE_VSNPRINTF
 
664
int
 
665
vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
 
666
{
 
667
 
 
668
        return xxxprintf(&str, n, 0, fmt, ap);
 
669
}
 
670
#endif /* HAVE_VSNPRINTF */
 
671
 
 
672
#ifndef HAVE_SNPRINTF
 
673
int
 
674
snprintf(char *str, size_t n, char const *fmt, ...)
 
675
{
 
676
        int ret;
 
677
        va_list ap;
 
678
 
 
679
        va_start(ap, fmt);
 
680
        ret = xxxprintf(&str, n, 0, fmt, ap);
 
681
        va_end(ap);
 
682
        return ret;
 
683
}
 
684
#endif /* HAVE_SNPRINTF */
 
685
 
 
686
#ifndef HAVE_VASPRINTF
 
687
int
 
688
vasprintf(char **str, const char *fmt, va_list ap)
 
689
{
 
690
 
 
691
        return xxxprintf(str, 0, 1, fmt, ap);
 
692
}
 
693
#endif /* HAVE_VASPRINTF */
 
694
 
 
695
#ifndef HAVE_ASPRINTF
 
696
int
 
697
asprintf(char **str, char const *fmt, ...)
 
698
{
 
699
        int ret;
 
700
        va_list ap;
 
701
 
 
702
        va_start(ap, fmt);
 
703
        ret = xxxprintf(str, 0, 1, fmt, ap);
 
704
        va_end(ap);
 
705
        return ret;
 
706
}
 
707
#endif /* HAVE_ASPRINTF */