1 /*
2  * Copyright © 2008-2014 Intel Corporation.
3  *
4  * Authors: David Woodhouse <dwmw2@infradead.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * version 2.1, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  */
15 
16 #include <config.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <stdarg.h>
21 #include "vasprintf.h"
22 
23 #ifndef HAVE_VASPRINTF
24 
_ocserv_vasprintf(char ** strp,const char * fmt,va_list ap)25 int _ocserv_vasprintf(char **strp, const char *fmt, va_list ap)
26 {
27 	va_list ap2;
28 	char *res = NULL;
29 	int len = 160, len2;
30 	int ret = 0;
31 	int errno_save = -ENOMEM;
32 
33 	res = malloc(160);
34 	if (!res)
35 		goto err;
36 
37 	/* Use a copy of 'ap', preserving it in case we need to retry into
38 	   a larger buffer. 160 characters should be sufficient for most
39 	   strings in openconnect. */
40 #ifdef HAVE_VA_COPY
41 	va_copy(ap2, ap);
42 #elif defined(HAVE___VA_COPY)
43 	__va_copy(ap2, ap);
44 #else
45 #error No va_copy()!
46 	/* You could try this. */
47 	ap2 = ap;
48 	/* Or this */
49 	*ap2 = *ap;
50 #endif
51 	len = vsnprintf(res, 160, fmt, ap2);
52 	va_end(ap2);
53 
54 	if (len < 0) {
55 	printf_err:
56 		errno_save = errno;
57 		free(res);
58 		res = NULL;
59 		goto err;
60 	}
61 	if (len >= 0 && len < 160)
62 		goto out;
63 
64 	free(res);
65 	res = malloc(len+1);
66 	if (!res)
67 		goto err;
68 
69 	len2 = vsnprintf(res, len+1, fmt, ap);
70 	if (len2 < 0 || len2 > len)
71 		goto printf_err;
72 
73 	ret = 0;
74 	goto out;
75 
76  err:
77 	errno = errno_save;
78 	ret = -1;
79  out:
80 	*strp = res;
81 	return ret;
82 }
83 
84 #endif
85