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