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