Line data Source code
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 <stdint.h>
40 : #include <string.h>
41 : #include <errno.h>
42 : #include <assert.h>
43 : #ifdef HAVE_SIGNAL_H
44 : # include <signal.h>
45 : #endif
46 : #include <unistd.h>
47 : #include <fcntl.h>
48 :
49 : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
50 : #undef HAVE_NPTH
51 : #undef USE_NPTH
52 : #endif
53 :
54 : #ifdef HAVE_NPTH
55 : #include <npth.h>
56 : #endif
57 : #include <sys/wait.h>
58 :
59 : #ifdef HAVE_GETRLIMIT
60 : #include <sys/time.h>
61 : #include <sys/resource.h>
62 : #endif /*HAVE_GETRLIMIT*/
63 :
64 : #ifdef HAVE_STAT
65 : # include <sys/stat.h>
66 : #endif
67 :
68 : #if __linux__
69 : # include <sys/types.h>
70 : # include <dirent.h>
71 : #endif /*__linux__ */
72 :
73 : #include "util.h"
74 : #include "i18n.h"
75 : #include "sysutils.h"
76 : #include "exechelp.h"
77 :
78 :
79 : /* Helper */
80 : static inline gpg_error_t
81 0 : my_error_from_syserror (void)
82 : {
83 0 : return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
84 : }
85 :
86 : static inline gpg_error_t
87 0 : my_error (int errcode)
88 : {
89 0 : return gpg_err_make (default_errsource, errcode);
90 : }
91 :
92 :
93 : /* Return the maximum number of currently allowed open file
94 : descriptors. Only useful on POSIX systems but returns a value on
95 : other systems too. */
96 : int
97 2425 : get_max_fds (void)
98 : {
99 2425 : int max_fds = -1;
100 : #ifdef HAVE_GETRLIMIT
101 : struct rlimit rl;
102 :
103 : /* Under Linux we can figure out the highest used file descriptor by
104 : * reading /proc/PID/fd. This is in the common cases much fast than
105 : * for example doing 4096 close calls where almost all of them will
106 : * fail. On a system with a limit of 4096 files and only 8 files
107 : * open with the highest number being 10, we speedup close_all_fds
108 : * from 125ms to 0.4ms including readdir.
109 : *
110 : * Another option would be to close the file descriptors as returned
111 : * from reading that directory - however then we need to snapshot
112 : * that list before starting to close them. */
113 : #ifdef __linux__
114 : {
115 2425 : DIR *dir = NULL;
116 : struct dirent *dir_entry;
117 : const char *s;
118 : int x;
119 :
120 2425 : dir = opendir ("/proc/self/fd");
121 2425 : if (dir)
122 : {
123 31203 : while ((dir_entry = readdir (dir)))
124 : {
125 26353 : s = dir_entry->d_name;
126 26353 : if ( *s < '0' || *s > '9')
127 4850 : continue;
128 21503 : x = atoi (s);
129 21503 : if (x > max_fds)
130 21503 : max_fds = x;
131 : }
132 2425 : closedir (dir);
133 : }
134 2425 : if (max_fds != -1)
135 2425 : return max_fds + 1;
136 : }
137 : #endif /* __linux__ */
138 :
139 :
140 : # ifdef RLIMIT_NOFILE
141 0 : if (!getrlimit (RLIMIT_NOFILE, &rl))
142 0 : max_fds = rl.rlim_max;
143 : # endif
144 :
145 : # ifdef RLIMIT_OFILE
146 0 : if (max_fds == -1 && !getrlimit (RLIMIT_OFILE, &rl))
147 0 : max_fds = rl.rlim_max;
148 :
149 : # endif
150 : #endif /*HAVE_GETRLIMIT*/
151 :
152 : #ifdef _SC_OPEN_MAX
153 0 : if (max_fds == -1)
154 : {
155 0 : long int scres = sysconf (_SC_OPEN_MAX);
156 0 : if (scres >= 0)
157 0 : max_fds = scres;
158 : }
159 : #endif
160 :
161 : #ifdef _POSIX_OPEN_MAX
162 0 : if (max_fds == -1)
163 0 : max_fds = _POSIX_OPEN_MAX;
164 : #endif
165 :
166 : #ifdef OPEN_MAX
167 : if (max_fds == -1)
168 : max_fds = OPEN_MAX;
169 : #endif
170 :
171 0 : if (max_fds == -1)
172 0 : max_fds = 256; /* Arbitrary limit. */
173 :
174 : /* AIX returns INT32_MAX instead of a proper value. We assume that
175 : this is always an error and use an arbitrary limit. */
176 : #ifdef INT32_MAX
177 0 : if (max_fds == INT32_MAX)
178 0 : max_fds = 256;
179 : #endif
180 :
181 0 : return max_fds;
182 : }
183 :
184 :
185 : /* Close all file descriptors starting with descriptor FIRST. If
186 : EXCEPT is not NULL, it is expected to be a list of file descriptors
187 : which shall not be closed. This list shall be sorted in ascending
188 : order with the end marked by -1. */
189 : void
190 2372 : close_all_fds (int first, int *except)
191 : {
192 2372 : int max_fd = get_max_fds ();
193 : int fd, i, except_start;
194 :
195 2372 : if (except)
196 : {
197 23 : except_start = 0;
198 179 : for (fd=first; fd < max_fd; fd++)
199 : {
200 156 : for (i=except_start; except[i] != -1; i++)
201 : {
202 0 : if (except[i] == fd)
203 : {
204 : /* If we found the descriptor in the exception list
205 : we can start the next compare run at the next
206 : index because the exception list is ordered. */
207 0 : except_start = i + 1;
208 0 : break;
209 : }
210 : }
211 156 : if (except[i] == -1)
212 156 : close (fd);
213 : }
214 : }
215 : else
216 : {
217 20339 : for (fd=first; fd < max_fd; fd++)
218 17990 : close (fd);
219 : }
220 :
221 2372 : gpg_err_set_errno (0);
222 2372 : }
223 :
224 :
225 : /* Returns an array with all currently open file descriptors. The end
226 : of the array is marked by -1. The caller needs to release this
227 : array using the *standard free* and not with xfree. This allow the
228 : use of this function right at startup even before libgcrypt has
229 : been initialized. Returns NULL on error and sets ERRNO
230 : accordingly. */
231 : int *
232 51 : get_all_open_fds (void)
233 : {
234 : int *array;
235 : size_t narray;
236 : int fd, max_fd, idx;
237 : #ifndef HAVE_STAT
238 : array = calloc (1, sizeof *array);
239 : if (array)
240 : array[0] = -1;
241 : #else /*HAVE_STAT*/
242 : struct stat statbuf;
243 :
244 51 : max_fd = get_max_fds ();
245 51 : narray = 32; /* If you change this change also t-exechelp.c. */
246 51 : array = calloc (narray, sizeof *array);
247 51 : if (!array)
248 0 : return NULL;
249 :
250 : /* Note: The list we return is ordered. */
251 258 : for (idx=0, fd=0; fd < max_fd; fd++)
252 207 : if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
253 : {
254 156 : if (idx+1 >= narray)
255 : {
256 : int *tmp;
257 :
258 0 : narray += (narray < 256)? 32:256;
259 0 : tmp = realloc (array, narray * sizeof *array);
260 0 : if (!tmp)
261 : {
262 0 : free (array);
263 0 : return NULL;
264 : }
265 0 : array = tmp;
266 : }
267 156 : array[idx++] = fd;
268 : }
269 51 : array[idx] = -1;
270 : #endif /*HAVE_STAT*/
271 51 : return array;
272 : }
273 :
274 :
275 : /* The exec core used right after the fork. This will never return. */
276 : static void
277 2371 : do_exec (const char *pgmname, const char *argv[],
278 : int fd_in, int fd_out, int fd_err,
279 : int *except, void (*preexec)(void) )
280 : {
281 : char **arg_list;
282 : int i, j;
283 : int fds[3];
284 :
285 2371 : fds[0] = fd_in;
286 2371 : fds[1] = fd_out;
287 2371 : fds[2] = fd_err;
288 :
289 : /* Create the command line argument array. */
290 2371 : i = 0;
291 2371 : if (argv)
292 19938 : while (argv[i])
293 15196 : i++;
294 2371 : arg_list = xcalloc (i+2, sizeof *arg_list);
295 2371 : arg_list[0] = strrchr (pgmname, '/');
296 2371 : if (arg_list[0])
297 2353 : arg_list[0]++;
298 : else
299 18 : arg_list[0] = xstrdup (pgmname);
300 2371 : if (argv)
301 17567 : for (i=0,j=1; argv[i]; i++, j++)
302 15196 : arg_list[j] = (char*)argv[i];
303 :
304 : /* Assign /dev/null to unused FDs. */
305 9484 : for (i=0; i <= 2; i++)
306 : {
307 7113 : if (fds[i] == -1 )
308 : {
309 710 : fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
310 710 : if (fds[i] == -1)
311 0 : log_fatal ("failed to open '%s': %s\n",
312 0 : "/dev/null", strerror (errno));
313 : }
314 : }
315 :
316 : /* Connect the standard files. */
317 9484 : for (i=0; i <= 2; i++)
318 : {
319 7113 : if (fds[i] != i && dup2 (fds[i], i) == -1)
320 0 : log_fatal ("dup2 std%s failed: %s\n",
321 0 : i==0?"in":i==1?"out":"err", strerror (errno));
322 : }
323 :
324 : /* Close all other files. */
325 2371 : close_all_fds (3, except);
326 :
327 2371 : if (preexec)
328 0 : preexec ();
329 2371 : execv (pgmname, arg_list);
330 : /* No way to print anything, as we have closed all streams. */
331 2371 : _exit (127);
332 : }
333 :
334 :
335 : static gpg_error_t
336 184 : do_create_pipe (int filedes[2])
337 : {
338 184 : gpg_error_t err = 0;
339 :
340 184 : if (pipe (filedes) == -1)
341 : {
342 0 : err = my_error_from_syserror ();
343 0 : filedes[0] = filedes[1] = -1;
344 : }
345 :
346 184 : return err;
347 : }
348 :
349 :
350 : static gpg_error_t
351 5961 : create_pipe_and_estream (int filedes[2], estream_t *r_fp,
352 : int outbound, int nonblock)
353 : {
354 : gpg_error_t err;
355 :
356 5961 : if (pipe (filedes) == -1)
357 : {
358 0 : err = my_error_from_syserror ();
359 0 : log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
360 0 : filedes[0] = filedes[1] = -1;
361 0 : *r_fp = NULL;
362 0 : return err;
363 : }
364 :
365 5961 : if (!outbound)
366 3974 : *r_fp = es_fdopen (filedes[0], nonblock? "r,nonblock" : "r");
367 : else
368 1987 : *r_fp = es_fdopen (filedes[1], nonblock? "w,nonblock" : "w");
369 5961 : if (!*r_fp)
370 : {
371 0 : err = my_error_from_syserror ();
372 0 : log_error (_("error creating a stream for a pipe: %s\n"),
373 : gpg_strerror (err));
374 0 : close (filedes[0]);
375 0 : close (filedes[1]);
376 0 : filedes[0] = filedes[1] = -1;
377 0 : return err;
378 : }
379 5961 : return 0;
380 : }
381 :
382 :
383 : /* Portable function to create a pipe. Under Windows the write end is
384 : inheritable. If R_FP is not NULL, an estream is created for the
385 : read end and stored at R_FP. */
386 : gpg_error_t
387 42 : gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
388 : {
389 42 : if (r_fp)
390 0 : return create_pipe_and_estream (filedes, r_fp, 0, nonblock);
391 : else
392 42 : return do_create_pipe (filedes);
393 : }
394 :
395 :
396 : /* Portable function to create a pipe. Under Windows the read end is
397 : inheritable. If R_FP is not NULL, an estream is created for the
398 : write end and stored at R_FP. */
399 : gpg_error_t
400 49 : gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
401 : {
402 49 : if (r_fp)
403 0 : return create_pipe_and_estream (filedes, r_fp, 1, nonblock);
404 : else
405 49 : return do_create_pipe (filedes);
406 : }
407 :
408 :
409 : /* Portable function to create a pipe. Under Windows both ends are
410 : inheritable. */
411 : gpg_error_t
412 93 : gnupg_create_pipe (int filedes[2])
413 : {
414 93 : return do_create_pipe (filedes);
415 : }
416 :
417 :
418 : /* Fork and exec the PGMNAME, see exechelp.h for details. */
419 : gpg_error_t
420 1987 : gnupg_spawn_process (const char *pgmname, const char *argv[],
421 : int *except, void (*preexec)(void), unsigned int flags,
422 : estream_t *r_infp,
423 : estream_t *r_outfp,
424 : estream_t *r_errfp,
425 : pid_t *pid)
426 : {
427 : gpg_error_t err;
428 1987 : int inpipe[2] = {-1, -1};
429 1987 : int outpipe[2] = {-1, -1};
430 1987 : int errpipe[2] = {-1, -1};
431 1987 : estream_t infp = NULL;
432 1987 : estream_t outfp = NULL;
433 1987 : estream_t errfp = NULL;
434 1987 : int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
435 :
436 1987 : if (r_infp)
437 1987 : *r_infp = NULL;
438 1987 : if (r_outfp)
439 1987 : *r_outfp = NULL;
440 1987 : if (r_errfp)
441 1987 : *r_errfp = NULL;
442 1987 : *pid = (pid_t)(-1); /* Always required. */
443 :
444 1987 : if (r_infp)
445 : {
446 1987 : err = create_pipe_and_estream (inpipe, &infp, 1, nonblock);
447 1987 : if (err)
448 0 : return err;
449 : }
450 :
451 1987 : if (r_outfp)
452 : {
453 1987 : err = create_pipe_and_estream (outpipe, &outfp, 0, nonblock);
454 1987 : if (err)
455 : {
456 0 : if (infp)
457 0 : es_fclose (infp);
458 0 : else if (inpipe[1] != -1)
459 0 : close (inpipe[1]);
460 0 : if (inpipe[0] != -1)
461 0 : close (inpipe[0]);
462 :
463 0 : return err;
464 : }
465 : }
466 :
467 1987 : if (r_errfp)
468 : {
469 1987 : err = create_pipe_and_estream (errpipe, &errfp, 0, nonblock);
470 1987 : if (err)
471 : {
472 0 : if (infp)
473 0 : es_fclose (infp);
474 0 : else if (inpipe[1] != -1)
475 0 : close (inpipe[1]);
476 0 : if (inpipe[0] != -1)
477 0 : close (inpipe[0]);
478 :
479 0 : if (outfp)
480 0 : es_fclose (outfp);
481 0 : else if (outpipe[0] != -1)
482 0 : close (outpipe[0]);
483 0 : if (outpipe[1] != -1)
484 0 : close (outpipe[1]);
485 :
486 0 : return err;
487 : }
488 : }
489 :
490 :
491 1987 : *pid = fork ();
492 3974 : if (*pid == (pid_t)(-1))
493 : {
494 0 : err = my_error_from_syserror ();
495 0 : log_error (_("error forking process: %s\n"), gpg_strerror (err));
496 :
497 0 : if (infp)
498 0 : es_fclose (infp);
499 0 : else if (inpipe[1] != -1)
500 0 : close (inpipe[1]);
501 0 : if (inpipe[0] != -1)
502 0 : close (inpipe[0]);
503 :
504 0 : if (outfp)
505 0 : es_fclose (outfp);
506 0 : else if (outpipe[0] != -1)
507 0 : close (outpipe[0]);
508 0 : if (outpipe[1] != -1)
509 0 : close (outpipe[1]);
510 :
511 0 : if (errfp)
512 0 : es_fclose (errfp);
513 0 : else if (errpipe[0] != -1)
514 0 : close (errpipe[0]);
515 0 : if (errpipe[1] != -1)
516 0 : close (errpipe[1]);
517 0 : return err;
518 : }
519 :
520 3974 : if (!*pid)
521 : {
522 : /* This is the child. */
523 1987 : gcry_control (GCRYCTL_TERM_SECMEM);
524 1987 : es_fclose (infp);
525 1987 : es_fclose (outfp);
526 1987 : es_fclose (errfp);
527 1987 : do_exec (pgmname, argv, inpipe[0], outpipe[1], errpipe[1],
528 : except, preexec);
529 : /*NOTREACHED*/
530 : }
531 :
532 : /* This is the parent. */
533 1987 : if (inpipe[0] != -1)
534 1987 : close (inpipe[0]);
535 1987 : if (outpipe[1] != -1)
536 1987 : close (outpipe[1]);
537 1987 : if (errpipe[1] != -1)
538 1987 : close (errpipe[1]);
539 :
540 1987 : if (r_infp)
541 1987 : *r_infp = infp;
542 1987 : if (r_outfp)
543 1987 : *r_outfp = outfp;
544 1987 : if (r_errfp)
545 1987 : *r_errfp = errfp;
546 :
547 1987 : return 0;
548 : }
549 :
550 :
551 :
552 : /* Simplified version of gnupg_spawn_process. This function forks and
553 : then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
554 : and ERRFD to stderr (any of them may be -1 to connect them to
555 : /dev/null). The arguments for the process are expected in the NULL
556 : terminated array ARGV. The program name itself should not be
557 : included there. Calling gnupg_wait_process is required.
558 :
559 : Returns 0 on success or an error code. */
560 : gpg_error_t
561 336 : gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
562 : int infd, int outfd, int errfd, pid_t *pid)
563 : {
564 : gpg_error_t err;
565 :
566 336 : *pid = fork ();
567 672 : if (*pid == (pid_t)(-1))
568 : {
569 0 : err = my_error_from_syserror ();
570 0 : log_error (_("error forking process: %s\n"), strerror (errno));
571 0 : return err;
572 : }
573 :
574 672 : if (!*pid)
575 : {
576 336 : gcry_control (GCRYCTL_TERM_SECMEM);
577 : /* Run child. */
578 336 : do_exec (pgmname, argv, infd, outfd, errfd, NULL, NULL);
579 : /*NOTREACHED*/
580 : }
581 :
582 336 : return 0;
583 : }
584 :
585 :
586 :
587 :
588 : /* Waiting for child processes.
589 :
590 : waitpid(2) may return information about terminated children that we
591 : did not yet request, and there is no portable way to wait for a
592 : specific set of children.
593 :
594 : As a workaround, we store the results of children for later use.
595 :
596 : XXX: This assumes that PIDs are not reused too quickly. */
597 :
598 : struct terminated_child
599 : {
600 : pid_t pid;
601 : int exitcode;
602 : struct terminated_child *next;
603 : };
604 :
605 : struct terminated_child *terminated_children;
606 :
607 :
608 : static gpg_error_t
609 0 : store_result (pid_t pid, int exitcode)
610 : {
611 : struct terminated_child *c;
612 :
613 0 : c = xtrymalloc (sizeof *c);
614 0 : if (c == NULL)
615 0 : return gpg_err_code_from_syserror ();
616 :
617 0 : c->pid = pid;
618 0 : c->exitcode = exitcode;
619 0 : c->next = terminated_children;
620 0 : terminated_children = c;
621 :
622 0 : return 0;
623 : }
624 :
625 :
626 : static int
627 183 : get_result (pid_t pid, int *r_exitcode)
628 : {
629 : struct terminated_child *c, **prevp;
630 :
631 366 : for (prevp = &terminated_children, c = terminated_children;
632 : c;
633 0 : prevp = &c->next, c = c->next)
634 0 : if (c->pid == pid)
635 : {
636 0 : *prevp = c->next;
637 0 : *r_exitcode = c->exitcode;
638 0 : xfree (c);
639 0 : return 1;
640 : }
641 :
642 183 : return 0;
643 : }
644 :
645 :
646 : /* See exechelp.h for a description. */
647 : gpg_error_t
648 2140 : gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
649 : {
650 : gpg_err_code_t ec;
651 : int i, status;
652 :
653 2140 : if (r_exitcode)
654 2117 : *r_exitcode = -1;
655 :
656 2140 : if (pid == (pid_t)(-1))
657 0 : return gpg_error (GPG_ERR_INV_VALUE);
658 :
659 : #ifdef USE_NPTH
660 0 : i = npth_waitpid (pid, &status, hang? 0:WNOHANG);
661 : #else
662 2140 : while ((i=waitpid (pid, &status, hang? 0:WNOHANG)) == (pid_t)(-1)
663 0 : && errno == EINTR);
664 : #endif
665 :
666 2140 : if (i == (pid_t)(-1))
667 : {
668 0 : ec = gpg_err_code_from_errno (errno);
669 0 : log_error (_("waiting for process %d to terminate failed: %s\n"),
670 0 : (int)pid, strerror (errno));
671 : }
672 2140 : else if (!i)
673 : {
674 0 : ec = GPG_ERR_TIMEOUT; /* Still running. */
675 : }
676 2140 : else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
677 : {
678 0 : log_error (_("error running '%s': probably not installed\n"), pgmname);
679 0 : ec = GPG_ERR_CONFIGURATION;
680 : }
681 2140 : else if (WIFEXITED (status) && WEXITSTATUS (status))
682 19 : {
683 19 : if (!r_exitcode)
684 1 : log_error (_("error running '%s': exit status %d\n"), pgmname,
685 1 : WEXITSTATUS (status));
686 : else
687 18 : *r_exitcode = WEXITSTATUS (status);
688 19 : ec = GPG_ERR_GENERAL;
689 : }
690 2121 : else if (!WIFEXITED (status))
691 : {
692 0 : log_error (_("error running '%s': terminated\n"), pgmname);
693 0 : ec = GPG_ERR_GENERAL;
694 : }
695 : else
696 : {
697 2121 : if (r_exitcode)
698 2099 : *r_exitcode = 0;
699 2121 : ec = 0;
700 : }
701 :
702 2140 : return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
703 : }
704 :
705 : /* See exechelp.h for a description. */
706 : gpg_error_t
707 134 : gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
708 : int hang, int *r_exitcodes)
709 : {
710 134 : gpg_err_code_t ec = 0;
711 : size_t i, left;
712 134 : int *dummy = NULL;
713 :
714 134 : if (r_exitcodes == NULL)
715 : {
716 0 : dummy = r_exitcodes = xtrymalloc (sizeof *r_exitcodes * count);
717 0 : if (dummy == NULL)
718 0 : return gpg_err_code_from_syserror ();
719 : }
720 :
721 317 : for (i = 0, left = count; i < count; i++)
722 : {
723 183 : int status = -1;
724 :
725 183 : if (pids[i] == (pid_t)(-1))
726 0 : return my_error (GPG_ERR_INV_VALUE);
727 :
728 : /* See if there was a previously stored result for this pid. */
729 183 : if (get_result (pids[i], &status))
730 0 : left -= 1;
731 :
732 183 : r_exitcodes[i] = status;
733 : }
734 :
735 451 : while (left > 0)
736 : {
737 : pid_t pid;
738 : int status;
739 :
740 : #ifdef USE_NPTH
741 0 : pid = npth_waitpid (-1, &status, hang ? 0 : WNOHANG);
742 : #else
743 183 : while ((pid = waitpid (-1, &status, hang ? 0 : WNOHANG)) == (pid_t)(-1)
744 0 : && errno == EINTR);
745 : #endif
746 :
747 183 : if (pid == (pid_t)(-1))
748 : {
749 0 : ec = gpg_err_code_from_errno (errno);
750 0 : log_error (_("waiting for processes to terminate failed: %s\n"),
751 0 : strerror (errno));
752 0 : break;
753 : }
754 183 : else if (!pid)
755 : {
756 0 : ec = GPG_ERR_TIMEOUT; /* Still running. */
757 0 : break;
758 : }
759 : else
760 : {
761 233 : for (i = 0; i < count; i++)
762 233 : if (pid == pids[i])
763 183 : break;
764 :
765 183 : if (i == count)
766 : {
767 : /* No match, store this result. */
768 0 : ec = store_result (pid, status);
769 0 : if (ec)
770 0 : break;
771 0 : continue;
772 : }
773 :
774 : /* Process PIDS[i] died. */
775 183 : if (r_exitcodes[i] != (pid_t) -1)
776 : {
777 0 : log_error ("PID %d was reused", pid);
778 0 : ec = GPG_ERR_GENERAL;
779 0 : break;
780 : }
781 :
782 183 : left -= 1;
783 183 : r_exitcodes[i] = status;
784 : }
785 : }
786 :
787 134 : if (ec == 0)
788 317 : for (i = 0; i < count; i++)
789 : {
790 183 : if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
791 : {
792 0 : log_error (_("error running '%s': probably not installed\n"),
793 0 : pgmnames[i]);
794 0 : ec = GPG_ERR_CONFIGURATION;
795 : }
796 183 : else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
797 10 : {
798 10 : if (dummy)
799 0 : log_error (_("error running '%s': exit status %d\n"),
800 0 : pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
801 : else
802 10 : r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
803 10 : ec = GPG_ERR_GENERAL;
804 : }
805 173 : else if (!WIFEXITED (r_exitcodes[i]))
806 : {
807 0 : log_error (_("error running '%s': terminated\n"), pgmnames[i]);
808 0 : ec = GPG_ERR_GENERAL;
809 : }
810 : }
811 :
812 134 : xfree (dummy);
813 134 : return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
814 : }
815 :
816 :
817 :
818 : void
819 23 : gnupg_release_process (pid_t pid)
820 : {
821 : (void)pid;
822 23 : }
823 :
824 :
825 : /* Spawn a new process and immediately detach from it. The name of
826 : the program to exec is PGMNAME and its arguments are in ARGV (the
827 : programname is automatically passed as first argument).
828 : Environment strings in ENVP are set. An error is returned if
829 : pgmname is not executable; to make this work it is necessary to
830 : provide an absolute file name. All standard file descriptors are
831 : connected to /dev/null. */
832 : gpg_error_t
833 48 : gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
834 : const char *envp[] )
835 : {
836 : pid_t pid;
837 : int i;
838 :
839 48 : if (getuid() != geteuid())
840 0 : return my_error (GPG_ERR_BUG);
841 :
842 48 : if (access (pgmname, X_OK))
843 0 : return my_error_from_syserror ();
844 :
845 48 : pid = fork ();
846 96 : if (pid == (pid_t)(-1))
847 : {
848 0 : log_error (_("error forking process: %s\n"), strerror (errno));
849 0 : return my_error_from_syserror ();
850 : }
851 96 : if (!pid)
852 : {
853 : pid_t pid2;
854 :
855 48 : gcry_control (GCRYCTL_TERM_SECMEM);
856 48 : if (setsid() == -1 || chdir ("/"))
857 0 : _exit (1);
858 :
859 48 : pid2 = fork (); /* Double fork to let init take over the new child. */
860 48 : if (pid2 == (pid_t)(-1))
861 0 : _exit (1);
862 48 : if (pid2)
863 0 : _exit (0); /* Let the parent exit immediately. */
864 :
865 48 : if (envp)
866 0 : for (i=0; envp[i]; i++)
867 0 : putenv (xstrdup (envp[i]));
868 :
869 48 : do_exec (pgmname, argv, -1, -1, -1, NULL, NULL);
870 :
871 : /*NOTREACHED*/
872 : }
873 :
874 48 : if (waitpid (pid, NULL, 0) == -1)
875 0 : log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
876 0 : strerror (errno));
877 :
878 48 : return 0;
879 : }
880 :
881 :
882 : /* Kill a process; that is send an appropriate signal to the process.
883 : gnupg_wait_process must be called to actually remove the process
884 : from the system. An invalid PID is ignored. */
885 : void
886 0 : gnupg_kill_process (pid_t pid)
887 : {
888 0 : if (pid != (pid_t)(-1))
889 : {
890 0 : kill (pid, SIGTERM);
891 : }
892 0 : }
|