libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2009, 2010, 2012, 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 int 00033 explain_execlp_on_error(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 hold_errno; 00043 int result; 00044 const char *dummy[100]; 00045 00046 /* 00047 * count the number of arguments 00048 */ 00049 va_start(ap, arg); 00050 va_copy(ap1, ap); 00051 argc = 1; 00052 for (;;) 00053 { 00054 const char *p = va_arg(ap1, const char *); 00055 if (!p) 00056 break; 00057 ++argc; 00058 } 00059 00060 /* 00061 * create an array to store the arguments in. 00062 */ 00063 if (argc < (int)SIZEOF(dummy)) 00064 { 00065 argv = dummy; 00066 } 00067 else 00068 { 00069 argv = malloc((argc + 1) * sizeof(const char *)); 00070 if (!argv) 00071 { 00072 argv = dummy; 00073 argc = SIZEOF(dummy) - 1; 00074 } 00075 } 00076 00077 /* 00078 * Now slurp the arguments into the array. 00079 */ 00080 va_copy(ap2, ap); 00081 argv[0] = arg; 00082 for (argc2 = 1; argc2 < argc; ++argc2) 00083 { 00084 argv[argc2] = va_arg(ap2, const char *); 00085 } 00086 argv[argc2] = NULL; 00087 00088 /* for ANSI C compliance */ 00089 va_end(ap1); 00090 00091 /* Note: if it returns at all, it has failed */ 00092 errno = 0; 00093 result = execvp(pathname, (char *const *)argv); 00094 /* assert(result < 0); */ 00095 00096 hold_errno = errno; 00097 /* assert(hold_errno != 0); */ 00098 00099 explain_string_buffer_init 00100 ( 00101 &sb, 00102 explain_common_message_buffer, 00103 explain_common_message_buffer_size 00104 ); 00105 explain_buffer_errno_execlpv(&sb, hold_errno, pathname, argc, argv); 00106 explain_output_error("%s", explain_common_message_buffer); 00107 errno = hold_errno; 00108 return result; 00109 } 00110 00111 00112 /* vim: set ts=8 sw=4 et : */