libexplain  1.4.D001
libexplain/asprintf_or_die.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU Lesser General Public License as published by
00007  * the Free Software Foundation; either version 3 of the License, or (at
00008  * your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/errno.h>
00020 #include <libexplain/ac/stdarg.h>
00021 #include <libexplain/ac/stdio.h>
00022 
00023 #include <libexplain/asprintf.h>
00024 #include <libexplain/buffer/errno/asprintf.h>
00025 #include <libexplain/common_message_buffer.h>
00026 #include <libexplain/output.h>
00027 #include <libexplain/string_buffer.h>
00028 
00029 
00030 int
00031 explain_asprintf_or_die(char **data, const char *format, ...)
00032 {
00033     int             result;
00034     int             hold_errno;
00035     va_list         ap;
00036     va_list         ap2;
00037 
00038     hold_errno = errno;
00039     errno = 0;
00040     va_start(ap, format);
00041 
00042     /*
00043      * To run arg list twice, we need two separate ap.
00044      * For some discussion about this see the Linux va_copy man page.
00045      */
00046     va_copy(ap2, ap);
00047 
00048 #ifdef HAVE_ASPRINTF
00049     result = vasprintf(data, format, ap);
00050 #else
00051     errno = ENOSYS;
00052     result = -1;
00053 #endif
00054     if (result < 0 || errno != 0)
00055     {
00056         explain_string_buffer_t sb;
00057 
00058         hold_errno = errno;
00059         explain_string_buffer_init
00060         (
00061             &sb,
00062             explain_common_message_buffer,
00063             explain_common_message_buffer_size
00064         );
00065         explain_buffer_errno_asprintf(&sb, hold_errno, data, format, ap2);
00066         explain_output_error_and_die("%s", explain_common_message_buffer);
00067         va_end(ap2);
00068     }
00069     va_end(ap);
00070     errno = hold_errno;
00071     return result;
00072 }
00073 
00074 
00075 int
00076 explain_asprintf_on_error(char **data, const char *format, ...)
00077 {
00078     int             result;
00079     int             hold_errno;
00080     va_list         ap;
00081     va_list         ap2;
00082 
00083     hold_errno = errno;
00084     errno = 0;
00085     va_start(ap, format);
00086 
00087     /*
00088      * To run arg list twice, we need two separate ap.
00089      * For some discussion about this see the Linux va_copy man page.
00090      */
00091     va_copy(ap2, ap);
00092 
00093 #ifdef HAVE_ASPRINTF
00094     result = vasprintf(data, format, ap);
00095 #else
00096     errno = ENOSYS;
00097     result = -1;
00098 #endif
00099     if (result < 0 || errno != 0)
00100     {
00101         explain_string_buffer_t sb;
00102 
00103         hold_errno = errno;
00104         result = -1;
00105         explain_string_buffer_init
00106         (
00107             &sb,
00108             explain_common_message_buffer,
00109             explain_common_message_buffer_size
00110         );
00111         explain_buffer_errno_asprintf(&sb, hold_errno, data, format, ap2);
00112         explain_output_error("%s", explain_common_message_buffer);
00113         va_end(ap2);
00114     }
00115     va_end(ap);
00116     errno = hold_errno;
00117     return result;
00118 }
00119 
00120 
00121 /* vim: set ts=8 sw=4 et : */