diff --git a/meson.build b/meson.build index b7aaeee..2c6d8e3 100644 --- a/meson.build +++ b/meson.build @@ -102,6 +102,11 @@ endif if cc.has_header_symbol('string.h', 'strndup', prefix: system_ext_define) configh_data.set('HAVE_STRNDUP', 1) endif +if cc.has_header_symbol('stdio.h', 'asprintf', prefix: system_ext_define) + configh_data.set('HAVE_ASPRINTF', 1) +elif cc.has_header_symbol('stdio.h', 'vasprintf', prefix: system_ext_define) + configh_data.set('HAVE_VASPRINTF', 1) +endif if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: system_ext_define) configh_data.set('HAVE_SECURE_GETENV', 1) elif cc.has_header_symbol('stdlib.h', '__secure_getenv', prefix: system_ext_define) diff --git a/src/utils.c b/src/utils.c index a71b570..a981a41 100644 --- a/src/utils.c +++ b/src/utils.c @@ -161,3 +161,48 @@ istrncmp(const char *a, const char *b, size_t n) } return 0; } + +#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF) +int +asprintf(char **strp, const char *fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vasprintf(strp, fmt, ap); + va_end(ap); + return ret; +} + +# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF) +int +vasprintf(char **strp, const char *fmt, va_list ap) +{ + int ret; + char *buf; + va_list ap_copy; + + /* + * The value of the va_list parameter is undefined after the call to + * vsnprintf() returns: pass a copy to make sure "ap" remains valid. + */ + va_copy(ap_copy, ap); + ret = vsnprintf(NULL, 0, fmt, ap_copy); + va_end(ap_copy); + + if (ret < 0) + return ret; + + if (!(buf = malloc(ret + 1))) + return -1; + + if ((ret = vsnprintf(buf, ret + 1, fmt, ap)) < 0) { + free(buf); + return ret; + } + + *strp = buf; + return ret; +} +# endif /* !HAVE_VASPRINTF */ +#endif /* !HAVE_ASPRINTF */ diff --git a/src/utils.h b/src/utils.h index d796e10..acd191e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -259,4 +259,12 @@ unmap_file(char *string, size_t size); #define ATTR_PACKED #endif +#if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF) +int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3); +# if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF) +# include +int vasprintf(char **strp, const char *fmt, va_list ap); +# endif /* !HAVE_VASPRINTF */ +#endif /* !HAVE_ASPRINTF */ + #endif /* UTILS_H */