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 gpg_err_source_t errsource)
320 if (pipe (filedes) == -1)
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;
329 *r_fp = es_fdopen (filedes[0], "r");
332 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
333 log_error (_("error creating a stream for a pipe: %s\n"),
337 filedes[0] = filedes[1] = -1;
345 /* Fork and exec the PGMNAME, see exechelp.h for details. */
347 gnupg_spawn_process (const char *pgmname, const char *argv[],
348 gpg_err_source_t errsource,
349 void (*preexec)(void), unsigned int flags,
357 int outpipe[2] = {-1, -1};
358 int errpipe[2] = {-1, -1};
359 estream_t outfp = NULL;
360 estream_t errfp = NULL;
362 (void)flags; /* Currently not used. */
368 *pid = (pid_t)(-1); /* Always required. */
374 infd = es_fileno (infp);
376 return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
381 err = create_pipe_and_estream (outpipe, &outfp, errsource);
388 err = create_pipe_and_estream (errpipe, &errfp, errsource);
393 else if (outpipe[0] != -1)
395 if (outpipe[1] != -1)
403 if (*pid == (pid_t)(-1))
405 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
406 log_error (_("error forking process: %s\n"), gpg_strerror (err));
410 else if (outpipe[0] != -1)
412 if (outpipe[1] != -1)
417 else if (errpipe[0] != -1)
419 if (errpipe[1] != -1)
426 /* This is the child. */
427 gcry_control (GCRYCTL_TERM_SECMEM);
430 do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
434 /* This is the parent. */
435 if (outpipe[1] != -1)
437 if (errpipe[1] != -1)
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.
457 Returns 0 on success or an error code. */
459 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
460 int infd, int outfd, int errfd, pid_t *pid)
465 if (*pid == (pid_t)(-1))
467 err = gpg_error_from_syserror ();
468 log_error (_("error forking process: %s\n"), strerror (errno));
474 gcry_control (GCRYCTL_TERM_SECMEM);
476 do_exec (pgmname, argv, infd, outfd, errfd, NULL);
484 /* See exechelp.h for the description. */
486 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
494 if (pid == (pid_t)(-1))
495 return gpg_error (GPG_ERR_INV_VALUE);
498 i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
500 while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
504 if (i == (pid_t)(-1))
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));
512 ec = GPG_ERR_TIMEOUT; /* Still running. */
514 else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
516 log_error (_("error running '%s': probably not installed\n"), pgmname);
517 ec = GPG_ERR_CONFIGURATION;
519 else if (WIFEXITED (status) && WEXITSTATUS (status))
522 log_error (_("error running '%s': exit status %d\n"), pgmname,
523 WEXITSTATUS (status));
525 *r_exitcode = WEXITSTATUS (status);
526 ec = GPG_ERR_GENERAL;
528 else if (!WIFEXITED (status))
530 log_error (_("error running '%s': terminated\n"), pgmname);
531 ec = GPG_ERR_GENERAL;
540 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
545 gnupg_release_process (pid_t pid)
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. */
559 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
565 if (getuid() != geteuid())
566 return gpg_error (GPG_ERR_BUG);
568 if (access (pgmname, X_OK))
569 return gpg_error_from_syserror ();
572 if (pid == (pid_t)(-1))
574 log_error (_("error forking process: %s\n"), strerror (errno));
575 return gpg_error_from_syserror ();
581 gcry_control (GCRYCTL_TERM_SECMEM);
582 if (setsid() == -1 || chdir ("/"))
585 pid2 = fork (); /* Double fork to let init take over the new child. */
586 if (pid2 == (pid_t)(-1))
589 _exit (0); /* Let the parent exit immediately. */
592 for (i=0; envp[i]; i++)
593 putenv (xstrdup (envp[i]));
595 do_exec (pgmname, argv, -1, -1, -1, NULL);
600 if (waitpid (pid, NULL, 0) == -1)
601 log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
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. */
612 gnupg_kill_process (pid_t pid)
614 if (pid != (pid_t)(-1))