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