Home | History | Annotate | Line # | Download | only in dist
      1 /* Id: compat_vasprintf.c,v 1.4 2020/06/15 01:37:15 schwarze Exp  */
      2 /*
      3  * Copyright (c) 2015 Ingo Schwarze <schwarze (at) openbsd.org>
      4  *
      5  * Permission to use, copy, modify, and distribute this software for any
      6  * purpose with or without fee is hereby granted, provided that the above
      7  * copyright notice and this permission notice appear in all copies.
      8  *
      9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  *
     17  * This fallback implementation is not efficient:
     18  * It does the formatting twice.
     19  * Short of fiddling with the unknown internals of the system's
     20  * printf(3) or completely reimplementing printf(3), i can't think
     21  * of another portable solution.
     22  */
     23 #include "config.h"
     24 
     25 #include <stdarg.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 
     29 int
     30 vasprintf(char **ret, const char *format, va_list ap)
     31 {
     32 	char	 buf[2];
     33 	va_list	 ap2;
     34 	int	 sz;
     35 
     36 	va_copy(ap2, ap);
     37 	sz = vsnprintf(buf, sizeof(buf), format, ap2);
     38 	va_end(ap2);
     39 
     40 	if (sz != -1 && (*ret = malloc(sz + 1)) != NULL) {
     41 		if (vsnprintf(*ret, sz + 1, format, ap) == sz)
     42 			return sz;
     43 		free(*ret);
     44 	}
     45 	*ret = NULL;
     46 	return -1;
     47 }
     48