1*052d159aSCy Schubert /* 2*052d159aSCy Schubert * xsbprintf.c - string buffer formatting helpers 3*052d159aSCy Schubert * 4*052d159aSCy Schubert * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 5*052d159aSCy Schubert * The contents of 'html/copyright.html' apply. 6*052d159aSCy Schubert */ 7*052d159aSCy Schubert 8*052d159aSCy Schubert #include <config.h> 9*052d159aSCy Schubert #include <sys/types.h> 10*052d159aSCy Schubert 11*052d159aSCy Schubert #include "ntp_stdlib.h" 12*052d159aSCy Schubert 13*052d159aSCy Schubert /* eXtended Varlist String Buffer printf 14*052d159aSCy Schubert * 15*052d159aSCy Schubert * Formats via 'vsnprintf' into a string buffer, with some semantic 16*052d159aSCy Schubert * specialties: 17*052d159aSCy Schubert * 18*052d159aSCy Schubert * - The start of the buffer pointer is updated according to the number 19*052d159aSCy Schubert * of characters written. 20*052d159aSCy Schubert * - If the buffer is insufficient to format the number of charactes, 21*052d159aSCy Schubert * the partial result will be be discarded, and zero is returned to 22*052d159aSCy Schubert * indicate nothing was written to the buffer. 23*052d159aSCy Schubert * - On successful formatting, the return code is the return value of 24*052d159aSCy Schubert * the inner call to 'vsnprintf()'. 25*052d159aSCy Schubert * - If there is any error, the state of the buffer will not be 26*052d159aSCy Schubert * changed. (Bytes in the buffer might be smashed, but the buffer 27*052d159aSCy Schubert * position does not change, and the NUL marker stays in place at the 28*052d159aSCy Schubert * current buffer position.) 29*052d159aSCy Schubert * - If '(*ppbuf - pend) <= 0' (or ppbuf is NULL), fail with EINVAL. 30*052d159aSCy Schubert */ 31*052d159aSCy Schubert int 32*052d159aSCy Schubert xvsbprintf( 33*052d159aSCy Schubert char **ppbuf, /* pointer to buffer pointer (I/O) */ 34*052d159aSCy Schubert char * const pend, /* buffer end (I) */ 35*052d159aSCy Schubert char const *pfmt, /* printf-like format string */ 36*052d159aSCy Schubert va_list va /* formatting args for above */ 37*052d159aSCy Schubert ) 38*052d159aSCy Schubert { 39*052d159aSCy Schubert char *pbuf = (ppbuf) ? *ppbuf : NULL; 40*052d159aSCy Schubert int rc = -1; 41*052d159aSCy Schubert if (pbuf && (pend - pbuf > 0)) { 42*052d159aSCy Schubert size_t blen = (size_t)(pend - pbuf); 43*052d159aSCy Schubert rc = vsnprintf(pbuf, blen, pfmt, va); 44*052d159aSCy Schubert if (rc > 0) { 45*052d159aSCy Schubert if ((size_t)rc >= blen) 46*052d159aSCy Schubert rc = 0; 47*052d159aSCy Schubert pbuf += rc; 48*052d159aSCy Schubert } 49*052d159aSCy Schubert *pbuf = '\0'; /* fear of bad vsnprintf */ 50*052d159aSCy Schubert *ppbuf = pbuf; 51*052d159aSCy Schubert } else { 52*052d159aSCy Schubert errno = EINVAL; 53*052d159aSCy Schubert } 54*052d159aSCy Schubert return rc; 55*052d159aSCy Schubert } 56*052d159aSCy Schubert 57*052d159aSCy Schubert /* variadic wrapper around the buffer string formatter */ 58*052d159aSCy Schubert int 59*052d159aSCy Schubert xsbprintf( 60*052d159aSCy Schubert char **ppbuf, /* pointer to buffer pointer (I/O) */ 61*052d159aSCy Schubert char * const pend, /* buffer end (I) */ 62*052d159aSCy Schubert char const *pfmt, /* printf-like format string */ 63*052d159aSCy Schubert ... /* formatting args for above */ 64*052d159aSCy Schubert ) 65*052d159aSCy Schubert { 66*052d159aSCy Schubert va_list va; 67*052d159aSCy Schubert int rc; 68*052d159aSCy Schubert 69*052d159aSCy Schubert va_start(va, pfmt); 70*052d159aSCy Schubert rc = xvsbprintf(ppbuf, pend, pfmt, va); 71*052d159aSCy Schubert va_end(va); 72*052d159aSCy Schubert return rc; 73*052d159aSCy Schubert } 74*052d159aSCy Schubert 75*052d159aSCy Schubert /* that's all folks! */ 76