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