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
48 #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
60 #include <sys/resource.h>
61 #endif /*HAVE_GETRLIMIT*/
64 # include <sys/stat.h>
73 /* Return the maximum number of currently allowed open file
74 descriptors. Only useful on POSIX systems but returns a value on
84 if (!getrlimit (RLIMIT_NOFILE, &rl))
85 max_fds = rl.rlim_max;
89 if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
90 max_fds = rl.rlim_max;
93 #endif /*HAVE_GETRLIMIT*/
98 long int scres = sysconf (_SC_OPEN_MAX);
104 #ifdef _POSIX_OPEN_MAX
106 max_fds = _POSIX_OPEN_MAX;
115 max_fds = 256; /* Arbitrary limit. */
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. */
126 close_all_fds (int first, int *except)
128 int max_fd = get_max_fds ();
129 int fd, i, except_start;
134 for (fd=first; fd < max_fd; fd++)
136 for (i=except_start; except[i] != -1; i++)
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;
153 for (fd=first; fd < max_fd; fd++)
157 gpg_err_set_errno (0);
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
168 get_all_open_fds (void)
174 array = calloc (1, sizeof *array);
180 max_fd = get_max_fds ();
181 narray = 32; /* If you change this change also t-exechelp.c. */
182 array = calloc (narray, sizeof *array);
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))
194 narray += (narray < 256)? 32:256;
195 tmp = realloc (array, narray * sizeof *array);
211 /* The exec core used right after the fork. This will never return. */
213 do_exec (const char *pgmname, const char *argv[],
214 int fd_in, int fd_out, int fd_err,
215 void (*preexec)(void) )
225 /* Create the command line argument array. */
230 arg_list = xcalloc (i+2, sizeof *arg_list);
231 arg_list[0] = strrchr (pgmname, '/');
235 arg_list[0] = xstrdup (pgmname);
237 for (i=0,j=1; argv[i]; i++, j++)
238 arg_list[j] = (char*)argv[i];
240 /* Assign /dev/null to unused FDs. */
241 for (i=0; i <= 2; i++)
245 fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
247 log_fatal ("failed to open '%s': %s\n",
248 "/dev/null", strerror (errno));
252 /* Connect the standard files. */
253 for (i=0; i <= 2; i++)
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));
260 /* Close all other files. */
261 close_all_fds (3, NULL);
265 execv (pgmname, arg_list);
266 /* No way to print anything, as we have closed all streams. */
272 do_create_pipe (int filedes[2])
276 if (pipe (filedes) == -1)
278 err = gpg_error_from_syserror ();
279 filedes[0] = filedes[1] = -1;
285 /* Portable function to create a pipe. Under Windows the write end is
288 gnupg_create_inbound_pipe (int filedes[2])
290 return do_create_pipe (filedes);
294 /* Portable function to create a pipe. Under Windows the read end is
297 gnupg_create_outbound_pipe (int filedes[2])
299 return do_create_pipe (filedes);
305 create_pipe_and_estream (int filedes[2], estream_t *r_fp,
306 gpg_err_source_t errsource)
310 if (pipe (filedes) == -1)
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;
319 *r_fp = es_fdopen (filedes[0], "r");
322 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
323 log_error (_("error creating a stream for a pipe: %s\n"),
327 filedes[0] = filedes[1] = -1;
335 /* Fork and exec the PGMNAME, see exechelp.h for details. */
337 gnupg_spawn_process (const char *pgmname, const char *argv[],
338 gpg_err_source_t errsource,
339 void (*preexec)(void), unsigned int flags,
347 int outpipe[2] = {-1, -1};
348 int errpipe[2] = {-1, -1};
349 estream_t outfp = NULL;
350 estream_t errfp = NULL;
352 (void)flags; /* Currently not used. */
358 *pid = (pid_t)(-1); /* Always required. */
364 infd = es_fileno (infp);
366 return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
371 err = create_pipe_and_estream (outpipe, &outfp, errsource);
378 err = create_pipe_and_estream (errpipe, &errfp, errsource);
383 else if (outpipe[0] != -1)
385 if (outpipe[1] != -1)
393 if (*pid == (pid_t)(-1))
395 err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
396 log_error (_("error forking process: %s\n"), gpg_strerror (err));
400 else if (outpipe[0] != -1)
402 if (outpipe[1] != -1)
407 else if (errpipe[0] != -1)
409 if (errpipe[1] != -1)
416 /* This is the child. */
417 gcry_control (GCRYCTL_TERM_SECMEM);
420 do_exec (pgmname, argv, infd, outpipe[1], errpipe[1], preexec);
424 /* This is the parent. */
425 if (outpipe[1] != -1)
427 if (errpipe[1] != -1)
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.
447 Returns 0 on success or an error code. */
449 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
450 int infd, int outfd, int errfd, pid_t *pid)
455 if (*pid == (pid_t)(-1))
457 err = gpg_error_from_syserror ();
458 log_error (_("error forking process: %s\n"), strerror (errno));
464 gcry_control (GCRYCTL_TERM_SECMEM);
466 do_exec (pgmname, argv, infd, outfd, errfd, NULL);
474 /* See exechelp.h for the description. */
476 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
484 if (pid == (pid_t)(-1))
485 return gpg_error (GPG_ERR_INV_VALUE);
488 i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
490 while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
494 if (i == (pid_t)(-1))
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));
502 ec = GPG_ERR_TIMEOUT; /* Still running. */
504 else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
506 log_error (_("error running '%s': probably not installed\n"), pgmname);
507 ec = GPG_ERR_CONFIGURATION;
509 else if (WIFEXITED (status) && WEXITSTATUS (status))
512 log_error (_("error running '%s': exit status %d\n"), pgmname,
513 WEXITSTATUS (status));
515 *r_exitcode = WEXITSTATUS (status);
516 ec = GPG_ERR_GENERAL;
518 else if (!WIFEXITED (status))
520 log_error (_("error running '%s': terminated\n"), pgmname);
521 ec = GPG_ERR_GENERAL;
530 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
535 gnupg_release_process (pid_t pid)
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. */
549 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
555 if (getuid() != geteuid())
556 return gpg_error (GPG_ERR_BUG);
558 if (access (pgmname, X_OK))
559 return gpg_error_from_syserror ();
562 if (pid == (pid_t)(-1))
564 log_error (_("error forking process: %s\n"), strerror (errno));
565 return gpg_error_from_syserror ();
571 gcry_control (GCRYCTL_TERM_SECMEM);
572 if (setsid() == -1 || chdir ("/"))
575 pid2 = fork (); /* Double fork to let init take over the new child. */
576 if (pid2 == (pid_t)(-1))
579 _exit (0); /* Let the parent exit immediately. */
582 for (i=0; envp[i]; i++)
583 putenv (xstrdup (envp[i]));
585 do_exec (pgmname, argv, -1, -1, -1, NULL);
590 if (waitpid (pid, NULL, 0) == -1)
591 log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
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. */
602 gnupg_kill_process (pid_t pid)
604 if (pid != (pid_t)(-1))