LTP GCOV extension - code coverage report
Current view: directory - lib/roken - simple_exec.c
Test: samba_4_0_test.lcov.info
Date: 2010-08-06 Instrumented lines: 136
Code covered: 0.0 % Executed lines: 0

       1                 : /*
       2                 :  * Copyright (c) 1998 - 2001, 2004 Kungliga Tekniska Högskolan
       3                 :  * (Royal Institute of Technology, Stockholm, Sweden).
       4                 :  * All rights reserved.
       5                 :  *
       6                 :  * Redistribution and use in source and binary forms, with or without
       7                 :  * modification, are permitted provided that the following conditions
       8                 :  * are met:
       9                 :  *
      10                 :  * 1. Redistributions of source code must retain the above copyright
      11                 :  *    notice, this list of conditions and the following disclaimer.
      12                 :  *
      13                 :  * 2. Redistributions in binary form must reproduce the above copyright
      14                 :  *    notice, this list of conditions and the following disclaimer in the
      15                 :  *    documentation and/or other materials provided with the distribution.
      16                 :  *
      17                 :  * 3. Neither the name of the Institute nor the names of its contributors
      18                 :  *    may be used to endorse or promote products derived from this software
      19                 :  *    without specific prior written permission.
      20                 :  *
      21                 :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22                 :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23                 :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24                 :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25                 :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26                 :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27                 :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28                 :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29                 :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30                 :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31                 :  * SUCH DAMAGE.
      32                 :  */
      33                 : 
      34                 : #include <config.h>
      35                 : 
      36                 : #include <stdarg.h>
      37                 : #include <stdlib.h>
      38                 : #ifdef HAVE_SYS_TYPES_H
      39                 : #include <sys/types.h>
      40                 : #endif
      41                 : #ifdef HAVE_SYS_WAIT_H
      42                 : #include <sys/wait.h>
      43                 : #endif
      44                 : #ifdef HAVE_UNISTD_H
      45                 : #include <unistd.h>
      46                 : #endif
      47                 : #include <errno.h>
      48                 : 
      49                 : #include "roken.h"
      50                 : 
      51                 : #define EX_NOEXEC       126
      52                 : #define EX_NOTFOUND     127
      53                 : 
      54                 : /* return values:
      55                 :    SE_E_UNSPECIFIED   on `unspecified' system errors
      56                 :    SE_E_FORKFAILED    on fork failures
      57                 :    SE_E_WAITPIDFAILED on waitpid errors
      58                 :    SE_E_EXECTIMEOUT   exec timeout
      59                 :    0-   is return value from subprocess
      60                 :    SE_E_NOEXEC        if the program couldn't be executed
      61                 :    SE_E_NOTFOUND      if the program couldn't be found
      62                 :    128- is 128 + signal that killed subprocess
      63                 : 
      64                 :    possible values `func' can return:
      65                 :    ((time_t)-2)         exit loop w/o killing child and return
      66                 :                         `exec timeout'/-4 from simple_exec
      67                 :    ((time_t)-1)         kill child with SIGTERM and wait for child to exit
      68                 :    0                    don't timeout again
      69                 :    n                    seconds to next timeout
      70                 :    */
      71                 : 
      72                 : static int sig_alarm;
      73                 : 
      74                 : static RETSIGTYPE
      75                 : sigtimeout(int sig)
      76               0 : {
      77               0 :     sig_alarm = 1;
      78                 :     SIGRETURN(0);
      79                 : }
      80                 : 
      81                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
      82                 : wait_for_process_timed(pid_t pid, time_t (*func)(void *),
      83                 :                        void *ptr, time_t timeout)
      84               0 : {
      85               0 :     RETSIGTYPE (*old_func)(int sig) = NULL;
      86               0 :     unsigned int oldtime = 0;
      87                 :     int ret;
      88                 : 
      89               0 :     sig_alarm = 0;
      90                 : 
      91               0 :     if (func) {
      92               0 :         old_func = signal(SIGALRM, sigtimeout);
      93               0 :         oldtime = alarm(timeout);
      94                 :     }
      95                 : 
      96                 :     while(1) {
      97                 :         int status;
      98                 : 
      99               0 :         while(waitpid(pid, &status, 0) < 0) {
     100               0 :             if (errno != EINTR) {
     101               0 :                 ret = SE_E_WAITPIDFAILED;
     102               0 :                 goto out;
     103                 :             }
     104               0 :             if (func == NULL)
     105               0 :                 continue;
     106               0 :             if (sig_alarm == 0)
     107               0 :                 continue;
     108               0 :             timeout = (*func)(ptr);
     109               0 :             if (timeout == (time_t)-1) {
     110               0 :                 kill(pid, SIGTERM);
     111               0 :                 continue;
     112               0 :             } else if (timeout == (time_t)-2) {
     113               0 :                 ret = SE_E_EXECTIMEOUT;
     114               0 :                 goto out;
     115                 :             }
     116               0 :             alarm(timeout);
     117                 :         }
     118               0 :         if(WIFSTOPPED(status))
     119               0 :             continue;
     120               0 :         if(WIFEXITED(status)) {
     121               0 :             ret = WEXITSTATUS(status);
     122               0 :             break;
     123                 :         }
     124               0 :         if(WIFSIGNALED(status)) {
     125               0 :             ret = WTERMSIG(status) + 128;
     126               0 :             break;
     127                 :         }
     128               0 :     }
     129               0 :  out:
     130               0 :     if (func) {
     131               0 :         signal(SIGALRM, old_func);
     132               0 :         alarm(oldtime);
     133                 :     }
     134               0 :     return ret;
     135                 : }
     136                 : 
     137                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     138                 : wait_for_process(pid_t pid)
     139               0 : {
     140               0 :     return wait_for_process_timed(pid, NULL, NULL, 0);
     141                 : }
     142                 : 
     143                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     144                 : pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd,
     145                 :            const char *file, ...)
     146               0 : {
     147                 :     int in_fd[2], out_fd[2], err_fd[2];
     148                 :     pid_t pid;
     149                 :     va_list ap;
     150                 :     char **argv;
     151                 : 
     152               0 :     if(stdin_fd != NULL)
     153               0 :         pipe(in_fd);
     154               0 :     if(stdout_fd != NULL)
     155               0 :         pipe(out_fd);
     156               0 :     if(stderr_fd != NULL)
     157               0 :         pipe(err_fd);
     158               0 :     pid = fork();
     159               0 :     switch(pid) {
     160                 :     case 0:
     161               0 :         va_start(ap, file);
     162               0 :         argv = vstrcollect(&ap);
     163               0 :         va_end(ap);
     164               0 :         if(argv == NULL)
     165               0 :             exit(-1);
     166                 : 
     167                 :         /* close pipes we're not interested in */
     168               0 :         if(stdin_fd != NULL)
     169               0 :             close(in_fd[1]);
     170               0 :         if(stdout_fd != NULL)
     171               0 :             close(out_fd[0]);
     172               0 :         if(stderr_fd != NULL)
     173               0 :             close(err_fd[0]);
     174                 : 
     175                 :         /* pipe everything caller doesn't care about to /dev/null */
     176               0 :         if(stdin_fd == NULL)
     177               0 :             in_fd[0] = open(_PATH_DEVNULL, O_RDONLY);
     178               0 :         if(stdout_fd == NULL)
     179               0 :             out_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
     180               0 :         if(stderr_fd == NULL)
     181               0 :             err_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
     182                 : 
     183                 :         /* move to proper descriptors */
     184               0 :         if(in_fd[0] != STDIN_FILENO) {
     185               0 :             dup2(in_fd[0], STDIN_FILENO);
     186               0 :             close(in_fd[0]);
     187                 :         }
     188               0 :         if(out_fd[1] != STDOUT_FILENO) {
     189               0 :             dup2(out_fd[1], STDOUT_FILENO);
     190               0 :             close(out_fd[1]);
     191                 :         }
     192               0 :         if(err_fd[1] != STDERR_FILENO) {
     193               0 :             dup2(err_fd[1], STDERR_FILENO);
     194               0 :             close(err_fd[1]);
     195                 :         }
     196                 : 
     197               0 :         closefrom(3);
     198                 : 
     199               0 :         execv(file, argv);
     200               0 :         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
     201                 :     case -1:
     202               0 :         if(stdin_fd != NULL) {
     203               0 :             close(in_fd[0]);
     204               0 :             close(in_fd[1]);
     205                 :         }
     206               0 :         if(stdout_fd != NULL) {
     207               0 :             close(out_fd[0]);
     208               0 :             close(out_fd[1]);
     209                 :         }
     210               0 :         if(stderr_fd != NULL) {
     211               0 :             close(err_fd[0]);
     212               0 :             close(err_fd[1]);
     213                 :         }
     214               0 :         return SE_E_FORKFAILED;
     215                 :     default:
     216               0 :         if(stdin_fd != NULL) {
     217               0 :             close(in_fd[0]);
     218               0 :             *stdin_fd = fdopen(in_fd[1], "w");
     219                 :         }
     220               0 :         if(stdout_fd != NULL) {
     221               0 :             close(out_fd[1]);
     222               0 :             *stdout_fd = fdopen(out_fd[0], "r");
     223                 :         }
     224               0 :         if(stderr_fd != NULL) {
     225               0 :             close(err_fd[1]);
     226               0 :             *stderr_fd = fdopen(err_fd[0], "r");
     227                 :         }
     228                 :     }
     229               0 :     return pid;
     230                 : }
     231                 : 
     232                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     233                 : simple_execvp_timed(const char *file, char *const args[],
     234                 :                     time_t (*func)(void *), void *ptr, time_t timeout)
     235               0 : {
     236               0 :     pid_t pid = fork();
     237               0 :     switch(pid){
     238                 :     case -1:
     239               0 :         return SE_E_FORKFAILED;
     240                 :     case 0:
     241               0 :         execvp(file, args);
     242               0 :         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
     243                 :     default:
     244               0 :         return wait_for_process_timed(pid, func, ptr, timeout);
     245                 :     }
     246                 : }
     247                 : 
     248                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     249                 : simple_execvp(const char *file, char *const args[])
     250               0 : {
     251               0 :     return simple_execvp_timed(file, args, NULL, NULL, 0);
     252                 : }
     253                 : 
     254                 : /* gee, I'd like a execvpe */
     255                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     256                 : simple_execve_timed(const char *file, char *const args[], char *const envp[],
     257                 :                     time_t (*func)(void *), void *ptr, time_t timeout)
     258               0 : {
     259               0 :     pid_t pid = fork();
     260               0 :     switch(pid){
     261                 :     case -1:
     262               0 :         return SE_E_FORKFAILED;
     263                 :     case 0:
     264               0 :         execve(file, args, envp);
     265               0 :         exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
     266                 :     default:
     267               0 :         return wait_for_process_timed(pid, func, ptr, timeout);
     268                 :     }
     269                 : }
     270                 : 
     271                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     272                 : simple_execve(const char *file, char *const args[], char *const envp[])
     273               0 : {
     274               0 :     return simple_execve_timed(file, args, envp, NULL, NULL, 0);
     275                 : }
     276                 : 
     277                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     278                 : simple_execlp(const char *file, ...)
     279               0 : {
     280                 :     va_list ap;
     281                 :     char **argv;
     282                 :     int ret;
     283                 : 
     284               0 :     va_start(ap, file);
     285               0 :     argv = vstrcollect(&ap);
     286               0 :     va_end(ap);
     287               0 :     if(argv == NULL)
     288               0 :         return SE_E_UNSPECIFIED;
     289               0 :     ret = simple_execvp(file, argv);
     290               0 :     free(argv);
     291               0 :     return ret;
     292                 : }
     293                 : 
     294                 : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     295                 : simple_execle(const char *file, ... /* ,char *const envp[] */)
     296               0 : {
     297                 :     va_list ap;
     298                 :     char **argv;
     299                 :     char *const* envp;
     300                 :     int ret;
     301                 : 
     302               0 :     va_start(ap, file);
     303               0 :     argv = vstrcollect(&ap);
     304               0 :     envp = va_arg(ap, char **);
     305               0 :     va_end(ap);
     306               0 :     if(argv == NULL)
     307               0 :         return SE_E_UNSPECIFIED;
     308               0 :     ret = simple_execve(file, argv, envp);
     309               0 :     free(argv);
     310               0 :     return ret;
     311                 : }

Generated by: LTP GCOV extension version 1.6