1 /* exechelp.c - Fork and exec helpers for POSIX
2 * Copyright (C) 2004, 2007, 2008, 2009,
3 * 2010 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of either
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.
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.
20 * or both in parallel, as here.
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.
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/>.
33 #if defined(HAVE_W32_SYSTEM) || defined (HAVE_W32CE_SYSTEM)
34 #error This code is only used on POSIX
51 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
63 #include <sys/resource.h>
64 #endif /*HAVE_GETRLIMIT*/
67 # include <sys/stat.h>
76 /* Return the maximum number of currently allowed open file
77 descriptors. Only useful on POSIX systems but returns a value on
87 if (!getrlimit (RLIMIT_NOFILE, &rl))
88 max_fds = rl.rlim_max;
92 if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
93 max_fds = rl.rlim_max;
96 #endif /*HAVE_GETRLIMIT*/
101 long int scres = sysconf (_SC_OPEN_MAX);
107 #ifdef _POSIX_OPEN_MAX
109 max_fds = _POSIX_OPEN_MAX;
118 max_fds = 256; /* Arbitrary limit. */
120 /* AIX returns INT32_MAX instead of a proper value. We assume that
121 this is always an error and use an arbitrary limit. */
123 if (max_fds == INT32_MAX)
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. */
136 close_all_fds (int first, int *except)
138 int max_fd = get_max_fds ();
139 int fd, i, except_start;
144 for (fd=first; fd < max_fd; fd++)
146 for (i=except_start; except[i] != -1; i++)
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;
163 for (fd=first; fd < max_fd; fd++)
167 gpg_err_set_errno (0);
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
178 get_all_open_fds (void)
184 array = calloc (1, sizeof *array);
190 max_fd = get_max_fds ();
191 narray = 32; /* If you change this change also t-exechelp.c. */
192 array = calloc (narray, sizeof *array);
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))
204 narray += (narray < 256)? 32:256;
205 tmp = realloc (array, narray * sizeof *array);
221 /* The exec core used right after the fork. This will never return. */
223 do_exec (const char *pgmname, const char *argv[],
224 int fd_in, int fd_out, int fd_err,
225 void (*preexec)(void) )
235 /* Create the command line argument array. */
240 arg_list = xcalloc (i+2, sizeof *arg_list);
241 arg_list[0] = strrchr (pgmname, '/');
245 arg_list[0] = xstrdup (pgmname);
247 for (i=0,j=1; argv[i]; i++, j++)
248 arg_list[j] = (char*)argv[i];
250 /* Assign /dev/null to unused FDs. */
251 for (i=0; i <= 2; i++)
255 fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
257 log_fatal ("failed to open '%s': %s\n",
258 "/dev/null", strerror (errno));
262 /* Connect the standard files. */
263 for (i=0; i <= 2; i++)
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));
270 /* Close all other files. */
271 close_all_fds (3, NULL);
275 execv (pgmname, arg_list);
276 /* No way to print anything, as we have closed all streams. */
282 do_create_pipe (int filedes[2])
286 if (pipe (filedes) == -1)
288 err = gpg_error_from_syserror ();
289 filedes[0] = filedes[1] = -1;
295 /* Portable function to create a pipe. Under Windows the write end is
298 gnupg_create_inbound_pipe (int filedes[2])
300 return do_create_pipe (filedes);
304 /* Portable function to create a pipe. Under Windows the read end is
307 gnupg_create_outbound_pipe (int filedes[2])
309 return do_create_pipe (filedes);
315 create_pipe_and_estream (int filedes[2], estream_t *r_fp,
316 int outbound, int nonblock,
317 gpg_err_source_t errsource)
321 if (pipe (filedes) == -1)
323 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
324 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
325 filedes[0] = filedes[1] = -1;
331 *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
333 *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
336 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
337 log_error (_("error creating a stream for a pipe: %s\n"),
341 filedes[0] = filedes[1] = -1;
349 /* Fork and exec the PGMNAME, see exechelp.h for details. */
351 gnupg_spawn_process (const char *pgmname, const char *argv[],
352 gpg_err_source_t errsource,
353 void (*preexec)(void), unsigned int flags,
360 int inpipe[2] = {-1, -1};
361 int outpipe[2] = {-1, -1};
362 int errpipe[2] = {-1, -1};
363 estream_t infp = NULL;
364 estream_t outfp = NULL;
365 estream_t errfp = NULL;
366 int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
374 *pid = (pid_t)(-1); /* Always required. */
378 err = create_pipe_and_estream (inpipe, &infp, 0, nonblock, errsource);
385 err = create_pipe_and_estream (outpipe, &outfp, 1, nonblock, errsource);
390 else if (inpipe[1] != -1)
401 err = create_pipe_and_estream (errpipe, &errfp, 1, nonblock, errsource);
406 else if (inpipe[1] != -1)
413 else if (outpipe[0] != -1)
415 if (outpipe[1] != -1)
424 if (*pid == (pid_t)(-1))
426 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
427 log_error (_("error forking process: %s\n"), gpg_strerror (err));
431 else if (inpipe[1] != -1)
438 else if (outpipe[0] != -1)
440 if (outpipe[1] != -1)
445 else if (errpipe[0] != -1)
447 if (errpipe[1] != -1)
454 /* This is the child. */
455 gcry_control (GCRYCTL_TERM_SECMEM);
458 do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1], preexec);
462 /* This is the parent. */
465 if (outpipe[1] != -1)
467 if (errpipe[1] != -1)
482 /* Simplified version of gnupg_spawn_process. This function forks and
483 then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
484 and ERRFD to stderr (any of them may be -1 to connect them to
485 /dev/null). The arguments for the process are expected in the NULL
486 terminated array ARGV. The program name itself should not be
487 included there. Calling gnupg_wait_process is required.
489 Returns 0 on success or an error code. */
491 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
492 int infd, int outfd, int errfd, pid_t *pid)
497 if (*pid == (pid_t)(-1))
499 err = gpg_error_from_syserror ();
500 log_error (_("error forking process: %s\n"), strerror (errno));
506 gcry_control (GCRYCTL_TERM_SECMEM);
508 do_exec (pgmname, argv, infd, outfd, errfd, NULL);
516 /* See exechelp.h for the description. */
518 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
526 if (pid == (pid_t)(-1))
527 return gpg_error (GPG_ERR_INV_VALUE);
530 i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
532 while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
536 if (i == (pid_t)(-1))
538 ec = gpg_err_code_from_errno (errno);
539 log_error (_("waiting for process %d to terminate failed: %s\n"),
540 (int)pid, strerror (errno));
544 ec = GPG_ERR_TIMEOUT; /* Still running. */
546 else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
548 log_error (_("error running '%s': probably not installed\n"), pgmname);
549 ec = GPG_ERR_CONFIGURATION;
551 else if (WIFEXITED (status) && WEXITSTATUS (status))
554 log_error (_("error running '%s': exit status %d\n"), pgmname,
555 WEXITSTATUS (status));
557 *r_exitcode = WEXITSTATUS (status);
558 ec = GPG_ERR_GENERAL;
560 else if (!WIFEXITED (status))
562 log_error (_("error running '%s': terminated\n"), pgmname);
563 ec = GPG_ERR_GENERAL;
572 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
577 gnupg_release_process (pid_t pid)
583 /* Spawn a new process and immediately detach from it. The name of
584 the program to exec is PGMNAME and its arguments are in ARGV (the
585 programname is automatically passed as first argument).
586 Environment strings in ENVP are set. An error is returned if
587 pgmname is not executable; to make this work it is necessary to
588 provide an absolute file name. All standard file descriptors are
589 connected to /dev/null. */
591 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
597 if (getuid() != geteuid())
598 return gpg_error (GPG_ERR_BUG);
600 if (access (pgmname, X_OK))
601 return gpg_error_from_syserror ();
604 if (pid == (pid_t)(-1))
606 log_error (_("error forking process: %s\n"), strerror (errno));
607 return gpg_error_from_syserror ();
613 gcry_control (GCRYCTL_TERM_SECMEM);
614 if (setsid() == -1 || chdir ("/"))
617 pid2 = fork (); /* Double fork to let init take over the new child. */
618 if (pid2 == (pid_t)(-1))
621 _exit (0); /* Let the parent exit immediately. */
624 for (i=0; envp[i]; i++)
625 putenv (xstrdup (envp[i]));
627 do_exec (pgmname, argv, -1, -1, -1, NULL);
632 if (waitpid (pid, NULL, 0) == -1)
633 log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
640 /* Kill a process; that is send an appropriate signal to the process.
641 gnupg_wait_process must be called to actually remove the process
642 from the system. An invalid PID is ignored. */
644 gnupg_kill_process (pid_t pid)
646 if (pid != (pid_t)(-1))