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