diff options
Diffstat (limited to 'lib/system/vasprintf.c')
-rw-r--r-- | lib/system/vasprintf.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/system/vasprintf.c b/lib/system/vasprintf.c new file mode 100644 index 0000000000..8362942a20 --- /dev/null +++ b/lib/system/vasprintf.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2008-2014 Intel Corporation. + * + * Authors: David Woodhouse <dwmw2@infradead.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <stdarg.h> +#include "vasprintf.h" + +#ifndef HAVE_VASPRINTF + +int _gnutls_vasprintf(char **strp, const char *fmt, va_list ap) +{ + va_list ap2; + char *res = NULL; + int len = 160, len2; + int ret = 0; + int errno_save = -ENOMEM; + + res = malloc(160); + if (!res) + goto err; + + /* Use a copy of 'ap', preserving it in case we need to retry into + a larger buffer. 160 characters should be sufficient for most + strings in openconnect. */ +#ifdef HAVE_VA_COPY + va_copy(ap2, ap); +#elif defined(HAVE___VA_COPY) + __va_copy(ap2, ap); +#else +#error No va_copy()! + /* You could try this. */ + ap2 = ap; + /* Or this */ + *ap2 = *ap; +#endif + len = vsnprintf(res, 160, fmt, ap2); + va_end(ap2); + + if (len < 0) { + printf_err: + errno_save = errno; + free(res); + res = NULL; + goto err; + } + if (len >= 0 && len < 160) + goto out; + + free(res); + res = malloc(len+1); + if (!res) + goto err; + + len2 = vsnprintf(res, len+1, fmt, ap); + if (len2 < 0 || len2 > len) + goto printf_err; + + ret = 0; + goto out; + + err: + errno = errno_save; + ret = -1; + out: + *strp = res; + return ret; +} + +#endif |