libexplain  1.4.D001
libexplain/buffer/errno/execlp.c
Go to the documentation of this file.
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 : */