Fix gpg-preset-passphrase bug.
[gnupg.git] / common / exechelp.c
1 /* exechelp.c - fork and exec helpers
2  *      Copyright (C) 2004, 2007, 2008 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 #include "util.h"
44 #include "i18n.h"
45 #include "exechelp.h"
46
47 /* Define to 1 do enable debugging.  */
48 #define DEBUG_W32_SPAWN 1
49
50
51 #ifdef _POSIX_OPEN_MAX
52 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
53 #else
54 #define MAX_OPEN_FDS 20
55 #endif
56
57 /* We have the usual problem here: Some modules are linked against pth
58    and some are not.  However we want to use pth_fork and pth_waitpid
59    here. Using a weak symbol works but is not portable - we should
60    provide a an explicit dummy pth module instead of using the
61    pragma.  */ 
62 #ifndef _WIN32
63 #pragma weak pth_fork
64 #pragma weak pth_waitpid
65 #endif
66
67 #ifdef HAVE_W32_SYSTEM
68 /* It seems Vista doesn't grok X_OK and so fails access() tests.
69    Previous versions interpreted X_OK as F_OK anyway, so we'll just
70    use F_OK directly. */
71 #undef X_OK
72 #define X_OK F_OK
73 #endif /* HAVE_W32_SYSTEM */
74
75
76 #ifdef HAVE_W32_SYSTEM
77 /* We assume that a HANDLE can be represented by an int which should
78    be true for all i386 systems (HANDLE is defined as void *) and
79    these are the only systems for which Windows is available.  Further
80    we assume that -1 denotes an invalid handle.  */
81 # define fd_to_handle(a)  ((HANDLE)(a))
82 # define handle_to_fd(a)  ((int)(a))
83 # define pid_to_handle(a) ((HANDLE)(a))
84 # define handle_to_pid(a) ((int)(a))
85 #endif
86
87
88 #ifdef HAVE_W32_SYSTEM
89 /* Helper function to build_w32_commandline. */
90 static char *
91 build_w32_commandline_copy (char *buffer, const char *string)
92 {
93   char *p = buffer;
94   const char *s;
95
96   if (!*string) /* Empty string. */
97     p = stpcpy (p, "\"\"");
98   else if (strpbrk (string, " \t\n\v\f\""))
99     {
100       /* Need top do some kind of quoting.  */
101       p = stpcpy (p, "\"");
102       for (s=string; *s; s++)
103         {
104           *p++ = *s;
105           if (*s == '\"')
106             *p++ = *s;
107         }
108       *p++ = '\"';
109       *p = 0;
110     }
111   else
112     p = stpcpy (p, string);
113
114   return p;
115 }
116
117 /* Build a command line for use with W32's CreateProcess.  On success
118    CMDLINE gets the address of a newly allocated string.  */
119 static gpg_error_t
120 build_w32_commandline (const char *pgmname, const char * const *argv, 
121                        char **cmdline)
122 {
123   int i, n;
124   const char *s;
125   char *buf, *p;
126
127   *cmdline = NULL;
128   n = 0;
129   s = pgmname;
130   n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
131   for (; *s; s++)
132     if (*s == '\"')
133       n++;  /* Need to double inner quotes.  */
134   for (i=0; (s=argv[i]); i++)
135     {
136       n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
137       for (; *s; s++)
138         if (*s == '\"')
139           n++;  /* Need to double inner quotes.  */
140     }
141   n++;
142
143   buf = p = xtrymalloc (n);
144   if (!buf)
145     return gpg_error_from_syserror ();
146
147   p = build_w32_commandline_copy (p, pgmname);
148   for (i=0; argv[i]; i++) 
149     {
150       *p++ = ' ';
151       p = build_w32_commandline_copy (p, argv[i]);
152     }
153
154   *cmdline= buf;
155   return 0;
156 }
157 #endif /*HAVE_W32_SYSTEM*/
158
159
160 #ifdef HAVE_W32_SYSTEM
161 /* Create  pipe where the write end is inheritable.  */
162 static int
163 create_inheritable_pipe (int filedes[2])
164 {
165   HANDLE r, w, h;
166   SECURITY_ATTRIBUTES sec_attr;
167
168   memset (&sec_attr, 0, sizeof sec_attr );
169   sec_attr.nLength = sizeof sec_attr;
170   sec_attr.bInheritHandle = FALSE;
171     
172   if (!CreatePipe (&r, &w, &sec_attr, 0))
173     return -1;
174
175   if (!DuplicateHandle (GetCurrentProcess(), w,
176                         GetCurrentProcess(), &h, 0,
177                         TRUE, DUPLICATE_SAME_ACCESS ))
178     {
179       log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
180       CloseHandle (r);
181       CloseHandle (w);
182       return -1;
183     }
184   CloseHandle (w);
185   w = h;
186
187   filedes[0] = handle_to_fd (r);
188   filedes[1] = handle_to_fd (w);
189   return 0;
190 }
191 #endif /*HAVE_W32_SYSTEM*/
192
193
194 #ifdef HAVE_W32_SYSTEM
195 static HANDLE
196 w32_open_null (int for_write)
197 {
198   HANDLE hfile;
199
200   hfile = CreateFile ("nul",
201                       for_write? GENERIC_WRITE : GENERIC_READ,
202                       FILE_SHARE_READ | FILE_SHARE_WRITE,
203                       NULL, OPEN_EXISTING, 0, NULL);
204   if (hfile == INVALID_HANDLE_VALUE)
205     log_debug ("can't open `nul': %s\n", w32_strerror (-1));
206   return hfile;
207 }
208 #endif /*HAVE_W32_SYSTEM*/
209
210
211 #ifndef HAVE_W32_SYSTEM
212 /* The exec core used right after the fork. This will never return. */
213 static void
214 do_exec (const char *pgmname, const char *argv[],
215          int fd_in, int fd_out, int fd_err,
216          void (*preexec)(void) )
217 {
218   char **arg_list;
219   int n, i, j;
220   int fds[3];
221
222   fds[0] = fd_in;
223   fds[1] = fd_out;
224   fds[2] = fd_err;
225
226   /* Create the command line argument array.  */
227   i = 0;
228   if (argv)
229     while (argv[i])
230       i++;
231   arg_list = xcalloc (i+2, sizeof *arg_list);
232   arg_list[0] = strrchr (pgmname, '/');
233   if (arg_list[0])
234     arg_list[0]++;
235   else
236     arg_list[0] = xstrdup (pgmname);
237   if (argv)
238     for (i=0,j=1; argv[i]; i++, j++)
239       arg_list[j] = (char*)argv[i];
240
241   /* Connect the standard files. */
242   for (i=0; i <= 2; i++)
243     {
244       if (fds[i] == -1 )
245         {
246           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
247           if (fds[i] == -1)
248             log_fatal ("failed to open `%s': %s\n",
249                        "/dev/null", strerror (errno));
250         }
251       else if (fds[i] != i && dup2 (fds[i], i) == -1)
252         log_fatal ("dup2 std%s failed: %s\n",
253                    i==0?"in":i==1?"out":"err", strerror (errno));
254     }
255
256   /* Close all other files. */
257   n = sysconf (_SC_OPEN_MAX);
258   if (n < 0)
259     n = MAX_OPEN_FDS;
260   for (i=3; i < n; i++)
261     close(i);
262   errno = 0;
263   
264   if (preexec)
265     preexec ();
266   execv (pgmname, arg_list);
267   /* No way to print anything, as we have closed all streams. */
268   _exit (127);
269 }
270 #endif /*!HAVE_W32_SYSTEM*/
271
272
273 /* Portable function to create a pipe.  Under Windows the write end is
274    inheritable.  */
275 gpg_error_t
276 gnupg_create_inbound_pipe (int filedes[2])
277 {
278   gpg_error_t err = 0;
279 #if HAVE_W32_SYSTEM
280   int fds[2];
281
282   filedes[0] = filedes[1] = -1;
283   err = gpg_error (GPG_ERR_GENERAL);
284   if (!create_inheritable_pipe (fds))
285     {
286       filedes[0] = _open_osfhandle (fds[0], 0);
287       if (filedes[0] == -1)
288         {
289           log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
290           CloseHandle (fd_to_handle (fds[1]));
291         }
292       else 
293         {
294           filedes[1] = _open_osfhandle (fds[1], 1);
295           if (filedes[1] == -1)
296             {
297               log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
298               close (filedes[0]);
299               filedes[0] = -1;
300               CloseHandle (fd_to_handle (fds[1]));
301             }
302           else
303             err = 0;
304         }
305     }
306 #else
307   if (pipe (filedes) == -1)
308     {
309       err = gpg_error_from_syserror ();
310       filedes[0] = filedes[1] = -1;
311     }
312 #endif
313   return err;
314 }
315
316
317 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
318    stdin, write the output to OUTFILE, return a new stream in
319    STATUSFILE for stderr and the pid of the process in PID. The
320    arguments for the process are expected in the NULL terminated array
321    ARGV.  The program name itself should not be included there.  If
322    PREEXEC is not NULL, that function will be called right before the
323    exec.  Calling gnupg_wait_process is required.
324
325    FLAGS is a bit vector with just one bit defined for now:
326
327    Bit 7: If set the process will be started as a background process.
328           This flag is only useful under W32 systems, so that no new
329           console is created and pops up a console window when
330           starting the server
331
332    Returns 0 on success or an error code. */
333 gpg_error_t
334 gnupg_spawn_process (const char *pgmname, const char *argv[],
335                      FILE *infile, FILE *outfile,
336                      void (*preexec)(void), unsigned int flags,
337                      FILE **statusfile, pid_t *pid)
338 {
339 #ifdef HAVE_W32_SYSTEM
340   gpg_error_t err;
341   SECURITY_ATTRIBUTES sec_attr;
342   PROCESS_INFORMATION pi = 
343     {
344       NULL,      /* Returns process handle.  */
345       0,         /* Returns primary thread handle.  */
346       0,         /* Returns pid.  */
347       0          /* Returns tid.  */
348     };
349   STARTUPINFO si;
350   int cr_flags;
351   char *cmdline;
352   int fd, fdout, rp[2];
353
354   /* Setup return values.  */
355   *statusfile = NULL;
356   *pid = (pid_t)(-1);
357   fflush (infile);
358   rewind (infile);
359   fd = _get_osfhandle (fileno (infile));
360   fdout = _get_osfhandle (fileno (outfile));
361   if (fd == -1 || fdout == -1)
362     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
363
364   /* Prepare security attributes.  */
365   memset (&sec_attr, 0, sizeof sec_attr );
366   sec_attr.nLength = sizeof sec_attr;
367   sec_attr.bInheritHandle = FALSE;
368   
369   /* Build the command line.  */
370   err = build_w32_commandline (pgmname, argv, &cmdline);
371   if (err)
372     return err; 
373
374   /* Create a pipe.  */
375   if (create_inheritable_pipe (rp))
376     {
377       err = gpg_error (GPG_ERR_GENERAL);
378       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
379       xfree (cmdline);
380       return err;
381     }
382   
383   /* Start the process.  Note that we can't run the PREEXEC function
384      because this would change our own environment. */
385   memset (&si, 0, sizeof si);
386   si.cb = sizeof (si);
387   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
388   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
389   si.hStdInput  = fd_to_handle (fd);
390   si.hStdOutput = fd_to_handle (fdout);
391   si.hStdError  = fd_to_handle (rp[1]);
392
393   cr_flags = (CREATE_DEFAULT_ERROR_MODE
394               | ((flags & 128)? DETACHED_PROCESS : 0)
395               | GetPriorityClass (GetCurrentProcess ())
396               | CREATE_SUSPENDED); 
397   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
398   if (!CreateProcess (pgmname,       /* Program to start.  */
399                       cmdline,       /* Command line arguments.  */
400                       &sec_attr,     /* Process security attributes.  */
401                       &sec_attr,     /* Thread security attributes.  */
402                       TRUE,          /* Inherit handles.  */
403                       cr_flags,      /* Creation flags.  */
404                       NULL,          /* Environment.  */
405                       NULL,          /* Use current drive/directory.  */
406                       &si,           /* Startup information. */
407                       &pi            /* Returns process information.  */
408                       ))
409     {
410       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
411       xfree (cmdline);
412       CloseHandle (fd_to_handle (rp[0]));
413       CloseHandle (fd_to_handle (rp[1]));
414       return gpg_error (GPG_ERR_GENERAL);
415     }
416   xfree (cmdline);
417   cmdline = NULL;
418
419   /* Close the other end of the pipe.  */
420   CloseHandle (fd_to_handle (rp[1]));
421   
422   log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
423              " dwProcessID=%d dwThreadId=%d\n",
424              pi.hProcess, pi.hThread,
425              (int) pi.dwProcessId, (int) pi.dwThreadId);
426
427   /* Process has been created suspended; resume it now. */
428   ResumeThread (pi.hThread);
429   CloseHandle (pi.hThread); 
430
431   {
432     int x;
433
434     x = _open_osfhandle (rp[0], 0);
435     if (x == -1)
436       log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
437     else 
438       *statusfile = fdopen (x, "r");
439   }
440   if (!*statusfile)
441     {
442       err = gpg_error_from_syserror ();
443       log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
444       CloseHandle (pi.hProcess);
445       return err;
446     }
447
448   *pid = handle_to_pid (pi.hProcess);
449   return 0;
450
451 #else /* !HAVE_W32_SYSTEM */
452   gpg_error_t err;
453   int fd, fdout, rp[2];
454
455   *statusfile = NULL;
456   *pid = (pid_t)(-1);
457   fflush (infile);
458   rewind (infile);
459   fd = fileno (infile);
460   fdout = fileno (outfile);
461   if (fd == -1 || fdout == -1)
462     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
463
464   if (pipe (rp) == -1)
465     {
466       err = gpg_error_from_syserror ();
467       log_error (_("error creating a pipe: %s\n"), strerror (errno));
468       return err;
469     }
470
471 #ifdef USE_GNU_PTH      
472   *pid = pth_fork? pth_fork () : fork ();
473 #else
474   *pid = fork ();
475 #endif
476   if (*pid == (pid_t)(-1))
477     {
478       err = gpg_error_from_syserror ();
479       log_error (_("error forking process: %s\n"), strerror (errno));
480       close (rp[0]);
481       close (rp[1]);
482       return err;
483     }
484
485   if (!*pid)
486     { 
487       gcry_control (GCRYCTL_TERM_SECMEM);
488       /* Run child. */
489       do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
490       /*NOTREACHED*/
491     }
492
493   /* Parent. */
494   close (rp[1]);
495
496   *statusfile = fdopen (rp[0], "r");
497   if (!*statusfile)
498     {
499       err = gpg_error_from_syserror ();
500       log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
501       kill (*pid, SIGTERM);
502       *pid = (pid_t)(-1);
503       return err;
504     }
505
506   return 0;
507 #endif /* !HAVE_W32_SYSTEM */
508 }
509
510
511
512 /* Simplified version of gnupg_spawn_process.  This function forks and
513    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
514    and ERRFD to stderr (any of them may be -1 to connect them to
515    /dev/null).  The arguments for the process are expected in the NULL
516    terminated array ARGV.  The program name itself should not be
517    included there.  Calling gnupg_wait_process is required.
518
519    Returns 0 on success or an error code. */
520 gpg_error_t
521 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
522                         int infd, int outfd, int errfd, pid_t *pid)
523 {
524 #ifdef HAVE_W32_SYSTEM
525   gpg_error_t err;
526   SECURITY_ATTRIBUTES sec_attr;
527   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
528   STARTUPINFO si;
529   char *cmdline;
530   int i;
531   HANDLE stdhd[3];
532
533   /* Setup return values.  */
534   *pid = (pid_t)(-1);
535
536   /* Prepare security attributes.  */
537   memset (&sec_attr, 0, sizeof sec_attr );
538   sec_attr.nLength = sizeof sec_attr;
539   sec_attr.bInheritHandle = FALSE;
540   
541   /* Build the command line.  */
542   err = build_w32_commandline (pgmname, argv, &cmdline);
543   if (err)
544     return err; 
545
546   memset (&si, 0, sizeof si);
547   si.cb = sizeof (si);
548   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
549   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
550   stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
551   stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
552   stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
553   si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
554   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
555   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
556
557   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
558   if (!CreateProcess (pgmname,       /* Program to start.  */
559                       cmdline,       /* Command line arguments.  */
560                       &sec_attr,     /* Process security attributes.  */
561                       &sec_attr,     /* Thread security attributes.  */
562                       TRUE,          /* Inherit handles.  */
563                       (CREATE_DEFAULT_ERROR_MODE
564                        | GetPriorityClass (GetCurrentProcess ())
565                        | CREATE_SUSPENDED | DETACHED_PROCESS),
566                       NULL,          /* Environment.  */
567                       NULL,          /* Use current drive/directory.  */
568                       &si,           /* Startup information. */
569                       &pi            /* Returns process information.  */
570                       ))
571     {
572       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
573       err = gpg_error (GPG_ERR_GENERAL);
574     }
575   else
576     err = 0;
577   xfree (cmdline);
578   for (i=0; i < 3; i++)
579     if (stdhd[i] != INVALID_HANDLE_VALUE)
580       CloseHandle (stdhd[i]);
581   if (err)
582     return err;
583
584   log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
585              " dwProcessID=%d dwThreadId=%d\n",
586              pi.hProcess, pi.hThread,
587              (int) pi.dwProcessId, (int) pi.dwThreadId);
588
589   /* Process has been created suspended; resume it now. */
590   ResumeThread (pi.hThread);
591   CloseHandle (pi.hThread); 
592
593   *pid = handle_to_pid (pi.hProcess);
594   return 0;
595
596 #else /* !HAVE_W32_SYSTEM */
597   gpg_error_t err;
598
599 #ifdef USE_GNU_PTH      
600   *pid = pth_fork? pth_fork () : fork ();
601 #else
602   *pid = fork ();
603 #endif
604   if (*pid == (pid_t)(-1))
605     {
606       err = gpg_error_from_syserror ();
607       log_error (_("error forking process: %s\n"), strerror (errno));
608       return err;
609     }
610
611   if (!*pid)
612     { 
613       gcry_control (GCRYCTL_TERM_SECMEM);
614       /* Run child. */
615       do_exec (pgmname, argv, infd, outfd, errfd, NULL);
616       /*NOTREACHED*/
617     }
618
619   return 0;
620 #endif /* !HAVE_W32_SYSTEM */
621 }
622
623
624 /* Wait for the process identified by PID to terminate. PGMNAME should
625    be the same as supplied to the spawn function and is only used for
626    diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
627    for any failures of the spawned program or other error codes.  If
628    EXITCODE is not NULL the exit code of the process is stored at this
629    address or -1 if it could not be retrieved. */
630 gpg_error_t
631 gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
632 {
633   gpg_err_code_t ec;
634
635 #ifdef HAVE_W32_SYSTEM
636   HANDLE proc = fd_to_handle (pid);
637   int code;
638   DWORD exc;
639
640   if (exitcode)
641     *exitcode = -1;
642
643   if (pid == (pid_t)(-1))
644     return gpg_error (GPG_ERR_INV_VALUE);
645
646   /* FIXME: We should do a pth_waitpid here.  However this has not yet
647      been implemented.  A special W32 pth system call would even be
648      better.  */
649   code = WaitForSingleObject (proc, INFINITE);
650   switch (code) 
651     {
652       case WAIT_FAILED:
653         log_error (_("waiting for process %d to terminate failed: %s\n"),
654                    (int)pid, w32_strerror (-1));
655         ec = GPG_ERR_GENERAL;
656         break;
657
658       case WAIT_OBJECT_0:
659         if (!GetExitCodeProcess (proc, &exc))
660           {
661             log_error (_("error getting exit code of process %d: %s\n"),
662                          (int)pid, w32_strerror (-1) );
663             ec = GPG_ERR_GENERAL;
664           }
665         else if (exc)
666           {
667             log_error (_("error running `%s': exit status %d\n"),
668                        pgmname, (int)exc );
669             if (exitcode)
670               *exitcode = (int)exc;
671             ec = GPG_ERR_GENERAL;
672           }
673         else
674           {
675             if (exitcode)
676               *exitcode = 0;
677             ec = 0;
678           }
679         CloseHandle (proc);
680         break;
681
682       default:
683         log_error ("WaitForSingleObject returned unexpected "
684                    "code %d for pid %d\n", code, (int)pid );
685         ec = GPG_ERR_GENERAL;
686         break;
687     }
688
689 #else /* !HAVE_W32_SYSTEM */
690   int i, status;
691
692   if (exitcode)
693     *exitcode = -1;
694
695   if (pid == (pid_t)(-1))
696     return gpg_error (GPG_ERR_INV_VALUE);
697
698 #ifdef USE_GNU_PTH
699   i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0);
700 #else
701   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
702     ;
703 #endif
704   if (i == (pid_t)(-1))
705     {
706       log_error (_("waiting for process %d to terminate failed: %s\n"),
707                  (int)pid, strerror (errno));
708       ec = gpg_err_code_from_errno (errno);
709     }
710   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
711     {
712       log_error (_("error running `%s': probably not installed\n"), pgmname);
713       ec = GPG_ERR_CONFIGURATION;
714     }
715   else if (WIFEXITED (status) && WEXITSTATUS (status))
716     {
717       log_error (_("error running `%s': exit status %d\n"), pgmname,
718                  WEXITSTATUS (status));
719       if (exitcode)
720         *exitcode = WEXITSTATUS (status);
721       ec = GPG_ERR_GENERAL;
722     }
723   else if (!WIFEXITED (status))
724     {
725       log_error (_("error running `%s': terminated\n"), pgmname);
726       ec = GPG_ERR_GENERAL;
727     }
728   else 
729     {
730       if (exitcode)
731         *exitcode = 0;
732       ec = 0;
733     }
734 #endif /* !HAVE_W32_SYSTEM */
735
736   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
737 }
738
739
740 /* Spawn a new process and immediatley detach from it.  The name of
741    the program to exec is PGMNAME and its arguments are in ARGV (the
742    programname is automatically passed as first argument).
743    Environment strings in ENVP are set.  An error is returned if
744    pgmname is not executable; to make this work it is necessary to
745    provide an absolute file name.  All standard file descriptors are
746    connected to /dev/null. */
747 gpg_error_t
748 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
749                               const char *envp[] )
750 {
751 #ifdef HAVE_W32_SYSTEM
752   gpg_error_t err;
753   SECURITY_ATTRIBUTES sec_attr;
754   PROCESS_INFORMATION pi = 
755     {
756       NULL,      /* Returns process handle.  */
757       0,         /* Returns primary thread handle.  */
758       0,         /* Returns pid.  */
759       0          /* Returns tid.  */
760     };
761   STARTUPINFO si;
762   int cr_flags;
763   char *cmdline;
764
765
766   /* FIXME: We don't make use of ENVP yet.  It is currently only used
767      to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
768      on windows is to use a standard socket, this does not really
769      matter.  */
770
771
772   if (access (pgmname, X_OK))
773     return gpg_error_from_syserror ();
774
775   /* Prepare security attributes.  */
776   memset (&sec_attr, 0, sizeof sec_attr );
777   sec_attr.nLength = sizeof sec_attr;
778   sec_attr.bInheritHandle = FALSE;
779   
780   /* Build the command line.  */
781   err = build_w32_commandline (pgmname, argv, &cmdline);
782   if (err)
783     return err; 
784
785   /* Start the process.  */
786   memset (&si, 0, sizeof si);
787   si.cb = sizeof (si);
788   si.dwFlags = STARTF_USESHOWWINDOW;
789   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
790
791   cr_flags = (CREATE_DEFAULT_ERROR_MODE
792               | GetPriorityClass (GetCurrentProcess ())
793               | CREATE_NEW_PROCESS_GROUP
794               | DETACHED_PROCESS); 
795   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
796              pgmname, cmdline);
797   if (!CreateProcess (pgmname,       /* Program to start.  */
798                       cmdline,       /* Command line arguments.  */
799                       &sec_attr,     /* Process security attributes.  */
800                       &sec_attr,     /* Thread security attributes.  */
801                       FALSE,         /* Inherit handles.  */
802                       cr_flags,      /* Creation flags.  */
803                       NULL,          /* Environment.  */
804                       NULL,          /* Use current drive/directory.  */
805                       &si,           /* Startup information. */
806                       &pi            /* Returns process information.  */
807                       ))
808     {
809       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
810       xfree (cmdline);
811       return gpg_error (GPG_ERR_GENERAL);
812     }
813   xfree (cmdline);
814   cmdline = NULL;
815
816   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
817              " dwProcessID=%d dwThreadId=%d\n",
818              pi.hProcess, pi.hThread,
819              (int) pi.dwProcessId, (int) pi.dwThreadId);
820
821   CloseHandle (pi.hThread); 
822
823   return 0;
824
825 #else
826   pid_t pid;
827   int i;
828
829   if (getuid() != geteuid())
830     return gpg_error (GPG_ERR_BUG);
831
832   if (access (pgmname, X_OK))
833     return gpg_error_from_syserror ();
834
835 #ifdef USE_GNU_PTH      
836   pid = pth_fork? pth_fork () : fork ();
837 #else
838   pid = fork ();
839 #endif
840   if (pid == (pid_t)(-1))
841     {
842       log_error (_("error forking process: %s\n"), strerror (errno));
843       return gpg_error_from_syserror ();
844     }
845   if (!pid)
846     {
847       gcry_control (GCRYCTL_TERM_SECMEM);
848       if (setsid() == -1 || chdir ("/"))
849         _exit (1);
850       pid = fork (); /* Double fork to let init takes over the new child. */
851       if (pid == (pid_t)(-1))
852         _exit (1);
853       if (pid)
854         _exit (0);  /* Let the parent exit immediately. */
855
856       if (envp)
857         for (i=0; envp[i]; i++)
858           putenv (xstrdup (envp[i]));
859       
860       do_exec (pgmname, argv, -1, -1, -1, NULL);
861
862       /*NOTREACHED*/
863     }
864   
865   if (waitpid (pid, NULL, 0) == -1)
866     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
867                strerror (errno));
868
869   return 0;
870 #endif /* !HAVE_W32_SYSTEM*/
871 }