2de4f750ca29fc9f9a77f32ffbb47f0b942a0fb0
[gnupg.git] / common / exechelp.c
1 /* exechelp.c - fork and exec helpers
2  *      Copyright (C) 2004 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 #ifndef HAVE_W32_SYSTEM
195 /* The exec core used right after the fork. This will never return. */
196 static void
197 do_exec (const char *pgmname, const char *argv[],
198          int fd_in, int fd_out, int fd_err,
199          void (*preexec)(void) )
200 {
201   char **arg_list;
202   int n, i, j;
203   int fds[3];
204
205   fds[0] = fd_in;
206   fds[1] = fd_out;
207   fds[2] = fd_err;
208
209   /* Create the command line argument array.  */
210   i = 0;
211   if (argv)
212     while (argv[i])
213       i++;
214   arg_list = xcalloc (i+2, sizeof *arg_list);
215   arg_list[0] = strrchr (pgmname, '/');
216   if (arg_list[0])
217     arg_list[0]++;
218   else
219     arg_list[0] = xstrdup (pgmname);
220   if (argv)
221     for (i=0,j=1; argv[i]; i++, j++)
222       arg_list[j] = (char*)argv[i];
223
224   /* Connect the standard files. */
225   for (i=0; i <= 2; i++)
226     {
227       if (fds[i] == -1 )
228         {
229           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
230           if (fds[i] == -1)
231             log_fatal ("failed to open `%s': %s\n",
232                        "/dev/null", strerror (errno));
233         }
234       else if (fds[i] != i && dup2 (fds[i], i) == -1)
235         log_fatal ("dup2 std%s failed: %s\n",
236                    i==0?"in":i==1?"out":"err", strerror (errno));
237     }
238
239   /* Close all other files. */
240   n = sysconf (_SC_OPEN_MAX);
241   if (n < 0)
242     n = MAX_OPEN_FDS;
243   for (i=3; i < n; i++)
244     close(i);
245   errno = 0;
246   
247   if (preexec)
248     preexec ();
249   execv (pgmname, arg_list);
250   /* No way to print anything, as we have closed all streams. */
251   _exit (127);
252 }
253 #endif /*!HAVE_W32_SYSTEM*/
254
255
256 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
257    stdin, write the output to OUTFILE, return a new stream in
258    STATUSFILE for stderr and the pid of the process in PID. The
259    arguments for the process are expected in the NULL terminated array
260    ARGV.  The program name itself should not be included there.  if
261    PREEXEC is not NULL, that function will be called right before the
262    exec.
263
264    Returns 0 on success or an error code. */
265 gpg_error_t
266 gnupg_spawn_process (const char *pgmname, const char *argv[],
267                      FILE *infile, FILE *outfile,
268                      void (*preexec)(void),
269                      FILE **statusfile, pid_t *pid)
270 {
271 #ifdef HAVE_W32_SYSTEM
272   gpg_error_t err;
273   SECURITY_ATTRIBUTES sec_attr;
274   PROCESS_INFORMATION pi = 
275     {
276       NULL,      /* Returns process handle.  */
277       0,         /* Returns primary thread handle.  */
278       0,         /* Returns pid.  */
279       0          /* Returns tid.  */
280     };
281   STARTUPINFO si;
282   int cr_flags;
283   char *cmdline;
284   int fd, fdout, rp[2];
285
286   /* Setup return values.  */
287   *statusfile = NULL;
288   *pid = (pid_t)(-1);
289   fflush (infile);
290   rewind (infile);
291   fd = _get_osfhandle (fileno (infile));
292   fdout = _get_osfhandle (fileno (outfile));
293   if (fd == -1 || fdout == -1)
294     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
295
296   /* Prepare security attributes.  */
297   memset (&sec_attr, 0, sizeof sec_attr );
298   sec_attr.nLength = sizeof sec_attr;
299   sec_attr.bInheritHandle = FALSE;
300   
301   /* Build the command line.  */
302   err = build_w32_commandline (pgmname, argv, &cmdline);
303   if (err)
304     return err; 
305
306   /* Create a pipe.  */
307   if (create_inheritable_pipe (rp))
308     {
309       err = gpg_error (GPG_ERR_GENERAL);
310       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
311       xfree (cmdline);
312       return err;
313     }
314   
315   /* Start the process.  Note that we can't run the PREEXEC function
316      because this would change our own environment. */
317   memset (&si, 0, sizeof si);
318   si.cb = sizeof (si);
319   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
320   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
321   si.hStdInput  = fd_to_handle (fd);
322   si.hStdOutput = fd_to_handle (fdout);
323   si.hStdError  = fd_to_handle (rp[1]);
324
325   cr_flags = (CREATE_DEFAULT_ERROR_MODE
326               | GetPriorityClass (GetCurrentProcess ())
327               | CREATE_SUSPENDED); 
328   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline);
329   if (!CreateProcess (pgmname,       /* Program to start.  */
330                       cmdline,       /* Command line arguments.  */
331                       &sec_attr,     /* Process security attributes.  */
332                       &sec_attr,     /* Thread security attributes.  */
333                       TRUE,          /* Inherit handles.  */
334                       cr_flags,      /* Creation flags.  */
335                       NULL,          /* Environment.  */
336                       NULL,          /* Use current drive/directory.  */
337                       &si,           /* Startup information. */
338                       &pi            /* Returns process information.  */
339                       ))
340     {
341       log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
342       xfree (cmdline);
343       CloseHandle (fd_to_handle (rp[0]));
344       CloseHandle (fd_to_handle (rp[1]));
345       return gpg_error (GPG_ERR_GENERAL);
346     }
347   xfree (cmdline);
348   cmdline = NULL;
349
350   /* Close the other end of the pipe.  */
351   CloseHandle (fd_to_handle (rp[1]));
352   
353   log_debug ("CreateProcess ready: hProcess=%p hThread=%p"
354              " dwProcessID=%d dwThreadId=%d\n",
355              pi.hProcess, pi.hThread,
356              (int) pi.dwProcessId, (int) pi.dwThreadId);
357
358   /* Process has been created suspended; resume it now. */
359   ResumeThread (pi.hThread);
360   CloseHandle (pi.hThread); 
361
362   {
363     int x;
364
365     x = _open_osfhandle (rp[0], 0);
366     if (x == -1)
367       log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
368     else 
369       *statusfile = fdopen (x, "r");
370   }
371   if (!*statusfile)
372     {
373       err = gpg_error_from_syserror ();
374       log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
375       CloseHandle (pi.hProcess);
376       return err;
377     }
378
379   *pid = handle_to_pid (pi.hProcess);
380   return 0;
381
382 #else /* !HAVE_W32_SYSTEM */
383   gpg_error_t err;
384   int fd, fdout, rp[2];
385
386   *statusfile = NULL;
387   *pid = (pid_t)(-1);
388   fflush (infile);
389   rewind (infile);
390   fd = fileno (infile);
391   fdout = fileno (outfile);
392   if (fd == -1 || fdout == -1)
393     log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
394
395   if (pipe (rp) == -1)
396     {
397       err = gpg_error_from_syserror ();
398       log_error (_("error creating a pipe: %s\n"), strerror (errno));
399       return err;
400     }
401
402 #ifdef USE_GNU_PTH      
403   *pid = pth_fork? pth_fork () : fork ();
404 #else
405   *pid = fork ();
406 #endif
407   if (*pid == (pid_t)(-1))
408     {
409       err = gpg_error_from_syserror ();
410       log_error (_("error forking process: %s\n"), strerror (errno));
411       close (rp[0]);
412       close (rp[1]);
413       return err;
414     }
415
416   if (!*pid)
417     { 
418       gcry_control (GCRYCTL_TERM_SECMEM);
419       /* Run child. */
420       do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
421       /*NOTREACHED*/
422     }
423
424   /* Parent. */
425   close (rp[1]);
426
427   *statusfile = fdopen (rp[0], "r");
428   if (!*statusfile)
429     {
430       err = gpg_error_from_syserror ();
431       log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
432       kill (*pid, SIGTERM);
433       *pid = (pid_t)(-1);
434       return err;
435     }
436
437   return 0;
438 #endif /* !HAVE_W32_SYSTEM */
439 }
440
441
442 /* Wait for the process identified by PID to terminate. PGMNAME should
443    be the same as suplieed to the spawn fucntion and is only used for
444    diagnostics. Returns 0 if the process succeded, GPG_ERR_GENERAL for
445    any failures of the spawned program or other error codes.*/
446 gpg_error_t
447 gnupg_wait_process (const char *pgmname, pid_t pid)
448 {
449   gpg_err_code_t ec;
450
451 #ifdef HAVE_W32_SYSTEM
452   HANDLE proc = fd_to_handle (pid);
453   int code;
454   DWORD exc;
455
456   if (pid == (pid_t)(-1))
457     return gpg_error (GPG_ERR_INV_VALUE);
458
459   /* FIXME: We should do a pth_waitpid here.  However this has not yet
460      been implemented.  A special W32 pth system call would even be
461      better.  */
462   code = WaitForSingleObject (proc, INFINITE);
463   switch (code) 
464     {
465       case WAIT_FAILED:
466         log_error (_("waiting for process %d to terminate failed: %s\n"),
467                    (int)pid, w32_strerror (-1));
468         ec = GPG_ERR_GENERAL;
469         break;
470
471       case WAIT_OBJECT_0:
472         if (!GetExitCodeProcess (proc, &exc))
473           {
474             log_error (_("error getting exit code of process %d: %s\n"),
475                          (int)pid, w32_strerror (-1) );
476             ec = GPG_ERR_GENERAL;
477           }
478         else if (exc)
479           {
480             log_error (_("error running `%s': exit status %d\n"),
481                        pgmname, (int)exc );
482             ec = GPG_ERR_GENERAL;
483           }
484         else
485           ec = 0;
486         break;
487
488       default:
489         log_error ("WaitForSingleObject returned unexpected "
490                    "code %d for pid %d\n", code, (int)pid );
491         ec = GPG_ERR_GENERAL;
492         break;
493     }
494
495 #else /* !HAVE_W32_SYSTEM */
496   int i, status;
497
498   if (pid == (pid_t)(-1))
499     return gpg_error (GPG_ERR_INV_VALUE);
500
501 #ifdef USE_GNU_PTH
502   i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0);
503 #else
504   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
505     ;
506 #endif
507   if (i == (pid_t)(-1))
508     {
509       log_error (_("waiting for process %d to terminate failed: %s\n"),
510                  (int)pid, strerror (errno));
511       ec = gpg_err_code_from_errno (errno);
512     }
513   else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
514     {
515       log_error (_("error running `%s': probably not installed\n"), pgmname);
516       ec = GPG_ERR_CONFIGURATION;
517     }
518   else if (WIFEXITED (status) && WEXITSTATUS (status))
519     {
520       log_error (_("error running `%s': exit status %d\n"), pgmname,
521                  WEXITSTATUS (status));
522       ec = GPG_ERR_GENERAL;
523     }
524   else if (!WIFEXITED (status))
525     {
526       log_error (_("error running `%s': terminated\n"), pgmname);
527       ec = GPG_ERR_GENERAL;
528     }
529   else 
530     ec = 0;
531 #endif /* !HAVE_W32_SYSTEM */
532
533   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
534
535 }
536
537
538 /* Spawn a new process and immediatley detach from it.  The name of
539    the program to exec is PGMNAME and its arguments are in ARGV (the
540    programname is automatically passed as first argument).
541    Environment strings in ENVP are set.  An error is returned if
542    pgmname is not executable; to make this work it is necessary to
543    provide an absolute file name.  All standard file descriptors are
544    connected to /dev/null. */
545 gpg_error_t
546 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
547                               const char *envp[] )
548 {
549 #ifdef HAVE_W32_SYSTEM
550   gpg_error_t err;
551   SECURITY_ATTRIBUTES sec_attr;
552   PROCESS_INFORMATION pi = 
553     {
554       NULL,      /* Returns process handle.  */
555       0,         /* Returns primary thread handle.  */
556       0,         /* Returns pid.  */
557       0          /* Returns tid.  */
558     };
559   STARTUPINFO si;
560   int cr_flags;
561   char *cmdline;
562
563
564   /* FIXME: We don't make use of ENVP yet.  It is currently only used
565      to pass the GPG_AGENT_INFO variable to gpg-agent.  As the default
566      on windows is to use a standard socket, this does not really
567      matter.  */
568
569
570   if (access (pgmname, X_OK))
571     return gpg_error_from_syserror ();
572
573   /* Prepare security attributes.  */
574   memset (&sec_attr, 0, sizeof sec_attr );
575   sec_attr.nLength = sizeof sec_attr;
576   sec_attr.bInheritHandle = FALSE;
577   
578   /* Build the command line.  */
579   err = build_w32_commandline (pgmname, argv, &cmdline);
580   if (err)
581     return err; 
582
583   /* Start the process.  */
584   memset (&si, 0, sizeof si);
585   si.cb = sizeof (si);
586   si.dwFlags = STARTF_USESHOWWINDOW;
587   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
588
589   cr_flags = (CREATE_DEFAULT_ERROR_MODE
590               | GetPriorityClass (GetCurrentProcess ())
591               | CREATE_NEW_PROCESS_GROUP
592               | DETACHED_PROCESS); 
593   log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n",
594              pgmname, cmdline);
595   if (!CreateProcess (pgmname,       /* Program to start.  */
596                       cmdline,       /* Command line arguments.  */
597                       &sec_attr,     /* Process security attributes.  */
598                       &sec_attr,     /* Thread security attributes.  */
599                       FALSE,         /* Inherit handles.  */
600                       cr_flags,      /* Creation flags.  */
601                       NULL,          /* Environment.  */
602                       NULL,          /* Use current drive/directory.  */
603                       &si,           /* Startup information. */
604                       &pi            /* Returns process information.  */
605                       ))
606     {
607       log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
608       xfree (cmdline);
609       return gpg_error (GPG_ERR_GENERAL);
610     }
611   xfree (cmdline);
612   cmdline = NULL;
613
614   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p"
615              " dwProcessID=%d dwThreadId=%d\n",
616              pi.hProcess, pi.hThread,
617              (int) pi.dwProcessId, (int) pi.dwThreadId);
618
619   CloseHandle (pi.hThread); 
620
621   return 0;
622
623 #else
624   pid_t pid;
625   int i;
626
627   if (getuid() != geteuid())
628     return gpg_error (GPG_ERR_BUG);
629
630   if (access (pgmname, X_OK))
631     return gpg_error_from_syserror ();
632
633 #ifdef USE_GNU_PTH      
634   pid = pth_fork? pth_fork () : fork ();
635 #else
636   pid = fork ();
637 #endif
638   if (pid == (pid_t)(-1))
639     {
640       log_error (_("error forking process: %s\n"), strerror (errno));
641       return gpg_error_from_syserror ();
642     }
643   if (!pid)
644     {
645       gcry_control (GCRYCTL_TERM_SECMEM);
646       if (setsid() == -1 || chdir ("/"))
647         _exit (1);
648       pid = fork (); /* Double fork to let init takes over the new child. */
649       if (pid == (pid_t)(-1))
650         _exit (1);
651       if (pid)
652         _exit (0);  /* Let the parent exit immediately. */
653
654       if (envp)
655         for (i=0; envp[i]; i++)
656           putenv (xstrdup (envp[i]));
657       
658       do_exec (pgmname, argv, -1, -1, -1, NULL);
659
660       /*NOTREACHED*/
661     }
662   
663   if (waitpid (pid, NULL, 0) == -1)
664     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
665                strerror (errno));
666
667   return 0;
668 #endif /* !HAVE_W32_SYSTEM*/
669 }