libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2009, 2011, 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/stdarg.h> 00020 #include <libexplain/ac/stdlib.h> 00021 #include <libexplain/ac/string.h> 00022 00023 #include <libexplain/buffer/errno/execlp.h> 00024 #include <libexplain/buffer/errno/execvp.h> 00025 #include <libexplain/buffer/pathname.h> 00026 #include <libexplain/buffer/pointer.h> 00027 #include <libexplain/explanation.h> 00028 #include <libexplain/is_efault.h> 00029 #include <libexplain/sizeof.h> 00030 00031 00032 static void 00033 explain_buffer_errno_execlp_system_call(explain_string_buffer_t *sb, int errnum, 00034 const char *pathname, int argc, const char **argv) 00035 { 00036 size_t argsize; 00037 int n; 00038 00039 (void)errnum; 00040 explain_string_buffer_puts(sb, "execlp(pathname = "); 00041 explain_buffer_pathname(sb, pathname); 00042 explain_string_buffer_puts(sb, ", arg = "); 00043 00044 /* 00045 * produce output similar to execve 00046 */ 00047 argsize = 0; 00048 for (n = 0; n < argc && argsize < 1000; ++n) 00049 { 00050 const char *s; 00051 00052 if (n) 00053 explain_string_buffer_puts(sb, ", "); 00054 /* 00055 * We know argv is not EFAULT, because we made it, but we don't 00056 * know about argv[n]. 00057 */ 00058 s = argv[n]; 00059 if (explain_is_efault_path(s)) 00060 { 00061 explain_buffer_pointer(sb, s); 00062 argsize += 8; 00063 } 00064 else 00065 { 00066 explain_string_buffer_puts_quoted(sb, s); 00067 argsize += strlen(s); 00068 } 00069 } 00070 if (n < argc) 00071 { 00072 explain_string_buffer_printf 00073 ( 00074 sb, 00075 /* FIXME: i18n */ 00076 "... plus another %d command line arguments", 00077 (int)(argc - n) 00078 ); 00079 } 00080 explain_string_buffer_puts(sb, ", NULL)"); 00081 } 00082 00083 00084 void 00085 explain_buffer_errno_execlp_explanation(explain_string_buffer_t *sb, int errnum, 00086 const char *syscall_name, const char *pathname, int argc, const char **argv) 00087 { 00088 /* 00089 * http://www.opengroup.org/onlinepubs/009695399/functions/execlp.html 00090 */ 00091 (void)argc; 00092 explain_buffer_errno_execvp_explanation 00093 ( 00094 sb, 00095 errnum, 00096 syscall_name, 00097 pathname, 00098 (char *const *)argv 00099 ); 00100 } 00101 00102 00103 void 00104 explain_buffer_errno_execlpv(explain_string_buffer_t *sb, int errnum, 00105 const char *pathname, int argc, const char **argv) 00106 { 00107 explain_explanation_t exp; 00108 00109 explain_explanation_init(&exp, errnum); 00110 explain_buffer_errno_execlp_system_call(&exp.system_call_sb, errnum, 00111 pathname, argc, argv); 00112 explain_buffer_errno_execlp_explanation(&exp.explanation_sb, errnum, 00113 "execlp", pathname, argc, argv); 00114 explain_explanation_assemble(&exp, sb); 00115 } 00116 00117 00118 void 00119 explain_buffer_errno_execlp(explain_string_buffer_t *sb, int errnum, 00120 const char *pathname, const char *arg, va_list ap) 00121 { 00122 va_list ap1; 00123 va_list ap2; 00124 int argc; 00125 int argc2; 00126 const char **argv; 00127 const char *dummy[100]; 00128 00129 /* 00130 * count the number of arguments 00131 */ 00132 va_copy(ap1, ap); 00133 argc = 1; 00134 for (;;) 00135 { 00136 const char *p = va_arg(ap1, const char *); 00137 if (!p) 00138 break; 00139 ++argc; 00140 } 00141 00142 /* 00143 * create an array to store the arguments in. 00144 */ 00145 if (argc < (int)SIZEOF(dummy)) 00146 { 00147 argv = dummy; 00148 } 00149 else 00150 { 00151 argv = malloc((argc + 1) * sizeof(const char *)); 00152 if (!argv) 00153 { 00154 argv = dummy; 00155 argc = SIZEOF(dummy) - 1; 00156 } 00157 } 00158 00159 /* 00160 * Now slurp the arguments into the array. 00161 */ 00162 va_copy(ap2, ap); 00163 argv[0] = arg; 00164 for (argc2 = 1; argc2 < argc; ++argc2) 00165 { 00166 argv[argc2] = va_arg(ap2, const char *); 00167 } 00168 argv[argc2] = NULL; 00169 00170 /* for ANSI C compliance */ 00171 va_end(ap1); 00172 00173 explain_buffer_errno_execlpv(sb, errnum, pathname, argc, argv); 00174 00175 if (argv != dummy) 00176 free(argv); 00177 } 00178 00179 00180 /* vim: set ts=8 sw=4 et : */