w32: Add icons and version information.
[gnupg.git] / common / exechelp-posix.c
1 /* exechelp.c - Fork and exec helpers for POSIX
2  * Copyright (C) 2004, 2007, 2008, 2009,
3  *               2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * This file is free software; you can redistribute it and/or modify
8  * it under the terms of either
9  *
10  *   - the GNU Lesser General Public License as published by the Free
11  *     Software Foundation; either version 3 of the License, or (at
12  *     your option) any later version.
13  *
14  * or
15  *
16  *   - the GNU General Public License as published by the Free
17  *     Software Foundation; either version 2 of the License, or (at
18  *     your option) any later version.
19  *
20  * or both in parallel, as here.
21  *
22  * This file is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, see <http://www.gnu.org/licenses/>.
29  */
30
31 #include <config.h>
32
33 #if defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
34 #error This code is only used on POSIX
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <assert.h>
42 #ifdef HAVE_SIGNAL_H
43 # include <signal.h>
44 #endif
45 #include <unistd.h>
46 #include <fcntl.h>
47
48 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
49 #undef HAVE_NPTH
50 #undef USE_NPTH
51 #endif
52
53 #ifdef USE_NPTH
54 #include <npth.h>
55 #endif
56 #include <sys/wait.h>
57
58 #ifdef HAVE_GETRLIMIT
59 #include <sys/time.h>
60 #include <sys/resource.h>
61 #endif /*HAVE_GETRLIMIT*/
62
63 #ifdef HAVE_STAT
64 # include <sys/stat.h>
65 #endif
66
67 #include "util.h"
68 #include "i18n.h"
69 #include "sysutils.h"
70 #include "exechelp.h"
71
72
73 /* We have the usual problem here: Some modules are linked against pth
74    and some are not.  However we want to use pth_fork and pth_waitpid
75    here. Using a weak symbol works but is not portable - we should
76    provide a an explicit dummy pth module instead of using the
77    pragma.  */
78 #pragma weak pth_fork
79 #pragma weak pth_waitpid
80
81
82 /* Return the maximum number of currently allowed open file
83    descriptors.  Only useful on POSIX systems but returns a value on
84    other systems too.  */
85 int
86 get_max_fds (void)
87 {
88   int max_fds = -1;
89 #ifdef HAVE_GETRLIMIT
90   struct rlimit rl;
91
92 # ifdef RLIMIT_NOFILE
93   if (!getrlimit (RLIMIT_NOFILE, &rl))
94     max_fds = rl.rlim_max;
95 # endif
96
97 # ifdef RLIMIT_OFILE
98   if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
99     max_fds = rl.rlim_max;
100
101 # endif
102 #endif /*HAVE_GETRLIMIT*/
103
104 #ifdef _SC_OPEN_MAX
105   if (max_fds == -1)
106     {
107       long int scres = sysconf (_SC_OPEN_MAX);
108       if (scres >= 0)
109         max_fds = scres;
110     }
111 #endif
112
113 #ifdef _POSIX_OPEN_MAX
114   if (max_fds == -1)
115     max_fds = _POSIX_OPEN_MAX;
116 #endif
117
118 #ifdef OPEN_MAX
119   if (max_fds == -1)
120     max_fds = OPEN_MAX;
121 #endif
122
123   if (max_fds == -1)
124     max_fds = 256;  /* Arbitrary limit.  */
125
126   return max_fds;
127 }
128
129
130 /* Close all file descriptors starting with descriptor FIRST.  If
131    EXCEPT is not NULL, it is expected to be a list of file descriptors
132    which shall not be closed.  This list shall be sorted in ascending
133    order with the end marked by -1.  */
134 void
135 close_all_fds (int first, int *except)
136 {
137   int max_fd = get_max_fds ();
138   int fd, i, except_start;
139
140   if (except)
141     {
142       except_start = 0;
143       for (fd=first; fd < max_fd; fd++)
144         {
145           for (i=except_start; except[i] != -1; i++)
146             {
147               if (except[i] == fd)
148                 {
149                   /* If we found the descriptor in the exception list
150                      we can start the next compare run at the next
151                      index because the exception list is ordered.  */
152                 except_start = i + 1;
153                 break;
154                 }
155             }
156           if (except[i] == -1)
157             close (fd);
158         }
159     }
160   else
161     {
162       for (fd=first; fd < max_fd; fd++)
163         close (fd);
164     }
165
166   gpg_err_set_errno (0);
167 }
168
169
170 /* Returns an array with all currently open file descriptors.  The end
171    of the array is marked by -1.  The caller needs to release this
172    array using the *standard free* and not with xfree.  This allow the
173    use of this fucntion right at startup even before libgcrypt has
174    been initialized.  Returns NULL on error and sets ERRNO
175    accordingly.  */
176 int *
177 get_all_open_fds (void)
178 {
179   int *array;
180   size_t narray;
181   int fd, max_fd, idx;
182 #ifndef HAVE_STAT
183   array = calloc (1, sizeof *array);
184   if (array)
185     array[0] = -1;
186 #else /*HAVE_STAT*/
187   struct stat statbuf;
188
189   max_fd = get_max_fds ();
190   narray = 32;  /* If you change this change also t-exechelp.c.  */
191   array = calloc (narray, sizeof *array);
192   if (!array)
193     return NULL;
194
195   /* Note:  The list we return is ordered.  */
196   for (idx=0, fd=0; fd < max_fd; fd++)
197     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
198       {
199         if (idx+1 >= narray)
200           {
201             int *tmp;
202
203             narray += (narray < 256)? 32:256;
204             tmp = realloc (array, narray * sizeof *array);
205             if (!tmp)
206               {
207                 free (array);
208                 return NULL;
209               }
210             array = tmp;
211           }
212         array[idx++] = fd;
213       }
214   array[idx] = -1;
215 #endif /*HAVE_STAT*/
216   return array;
217 }
218
219
220 /* The exec core used right after the fork. This will never return. */
221 static void
222 do_exec (const char *pgmname, const char *argv[],
223          int fd_in, int fd_out, int fd_err,
224          void (*preexec)(void) )
225 {
226   char **arg_list;
227   int i, j;
228   int fds[3];
229
230   fds[0] = fd_in;
231   fds[1] = fd_out;
232   fds[2] = fd_err;
233
234   /* Create the command line argument array.  */
235   i = 0;
236   if (argv)
237     while (argv[i])
238       i++;
239   arg_list = xcalloc (i+2, sizeof *arg_list);
240   arg_list[0] = strrchr (pgmname, '/');
241   if (arg_list[0])
242     arg_list[0]++;
243   else
244     arg_list[0] = xstrdup (pgmname);
245   if (argv)
246     for (i=0,j=1; argv[i]; i++, j++)
247       arg_list[j] = (char*)argv[i];
248
249   /* Assign /dev/null to unused FDs. */
250   for (i=0; i <= 2; i++)
251     {
252       if (fds[i] == -1 )
253         {
254           fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
255           if (fds[i] == -1)
256             log_fatal ("failed to open '%s': %s\n",
257                        "/dev/null", strerror (errno));
258         }
259     }
260
261   /* Connect the standard files.  */
262   for (i=0; i <= 2; i++)
263     {
264       if (fds[i] != i && dup2 (fds[i], i) == -1)
265         log_fatal ("dup2 std%s failed: %s\n",
266                    i==0?"in":i==1?"out":"err", strerror (errno));
267     }
268
269   /* Close all other files. */
270   close_all_fds (3, NULL);
271
272   if (preexec)
273     preexec ();
274   execv (pgmname, arg_list);
275   /* No way to print anything, as we have closed all streams. */
276   _exit (127);
277 }
278
279
280 static gpg_error_t
281 do_create_pipe (int filedes[2])
282 {
283   gpg_error_t err = 0;
284
285   if (pipe (filedes) == -1)
286     {
287       err = gpg_error_from_syserror ();
288       filedes[0] = filedes[1] = -1;
289     }
290
291   return err;
292 }
293
294 /* Portable function to create a pipe.  Under Windows the write end is
295    inheritable.  */
296 gpg_error_t
297 gnupg_create_inbound_pipe (int filedes[2])
298 {
299   return do_create_pipe (filedes);
300 }
301
302
303 /* Portable function to create a pipe.  Under Windows the read end is
304    inheritable.  */
305 gpg_error_t
306 gnupg_create_outbound_pipe (int filedes[2])
307 {
308   return do_create_pipe (filedes);
309 }
310
311
312
313 static gpg_error_t
314 create_pipe_and_estream (int filedes[2], estream_t *r_fp,
315                          gpg_err_source_t errsource)
316 {
317   gpg_error_t err;
318
319   if (pipe (filedes) == -1)
320     {
321       err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
322       log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
323       filedes[0] = filedes[1] = -1;
324       *r_fp = NULL;
325       return err;
326     }
327
328   *r_fp = es_fdopen (filedes[0], "r");
329   if (!*r_fp)
330     {
331       err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
332       log_error (_("error creating a stream for a pipe: %s\n"),
333                  gpg_strerror (err));
334       close (filedes[0]);
335       close (filedes[1]);
336       filedes[0] = filedes[1] = -1;
337       return err;
338     }
339   return 0;
340 }
341
342
343
344 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
345 gpg_error_t
346 gnupg_spawn_process (const char *pgmname, const char *argv[],
347                      gpg_err_source_t errsource,
348                      void (*preexec)(void), unsigned int flags,
349                      estream_t infp,
350                      estream_t *r_outfp,
351                      estream_t *r_errfp,
352                      pid_t *pid)
353 {
354   gpg_error_t err;
355   int infd = -1;
356   int outpipe[2] = {-1, -1};
357   int errpipe[2] = {-1, -1};
358   estream_t outfp = NULL;
359   estream_t errfp = NULL;
360
361   (void)flags; /* Currently not used.  */
362
363   if (r_outfp)
364     *r_outfp = NULL;
365   if (r_errfp)
366     *r_errfp = NULL;
367   *pid = (pid_t)(-1); /* Always required.  */
368
369   if (infp)
370     {
371       es_fflush (infp);
372       es_rewind (infp);
373       infd = es_fileno (infp);
374       if (infd == -1)
375         return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
376     }
377
378   if (r_outfp)
379     {
380       err = create_pipe_and_estream (outpipe, &outfp, errsource);
381       if (err)
382         return err;
383     }
384
385   if (r_errfp)
386     {
387       err = create_pipe_and_estream (errpipe, &errfp, errsource);
388       if (err)
389         {
390           if (outfp)
391             es_fclose (outfp);
392           else if (outpipe[0] != -1)
393             close (outpipe[0]);
394           if (outpipe[1] != -1)
395             close (outpipe[1]);
396           return err;
397         }
398     }
399
400
401   *pid = fork ();
402   if (*pid == (pid_t)(-1))
403     {
404       err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
405       log_error (_("error forking process: %s\n"), gpg_strerror (err));
406
407       if (outfp)
408         es_fclose (outfp);
409       else if (outpipe[0] != -1)
410         close (outpipe[0]);
411       if (outpipe[1] != -1)
412         close (outpipe[1]);
413
414       if (errfp)
415         es_fclose (errfp);
416       else if (errpipe[0] != -1)
417         close (errpipe[0]);
418       if (errpipe[1] != -1)
419         close (errpipe[1]);
420       return err;
421     }
422
423   if (!*pid)
424     {
425       /* This is the child. */
426       gcry_control (GCRYCTL_TERM_SECMEM);
427       es_fclose (outfp);
428       es_fclose (errfp);
429       do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
430       /*NOTREACHED*/
431     }
432
433   /* This is the parent. */
434   if (outpipe[1] != -1)
435     close (outpipe[1]);
436   if (errpipe[1] != -1)
437     close (errpipe[1]);
438
439   if (r_outfp)
440     *r_outfp = outfp;
441   if (r_errfp)
442     *r_errfp = errfp;
443
444   return 0;
445 }
446
447
448
449 /* Simplified version of gnupg_spawn_process.  This function forks and
450    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
451    and ERRFD to stderr (any of them may be -1 to connect them to
452    /dev/null).  The arguments for the process are expected in the NULL
453    terminated array ARGV.  The program name itself should not be
454    included there.  Calling gnupg_wait_process is required.
455
456    Returns 0 on success or an error code. */
457 gpg_error_t
458 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
459                         int infd, int outfd, int errfd, pid_t *pid)
460 {
461   gpg_error_t err;
462
463   *pid = fork ();
464   if (*pid == (pid_t)(-1))
465     {
466       err = gpg_error_from_syserror ();
467       log_error (_("error forking process: %s\n"), strerror (errno));
468       return err;
469     }
470
471   if (!*pid)
472     {
473       gcry_control (GCRYCTL_TERM_SECMEM);
474       /* Run child. */
475       do_exec (pgmname, argv, infd, outfd, errfd, NULL);
476       /*NOTREACHED*/
477     }
478
479   return 0;
480 }
481
482
483 /* See exechelp.h for the description.  */
484 gpg_error_t
485 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
486 {
487   gpg_err_code_t ec;
488   int i, status;
489
490   if (r_exitcode)
491     *r_exitcode = -1;
492
493   if (pid == (pid_t)(-1))
494     return gpg_error (GPG_ERR_INV_VALUE);
495
496 #ifdef USE_NPTH
497   i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
498 #else
499   while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
500          && errno == EINTR);
501 #endif
502
503   if (i == (pid_t)(-1))
504     {
505       ec = gpg_err_code_from_errno (errno);
506       log_error (_("waiting for process %d to terminate failed: %s\n"),
507                  (int)pid, strerror (errno));
508     }
509   else if (!i)
510     {
511       ec = GPG_ERR_TIMEOUT; /* Still running.  */
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       if (!r_exitcode)
521         log_error (_("error running '%s': exit status %d\n"), pgmname,
522                    WEXITSTATUS (status));
523       else
524         *r_exitcode = WEXITSTATUS (status);
525       ec = GPG_ERR_GENERAL;
526     }
527   else if (!WIFEXITED (status))
528     {
529       log_error (_("error running '%s': terminated\n"), pgmname);
530       ec = GPG_ERR_GENERAL;
531     }
532   else
533     {
534       if (r_exitcode)
535         *r_exitcode = 0;
536       ec = 0;
537     }
538
539   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
540 }
541
542
543 void
544 gnupg_release_process (pid_t pid)
545 {
546   (void)pid;
547 }
548
549
550 /* Spawn a new process and immediately detach from it.  The name of
551    the program to exec is PGMNAME and its arguments are in ARGV (the
552    programname is automatically passed as first argument).
553    Environment strings in ENVP are set.  An error is returned if
554    pgmname is not executable; to make this work it is necessary to
555    provide an absolute file name.  All standard file descriptors are
556    connected to /dev/null. */
557 gpg_error_t
558 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
559                               const char *envp[] )
560 {
561   pid_t pid;
562   int i;
563
564   if (getuid() != geteuid())
565     return gpg_error (GPG_ERR_BUG);
566
567   if (access (pgmname, X_OK))
568     return gpg_error_from_syserror ();
569
570   pid = fork ();
571   if (pid == (pid_t)(-1))
572     {
573       log_error (_("error forking process: %s\n"), strerror (errno));
574       return gpg_error_from_syserror ();
575     }
576   if (!pid)
577     {
578       pid_t pid2;
579
580       gcry_control (GCRYCTL_TERM_SECMEM);
581       if (setsid() == -1 || chdir ("/"))
582         _exit (1);
583
584       pid2 = fork (); /* Double fork to let init take over the new child. */
585       if (pid2 == (pid_t)(-1))
586         _exit (1);
587       if (pid2)
588         _exit (0);  /* Let the parent exit immediately. */
589
590       if (envp)
591         for (i=0; envp[i]; i++)
592           putenv (xstrdup (envp[i]));
593
594       do_exec (pgmname, argv, -1, -1, -1, NULL);
595
596       /*NOTREACHED*/
597     }
598
599   if (waitpid (pid, NULL, 0) == -1)
600     log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
601                strerror (errno));
602
603   return 0;
604 }
605
606
607 /* Kill a process; that is send an appropriate signal to the process.
608    gnupg_wait_process must be called to actually remove the process
609    from the system.  An invalid PID is ignored.  */
610 void
611 gnupg_kill_process (pid_t pid)
612 {
613   if (pid != (pid_t)(-1))
614     {
615       kill (pid, SIGTERM);
616     }
617 }