libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2009-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 00012 * ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNULesser 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/stdlib.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/errno/execlp.h> 00025 #include <libexplain/common_message_buffer.h> 00026 #include <libexplain/execlp.h> 00027 #include <libexplain/sizeof.h> 00028 #include <libexplain/string_buffer.h> 00029 #include <libexplain/output.h> 00030 00031 00032 void 00033 explain_execlp_or_die(const char *pathname, const char *arg, ...) 00034 { 00035 va_list ap; 00036 va_list ap1; 00037 va_list ap2; 00038 int argc; 00039 int argc2; 00040 const char **argv; 00041 explain_string_buffer_t sb; 00042 int errnum; 00043 const char *dummy[100]; 00044 00045 /* 00046 * count the number of arguments 00047 */ 00048 va_start(ap, arg); 00049 va_copy(ap1, ap); 00050 argc = 1; 00051 for (;;) 00052 { 00053 const char *p = va_arg(ap1, const char *); 00054 if (!p) 00055 break; 00056 ++argc; 00057 } 00058 00059 /* 00060 * create an array to store the arguments in. 00061 */ 00062 if (argc < (int)SIZEOF(dummy)) 00063 { 00064 argv = dummy; 00065 } 00066 else 00067 { 00068 argv = malloc((argc + 1) * sizeof(const char *)); 00069 if (!argv) 00070 { 00071 argv = dummy; 00072 argc = SIZEOF(dummy) - 1; 00073 } 00074 } 00075 00076 /* 00077 * Now slurp the arguments into the array. 00078 */ 00079 va_copy(ap2, ap); 00080 argv[0] = arg; 00081 for (argc2 = 1; argc2 < argc; ++argc2) 00082 { 00083 argv[argc2] = va_arg(ap2, const char *); 00084 } 00085 argv[argc] = NULL; 00086 00087 /* for ANSI C compliance */ 00088 va_end(ap1); 00089 00090 /* Note: if it returns at all, it has failed */ 00091 errno = 0; 00092 if (execvp(pathname, (char *const *)argv)) 00093 { 00094 /* 00095 * Ordinarily, the warning "ignoring return value of function" 00096 * is a great way of discovering bugs. In this case, however, 00097 * we aren't concerned with the actual return value, but with 00098 * the error that results from the call. 00099 */ 00100 } 00101 00102 errnum = errno; 00103 /* assert(errnum != 0); */ 00104 00105 explain_string_buffer_init 00106 ( 00107 &sb, 00108 explain_common_message_buffer, 00109 explain_common_message_buffer_size 00110 ); 00111 explain_buffer_errno_execlpv(&sb, errnum, pathname, argc, argv); 00112 explain_output_error_and_die("%s", explain_common_message_buffer); 00113 } 00114 00115 00116 /* vim: set ts=8 sw=4 et : */