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