LCOV - code coverage report
Current view: top level - common - exechelp-posix.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 206 368 56.0 %
Date: 2016-09-12 12:29:17 Functions: 16 20 80.0 %

          Line data    Source code
       1             : /* exechelp.c - Fork and exec helpers for POSIX
       2             :  * Copyright (C) 2004, 2007, 2008, 2009,
       3             :  *               2010 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * This file is free software; you can redistribute it and/or modify
       8             :  * it under the terms of either
       9             :  *
      10             :  *   - the GNU Lesser General Public License as published by the Free
      11             :  *     Software Foundation; either version 3 of the License, or (at
      12             :  *     your option) any later version.
      13             :  *
      14             :  * or
      15             :  *
      16             :  *   - the GNU General Public License as published by the Free
      17             :  *     Software Foundation; either version 2 of the License, or (at
      18             :  *     your option) any later version.
      19             :  *
      20             :  * or both in parallel, as here.
      21             :  *
      22             :  * This file is distributed in the hope that it will be useful,
      23             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      24             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      25             :  * GNU General Public License for more details.
      26             :  *
      27             :  * You should have received a copy of the GNU General Public License
      28             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      29             :  */
      30             : 
      31             : #include <config.h>
      32             : 
      33             : #if defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
      34             : #error This code is only used on POSIX
      35             : #endif
      36             : 
      37             : #include <stdio.h>
      38             : #include <stdlib.h>
      39             : #include <stdint.h>
      40             : #include <string.h>
      41             : #include <errno.h>
      42             : #include <assert.h>
      43             : #ifdef HAVE_SIGNAL_H
      44             : # include <signal.h>
      45             : #endif
      46             : #include <unistd.h>
      47             : #include <fcntl.h>
      48             : 
      49             : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
      50             : #undef HAVE_NPTH
      51             : #undef USE_NPTH
      52             : #endif
      53             : 
      54             : #ifdef HAVE_NPTH
      55             : #include <npth.h>
      56             : #endif
      57             : #include <sys/wait.h>
      58             : 
      59             : #ifdef HAVE_GETRLIMIT
      60             : #include <sys/time.h>
      61             : #include <sys/resource.h>
      62             : #endif /*HAVE_GETRLIMIT*/
      63             : 
      64             : #ifdef HAVE_STAT
      65             : # include <sys/stat.h>
      66             : #endif
      67             : 
      68             : #if __linux__
      69             : # include <sys/types.h>
      70             : # include <dirent.h>
      71             : #endif /*__linux__ */
      72             : 
      73             : #include "util.h"
      74             : #include "i18n.h"
      75             : #include "sysutils.h"
      76             : #include "exechelp.h"
      77             : 
      78             : 
      79             : /* Helper */
      80             : static inline gpg_error_t
      81           0 : my_error_from_syserror (void)
      82             : {
      83           0 :   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
      84             : }
      85             : 
      86             : static inline gpg_error_t
      87           0 : my_error (int errcode)
      88             : {
      89           0 :   return gpg_err_make (default_errsource, errcode);
      90             : }
      91             : 
      92             : 
      93             : /* Return the maximum number of currently allowed open file
      94             :    descriptors.  Only useful on POSIX systems but returns a value on
      95             :    other systems too.  */
      96             : int
      97        2425 : get_max_fds (void)
      98             : {
      99        2425 :   int max_fds = -1;
     100             : #ifdef HAVE_GETRLIMIT
     101             :   struct rlimit rl;
     102             : 
     103             :   /* Under Linux we can figure out the highest used file descriptor by
     104             :    * reading /proc/PID/fd.  This is in the common cases much fast than
     105             :    * for example doing 4096 close calls where almost all of them will
     106             :    * fail.  On a system with a limit of 4096 files and only 8 files
     107             :    * open with the highest number being 10, we speedup close_all_fds
     108             :    * from 125ms to 0.4ms including readdir.
     109             :    *
     110             :    * Another option would be to close the file descriptors as returned
     111             :    * from reading that directory - however then we need to snapshot
     112             :    * that list before starting to close them.  */
     113             : #ifdef __linux__
     114             :   {
     115        2425 :     DIR *dir = NULL;
     116             :     struct dirent *dir_entry;
     117             :     const char *s;
     118             :     int x;
     119             : 
     120        2425 :     dir = opendir ("/proc/self/fd");
     121        2425 :     if (dir)
     122             :       {
     123       31203 :         while ((dir_entry = readdir (dir)))
     124             :           {
     125       26353 :             s = dir_entry->d_name;
     126       26353 :             if ( *s < '0' || *s > '9')
     127        4850 :               continue;
     128       21503 :             x = atoi (s);
     129       21503 :             if (x > max_fds)
     130       21503 :               max_fds = x;
     131             :           }
     132        2425 :         closedir (dir);
     133             :       }
     134        2425 :     if (max_fds != -1)
     135        2425 :       return max_fds + 1;
     136             :     }
     137             : #endif /* __linux__ */
     138             : 
     139             : 
     140             : # ifdef RLIMIT_NOFILE
     141           0 :   if (!getrlimit (RLIMIT_NOFILE, &rl))
     142           0 :     max_fds = rl.rlim_max;
     143             : # endif
     144             : 
     145             : # ifdef RLIMIT_OFILE
     146           0 :   if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
     147           0 :     max_fds = rl.rlim_max;
     148             : 
     149             : # endif
     150             : #endif /*HAVE_GETRLIMIT*/
     151             : 
     152             : #ifdef _SC_OPEN_MAX
     153           0 :   if (max_fds == -1)
     154             :     {
     155           0 :       long int scres = sysconf (_SC_OPEN_MAX);
     156           0 :       if (scres >= 0)
     157           0 :         max_fds = scres;
     158             :     }
     159             : #endif
     160             : 
     161             : #ifdef _POSIX_OPEN_MAX
     162           0 :   if (max_fds == -1)
     163           0 :     max_fds = _POSIX_OPEN_MAX;
     164             : #endif
     165             : 
     166             : #ifdef OPEN_MAX
     167             :   if (max_fds == -1)
     168             :     max_fds = OPEN_MAX;
     169             : #endif
     170             : 
     171           0 :   if (max_fds == -1)
     172           0 :     max_fds = 256;  /* Arbitrary limit.  */
     173             : 
     174             :   /* AIX returns INT32_MAX instead of a proper value.  We assume that
     175             :      this is always an error and use an arbitrary limit.  */
     176             : #ifdef INT32_MAX
     177           0 :   if (max_fds == INT32_MAX)
     178           0 :     max_fds = 256;
     179             : #endif
     180             : 
     181           0 :   return max_fds;
     182             : }
     183             : 
     184             : 
     185             : /* Close all file descriptors starting with descriptor FIRST.  If
     186             :    EXCEPT is not NULL, it is expected to be a list of file descriptors
     187             :    which shall not be closed.  This list shall be sorted in ascending
     188             :    order with the end marked by -1.  */
     189             : void
     190        2372 : close_all_fds (int first, int *except)
     191             : {
     192        2372 :   int max_fd = get_max_fds ();
     193             :   int fd, i, except_start;
     194             : 
     195        2372 :   if (except)
     196             :     {
     197          23 :       except_start = 0;
     198         179 :       for (fd=first; fd < max_fd; fd++)
     199             :         {
     200         156 :           for (i=except_start; except[i] != -1; i++)
     201             :             {
     202           0 :               if (except[i] == fd)
     203             :                 {
     204             :                   /* If we found the descriptor in the exception list
     205             :                      we can start the next compare run at the next
     206             :                      index because the exception list is ordered.  */
     207           0 :                 except_start = i + 1;
     208           0 :                 break;
     209             :                 }
     210             :             }
     211         156 :           if (except[i] == -1)
     212         156 :             close (fd);
     213             :         }
     214             :     }
     215             :   else
     216             :     {
     217       20339 :       for (fd=first; fd < max_fd; fd++)
     218       17990 :         close (fd);
     219             :     }
     220             : 
     221        2372 :   gpg_err_set_errno (0);
     222        2372 : }
     223             : 
     224             : 
     225             : /* Returns an array with all currently open file descriptors.  The end
     226             :    of the array is marked by -1.  The caller needs to release this
     227             :    array using the *standard free* and not with xfree.  This allow the
     228             :    use of this function right at startup even before libgcrypt has
     229             :    been initialized.  Returns NULL on error and sets ERRNO
     230             :    accordingly.  */
     231             : int *
     232          51 : get_all_open_fds (void)
     233             : {
     234             :   int *array;
     235             :   size_t narray;
     236             :   int fd, max_fd, idx;
     237             : #ifndef HAVE_STAT
     238             :   array = calloc (1, sizeof *array);
     239             :   if (array)
     240             :     array[0] = -1;
     241             : #else /*HAVE_STAT*/
     242             :   struct stat statbuf;
     243             : 
     244          51 :   max_fd = get_max_fds ();
     245          51 :   narray = 32;  /* If you change this change also t-exechelp.c.  */
     246          51 :   array = calloc (narray, sizeof *array);
     247          51 :   if (!array)
     248           0 :     return NULL;
     249             : 
     250             :   /* Note:  The list we return is ordered.  */
     251         258 :   for (idx=0, fd=0; fd < max_fd; fd++)
     252         207 :     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
     253             :       {
     254         156 :         if (idx+1 >= narray)
     255             :           {
     256             :             int *tmp;
     257             : 
     258           0 :             narray += (narray < 256)? 32:256;
     259           0 :             tmp = realloc (array, narray * sizeof *array);
     260           0 :             if (!tmp)
     261             :               {
     262           0 :                 free (array);
     263           0 :                 return NULL;
     264             :               }
     265           0 :             array = tmp;
     266             :           }
     267         156 :         array[idx++] = fd;
     268             :       }
     269          51 :   array[idx] = -1;
     270             : #endif /*HAVE_STAT*/
     271          51 :   return array;
     272             : }
     273             : 
     274             : 
     275             : /* The exec core used right after the fork. This will never return. */
     276             : static void
     277        2371 : do_exec (const char *pgmname, const char *argv[],
     278             :          int fd_in, int fd_out, int fd_err,
     279             :          int *except, void (*preexec)(void) )
     280             : {
     281             :   char **arg_list;
     282             :   int i, j;
     283             :   int fds[3];
     284             : 
     285        2371 :   fds[0] = fd_in;
     286        2371 :   fds[1] = fd_out;
     287        2371 :   fds[2] = fd_err;
     288             : 
     289             :   /* Create the command line argument array.  */
     290        2371 :   i = 0;
     291        2371 :   if (argv)
     292       19938 :     while (argv[i])
     293       15196 :       i++;
     294        2371 :   arg_list = xcalloc (i+2, sizeof *arg_list);
     295        2371 :   arg_list[0] = strrchr (pgmname, '/');
     296        2371 :   if (arg_list[0])
     297        2353 :     arg_list[0]++;
     298             :   else
     299          18 :     arg_list[0] = xstrdup (pgmname);
     300        2371 :   if (argv)
     301       17567 :     for (i=0,j=1; argv[i]; i++, j++)
     302       15196 :       arg_list[j] = (char*)argv[i];
     303             : 
     304             :   /* Assign /dev/null to unused FDs. */
     305        9484 :   for (i=0; i <= 2; i++)
     306             :     {
     307        7113 :       if (fds[i] == -1 )
     308             :         {
     309         710 :           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
     310         710 :           if (fds[i] == -1)
     311           0 :             log_fatal ("failed to open '%s': %s\n",
     312           0 :                        "/dev/null", strerror (errno));
     313             :         }
     314             :     }
     315             : 
     316             :   /* Connect the standard files.  */
     317        9484 :   for (i=0; i <= 2; i++)
     318             :     {
     319        7113 :       if (fds[i] != i && dup2 (fds[i], i) == -1)
     320           0 :         log_fatal ("dup2 std%s failed: %s\n",
     321           0 :                    i==0?"in":i==1?"out":"err", strerror (errno));
     322             :     }
     323             : 
     324             :   /* Close all other files. */
     325        2371 :   close_all_fds (3, except);
     326             : 
     327        2371 :   if (preexec)
     328           0 :     preexec ();
     329        2371 :   execv (pgmname, arg_list);
     330             :   /* No way to print anything, as we have closed all streams. */
     331        2371 :   _exit (127);
     332             : }
     333             : 
     334             : 
     335             : static gpg_error_t
     336         184 : do_create_pipe (int filedes[2])
     337             : {
     338         184 :   gpg_error_t err = 0;
     339             : 
     340         184 :   if (pipe (filedes) == -1)
     341             :     {
     342           0 :       err = my_error_from_syserror ();
     343           0 :       filedes[0] = filedes[1] = -1;
     344             :     }
     345             : 
     346         184 :   return err;
     347             : }
     348             : 
     349             : 
     350             : static gpg_error_t
     351        5961 : create_pipe_and_estream (int filedes[2], estream_t *r_fp,
     352             :                          int outbound, int nonblock)
     353             : {
     354             :   gpg_error_t err;
     355             : 
     356        5961 :   if (pipe (filedes) == -1)
     357             :     {
     358           0 :       err = my_error_from_syserror ();
     359           0 :       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
     360           0 :       filedes[0] = filedes[1] = -1;
     361           0 :       *r_fp = NULL;
     362           0 :       return err;
     363             :     }
     364             : 
     365        5961 :   if (!outbound)
     366        3974 :     *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
     367             :   else
     368        1987 :     *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
     369        5961 :   if (!*r_fp)
     370             :     {
     371           0 :       err = my_error_from_syserror ();
     372           0 :       log_error (_("error creating a stream for a pipe: %s\n"),
     373             :                  gpg_strerror (err));
     374           0 :       close (filedes[0]);
     375           0 :       close (filedes[1]);
     376           0 :       filedes[0] = filedes[1] = -1;
     377           0 :       return err;
     378             :     }
     379        5961 :   return 0;
     380             : }
     381             : 
     382             : 
     383             : /* Portable function to create a pipe.  Under Windows the write end is
     384             :    inheritable.  If R_FP is not NULL, an estream is created for the
     385             :    read end and stored at R_FP.  */
     386             : gpg_error_t
     387          42 : gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
     388             : {
     389          42 :   if (r_fp)
     390           0 :     return create_pipe_and_estream (filedes, r_fp, 0, nonblock);
     391             :   else
     392          42 :     return do_create_pipe (filedes);
     393             : }
     394             : 
     395             : 
     396             : /* Portable function to create a pipe.  Under Windows the read end is
     397             :    inheritable.  If R_FP is not NULL, an estream is created for the
     398             :    write end and stored at R_FP.  */
     399             : gpg_error_t
     400          49 : gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
     401             : {
     402          49 :   if (r_fp)
     403           0 :     return create_pipe_and_estream (filedes, r_fp, 1, nonblock);
     404             :   else
     405          49 :     return do_create_pipe (filedes);
     406             : }
     407             : 
     408             : 
     409             : /* Portable function to create a pipe.  Under Windows both ends are
     410             :    inheritable.  */
     411             : gpg_error_t
     412          93 : gnupg_create_pipe (int filedes[2])
     413             : {
     414          93 :   return do_create_pipe (filedes);
     415             : }
     416             : 
     417             : 
     418             : /* Fork and exec the PGMNAME, see exechelp.h for details.  */
     419             : gpg_error_t
     420        1987 : gnupg_spawn_process (const char *pgmname, const char *argv[],
     421             :                      int *except, void (*preexec)(void), unsigned int flags,
     422             :                      estream_t *r_infp,
     423             :                      estream_t *r_outfp,
     424             :                      estream_t *r_errfp,
     425             :                      pid_t *pid)
     426             : {
     427             :   gpg_error_t err;
     428        1987 :   int inpipe[2] = {-1, -1};
     429        1987 :   int outpipe[2] = {-1, -1};
     430        1987 :   int errpipe[2] = {-1, -1};
     431        1987 :   estream_t infp = NULL;
     432        1987 :   estream_t outfp = NULL;
     433        1987 :   estream_t errfp = NULL;
     434        1987 :   int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
     435             : 
     436        1987 :   if (r_infp)
     437        1987 :     *r_infp = NULL;
     438        1987 :   if (r_outfp)
     439        1987 :     *r_outfp = NULL;
     440        1987 :   if (r_errfp)
     441        1987 :     *r_errfp = NULL;
     442        1987 :   *pid = (pid_t)(-1); /* Always required.  */
     443             : 
     444        1987 :   if (r_infp)
     445             :     {
     446        1987 :       err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
     447        1987 :       if (err)
     448           0 :         return err;
     449             :     }
     450             : 
     451        1987 :   if (r_outfp)
     452             :     {
     453        1987 :       err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
     454        1987 :       if (err)
     455             :         {
     456           0 :           if (infp)
     457           0 :             es_fclose (infp);
     458           0 :           else if (inpipe[1] != -1)
     459           0 :             close (inpipe[1]);
     460           0 :           if (inpipe[0] != -1)
     461           0 :             close (inpipe[0]);
     462             : 
     463           0 :           return err;
     464             :         }
     465             :     }
     466             : 
     467        1987 :   if (r_errfp)
     468             :     {
     469        1987 :       err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
     470        1987 :       if (err)
     471             :         {
     472           0 :           if (infp)
     473           0 :             es_fclose (infp);
     474           0 :           else if (inpipe[1] != -1)
     475           0 :             close (inpipe[1]);
     476           0 :           if (inpipe[0] != -1)
     477           0 :             close (inpipe[0]);
     478             : 
     479           0 :           if (outfp)
     480           0 :             es_fclose (outfp);
     481           0 :           else if (outpipe[0] != -1)
     482           0 :             close (outpipe[0]);
     483           0 :           if (outpipe[1] != -1)
     484           0 :             close (outpipe[1]);
     485             : 
     486           0 :           return err;
     487             :         }
     488             :     }
     489             : 
     490             : 
     491        1987 :   *pid = fork ();
     492        3974 :   if (*pid == (pid_t)(-1))
     493             :     {
     494           0 :       err = my_error_from_syserror ();
     495           0 :       log_error (_("error forking process: %s\n"), gpg_strerror (err));
     496             : 
     497           0 :       if (infp)
     498           0 :         es_fclose (infp);
     499           0 :       else if (inpipe[1] != -1)
     500           0 :         close (inpipe[1]);
     501           0 :       if (inpipe[0] != -1)
     502           0 :         close (inpipe[0]);
     503             : 
     504           0 :       if (outfp)
     505           0 :         es_fclose (outfp);
     506           0 :       else if (outpipe[0] != -1)
     507           0 :         close (outpipe[0]);
     508           0 :       if (outpipe[1] != -1)
     509           0 :         close (outpipe[1]);
     510             : 
     511           0 :       if (errfp)
     512           0 :         es_fclose (errfp);
     513           0 :       else if (errpipe[0] != -1)
     514           0 :         close (errpipe[0]);
     515           0 :       if (errpipe[1] != -1)
     516           0 :         close (errpipe[1]);
     517           0 :       return err;
     518             :     }
     519             : 
     520        3974 :   if (!*pid)
     521             :     {
     522             :       /* This is the child. */
     523        1987 :       gcry_control (GCRYCTL_TERM_SECMEM);
     524        1987 :       es_fclose (infp);
     525        1987 :       es_fclose (outfp);
     526        1987 :       es_fclose (errfp);
     527        1987 :       do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
     528             :                except, preexec);
     529             :       /*NOTREACHED*/
     530             :     }
     531             : 
     532             :   /* This is the parent. */
     533        1987 :   if (inpipe[0] != -1)
     534        1987 :     close (inpipe[0]);
     535        1987 :   if (outpipe[1] != -1)
     536        1987 :     close (outpipe[1]);
     537        1987 :   if (errpipe[1] != -1)
     538        1987 :     close (errpipe[1]);
     539             : 
     540        1987 :   if (r_infp)
     541        1987 :     *r_infp = infp;
     542        1987 :   if (r_outfp)
     543        1987 :     *r_outfp = outfp;
     544        1987 :   if (r_errfp)
     545        1987 :     *r_errfp = errfp;
     546             : 
     547        1987 :   return 0;
     548             : }
     549             : 
     550             : 
     551             : 
     552             : /* Simplified version of gnupg_spawn_process.  This function forks and
     553             :    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
     554             :    and ERRFD to stderr (any of them may be -1 to connect them to
     555             :    /dev/null).  The arguments for the process are expected in the NULL
     556             :    terminated array ARGV.  The program name itself should not be
     557             :    included there.  Calling gnupg_wait_process is required.
     558             : 
     559             :    Returns 0 on success or an error code. */
     560             : gpg_error_t
     561         336 : gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
     562             :                         int infd, int outfd, int errfd, pid_t *pid)
     563             : {
     564             :   gpg_error_t err;
     565             : 
     566         336 :   *pid = fork ();
     567         672 :   if (*pid == (pid_t)(-1))
     568             :     {
     569           0 :       err = my_error_from_syserror ();
     570           0 :       log_error (_("error forking process: %s\n"), strerror (errno));
     571           0 :       return err;
     572             :     }
     573             : 
     574         672 :   if (!*pid)
     575             :     {
     576         336 :       gcry_control (GCRYCTL_TERM_SECMEM);
     577             :       /* Run child. */
     578         336 :       do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
     579             :       /*NOTREACHED*/
     580             :     }
     581             : 
     582         336 :   return 0;
     583             : }
     584             : 
     585             : 
     586             : 
     587             : 
     588             : /* Waiting for child processes.
     589             : 
     590             :    waitpid(2) may return information about terminated children that we
     591             :    did not yet request, and there is no portable way to wait for a
     592             :    specific set of children.
     593             : 
     594             :    As a workaround, we store the results of children for later use.
     595             : 
     596             :    XXX: This assumes that PIDs are not reused too quickly.  */
     597             : 
     598             : struct terminated_child
     599             : {
     600             :   pid_t pid;
     601             :   int exitcode;
     602             :   struct terminated_child *next;
     603             : };
     604             : 
     605             : struct terminated_child *terminated_children;
     606             : 
     607             : 
     608             : static gpg_error_t
     609           0 : store_result (pid_t pid, int exitcode)
     610             : {
     611             :   struct terminated_child *c;
     612             : 
     613           0 :   c = xtrymalloc (sizeof *c);
     614           0 :   if (c == NULL)
     615           0 :     return gpg_err_code_from_syserror ();
     616             : 
     617           0 :   c->pid = pid;
     618           0 :   c->exitcode = exitcode;
     619           0 :   c->next = terminated_children;
     620           0 :   terminated_children = c;
     621             : 
     622           0 :   return 0;
     623             : }
     624             : 
     625             : 
     626             : static int
     627         183 : get_result (pid_t pid, int *r_exitcode)
     628             : {
     629             :   struct terminated_child *c, **prevp;
     630             : 
     631         366 :   for (prevp = &terminated_children, c = terminated_children;
     632             :        c;
     633           0 :        prevp = &c->next, c = c->next)
     634           0 :     if (c->pid == pid)
     635             :       {
     636           0 :         *prevp = c->next;
     637           0 :         *r_exitcode = c->exitcode;
     638           0 :         xfree (c);
     639           0 :         return 1;
     640             :       }
     641             : 
     642         183 :   return 0;
     643             : }
     644             : 
     645             : 
     646             : /* See exechelp.h for a description.  */
     647             : gpg_error_t
     648        2140 : gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
     649             : {
     650             :   gpg_err_code_t ec;
     651             :   int i, status;
     652             : 
     653        2140 :   if (r_exitcode)
     654        2117 :     *r_exitcode = -1;
     655             : 
     656        2140 :   if (pid == (pid_t)(-1))
     657           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     658             : 
     659             : #ifdef USE_NPTH
     660           0 :   i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
     661             : #else
     662        2140 :   while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
     663           0 :          && errno == EINTR);
     664             : #endif
     665             : 
     666        2140 :   if (i == (pid_t)(-1))
     667             :     {
     668           0 :       ec = gpg_err_code_from_errno (errno);
     669           0 :       log_error (_("waiting for process %d to terminate failed: %s\n"),
     670           0 :                  (int)pid, strerror (errno));
     671             :     }
     672        2140 :   else if (!i)
     673             :     {
     674           0 :       ec = GPG_ERR_TIMEOUT; /* Still running.  */
     675             :     }
     676        2140 :   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
     677             :     {
     678           0 :       log_error (_("error running '%s': probably not installed\n"), pgmname);
     679           0 :       ec = GPG_ERR_CONFIGURATION;
     680             :     }
     681        2140 :   else if (WIFEXITED (status) && WEXITSTATUS (status))
     682          19 :     {
     683          19 :       if (!r_exitcode)
     684           1 :         log_error (_("error running '%s': exit status %d\n"), pgmname,
     685           1 :                    WEXITSTATUS (status));
     686             :       else
     687          18 :         *r_exitcode = WEXITSTATUS (status);
     688          19 :       ec = GPG_ERR_GENERAL;
     689             :     }
     690        2121 :   else if (!WIFEXITED (status))
     691             :     {
     692           0 :       log_error (_("error running '%s': terminated\n"), pgmname);
     693           0 :       ec = GPG_ERR_GENERAL;
     694             :     }
     695             :   else
     696             :     {
     697        2121 :       if (r_exitcode)
     698        2099 :         *r_exitcode = 0;
     699        2121 :       ec = 0;
     700             :     }
     701             : 
     702        2140 :   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
     703             : }
     704             : 
     705             : /* See exechelp.h for a description.  */
     706             : gpg_error_t
     707         134 : gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
     708             :                       int hang, int *r_exitcodes)
     709             : {
     710         134 :   gpg_err_code_t ec = 0;
     711             :   size_t i, left;
     712         134 :   int *dummy = NULL;
     713             : 
     714         134 :   if (r_exitcodes == NULL)
     715             :     {
     716           0 :       dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count);
     717           0 :       if (dummy == NULL)
     718           0 :         return gpg_err_code_from_syserror ();
     719             :     }
     720             : 
     721         317 :   for (i = 0, left = count; i < count; i++)
     722             :     {
     723         183 :       int status = -1;
     724             : 
     725         183 :       if (pids[i] == (pid_t)(-1))
     726           0 :         return my_error (GPG_ERR_INV_VALUE);
     727             : 
     728             :       /* See if there was a previously stored result for this pid.  */
     729         183 :       if (get_result (pids[i], &status))
     730           0 :         left -= 1;
     731             : 
     732         183 :       r_exitcodes[i] = status;
     733             :     }
     734             : 
     735         451 :   while (left > 0)
     736             :     {
     737             :       pid_t pid;
     738             :       int status;
     739             : 
     740             : #ifdef USE_NPTH
     741           0 :       pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG);
     742             : #else
     743         183 :       while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
     744           0 :              && errno == EINTR);
     745             : #endif
     746             : 
     747         183 :       if (pid == (pid_t)(-1))
     748             :         {
     749           0 :           ec = gpg_err_code_from_errno (errno);
     750           0 :           log_error (_("waiting for processes to terminate failed: %s\n"),
     751           0 :                      strerror (errno));
     752           0 :           break;
     753             :         }
     754         183 :       else if (!pid)
     755             :         {
     756           0 :           ec = GPG_ERR_TIMEOUT; /* Still running.  */
     757           0 :           break;
     758             :         }
     759             :       else
     760             :         {
     761         233 :           for (i = 0; i < count; i++)
     762         233 :             if (pid == pids[i])
     763         183 :               break;
     764             : 
     765         183 :           if (i == count)
     766             :             {
     767             :               /* No match, store this result.  */
     768           0 :               ec = store_result (pid, status);
     769           0 :               if (ec)
     770           0 :                 break;
     771           0 :               continue;
     772             :             }
     773             : 
     774             :           /* Process PIDS[i] died.  */
     775         183 :           if (r_exitcodes[i] != (pid_t) -1)
     776             :             {
     777           0 :               log_error ("PID %d was reused", pid);
     778           0 :               ec = GPG_ERR_GENERAL;
     779           0 :               break;
     780             :             }
     781             : 
     782         183 :           left -= 1;
     783         183 :           r_exitcodes[i] = status;
     784             :         }
     785             :     }
     786             : 
     787         134 :   if (ec == 0)
     788         317 :     for (i = 0; i < count; i++)
     789             :       {
     790         183 :         if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
     791             :           {
     792           0 :             log_error (_("error running '%s': probably not installed\n"),
     793           0 :                        pgmnames[i]);
     794           0 :             ec = GPG_ERR_CONFIGURATION;
     795             :           }
     796         183 :         else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
     797          10 :           {
     798          10 :             if (dummy)
     799           0 :               log_error (_("error running '%s': exit status %d\n"),
     800           0 :                          pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
     801             :             else
     802          10 :               r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
     803          10 :             ec = GPG_ERR_GENERAL;
     804             :           }
     805         173 :         else if (!WIFEXITED (r_exitcodes[i]))
     806             :           {
     807           0 :             log_error (_("error running '%s': terminated\n"), pgmnames[i]);
     808           0 :             ec = GPG_ERR_GENERAL;
     809             :           }
     810             :       }
     811             : 
     812         134 :   xfree (dummy);
     813         134 :   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
     814             : }
     815             : 
     816             : 
     817             : 
     818             : void
     819          23 : gnupg_release_process (pid_t pid)
     820             : {
     821             :   (void)pid;
     822          23 : }
     823             : 
     824             : 
     825             : /* Spawn a new process and immediately detach from it.  The name of
     826             :    the program to exec is PGMNAME and its arguments are in ARGV (the
     827             :    programname is automatically passed as first argument).
     828             :    Environment strings in ENVP are set.  An error is returned if
     829             :    pgmname is not executable; to make this work it is necessary to
     830             :    provide an absolute file name.  All standard file descriptors are
     831             :    connected to /dev/null. */
     832             : gpg_error_t
     833          48 : gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
     834             :                               const char *envp[] )
     835             : {
     836             :   pid_t pid;
     837             :   int i;
     838             : 
     839          48 :   if (getuid() != geteuid())
     840           0 :     return my_error (GPG_ERR_BUG);
     841             : 
     842          48 :   if (access (pgmname, X_OK))
     843           0 :     return my_error_from_syserror ();
     844             : 
     845          48 :   pid = fork ();
     846          96 :   if (pid == (pid_t)(-1))
     847             :     {
     848           0 :       log_error (_("error forking process: %s\n"), strerror (errno));
     849           0 :       return my_error_from_syserror ();
     850             :     }
     851          96 :   if (!pid)
     852             :     {
     853             :       pid_t pid2;
     854             : 
     855          48 :       gcry_control (GCRYCTL_TERM_SECMEM);
     856          48 :       if (setsid() == -1 || chdir ("/"))
     857           0 :         _exit (1);
     858             : 
     859          48 :       pid2 = fork (); /* Double fork to let init take over the new child. */
     860          48 :       if (pid2 == (pid_t)(-1))
     861           0 :         _exit (1);
     862          48 :       if (pid2)
     863           0 :         _exit (0);  /* Let the parent exit immediately. */
     864             : 
     865          48 :       if (envp)
     866           0 :         for (i=0; envp[i]; i++)
     867           0 :           putenv (xstrdup (envp[i]));
     868             : 
     869          48 :       do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
     870             : 
     871             :       /*NOTREACHED*/
     872             :     }
     873             : 
     874          48 :   if (waitpid (pid, NULL, 0) == -1)
     875           0 :     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
     876           0 :                strerror (errno));
     877             : 
     878          48 :   return 0;
     879             : }
     880             : 
     881             : 
     882             : /* Kill a process; that is send an appropriate signal to the process.
     883             :    gnupg_wait_process must be called to actually remove the process
     884             :    from the system.  An invalid PID is ignored.  */
     885             : void
     886           0 : gnupg_kill_process (pid_t pid)
     887             : {
     888           0 :   if (pid != (pid_t)(-1))
     889             :     {
     890           0 :       kill (pid, SIGTERM);
     891             :     }
     892           0 : }

Generated by: LCOV version 1.11