1 /* 2 * Replacement for a missing asprintf and vasprintf. 3 * 4 * Provides the same functionality as the standard GNU library routines 5 * asprintf and vasprintf for those platforms that don't have them. 6 * 7 * The canonical version of this file is maintained in the rra-c-util package, 8 * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>. 9 * 10 * Written by Russ Allbery <eagle@eyrie.org> 11 * Copyright 2006, 2015 Russ Allbery <eagle@eyrie.org> 12 * Copyright 2008-2009, 2011, 2013 13 * The Board of Trustees of the Leland Stanford Junior University 14 * 15 * Copying and distribution of this file, with or without modification, are 16 * permitted in any medium without royalty provided the copyright notice and 17 * this notice are preserved. This file is offered as-is, without any 18 * warranty. 19 * 20 * SPDX-License-Identifier: FSFAP 21 */ 22 23 #include <config.h> 24 #include <portable/macros.h> 25 #include <portable/system.h> 26 27 #include <errno.h> 28 29 /* 30 * If we're running the test suite, rename the functions to avoid conflicts 31 * with the system versions. 32 */ 33 #if TESTING 34 # undef asprintf 35 # undef vasprintf 36 # define asprintf test_asprintf 37 # define vasprintf test_vasprintf 38 int test_asprintf(char **, const char *, ...) 39 __attribute__((__format__(printf, 2, 3))); 40 int test_vasprintf(char **, const char *, va_list) 41 __attribute__((__format__(printf, 2, 0))); 42 #endif 43 44 45 int 46 asprintf(char **strp, const char *fmt, ...) 47 { 48 va_list args; 49 int status; 50 51 va_start(args, fmt); 52 status = vasprintf(strp, fmt, args); 53 va_end(args); 54 return status; 55 } 56 57 58 int 59 vasprintf(char **strp, const char *fmt, va_list args) 60 { 61 va_list args_copy; 62 int status, needed, oerrno; 63 64 va_copy(args_copy, args); 65 needed = vsnprintf(NULL, 0, fmt, args_copy); 66 va_end(args_copy); 67 if (needed < 0) { 68 *strp = NULL; 69 return needed; 70 } 71 *strp = malloc(needed + 1); 72 if (*strp == NULL) 73 return -1; 74 status = vsnprintf(*strp, needed + 1, fmt, args); 75 if (status >= 0) 76 return status; 77 else { 78 oerrno = errno; 79 free(*strp); 80 *strp = NULL; 81 errno = oerrno; 82 return status; 83 } 84 } 85