Marked all unused args on non-W32 platforms.
[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   (void)preexec;
355
356   /* Setup return values.  */
357   *statusfile = NULL;
358   *pid = (pid_t)(-1);
359   fflush (infile);
360   rewind (infile);
361   fd = _get_osfhandle (fileno (infile));
362   fdout = _get_osfhandle (fileno (outfile));
363   if (fd == -1 || fdout == -1)
364     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
365
366   /* Prepare security attributes.  */
367   memset (&sec_attr, 0, sizeof sec_attr );
368   sec_attr.nLength = sizeof sec_attr;
369   sec_attr.bInheritHandle = FALSE;
370   
371   /* Build the command line.  */
372   err = build_w32_commandline (pgmname, argv, &cmdline);
373   if (err)
374     return err; 
375
376   /* Create a pipe.  */
377   if (create_inheritable_pipe (rp))
378     {
379       err = gpg_error (GPG_ERR_GENERAL);
380       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
381       xfree (cmdline);
382       return err;
383     }
384   
385   /* Start the process.  Note that we can't run the PREEXEC function
386      because this would change our own environment. */
387   memset (&si, 0, sizeof si);
388   si.cb = sizeof (si);
389   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
390   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
391   si.hStdInput  = fd_to_handle (fd);
392   si.hStdOutput = fd_to_handle (fdout);
393   si.hStdError  = fd_to_handle (rp[1]);
394
395   cr_flags = (CREATE_DEFAULT_ERROR_MODE
396               | ((flags & 128)? DETACHED_PROCESS : 0)
397               | GetPriorityClass (GetCurrentProcess ())
398               | CREATE_SUSPENDED); 
399   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
400   if (!CreateProcess (pgmname,       /* Program to start.  */
401                       cmdline,       /* Command line arguments.  */
402                       &sec_attr,     /* Process security attributes.  */
403                       &sec_attr,     /* Thread security attributes.  */
404                       TRUE,          /* Inherit handles.  */
405                       cr_flags,      /* Creation flags.  */
406                       NULL,          /* Environment.  */
407                       NULL,          /* Use current drive/directory.  */
408                       &si,           /* Startup information. */
409                       &pi            /* Returns process information.  */
410                       ))
411     {
412       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
413       xfree (cmdline);
414       CloseHandle (fd_to_handle (rp[0]));
415       CloseHandle (fd_to_handle (rp[1]));
416       return gpg_error (GPG_ERR_GENERAL);
417     }
418   xfree (cmdline);
419   cmdline = NULL;
420
421   /* Close the other end of the pipe.  */
422   CloseHandle (fd_to_handle (rp[1]));
423   
424   log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
425              " dwProcessID=%d dwThreadId=%d\n",
426              pi.hProcess, pi.hThread,
427              (int) pi.dwProcessId, (int) pi.dwThreadId);
428
429   /* Process has been created suspended; resume it now. */
430   ResumeThread (pi.hThread);
431   CloseHandle (pi.hThread); 
432
433   {
434     int x;
435
436     x = _open_osfhandle (rp[0], 0);
437     if (x == -1)
438       log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
439     else 
440       *statusfile = fdopen (x, "r");
441   }
442   if (!*statusfile)
443     {
444       err = gpg_error_from_syserror ();
445       log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
446       CloseHandle (pi.hProcess);
447       return err;
448     }
449
450   *pid = handle_to_pid (pi.hProcess);
451   return 0;
452
453 #else /* !HAVE_W32_SYSTEM */
454   gpg_error_t err;
455   int fd, fdout, rp[2];
456
457   (void)flags; /* Currently not used.  */
458
459   *statusfile = NULL;
460   *pid = (pid_t)(-1);
461   fflush (infile);
462   rewind (infile);
463   fd = fileno (infile);
464   fdout = fileno (outfile);
465   if (fd == -1 || fdout == -1)
466     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
467
468   if (pipe (rp) == -1)
469     {
470       err = gpg_error_from_syserror ();
471       log_error (_("error creating a pipe: %s\n"), strerror (errno));
472       return err;
473     }
474
475 #ifdef USE_GNU_PTH      
476   *pid = pth_fork? pth_fork () : fork ();
477 #else
478   *pid = fork ();
479 #endif
480   if (*pid == (pid_t)(-1))
481     {
482       err = gpg_error_from_syserror ();
483       log_error (_("error forking process: %s\n"), strerror (errno));
484       close (rp[0]);
485       close (rp[1]);
486       return err;
487     }
488
489   if (!*pid)
490     { 
491       gcry_control (GCRYCTL_TERM_SECMEM);
492       /* Run child. */
493       do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
494       /*NOTREACHED*/
495     }
496
497   /* Parent. */
498   close (rp[1]);
499
500   *statusfile = fdopen (rp[0], "r");
501   if (!*statusfile)
502     {
503       err = gpg_error_from_syserror ();
504       log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
505       kill (*pid, SIGTERM);
506       *pid = (pid_t)(-1);
507       return err;
508     }
509
510   return 0;
511 #endif /* !HAVE_W32_SYSTEM */
512 }
513
514
515
516 /* Simplified version of gnupg_spawn_process.  This function forks and
517    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
518    and ERRFD to stderr (any of them may be -1 to connect them to
519    /dev/null).  The arguments for the process are expected in the NULL
520    terminated array ARGV.  The program name itself should not be
521    included there.  Calling gnupg_wait_process is required.
522
523    Returns 0 on success or an error code. */
524 gpg_error_t
525 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
526                         int infd, int outfd, int errfd, pid_t *pid)
527 {
528 #ifdef HAVE_W32_SYSTEM
529   gpg_error_t err;
530   SECURITY_ATTRIBUTES sec_attr;
531   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
532   STARTUPINFO si;
533   char *cmdline;
534   int i;
535   HANDLE stdhd[3];
536
537   /* Setup return values.  */
538   *pid = (pid_t)(-1);
539
540   /* Prepare security attributes.  */
541   memset (&sec_attr, 0, sizeof sec_attr );
542   sec_attr.nLength = sizeof sec_attr;
543   sec_attr.bInheritHandle = FALSE;
544   
545   /* Build the command line.  */
546   err = build_w32_commandline (pgmname, argv, &cmdline);
547   if (err)
548     return err; 
549
550   memset (&si, 0, sizeof si);
551   si.cb = sizeof (si);
552   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
553   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
554   stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
555   stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
556   stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
557   si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
558   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
559   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
560
561   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
562   if (!CreateProcess (pgmname,       /* Program to start.  */
563                       cmdline,       /* Command line arguments.  */
564                       &sec_attr,     /* Process security attributes.  */
565                       &sec_attr,     /* Thread security attributes.  */
566                       TRUE,          /* Inherit handles.  */
567                       (CREATE_DEFAULT_ERROR_MODE
568                        | GetPriorityClass (GetCurrentProcess ())
569                        | CREATE_SUSPENDED | DETACHED_PROCESS),
570                       NULL,          /* Environment.  */
571                       NULL,          /* Use current drive/directory.  */
572                       &si,           /* Startup information. */
573                       &pi            /* Returns process information.  */
574                       ))
575     {
576       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
577       err = gpg_error (GPG_ERR_GENERAL);
578     }
579   else
580     err = 0;
581   xfree (cmdline);
582   for (i=0; i < 3; i++)
583     if (stdhd[i] != INVALID_HANDLE_VALUE)
584       CloseHandle (stdhd[i]);
585   if (err)
586     return err;
587
588   log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
589              " dwProcessID=%d dwThreadId=%d\n",
590              pi.hProcess, pi.hThread,
591              (int) pi.dwProcessId, (int) pi.dwThreadId);
592
593   /* Process has been created suspended; resume it now. */
594   ResumeThread (pi.hThread);
595   CloseHandle (pi.hThread); 
596
597   *pid = handle_to_pid (pi.hProcess);
598   return 0;
599
600 #else /* !HAVE_W32_SYSTEM */
601   gpg_error_t err;
602
603 #ifdef USE_GNU_PTH      
604   *pid = pth_fork? pth_fork () : fork ();
605 #else
606   *pid = fork ();
607 #endif
608   if (*pid == (pid_t)(-1))
609     {
610       err = gpg_error_from_syserror ();
611       log_error (_("error forking process: %s\n"), strerror (errno));
612       return err;
613     }
614
615   if (!*pid)
616     { 
617       gcry_control (GCRYCTL_TERM_SECMEM);
618       /* Run child. */
619       do_exec (pgmname, argv, infd, outfd, errfd, NULL);
620       /*NOTREACHED*/
621     }
622
623   return 0;
624 #endif /* !HAVE_W32_SYSTEM */
625 }
626
627
628 /* Wait for the process identified by PID to terminate. PGMNAME should
629    be the same as supplied to the spawn function and is only used for
630    diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
631    for any failures of the spawned program or other error codes.  If
632    EXITCODE is not NULL the exit code of the process is stored at this
633    address or -1 if it could not be retrieved. */
634 gpg_error_t
635 gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
636 {
637   gpg_err_code_t ec;
638
639 #ifdef HAVE_W32_SYSTEM
640   HANDLE proc = fd_to_handle (pid);
641   int code;
642   DWORD exc;
643
644   if (exitcode)
645     *exitcode = -1;
646
647   if (pid == (pid_t)(-1))
648     return gpg_error (GPG_ERR_INV_VALUE);
649
650   /* FIXME: We should do a pth_waitpid here.  However this has not yet
651      been implemented.  A special W32 pth system call would even be
652      better.  */
653   code = WaitForSingleObject (proc, INFINITE);
654   switch (code) 
655     {
656       case WAIT_FAILED:
657         log_error (_("waiting for process %d to terminate failed: %s\n"),
658                    (int)pid, w32_strerror (-1));
659         ec = GPG_ERR_GENERAL;
660         break;
661
662       case WAIT_OBJECT_0:
663         if (!GetExitCodeProcess (proc, &exc))
664           {
665             log_error (_("error getting exit code of process %d: %s\n"),
666                          (int)pid, w32_strerror (-1) );
667             ec = GPG_ERR_GENERAL;
668           }
669         else if (exc)
670           {
671             log_error (_("error running `%s': exit status %d\n"),
672                        pgmname, (int)exc );
673             if (exitcode)
674               *exitcode = (int)exc;
675             ec = GPG_ERR_GENERAL;
676           }
677         else
678           {
679             if (exitcode)
680               *exitcode = 0;
681             ec = 0;
682           }
683         CloseHandle (proc);
684         break;
685
686       default:
687         log_error ("WaitForSingleObject returned unexpected "
688                    "code %d for pid %d\n", code, (int)pid );
689         ec = GPG_ERR_GENERAL;
690         break;
691     }
692
693 #else /* !HAVE_W32_SYSTEM */
694   int i, status;
695
696   if (exitcode)
697     *exitcode = -1;
698
699   if (pid == (pid_t)(-1))
700     return gpg_error (GPG_ERR_INV_VALUE);
701
702 #ifdef USE_GNU_PTH
703   i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0);
704 #else
705   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
706     ;
707 #endif
708   if (i == (pid_t)(-1))
709     {
710       log_error (_("waiting for process %d to terminate failed: %s\n"),
711                  (int)pid, strerror (errno));
712       ec = gpg_err_code_from_errno (errno);
713     }
714   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
715     {
716       log_error (_("error running `%s': probably not installed\n"), pgmname);
717       ec = GPG_ERR_CONFIGURATION;
718     }
719   else if (WIFEXITED (status) && WEXITSTATUS (status))
720     {
721       log_error (_("error running `%s': exit status %d\n"), pgmname,
722                  WEXITSTATUS (status));
723       if (exitcode)
724         *exitcode = WEXITSTATUS (status);
725       ec = GPG_ERR_GENERAL;
726     }
727   else if (!WIFEXITED (status))
728     {
729       log_error (_("error running `%s': terminated\n"), pgmname);
730       ec = GPG_ERR_GENERAL;
731     }
732   else 
733     {
734       if (exitcode)
735         *exitcode = 0;
736       ec = 0;
737     }
738 #endif /* !HAVE_W32_SYSTEM */
739
740   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
741 }
742
743
744 /* Spawn a new process and immediatley detach from it.  The name of
745    the program to exec is PGMNAME and its arguments are in ARGV (the
746    programname is automatically passed as first argument).
747    Environment strings in ENVP are set.  An error is returned if
748    pgmname is not executable; to make this work it is necessary to
749    provide an absolute file name.  All standard file descriptors are
750    connected to /dev/null. */
751 gpg_error_t
752 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
753                               const char *envp[] )
754 {
755 #ifdef HAVE_W32_SYSTEM
756   gpg_error_t err;
757   SECURITY_ATTRIBUTES sec_attr;
758   PROCESS_INFORMATION pi = 
759     {
760       NULL,      /* Returns process handle.  */
761       0,         /* Returns primary thread handle.  */
762       0,         /* Returns pid.  */
763       0          /* Returns tid.  */
764     };
765   STARTUPINFO si;
766   int cr_flags;
767   char *cmdline;
768
769
770   /* FIXME: We don't make use of ENVP yet.  It is currently only used
771      to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
772      on windows is to use a standard socket, this does not really
773      matter.  */
774   (void)envp;
775
776   if (access (pgmname, X_OK))
777     return gpg_error_from_syserror ();
778
779   /* Prepare security attributes.  */
780   memset (&sec_attr, 0, sizeof sec_attr );
781   sec_attr.nLength = sizeof sec_attr;
782   sec_attr.bInheritHandle = FALSE;
783   
784   /* Build the command line.  */
785   err = build_w32_commandline (pgmname, argv, &cmdline);
786   if (err)
787     return err; 
788
789   /* Start the process.  */
790   memset (&si, 0, sizeof si);
791   si.cb = sizeof (si);
792   si.dwFlags = STARTF_USESHOWWINDOW;
793   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
794
795   cr_flags = (CREATE_DEFAULT_ERROR_MODE
796               | GetPriorityClass (GetCurrentProcess ())
797               | CREATE_NEW_PROCESS_GROUP
798               | DETACHED_PROCESS); 
799   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
800              pgmname, cmdline);
801   if (!CreateProcess (pgmname,       /* Program to start.  */
802                       cmdline,       /* Command line arguments.  */
803                       &sec_attr,     /* Process security attributes.  */
804                       &sec_attr,     /* Thread security attributes.  */
805                       FALSE,         /* Inherit handles.  */
806                       cr_flags,      /* Creation flags.  */
807                       NULL,          /* Environment.  */
808                       NULL,          /* Use current drive/directory.  */
809                       &si,           /* Startup information. */
810                       &pi            /* Returns process information.  */
811                       ))
812     {
813       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
814       xfree (cmdline);
815       return gpg_error (GPG_ERR_GENERAL);
816     }
817   xfree (cmdline);
818   cmdline = NULL;
819
820   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
821              " dwProcessID=%d dwThreadId=%d\n",
822              pi.hProcess, pi.hThread,
823              (int) pi.dwProcessId, (int) pi.dwThreadId);
824
825   CloseHandle (pi.hThread); 
826
827   return 0;
828
829 #else
830   pid_t pid;
831   int i;
832
833   if (getuid() != geteuid())
834     return gpg_error (GPG_ERR_BUG);
835
836   if (access (pgmname, X_OK))
837     return gpg_error_from_syserror ();
838
839 #ifdef USE_GNU_PTH      
840   pid = pth_fork? pth_fork () : fork ();
841 #else
842   pid = fork ();
843 #endif
844   if (pid == (pid_t)(-1))
845     {
846       log_error (_("error forking process: %s\n"), strerror (errno));
847       return gpg_error_from_syserror ();
848     }
849   if (!pid)
850     {
851       gcry_control (GCRYCTL_TERM_SECMEM);
852       if (setsid() == -1 || chdir ("/"))
853         _exit (1);
854       pid = fork (); /* Double fork to let init takes over the new child. */
855       if (pid == (pid_t)(-1))
856         _exit (1);
857       if (pid)
858         _exit (0);  /* Let the parent exit immediately. */
859
860       if (envp)
861         for (i=0; envp[i]; i++)
862           putenv (xstrdup (envp[i]));
863       
864       do_exec (pgmname, argv, -1, -1, -1, NULL);
865
866       /*NOTREACHED*/
867     }
868   
869   if (waitpid (pid, NULL, 0) == -1)
870     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
871                strerror (errno));
872
873   return 0;
874 #endif /* !HAVE_W32_SYSTEM*/
875 }