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