chiark / gitweb /
gnupg2 (2.1.17-3) unstable; urgency=medium
[gnupg2.git] / common / exechelp-posix.c
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 <https://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 my_error_from_syserror (void)
82 {
83   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
84 }
85
86 static inline gpg_error_t
87 my_error (int errcode)
88 {
89   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 get_max_fds (void)
98 {
99   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     DIR *dir = NULL;
116     struct dirent *dir_entry;
117     const char *s;
118     int x;
119
120     dir = opendir ("/proc/self/fd");
121     if (dir)
122       {
123         while ((dir_entry = readdir (dir)))
124           {
125             s = dir_entry->d_name;
126             if ( *s < '0' || *s > '9')
127               continue;
128             x = atoi (s);
129             if (x > max_fds)
130               max_fds = x;
131           }
132         closedir (dir);
133       }
134     if (max_fds != -1)
135       return max_fds + 1;
136     }
137 #endif /* __linux__ */
138
139
140 # ifdef RLIMIT_NOFILE
141   if (!getrlimit (RLIMIT_NOFILE, &rl))
142     max_fds = rl.rlim_max;
143 # endif
144
145 # ifdef RLIMIT_OFILE
146   if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
147     max_fds = rl.rlim_max;
148
149 # endif
150 #endif /*HAVE_GETRLIMIT*/
151
152 #ifdef _SC_OPEN_MAX
153   if (max_fds == -1)
154     {
155       long int scres = sysconf (_SC_OPEN_MAX);
156       if (scres >= 0)
157         max_fds = scres;
158     }
159 #endif
160
161 #ifdef _POSIX_OPEN_MAX
162   if (max_fds == -1)
163     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   if (max_fds == -1)
172     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   if (max_fds == INT32_MAX)
178     max_fds = 256;
179 #endif
180
181   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 close_all_fds (int first, int *except)
191 {
192   int max_fd = get_max_fds ();
193   int fd, i, except_start;
194
195   if (except)
196     {
197       except_start = 0;
198       for (fd=first; fd < max_fd; fd++)
199         {
200           for (i=except_start; except[i] != -1; i++)
201             {
202               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                 except_start = i + 1;
208                 break;
209                 }
210             }
211           if (except[i] == -1)
212             close (fd);
213         }
214     }
215   else
216     {
217       for (fd=first; fd < max_fd; fd++)
218         close (fd);
219     }
220
221   gpg_err_set_errno (0);
222 }
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 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   max_fd = get_max_fds ();
245   narray = 32;  /* If you change this change also t-exechelp.c.  */
246   array = calloc (narray, sizeof *array);
247   if (!array)
248     return NULL;
249
250   /* Note:  The list we return is ordered.  */
251   for (idx=0, fd=0; fd < max_fd; fd++)
252     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
253       {
254         if (idx+1 >= narray)
255           {
256             int *tmp;
257
258             narray += (narray < 256)? 32:256;
259             tmp = realloc (array, narray * sizeof *array);
260             if (!tmp)
261               {
262                 free (array);
263                 return NULL;
264               }
265             array = tmp;
266           }
267         array[idx++] = fd;
268       }
269   array[idx] = -1;
270 #endif /*HAVE_STAT*/
271   return array;
272 }
273
274
275 /* The exec core used right after the fork. This will never return. */
276 static void
277 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   fds[0] = fd_in;
286   fds[1] = fd_out;
287   fds[2] = fd_err;
288
289   /* Create the command line argument array.  */
290   i = 0;
291   if (argv)
292     while (argv[i])
293       i++;
294   arg_list = xcalloc (i+2, sizeof *arg_list);
295   arg_list[0] = strrchr (pgmname, '/');
296   if (arg_list[0])
297     arg_list[0]++;
298   else
299     arg_list[0] = xstrdup (pgmname);
300   if (argv)
301     for (i=0,j=1; argv[i]; i++, j++)
302       arg_list[j] = (char*)argv[i];
303
304   /* Assign /dev/null to unused FDs. */
305   for (i=0; i <= 2; i++)
306     {
307       if (fds[i] == -1 )
308         {
309           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
310           if (fds[i] == -1)
311             log_fatal ("failed to open '%s': %s\n",
312                        "/dev/null", strerror (errno));
313         }
314     }
315
316   /* Connect the standard files.  */
317   for (i=0; i <= 2; i++)
318     {
319       if (fds[i] != i && dup2 (fds[i], i) == -1)
320         log_fatal ("dup2 std%s failed: %s\n",
321                    i==0?"in":i==1?"out":"err", strerror (errno));
322     }
323
324   /* Close all other files. */
325   close_all_fds (3, except);
326
327   if (preexec)
328     preexec ();
329   execv (pgmname, arg_list);
330   /* No way to print anything, as we have closed all streams. */
331   _exit (127);
332 }
333
334
335 static gpg_error_t
336 do_create_pipe (int filedes[2])
337 {
338   gpg_error_t err = 0;
339
340   if (pipe (filedes) == -1)
341     {
342       err = my_error_from_syserror ();
343       filedes[0] = filedes[1] = -1;
344     }
345
346   return err;
347 }
348
349
350 static gpg_error_t
351 create_pipe_and_estream (int filedes[2], estream_t *r_fp,
352                          int outbound, int nonblock)
353 {
354   gpg_error_t err;
355
356   if (pipe (filedes) == -1)
357     {
358       err = my_error_from_syserror ();
359       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
360       filedes[0] = filedes[1] = -1;
361       *r_fp = NULL;
362       return err;
363     }
364
365   if (!outbound)
366     *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
367   else
368     *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
369   if (!*r_fp)
370     {
371       err = my_error_from_syserror ();
372       log_error (_("error creating a stream for a pipe: %s\n"),
373                  gpg_strerror (err));
374       close (filedes[0]);
375       close (filedes[1]);
376       filedes[0] = filedes[1] = -1;
377       return err;
378     }
379   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 gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
388 {
389   if (r_fp)
390     return create_pipe_and_estream (filedes, r_fp, 0, nonblock);
391   else
392     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 gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
401 {
402   if (r_fp)
403     return create_pipe_and_estream (filedes, r_fp, 1, nonblock);
404   else
405     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 gnupg_create_pipe (int filedes[2])
413 {
414   return do_create_pipe (filedes);
415 }
416
417
418 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
419 gpg_error_t
420 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   int inpipe[2] = {-1, -1};
429   int outpipe[2] = {-1, -1};
430   int errpipe[2] = {-1, -1};
431   estream_t infp = NULL;
432   estream_t outfp = NULL;
433   estream_t errfp = NULL;
434   int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
435
436   if (r_infp)
437     *r_infp = NULL;
438   if (r_outfp)
439     *r_outfp = NULL;
440   if (r_errfp)
441     *r_errfp = NULL;
442   *pid = (pid_t)(-1); /* Always required.  */
443
444   if (r_infp)
445     {
446       err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
447       if (err)
448         return err;
449     }
450
451   if (r_outfp)
452     {
453       err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
454       if (err)
455         {
456           if (infp)
457             es_fclose (infp);
458           else if (inpipe[1] != -1)
459             close (inpipe[1]);
460           if (inpipe[0] != -1)
461             close (inpipe[0]);
462
463           return err;
464         }
465     }
466
467   if (r_errfp)
468     {
469       err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
470       if (err)
471         {
472           if (infp)
473             es_fclose (infp);
474           else if (inpipe[1] != -1)
475             close (inpipe[1]);
476           if (inpipe[0] != -1)
477             close (inpipe[0]);
478
479           if (outfp)
480             es_fclose (outfp);
481           else if (outpipe[0] != -1)
482             close (outpipe[0]);
483           if (outpipe[1] != -1)
484             close (outpipe[1]);
485
486           return err;
487         }
488     }
489
490
491   *pid = fork ();
492   if (*pid == (pid_t)(-1))
493     {
494       err = my_error_from_syserror ();
495       log_error (_("error forking process: %s\n"), gpg_strerror (err));
496
497       if (infp)
498         es_fclose (infp);
499       else if (inpipe[1] != -1)
500         close (inpipe[1]);
501       if (inpipe[0] != -1)
502         close (inpipe[0]);
503
504       if (outfp)
505         es_fclose (outfp);
506       else if (outpipe[0] != -1)
507         close (outpipe[0]);
508       if (outpipe[1] != -1)
509         close (outpipe[1]);
510
511       if (errfp)
512         es_fclose (errfp);
513       else if (errpipe[0] != -1)
514         close (errpipe[0]);
515       if (errpipe[1] != -1)
516         close (errpipe[1]);
517       return err;
518     }
519
520   if (!*pid)
521     {
522       /* This is the child. */
523       gcry_control (GCRYCTL_TERM_SECMEM);
524       es_fclose (infp);
525       es_fclose (outfp);
526       es_fclose (errfp);
527       do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
528                except, preexec);
529       /*NOTREACHED*/
530     }
531
532   /* This is the parent. */
533   if (inpipe[0] != -1)
534     close (inpipe[0]);
535   if (outpipe[1] != -1)
536     close (outpipe[1]);
537   if (errpipe[1] != -1)
538     close (errpipe[1]);
539
540   if (r_infp)
541     *r_infp = infp;
542   if (r_outfp)
543     *r_outfp = outfp;
544   if (r_errfp)
545     *r_errfp = errfp;
546
547   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 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   *pid = fork ();
567   if (*pid == (pid_t)(-1))
568     {
569       err = my_error_from_syserror ();
570       log_error (_("error forking process: %s\n"), strerror (errno));
571       return err;
572     }
573
574   if (!*pid)
575     {
576       gcry_control (GCRYCTL_TERM_SECMEM);
577       /* Run child. */
578       do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
579       /*NOTREACHED*/
580     }
581
582   return 0;
583 }
584
585
586 \f
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 store_result (pid_t pid, int exitcode)
610 {
611   struct terminated_child *c;
612
613   c = xtrymalloc (sizeof *c);
614   if (c == NULL)
615     return gpg_err_code_from_syserror ();
616
617   c->pid = pid;
618   c->exitcode = exitcode;
619   c->next = terminated_children;
620   terminated_children = c;
621
622   return 0;
623 }
624
625
626 static int
627 get_result (pid_t pid, int *r_exitcode)
628 {
629   struct terminated_child *c, **prevp;
630
631   for (prevp = &terminated_children, c = terminated_children;
632        c;
633        prevp = &c->next, c = c->next)
634     if (c->pid == pid)
635       {
636         *prevp = c->next;
637         *r_exitcode = c->exitcode;
638         xfree (c);
639         return 1;
640       }
641
642   return 0;
643 }
644
645
646 /* See exechelp.h for a description.  */
647 gpg_error_t
648 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   if (r_exitcode)
654     *r_exitcode = -1;
655
656   if (pid == (pid_t)(-1))
657     return gpg_error (GPG_ERR_INV_VALUE);
658
659 #ifdef USE_NPTH
660   i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
661 #else
662   while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
663          && errno == EINTR);
664 #endif
665
666   if (i == (pid_t)(-1))
667     {
668       ec = gpg_err_code_from_errno (errno);
669       log_error (_("waiting for process %d to terminate failed: %s\n"),
670                  (int)pid, strerror (errno));
671     }
672   else if (!i)
673     {
674       ec = GPG_ERR_TIMEOUT; /* Still running.  */
675     }
676   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
677     {
678       log_error (_("error running '%s': probably not installed\n"), pgmname);
679       ec = GPG_ERR_CONFIGURATION;
680     }
681   else if (WIFEXITED (status) && WEXITSTATUS (status))
682     {
683       if (!r_exitcode)
684         log_error (_("error running '%s': exit status %d\n"), pgmname,
685                    WEXITSTATUS (status));
686       else
687         *r_exitcode = WEXITSTATUS (status);
688       ec = GPG_ERR_GENERAL;
689     }
690   else if (!WIFEXITED (status))
691     {
692       log_error (_("error running '%s': terminated\n"), pgmname);
693       ec = GPG_ERR_GENERAL;
694     }
695   else
696     {
697       if (r_exitcode)
698         *r_exitcode = 0;
699       ec = 0;
700     }
701
702   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
703 }
704
705 /* See exechelp.h for a description.  */
706 gpg_error_t
707 gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
708                       int hang, int *r_exitcodes)
709 {
710   gpg_err_code_t ec = 0;
711   size_t i, left;
712   int *dummy = NULL;
713
714   if (r_exitcodes == NULL)
715     {
716       dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count);
717       if (dummy == NULL)
718         return gpg_err_code_from_syserror ();
719     }
720
721   for (i = 0, left = count; i < count; i++)
722     {
723       int status = -1;
724
725       if (pids[i] == (pid_t)(-1))
726         return my_error (GPG_ERR_INV_VALUE);
727
728       /* See if there was a previously stored result for this pid.  */
729       if (get_result (pids[i], &status))
730         left -= 1;
731
732       r_exitcodes[i] = status;
733     }
734
735   while (left > 0)
736     {
737       pid_t pid;
738       int status;
739
740 #ifdef USE_NPTH
741       pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG);
742 #else
743       while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
744              && errno == EINTR);
745 #endif
746
747       if (pid == (pid_t)(-1))
748         {
749           ec = gpg_err_code_from_errno (errno);
750           log_error (_("waiting for processes to terminate failed: %s\n"),
751                      strerror (errno));
752           break;
753         }
754       else if (!pid)
755         {
756           ec = GPG_ERR_TIMEOUT; /* Still running.  */
757           break;
758         }
759       else
760         {
761           for (i = 0; i < count; i++)
762             if (pid == pids[i])
763               break;
764
765           if (i == count)
766             {
767               /* No match, store this result.  */
768               ec = store_result (pid, status);
769               if (ec)
770                 break;
771               continue;
772             }
773
774           /* Process PIDS[i] died.  */
775           if (r_exitcodes[i] != (pid_t) -1)
776             {
777               log_error ("PID %d was reused", pid);
778               ec = GPG_ERR_GENERAL;
779               break;
780             }
781
782           left -= 1;
783           r_exitcodes[i] = status;
784         }
785     }
786
787   if (ec == 0)
788     for (i = 0; i < count; i++)
789       {
790         if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
791           {
792             log_error (_("error running '%s': probably not installed\n"),
793                        pgmnames[i]);
794             ec = GPG_ERR_CONFIGURATION;
795           }
796         else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
797           {
798             if (dummy)
799               log_error (_("error running '%s': exit status %d\n"),
800                          pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
801             else
802               r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
803             ec = GPG_ERR_GENERAL;
804           }
805         else if (!WIFEXITED (r_exitcodes[i]))
806           {
807             log_error (_("error running '%s': terminated\n"), pgmnames[i]);
808             ec = GPG_ERR_GENERAL;
809           }
810       }
811
812   xfree (dummy);
813   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
814 }
815
816 \f
817
818 void
819 gnupg_release_process (pid_t pid)
820 {
821   (void)pid;
822 }
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 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
834                               const char *envp[] )
835 {
836   pid_t pid;
837   int i;
838
839   if (getuid() != geteuid())
840     return my_error (GPG_ERR_BUG);
841
842   if (access (pgmname, X_OK))
843     return my_error_from_syserror ();
844
845   pid = fork ();
846   if (pid == (pid_t)(-1))
847     {
848       log_error (_("error forking process: %s\n"), strerror (errno));
849       return my_error_from_syserror ();
850     }
851   if (!pid)
852     {
853       pid_t pid2;
854
855       gcry_control (GCRYCTL_TERM_SECMEM);
856       if (setsid() == -1 || chdir ("/"))
857         _exit (1);
858
859       pid2 = fork (); /* Double fork to let init take over the new child. */
860       if (pid2 == (pid_t)(-1))
861         _exit (1);
862       if (pid2)
863         _exit (0);  /* Let the parent exit immediately. */
864
865       if (envp)
866         for (i=0; envp[i]; i++)
867           putenv (xstrdup (envp[i]));
868
869       do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
870
871       /*NOTREACHED*/
872     }
873
874   if (waitpid (pid, NULL, 0) == -1)
875     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
876                strerror (errno));
877
878   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 gnupg_kill_process (pid_t pid)
887 {
888   if (pid != (pid_t)(-1))
889     {
890       kill (pid, SIGTERM);
891     }
892 }