/* * Replacement for a missing asprintf and vasprintf. * * Provides the same functionality as the standard GNU library routines * asprintf and vasprintf for those platforms that don't have them. * * The canonical version of this file is maintained in the rra-c-util package, * which can be found at . * * Written by Russ Allbery * * The authors hereby relinquish any claim to any copyright that they may have * in this work, whether granted under contract or by operation of law or * international treaty, and hereby commit to the public, at large, that they * shall not, at any time in the future, seek to enforce any copyright in this * work against any person or entity, or prevent any person or entity from * copying, publishing, distributing or creating derivative works of this * work. */ #include #include #include /* * If we're running the test suite, rename the functions to avoid conflicts * with the system versions. */ #if TESTING # define asprintf test_asprintf # define vasprintf test_vasprintf int test_asprintf(char **, const char *, ...) __attribute__((__format__(printf, 2, 3))); int test_vasprintf(char **, const char *, va_list); #endif int asprintf(char **strp, const char *fmt, ...) { va_list args; int status; va_start(args, fmt); status = vasprintf(strp, fmt, args); va_end(args); return status; } int vasprintf(char **strp, const char *fmt, va_list args) { va_list args_copy; int status, needed, oerrno; va_copy(args_copy, args); needed = vsnprintf(NULL, 0, fmt, args_copy); va_end(args_copy); if (needed < 0) { *strp = NULL; return needed; } *strp = malloc(needed + 1); if (*strp == NULL) return -1; status = vsnprintf(*strp, needed + 1, fmt, args); if (status >= 0) return status; else { oerrno = errno; free(*strp); *strp = NULL; errno = oerrno; return status; } }