Re-indent code and use test macros for betetr readability
[gnupg.git] / common / exechelp.c
1 /* exechelp.c - fork and exec helpers
2  * Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <signal.h>
28 #include <unistd.h> 
29 #include <fcntl.h>
30
31 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
32 #undef HAVE_PTH
33 #undef USE_GNU_PTH
34 #endif
35
36 #ifdef USE_GNU_PTH      
37 #include <pth.h>
38 #endif
39 #ifndef HAVE_W32_SYSTEM
40 #include <sys/wait.h>
41 #endif
42
43 #ifdef HAVE_GETRLIMIT
44 #include <sys/time.h>
45 #include <sys/resource.h>
46 #endif /*HAVE_GETRLIMIT*/
47
48 #ifdef HAVE_STAT
49 # include <sys/stat.h>
50 #endif
51
52
53 #include "util.h"
54 #include "i18n.h"
55 #include "sysutils.h"
56 #include "exechelp.h"
57
58 /* Define to 1 do enable debugging.  */
59 #define DEBUG_W32_SPAWN 1
60
61
62 /* We have the usual problem here: Some modules are linked against pth
63    and some are not.  However we want to use pth_fork and pth_waitpid
64    here. Using a weak symbol works but is not portable - we should
65    provide a an explicit dummy pth module instead of using the
66    pragma.  */ 
67 #ifndef _WIN32
68 #pragma weak pth_fork
69 #pragma weak pth_waitpid
70 #endif
71
72 #ifdef HAVE_W32_SYSTEM
73 /* It seems Vista doesn't grok X_OK and so fails access() tests.
74    Previous versions interpreted X_OK as F_OK anyway, so we'll just
75    use F_OK directly. */
76 #undef X_OK
77 #define X_OK F_OK
78 #endif /* HAVE_W32_SYSTEM */
79
80
81 #ifdef HAVE_W32_SYSTEM
82 /* We assume that a HANDLE can be represented by an int which should
83    be true for all i386 systems (HANDLE is defined as void *) and
84    these are the only systems for which Windows is available.  Further
85    we assume that -1 denotes an invalid handle.  */
86 # define fd_to_handle(a)  ((HANDLE)(a))
87 # define handle_to_fd(a)  ((int)(a))
88 # define pid_to_handle(a) ((HANDLE)(a))
89 # define handle_to_pid(a) ((int)(a))
90 #endif
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 # ifdef RLIMIT_NOFILE
104   if (!getrlimit (RLIMIT_NOFILE, &rl))
105     max_fds = rl.rlim_max;
106 # endif
107
108 # ifdef RLIMIT_OFILE
109   if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
110     max_fds = rl.rlim_max;
111
112 # endif
113 #endif /*HAVE_GETRLIMIT*/
114
115 #ifdef _SC_OPEN_MAX
116   if (max_fds == -1)
117     {
118       long int scres = sysconf (_SC_OPEN_MAX);
119       if (scres >= 0)
120         max_fds = scres;
121     }
122 #endif
123
124 #ifdef _POSIX_OPEN_MAX
125   if (max_fds == -1)
126     max_fds = _POSIX_OPEN_MAX;
127 #endif
128
129 #ifdef OPEN_MAX
130   if (max_fds == -1)
131     max_fds = OPEN_MAX;
132 #endif
133
134   if (max_fds == -1)
135     max_fds = 256;  /* Arbitrary limit.  */
136
137   return max_fds;
138 }
139
140
141 /* Close all file descriptors starting with descriptor FIRST.  If
142    EXCEPT is not NULL, it is expected to be a list of file descriptors
143    which shall not be closed.  This list shall be sorted in ascending
144    order with the end marked by -1.  */
145 void
146 close_all_fds (int first, int *except)
147 {
148   int max_fd = get_max_fds ();
149   int fd, i, except_start;
150
151   if (except)
152     {
153       except_start = 0;
154       for (fd=first; fd < max_fd; fd++)
155         {
156           for (i=except_start; except[i] != -1; i++)
157             {
158               if (except[i] == fd)
159                 {
160                   /* If we found the descriptor in the exception list
161                      we can start the next compare run at the next
162                      index because the exception list is ordered.  */
163                 except_start = i + 1;
164                 break;
165                 }
166             }
167           if (except[i] == -1)
168             close (fd);
169         }
170     }
171   else
172     {
173       for (fd=first; fd < max_fd; fd++)
174         close (fd);
175     }
176
177   errno = 0;
178 }
179
180
181 /* Returns an array with all currently open file descriptors.  The end
182    of the array is marked by -1.  The caller needs to release this
183    array using the *standard free* and not with xfree.  This allow the
184    use of this fucntion right at startup even before libgcrypt has
185    been initialized.  Returns NULL on error and sets ERRNO
186    accordingly.  */
187 int *
188 get_all_open_fds (void)
189 {
190   int *array;
191   size_t narray;
192   int fd, max_fd, idx;
193 #ifndef HAVE_STAT
194   array = calloc (1, sizeof *array);
195   if (array)
196     array[0] = -1;
197 #else /*HAVE_STAT*/
198   struct stat statbuf;
199
200   max_fd = get_max_fds ();
201   narray = 32;  /* If you change this change also t-exechelp.c.  */
202   array = calloc (narray, sizeof *array);
203   if (!array)
204     return NULL;
205   
206   /* Note:  The list we return is ordered.  */
207   for (idx=0, fd=0; fd < max_fd; fd++)
208     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
209       {
210         if (idx+1 >= narray)
211           {
212             int *tmp;
213
214             narray += (narray < 256)? 32:256;
215             tmp = realloc (array, narray * sizeof *array);
216             if (!tmp)
217               {
218                 free (array);
219                 return NULL;
220               }
221             array = tmp;
222           }
223         array[idx++] = fd;
224       }
225   array[idx] = -1;
226 #endif /*HAVE_STAT*/
227   return array;
228 }
229
230
231
232 #ifdef HAVE_W32_SYSTEM
233 /* Helper function to build_w32_commandline. */
234 static char *
235 build_w32_commandline_copy (char *buffer, const char *string)
236 {
237   char *p = buffer;
238   const char *s;
239
240   if (!*string) /* Empty string. */
241     p = stpcpy (p, "\"\"");
242   else if (strpbrk (string, " \t\n\v\f\""))
243     {
244       /* Need top do some kind of quoting.  */
245       p = stpcpy (p, "\"");
246       for (s=string; *s; s++)
247         {
248           *p++ = *s;
249           if (*s == '\"')
250             *p++ = *s;
251         }
252       *p++ = '\"';
253       *p = 0;
254     }
255   else
256     p = stpcpy (p, string);
257
258   return p;
259 }
260
261 /* Build a command line for use with W32's CreateProcess.  On success
262    CMDLINE gets the address of a newly allocated string.  */
263 static gpg_error_t
264 build_w32_commandline (const char *pgmname, const char * const *argv, 
265                        char **cmdline)
266 {
267   int i, n;
268   const char *s;
269   char *buf, *p;
270
271   *cmdline = NULL;
272   n = 0;
273   s = pgmname;
274   n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
275   for (; *s; s++)
276     if (*s == '\"')
277       n++;  /* Need to double inner quotes.  */
278   for (i=0; (s=argv[i]); i++)
279     {
280       n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
281       for (; *s; s++)
282         if (*s == '\"')
283           n++;  /* Need to double inner quotes.  */
284     }
285   n++;
286
287   buf = p = xtrymalloc (n);
288   if (!buf)
289     return gpg_error_from_syserror ();
290
291   p = build_w32_commandline_copy (p, pgmname);
292   for (i=0; argv[i]; i++) 
293     {
294       *p++ = ' ';
295       p = build_w32_commandline_copy (p, argv[i]);
296     }
297
298   *cmdline= buf;
299   return 0;
300 }
301 #endif /*HAVE_W32_SYSTEM*/
302
303
304 #ifdef HAVE_W32_SYSTEM
305 /* Create  pipe where the write end is inheritable.  */
306 static int
307 create_inheritable_pipe (int filedes[2])
308 {
309   HANDLE r, w, h;
310   SECURITY_ATTRIBUTES sec_attr;
311
312   memset (&sec_attr, 0, sizeof sec_attr );
313   sec_attr.nLength = sizeof sec_attr;
314   sec_attr.bInheritHandle = FALSE;
315     
316   if (!CreatePipe (&r, &w, &sec_attr, 0))
317     return -1;
318
319   if (!DuplicateHandle (GetCurrentProcess(), w,
320                         GetCurrentProcess(), &h, 0,
321                         TRUE, DUPLICATE_SAME_ACCESS ))
322     {
323       log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
324       CloseHandle (r);
325       CloseHandle (w);
326       return -1;
327     }
328   CloseHandle (w);
329   w = h;
330
331   filedes[0] = handle_to_fd (r);
332   filedes[1] = handle_to_fd (w);
333   return 0;
334 }
335 #endif /*HAVE_W32_SYSTEM*/
336
337
338 #ifdef HAVE_W32_SYSTEM
339 static HANDLE
340 w32_open_null (int for_write)
341 {
342   HANDLE hfile;
343
344   hfile = CreateFile ("nul",
345                       for_write? GENERIC_WRITE : GENERIC_READ,
346                       FILE_SHARE_READ | FILE_SHARE_WRITE,
347                       NULL, OPEN_EXISTING, 0, NULL);
348   if (hfile == INVALID_HANDLE_VALUE)
349     log_debug ("can't open `nul': %s\n", w32_strerror (-1));
350   return hfile;
351 }
352 #endif /*HAVE_W32_SYSTEM*/
353
354
355 #ifndef HAVE_W32_SYSTEM
356 /* The exec core used right after the fork. This will never return. */
357 static void
358 do_exec (const char *pgmname, const char *argv[],
359          int fd_in, int fd_out, int fd_err,
360          void (*preexec)(void) )
361 {
362   char **arg_list;
363   int i, j;
364   int fds[3];
365
366   fds[0] = fd_in;
367   fds[1] = fd_out;
368   fds[2] = fd_err;
369
370   /* Create the command line argument array.  */
371   i = 0;
372   if (argv)
373     while (argv[i])
374       i++;
375   arg_list = xcalloc (i+2, sizeof *arg_list);
376   arg_list[0] = strrchr (pgmname, '/');
377   if (arg_list[0])
378     arg_list[0]++;
379   else
380     arg_list[0] = xstrdup (pgmname);
381   if (argv)
382     for (i=0,j=1; argv[i]; i++, j++)
383       arg_list[j] = (char*)argv[i];
384
385   /* Assign /dev/null to unused FDs. */
386   for (i=0; i <= 2; i++)
387     {
388       if (fds[i] == -1 )
389         {
390           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
391           if (fds[i] == -1)
392             log_fatal ("failed to open `%s': %s\n",
393                        "/dev/null", strerror (errno));
394         }
395     }
396
397   /* Connect the standard files.  */
398   for (i=0; i <= 2; i++)
399     {
400       if (fds[i] != i && dup2 (fds[i], i) == -1)
401         log_fatal ("dup2 std%s failed: %s\n",
402                    i==0?"in":i==1?"out":"err", strerror (errno));
403     }
404
405   /* Close all other files. */
406   close_all_fds (3, NULL);
407   
408   if (preexec)
409     preexec ();
410   execv (pgmname, arg_list);
411   /* No way to print anything, as we have closed all streams. */
412   _exit (127);
413 }
414 #endif /*!HAVE_W32_SYSTEM*/
415
416
417 /* Portable function to create a pipe.  Under Windows the write end is
418    inheritable.  */
419 gpg_error_t
420 gnupg_create_inbound_pipe (int filedes[2])
421 {
422   gpg_error_t err = 0;
423 #if HAVE_W32_SYSTEM
424   int fds[2];
425
426   filedes[0] = filedes[1] = -1;
427   err = gpg_error (GPG_ERR_GENERAL);
428   if (!create_inheritable_pipe (fds))
429     {
430       filedes[0] = _open_osfhandle (fds[0], 0);
431       if (filedes[0] == -1)
432         {
433           log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
434           CloseHandle (fd_to_handle (fds[1]));
435         }
436       else 
437         {
438           filedes[1] = _open_osfhandle (fds[1], 1);
439           if (filedes[1] == -1)
440             {
441               log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
442               close (filedes[0]);
443               filedes[0] = -1;
444               CloseHandle (fd_to_handle (fds[1]));
445             }
446           else
447             err = 0;
448         }
449     }
450 #else
451   if (pipe (filedes) == -1)
452     {
453       err = gpg_error_from_syserror ();
454       filedes[0] = filedes[1] = -1;
455     }
456 #endif
457   return err;
458 }
459
460
461 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
462    stdin, write the output to OUTFILE, return a new stream in
463    STATUSFILE for stderr and the pid of the process in PID. The
464    arguments for the process are expected in the NULL terminated array
465    ARGV.  The program name itself should not be included there.  If
466    PREEXEC is not NULL, that function will be called right before the
467    exec.  Calling gnupg_wait_process is required.
468
469    FLAGS is a bit vector with just one bit defined for now:
470
471    Bit 7: If set the process will be started as a background process.
472           This flag is only useful under W32 systems, so that no new
473           console is created and pops up a console window when
474           starting the server
475  
476    Bit 6: On W32 run AllowSetForegroundWindow for the child.  Due to
477           error problems this actually allows SetForegroundWindow for
478           childs of this process.
479
480    Returns 0 on success or an error code. */
481 gpg_error_t
482 gnupg_spawn_process (const char *pgmname, const char *argv[],
483                      FILE *infile, FILE *outfile,
484                      void (*preexec)(void), unsigned int flags,
485                      FILE **statusfile, pid_t *pid)
486 {
487 #ifdef HAVE_W32_SYSTEM
488   gpg_error_t err;
489   SECURITY_ATTRIBUTES sec_attr;
490   PROCESS_INFORMATION pi = 
491     {
492       NULL,      /* Returns process handle.  */
493       0,         /* Returns primary thread handle.  */
494       0,         /* Returns pid.  */
495       0          /* Returns tid.  */
496     };
497   STARTUPINFO si;
498   int cr_flags;
499   char *cmdline;
500   int fd, fdout, rp[2];
501
502   (void)preexec;
503
504   /* Setup return values.  */
505   *statusfile = NULL;
506   *pid = (pid_t)(-1);
507   fflush (infile);
508   rewind (infile);
509   fd = _get_osfhandle (fileno (infile));
510   fdout = _get_osfhandle (fileno (outfile));
511   if (fd == -1 || fdout == -1)
512     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
513
514   /* Prepare security attributes.  */
515   memset (&sec_attr, 0, sizeof sec_attr );
516   sec_attr.nLength = sizeof sec_attr;
517   sec_attr.bInheritHandle = FALSE;
518   
519   /* Build the command line.  */
520   err = build_w32_commandline (pgmname, argv, &cmdline);
521   if (err)
522     return err; 
523
524   /* Create a pipe.  */
525   if (create_inheritable_pipe (rp))
526     {
527       err = gpg_error (GPG_ERR_GENERAL);
528       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
529       xfree (cmdline);
530       return err;
531     }
532   
533   /* Start the process.  Note that we can't run the PREEXEC function
534      because this would change our own environment. */
535   memset (&si, 0, sizeof si);
536   si.cb = sizeof (si);
537   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
538   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
539   si.hStdInput  = fd_to_handle (fd);
540   si.hStdOutput = fd_to_handle (fdout);
541   si.hStdError  = fd_to_handle (rp[1]);
542
543   cr_flags = (CREATE_DEFAULT_ERROR_MODE
544               | ((flags & 128)? DETACHED_PROCESS : 0)
545               | GetPriorityClass (GetCurrentProcess ())
546               | CREATE_SUSPENDED); 
547 /*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
548   if (!CreateProcess (pgmname,       /* Program to start.  */
549                       cmdline,       /* Command line arguments.  */
550                       &sec_attr,     /* Process security attributes.  */
551                       &sec_attr,     /* Thread security attributes.  */
552                       TRUE,          /* Inherit handles.  */
553                       cr_flags,      /* Creation flags.  */
554                       NULL,          /* Environment.  */
555                       NULL,          /* Use current drive/directory.  */
556                       &si,           /* Startup information. */
557                       &pi            /* Returns process information.  */
558                       ))
559     {
560       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
561       xfree (cmdline);
562       CloseHandle (fd_to_handle (rp[0]));
563       CloseHandle (fd_to_handle (rp[1]));
564       return gpg_error (GPG_ERR_GENERAL);
565     }
566   xfree (cmdline);
567   cmdline = NULL;
568
569   /* Close the other end of the pipe.  */
570   CloseHandle (fd_to_handle (rp[1]));
571   
572 /*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
573 /*              " dwProcessID=%d dwThreadId=%d\n", */
574 /*              pi.hProcess, pi.hThread, */
575 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
576   
577   /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
578      invalid argument error if we pass the correct processID to
579      it.  As a workaround we use -1 (ASFW_ANY).  */
580   if ( (flags & 64) )
581     gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
582
583   /* Process has been created suspended; resume it now. */
584   ResumeThread (pi.hThread);
585   CloseHandle (pi.hThread); 
586
587   {
588     int x;
589
590     x = _open_osfhandle (rp[0], 0);
591     if (x == -1)
592       log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
593     else 
594       *statusfile = fdopen (x, "r");
595   }
596   if (!*statusfile)
597     {
598       err = gpg_error_from_syserror ();
599       log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
600       CloseHandle (pi.hProcess);
601       return err;
602     }
603
604   *pid = handle_to_pid (pi.hProcess);
605   return 0;
606
607 #else /* !HAVE_W32_SYSTEM */
608   gpg_error_t err;
609   int fd, fdout, rp[2];
610
611   (void)flags; /* Currently not used.  */
612
613   *statusfile = NULL;
614   *pid = (pid_t)(-1);
615   fflush (infile);
616   rewind (infile);
617   fd = fileno (infile);
618   fdout = fileno (outfile);
619   if (fd == -1 || fdout == -1)
620     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
621
622   if (pipe (rp) == -1)
623     {
624       err = gpg_error_from_syserror ();
625       log_error (_("error creating a pipe: %s\n"), strerror (errno));
626       return err;
627     }
628
629 #ifdef USE_GNU_PTH      
630   *pid = pth_fork? pth_fork () : fork ();
631 #else
632   *pid = fork ();
633 #endif
634   if (*pid == (pid_t)(-1))
635     {
636       err = gpg_error_from_syserror ();
637       log_error (_("error forking process: %s\n"), strerror (errno));
638       close (rp[0]);
639       close (rp[1]);
640       return err;
641     }
642
643   if (!*pid)
644     { 
645       gcry_control (GCRYCTL_TERM_SECMEM);
646       /* Run child. */
647       do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
648       /*NOTREACHED*/
649     }
650
651   /* Parent. */
652   close (rp[1]);
653
654   *statusfile = fdopen (rp[0], "r");
655   if (!*statusfile)
656     {
657       err = gpg_error_from_syserror ();
658       log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
659       kill (*pid, SIGTERM);
660       *pid = (pid_t)(-1);
661       return err;
662     }
663
664   return 0;
665 #endif /* !HAVE_W32_SYSTEM */
666 }
667
668
669
670 /* Simplified version of gnupg_spawn_process.  This function forks and
671    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
672    and ERRFD to stderr (any of them may be -1 to connect them to
673    /dev/null).  The arguments for the process are expected in the NULL
674    terminated array ARGV.  The program name itself should not be
675    included there.  Calling gnupg_wait_process is required.
676
677    Returns 0 on success or an error code. */
678 gpg_error_t
679 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
680                         int infd, int outfd, int errfd, pid_t *pid)
681 {
682 #ifdef HAVE_W32_SYSTEM
683   gpg_error_t err;
684   SECURITY_ATTRIBUTES sec_attr;
685   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
686   STARTUPINFO si;
687   char *cmdline;
688   int i;
689   HANDLE stdhd[3];
690
691   /* Setup return values.  */
692   *pid = (pid_t)(-1);
693
694   /* Prepare security attributes.  */
695   memset (&sec_attr, 0, sizeof sec_attr );
696   sec_attr.nLength = sizeof sec_attr;
697   sec_attr.bInheritHandle = FALSE;
698   
699   /* Build the command line.  */
700   err = build_w32_commandline (pgmname, argv, &cmdline);
701   if (err)
702     return err; 
703
704   memset (&si, 0, sizeof si);
705   si.cb = sizeof (si);
706   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
707   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
708   stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
709   stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
710   stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
711   si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
712   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
713   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
714
715 /*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
716   if (!CreateProcess (pgmname,       /* Program to start.  */
717                       cmdline,       /* Command line arguments.  */
718                       &sec_attr,     /* Process security attributes.  */
719                       &sec_attr,     /* Thread security attributes.  */
720                       TRUE,          /* Inherit handles.  */
721                       (CREATE_DEFAULT_ERROR_MODE
722                        | GetPriorityClass (GetCurrentProcess ())
723                        | CREATE_SUSPENDED | DETACHED_PROCESS),
724                       NULL,          /* Environment.  */
725                       NULL,          /* Use current drive/directory.  */
726                       &si,           /* Startup information. */
727                       &pi            /* Returns process information.  */
728                       ))
729     {
730       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
731       err = gpg_error (GPG_ERR_GENERAL);
732     }
733   else
734     err = 0;
735   xfree (cmdline);
736   for (i=0; i < 3; i++)
737     if (stdhd[i] != INVALID_HANDLE_VALUE)
738       CloseHandle (stdhd[i]);
739   if (err)
740     return err;
741
742 /*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
743 /*              " dwProcessID=%d dwThreadId=%d\n", */
744 /*              pi.hProcess, pi.hThread, */
745 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
746
747   /* Process has been created suspended; resume it now. */
748   ResumeThread (pi.hThread);
749   CloseHandle (pi.hThread); 
750
751   *pid = handle_to_pid (pi.hProcess);
752   return 0;
753
754 #else /* !HAVE_W32_SYSTEM */
755   gpg_error_t err;
756
757 #ifdef USE_GNU_PTH      
758   *pid = pth_fork? pth_fork () : fork ();
759 #else
760   *pid = fork ();
761 #endif
762   if (*pid == (pid_t)(-1))
763     {
764       err = gpg_error_from_syserror ();
765       log_error (_("error forking process: %s\n"), strerror (errno));
766       return err;
767     }
768
769   if (!*pid)
770     { 
771       gcry_control (GCRYCTL_TERM_SECMEM);
772       /* Run child. */
773       do_exec (pgmname, argv, infd, outfd, errfd, NULL);
774       /*NOTREACHED*/
775     }
776
777   return 0;
778 #endif /* !HAVE_W32_SYSTEM */
779 }
780
781
782 /* Wait for the process identified by PID to terminate. PGMNAME should
783    be the same as supplied to the spawn function and is only used for
784    diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
785    for any failures of the spawned program or other error codes.  If
786    EXITCODE is not NULL the exit code of the process is stored at this
787    address or -1 if it could not be retrieved. */
788 gpg_error_t
789 gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
790 {
791   gpg_err_code_t ec;
792
793 #ifdef HAVE_W32_SYSTEM
794   HANDLE proc = fd_to_handle (pid);
795   int code;
796   DWORD exc;
797
798   if (exitcode)
799     *exitcode = -1;
800
801   if (pid == (pid_t)(-1))
802     return gpg_error (GPG_ERR_INV_VALUE);
803
804   /* FIXME: We should do a pth_waitpid here.  However this has not yet
805      been implemented.  A special W32 pth system call would even be
806      better.  */
807   code = WaitForSingleObject (proc, INFINITE);
808   switch (code) 
809     {
810       case WAIT_FAILED:
811         log_error (_("waiting for process %d to terminate failed: %s\n"),
812                    (int)pid, w32_strerror (-1));
813         ec = GPG_ERR_GENERAL;
814         break;
815
816       case WAIT_OBJECT_0:
817         if (!GetExitCodeProcess (proc, &exc))
818           {
819             log_error (_("error getting exit code of process %d: %s\n"),
820                          (int)pid, w32_strerror (-1) );
821             ec = GPG_ERR_GENERAL;
822           }
823         else if (exc)
824           {
825             log_error (_("error running `%s': exit status %d\n"),
826                        pgmname, (int)exc );
827             if (exitcode)
828               *exitcode = (int)exc;
829             ec = GPG_ERR_GENERAL;
830           }
831         else
832           {
833             if (exitcode)
834               *exitcode = 0;
835             ec = 0;
836           }
837         CloseHandle (proc);
838         break;
839
840       default:
841         log_error ("WaitForSingleObject returned unexpected "
842                    "code %d for pid %d\n", code, (int)pid );
843         ec = GPG_ERR_GENERAL;
844         break;
845     }
846
847 #else /* !HAVE_W32_SYSTEM */
848   int i, status;
849
850   if (exitcode)
851     *exitcode = -1;
852
853   if (pid == (pid_t)(-1))
854     return gpg_error (GPG_ERR_INV_VALUE);
855
856 #ifdef USE_GNU_PTH
857   i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0);
858 #else
859   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
860     ;
861 #endif
862   if (i == (pid_t)(-1))
863     {
864       log_error (_("waiting for process %d to terminate failed: %s\n"),
865                  (int)pid, strerror (errno));
866       ec = gpg_err_code_from_errno (errno);
867     }
868   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
869     {
870       log_error (_("error running `%s': probably not installed\n"), pgmname);
871       ec = GPG_ERR_CONFIGURATION;
872     }
873   else if (WIFEXITED (status) && WEXITSTATUS (status))
874     {
875       
876       if (!exitcode)
877         log_error (_("error running `%s': exit status %d\n"), pgmname,
878                    WEXITSTATUS (status));
879       else
880         *exitcode = WEXITSTATUS (status);
881       ec = GPG_ERR_GENERAL;
882     }
883   else if (!WIFEXITED (status))
884     {
885       log_error (_("error running `%s': terminated\n"), pgmname);
886       ec = GPG_ERR_GENERAL;
887     }
888   else 
889     {
890       if (exitcode)
891         *exitcode = 0;
892       ec = 0;
893     }
894 #endif /* !HAVE_W32_SYSTEM */
895
896   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
897 }
898
899
900 /* Spawn a new process and immediatley detach from it.  The name of
901    the program to exec is PGMNAME and its arguments are in ARGV (the
902    programname is automatically passed as first argument).
903    Environment strings in ENVP are set.  An error is returned if
904    pgmname is not executable; to make this work it is necessary to
905    provide an absolute file name.  All standard file descriptors are
906    connected to /dev/null. */
907 gpg_error_t
908 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
909                               const char *envp[] )
910 {
911 #ifdef HAVE_W32_SYSTEM
912   gpg_error_t err;
913   SECURITY_ATTRIBUTES sec_attr;
914   PROCESS_INFORMATION pi = 
915     {
916       NULL,      /* Returns process handle.  */
917       0,         /* Returns primary thread handle.  */
918       0,         /* Returns pid.  */
919       0          /* Returns tid.  */
920     };
921   STARTUPINFO si;
922   int cr_flags;
923   char *cmdline;
924
925
926   /* FIXME: We don't make use of ENVP yet.  It is currently only used
927      to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
928      on windows is to use a standard socket, this does not really
929      matter.  */
930   (void)envp;
931
932   if (access (pgmname, X_OK))
933     return gpg_error_from_syserror ();
934
935   /* Prepare security attributes.  */
936   memset (&sec_attr, 0, sizeof sec_attr );
937   sec_attr.nLength = sizeof sec_attr;
938   sec_attr.bInheritHandle = FALSE;
939   
940   /* Build the command line.  */
941   err = build_w32_commandline (pgmname, argv, &cmdline);
942   if (err)
943     return err; 
944
945   /* Start the process.  */
946   memset (&si, 0, sizeof si);
947   si.cb = sizeof (si);
948   si.dwFlags = STARTF_USESHOWWINDOW;
949   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
950
951   cr_flags = (CREATE_DEFAULT_ERROR_MODE
952               | GetPriorityClass (GetCurrentProcess ())
953               | CREATE_NEW_PROCESS_GROUP
954               | DETACHED_PROCESS); 
955 /*   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
956 /*              pgmname, cmdline); */
957   if (!CreateProcess (pgmname,       /* Program to start.  */
958                       cmdline,       /* Command line arguments.  */
959                       &sec_attr,     /* Process security attributes.  */
960                       &sec_attr,     /* Thread security attributes.  */
961                       FALSE,         /* Inherit handles.  */
962                       cr_flags,      /* Creation flags.  */
963                       NULL,          /* Environment.  */
964                       NULL,          /* Use current drive/directory.  */
965                       &si,           /* Startup information. */
966                       &pi            /* Returns process information.  */
967                       ))
968     {
969       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
970       xfree (cmdline);
971       return gpg_error (GPG_ERR_GENERAL);
972     }
973   xfree (cmdline);
974   cmdline = NULL;
975
976 /*   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
977 /*              " dwProcessID=%d dwThreadId=%d\n", */
978 /*              pi.hProcess, pi.hThread, */
979 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
980
981   CloseHandle (pi.hThread); 
982
983   return 0;
984
985 #else
986   pid_t pid;
987   int i;
988
989   if (getuid() != geteuid())
990     return gpg_error (GPG_ERR_BUG);
991
992   if (access (pgmname, X_OK))
993     return gpg_error_from_syserror ();
994
995 #ifdef USE_GNU_PTH      
996   pid = pth_fork? pth_fork () : fork ();
997 #else
998   pid = fork ();
999 #endif
1000   if (pid == (pid_t)(-1))
1001     {
1002       log_error (_("error forking process: %s\n"), strerror (errno));
1003       return gpg_error_from_syserror ();
1004     }
1005   if (!pid)
1006     {
1007       pid_t pid2; 
1008
1009       gcry_control (GCRYCTL_TERM_SECMEM);
1010       if (setsid() == -1 || chdir ("/"))
1011         _exit (1);
1012       pid2 = fork (); /* Double fork to let init takes over the new child. */
1013       if (pid2 == (pid_t)(-1))
1014         _exit (1);
1015       if (pid2)
1016         _exit (0);  /* Let the parent exit immediately. */
1017
1018       if (envp)
1019         for (i=0; envp[i]; i++)
1020           putenv (xstrdup (envp[i]));
1021       
1022       do_exec (pgmname, argv, -1, -1, -1, NULL);
1023
1024       /*NOTREACHED*/
1025     }
1026   
1027   if (waitpid (pid, NULL, 0) == -1)
1028     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
1029                strerror (errno));
1030
1031   return 0;
1032 #endif /* !HAVE_W32_SYSTEM*/
1033 }