agent: Fix segv running in --server mode
[gnupg.git] / common / exechelp-posix.c
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
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
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
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
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 *
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
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
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
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
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
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
413 gnupg_create_pipe (int filedes[2])
414 {
415   return do_create_pipe (filedes);
416 }
417
418
419 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
420 gpg_error_t
421 gnupg_spawn_process (const char *pgmname, const char *argv[],
422                      int *except, void (*preexec)(void), unsigned int flags,
423                      estream_t *r_infp,
424                      estream_t *r_outfp,
425                      estream_t *r_errfp,
426                      pid_t *pid)
427 {
428   gpg_error_t err;
429   int inpipe[2] = {-1, -1};
430   int outpipe[2] = {-1, -1};
431   int errpipe[2] = {-1, -1};
432   estream_t infp = NULL;
433   estream_t outfp = NULL;
434   estream_t errfp = NULL;
435   int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
436
437   if (r_infp)
438     *r_infp = NULL;
439   if (r_outfp)
440     *r_outfp = NULL;
441   if (r_errfp)
442     *r_errfp = NULL;
443   *pid = (pid_t)(-1); /* Always required.  */
444
445   if (r_infp)
446     {
447       err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
448       if (err)
449         return err;
450     }
451
452   if (r_outfp)
453     {
454       err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
455       if (err)
456         {
457           if (infp)
458             es_fclose (infp);
459           else if (inpipe[1] != -1)
460             close (inpipe[1]);
461           if (inpipe[0] != -1)
462             close (inpipe[0]);
463
464           return err;
465         }
466     }
467
468   if (r_errfp)
469     {
470       err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
471       if (err)
472         {
473           if (infp)
474             es_fclose (infp);
475           else if (inpipe[1] != -1)
476             close (inpipe[1]);
477           if (inpipe[0] != -1)
478             close (inpipe[0]);
479
480           if (outfp)
481             es_fclose (outfp);
482           else if (outpipe[0] != -1)
483             close (outpipe[0]);
484           if (outpipe[1] != -1)
485             close (outpipe[1]);
486
487           return err;
488         }
489     }
490
491
492   *pid = fork ();
493   if (*pid == (pid_t)(-1))
494     {
495       err = my_error_from_syserror ();
496       log_error (_("error forking process: %s\n"), gpg_strerror (err));
497
498       if (infp)
499         es_fclose (infp);
500       else if (inpipe[1] != -1)
501         close (inpipe[1]);
502       if (inpipe[0] != -1)
503         close (inpipe[0]);
504
505       if (outfp)
506         es_fclose (outfp);
507       else if (outpipe[0] != -1)
508         close (outpipe[0]);
509       if (outpipe[1] != -1)
510         close (outpipe[1]);
511
512       if (errfp)
513         es_fclose (errfp);
514       else if (errpipe[0] != -1)
515         close (errpipe[0]);
516       if (errpipe[1] != -1)
517         close (errpipe[1]);
518       return err;
519     }
520
521   if (!*pid)
522     {
523       /* This is the child. */
524       gcry_control (GCRYCTL_TERM_SECMEM);
525       es_fclose (infp);
526       es_fclose (outfp);
527       es_fclose (errfp);
528       do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
529                except, preexec);
530       /*NOTREACHED*/
531     }
532
533   /* This is the parent. */
534   if (inpipe[0] != -1)
535     close (inpipe[0]);
536   if (outpipe[1] != -1)
537     close (outpipe[1]);
538   if (errpipe[1] != -1)
539     close (errpipe[1]);
540
541   if (r_infp)
542     *r_infp = infp;
543   if (r_outfp)
544     *r_outfp = outfp;
545   if (r_errfp)
546     *r_errfp = errfp;
547
548   return 0;
549 }
550
551
552
553 /* Simplified version of gnupg_spawn_process.  This function forks and
554    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
555    and ERRFD to stderr (any of them may be -1 to connect them to
556    /dev/null).  The arguments for the process are expected in the NULL
557    terminated array ARGV.  The program name itself should not be
558    included there.  Calling gnupg_wait_process is required.
559
560    Returns 0 on success or an error code. */
561 gpg_error_t
562 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
563                         int infd, int outfd, int errfd, pid_t *pid)
564 {
565   gpg_error_t err;
566
567   *pid = fork ();
568   if (*pid == (pid_t)(-1))
569     {
570       err = my_error_from_syserror ();
571       log_error (_("error forking process: %s\n"), strerror (errno));
572       return err;
573     }
574
575   if (!*pid)
576     {
577       gcry_control (GCRYCTL_TERM_SECMEM);
578       /* Run child. */
579       do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
580       /*NOTREACHED*/
581     }
582
583   return 0;
584 }
585
586
587 \f
588
589 /* Waiting for child processes.
590
591    waitpid(2) may return information about terminated children that we
592    did not yet request, and there is no portable way to wait for a
593    specific set of children.
594
595    As a workaround, we store the results of children for later use.
596
597    XXX: This assumes that PIDs are not reused too quickly.  */
598
599 struct terminated_child
600 {
601   pid_t pid;
602   int exitcode;
603   struct terminated_child *next;
604 };
605
606 struct terminated_child *terminated_children;
607
608
609 static gpg_error_t
610 store_result (pid_t pid, int exitcode)
611 {
612   struct terminated_child *c;
613
614   c = xtrymalloc (sizeof *c);
615   if (c == NULL)
616     return gpg_err_code_from_syserror ();
617
618   c->pid = pid;
619   c->exitcode = exitcode;
620   c->next = terminated_children;
621   terminated_children = c;
622
623   return 0;
624 }
625
626
627 static int
628 get_result (pid_t pid, int *r_exitcode)
629 {
630   struct terminated_child *c, **prevp;
631
632   for (prevp = &terminated_children, c = terminated_children;
633        c;
634        prevp = &c->next, c = c->next)
635     if (c->pid == pid)
636       {
637         *prevp = c->next;
638         *r_exitcode = c->exitcode;
639         xfree (c);
640         return 1;
641       }
642
643   return 0;
644 }
645
646
647 /* See exechelp.h for a description.  */
648 gpg_error_t
649 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
650 {
651   gpg_err_code_t ec;
652   int i, status;
653
654   if (r_exitcode)
655     *r_exitcode = -1;
656
657   if (pid == (pid_t)(-1))
658     return gpg_error (GPG_ERR_INV_VALUE);
659
660 #ifdef USE_NPTH
661   i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
662 #else
663   while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
664          && errno == EINTR);
665 #endif
666
667   if (i == (pid_t)(-1))
668     {
669       ec = gpg_err_code_from_errno (errno);
670       log_error (_("waiting for process %d to terminate failed: %s\n"),
671                  (int)pid, strerror (errno));
672     }
673   else if (!i)
674     {
675       ec = GPG_ERR_TIMEOUT; /* Still running.  */
676     }
677   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
678     {
679       log_error (_("error running '%s': probably not installed\n"), pgmname);
680       ec = GPG_ERR_CONFIGURATION;
681     }
682   else if (WIFEXITED (status) && WEXITSTATUS (status))
683     {
684       if (!r_exitcode)
685         log_error (_("error running '%s': exit status %d\n"), pgmname,
686                    WEXITSTATUS (status));
687       else
688         *r_exitcode = WEXITSTATUS (status);
689       ec = GPG_ERR_GENERAL;
690     }
691   else if (!WIFEXITED (status))
692     {
693       log_error (_("error running '%s': terminated\n"), pgmname);
694       ec = GPG_ERR_GENERAL;
695     }
696   else
697     {
698       if (r_exitcode)
699         *r_exitcode = 0;
700       ec = 0;
701     }
702
703   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
704 }
705
706 /* See exechelp.h for a description.  */
707 gpg_error_t
708 gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
709                       int hang, int *r_exitcodes)
710 {
711   gpg_err_code_t ec = 0;
712   size_t i, left;
713   int *dummy = NULL;
714
715   if (r_exitcodes == NULL)
716     {
717       dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count);
718       if (dummy == NULL)
719         return gpg_err_code_from_syserror ();
720     }
721
722   for (i = 0, left = count; i < count; i++)
723     {
724       int status = -1;
725
726       if (pids[i] == (pid_t)(-1))
727         return my_error (GPG_ERR_INV_VALUE);
728
729       /* See if there was a previously stored result for this pid.  */
730       if (get_result (pids[i], &status))
731         left -= 1;
732
733       r_exitcodes[i] = status;
734     }
735
736   while (left > 0)
737     {
738       pid_t pid;
739       int status;
740
741 #ifdef USE_NPTH
742       pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG);
743 #else
744       while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
745              && errno == EINTR);
746 #endif
747
748       if (pid == (pid_t)(-1))
749         {
750           ec = gpg_err_code_from_errno (errno);
751           log_error (_("waiting for processes to terminate failed: %s\n"),
752                      strerror (errno));
753           break;
754         }
755       else if (!pid)
756         {
757           ec = GPG_ERR_TIMEOUT; /* Still running.  */
758           break;
759         }
760       else
761         {
762           for (i = 0; i < count; i++)
763             if (pid == pids[i])
764               break;
765
766           if (i == count)
767             {
768               /* No match, store this result.  */
769               ec = store_result (pid, status);
770               if (ec)
771                 break;
772               continue;
773             }
774
775           /* Process PIDS[i] died.  */
776           if (r_exitcodes[i] != (pid_t) -1)
777             {
778               log_error ("PID %d was reused", pid);
779               ec = GPG_ERR_GENERAL;
780               break;
781             }
782
783           left -= 1;
784           r_exitcodes[i] = status;
785         }
786     }
787
788   for (i = 0; i < count; i++)
789     {
790       if (r_exitcodes[i] == -1)
791         continue;
792
793       if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
794         {
795           log_error (_("error running '%s': probably not installed\n"),
796                      pgmnames[i]);
797           ec = GPG_ERR_CONFIGURATION;
798         }
799       else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
800         {
801           if (dummy)
802             log_error (_("error running '%s': exit status %d\n"),
803                        pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
804           else
805             r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
806           ec = GPG_ERR_GENERAL;
807         }
808       else if (!WIFEXITED (r_exitcodes[i]))
809         {
810           log_error (_("error running '%s': terminated\n"), pgmnames[i]);
811           ec = GPG_ERR_GENERAL;
812         }
813     }
814
815   xfree (dummy);
816   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
817 }
818
819 \f
820
821 void
822 gnupg_release_process (pid_t pid)
823 {
824   (void)pid;
825 }
826
827
828 /* Spawn a new process and immediately detach from it.  The name of
829    the program to exec is PGMNAME and its arguments are in ARGV (the
830    programname is automatically passed as first argument).
831    Environment strings in ENVP are set.  An error is returned if
832    pgmname is not executable; to make this work it is necessary to
833    provide an absolute file name.  All standard file descriptors are
834    connected to /dev/null. */
835 gpg_error_t
836 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
837                               const char *envp[] )
838 {
839   pid_t pid;
840   int i;
841
842   if (getuid() != geteuid())
843     return my_error (GPG_ERR_BUG);
844
845   if (access (pgmname, X_OK))
846     return my_error_from_syserror ();
847
848   pid = fork ();
849   if (pid == (pid_t)(-1))
850     {
851       log_error (_("error forking process: %s\n"), strerror (errno));
852       return my_error_from_syserror ();
853     }
854   if (!pid)
855     {
856       pid_t pid2;
857
858       gcry_control (GCRYCTL_TERM_SECMEM);
859       if (setsid() == -1 || chdir ("/"))
860         _exit (1);
861
862       pid2 = fork (); /* Double fork to let init take over the new child. */
863       if (pid2 == (pid_t)(-1))
864         _exit (1);
865       if (pid2)
866         _exit (0);  /* Let the parent exit immediately. */
867
868       if (envp)
869         for (i=0; envp[i]; i++)
870           putenv (xstrdup (envp[i]));
871
872       do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
873
874       /*NOTREACHED*/
875     }
876
877   if (waitpid (pid, NULL, 0) == -1)
878     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
879                strerror (errno));
880
881   return 0;
882 }
883
884
885 /* Kill a process; that is send an appropriate signal to the process.
886    gnupg_wait_process must be called to actually remove the process
887    from the system.  An invalid PID is ignored.  */
888 void
889 gnupg_kill_process (pid_t pid)
890 {
891   if (pid != (pid_t)(-1))
892     {
893       kill (pid, SIGTERM);
894     }
895 }