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