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