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