xref: /freebsd/contrib/ntp/libntp/xsbprintf.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
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
xvsbprintf(char ** ppbuf,char * const pend,char const * pfmt,va_list va)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
xsbprintf(char ** ppbuf,char * const pend,char const * pfmt,...)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