Move password repetition from gpg to gpg-agent.
[gnupg.git] / common / exechelp.c
blob4da3c97876e46d01b18c5300733c603c7917f3b3
1 /* exechelp.c - fork and exec helpers
2 * Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <fcntl.h>
31 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
32 #undef HAVE_PTH
33 #undef USE_GNU_PTH
34 #endif
36 #ifdef USE_GNU_PTH
37 #include <pth.h>
38 #endif
39 #ifndef HAVE_W32_SYSTEM
40 #include <sys/wait.h>
41 #endif
43 #include "util.h"
44 #include "i18n.h"
45 #include "exechelp.h"
47 /* Define to 1 do enable debugging. */
48 #define DEBUG_W32_SPAWN 1
51 #ifdef _POSIX_OPEN_MAX
52 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
53 #else
54 #define MAX_OPEN_FDS 20
55 #endif
57 /* We have the usual problem here: Some modules are linked against pth
58 and some are not. However we want to use pth_fork and pth_waitpid
59 here. Using a weak symbol works but is not portable - we should
60 provide a an explicit dummy pth module instead of using the
61 pragma. */
62 #ifndef _WIN32
63 #pragma weak pth_fork
64 #pragma weak pth_waitpid
65 #endif
67 #ifdef HAVE_W32_SYSTEM
68 /* It seems Vista doesn't grok X_OK and so fails access() tests.
69 Previous versions interpreted X_OK as F_OK anyway, so we'll just
70 use F_OK directly. */
71 #undef X_OK
72 #define X_OK F_OK
73 #endif /* HAVE_W32_SYSTEM */
76 #ifdef HAVE_W32_SYSTEM
77 /* We assume that a HANDLE can be represented by an int which should
78 be true for all i386 systems (HANDLE is defined as void *) and
79 these are the only systems for which Windows is available. Further
80 we assume that -1 denotes an invalid handle. */
81 # define fd_to_handle(a) ((HANDLE)(a))
82 # define handle_to_fd(a) ((int)(a))
83 # define pid_to_handle(a) ((HANDLE)(a))
84 # define handle_to_pid(a) ((int)(a))
85 #endif
88 #ifdef HAVE_W32_SYSTEM
89 /* Helper function to build_w32_commandline. */
90 static char *
91 build_w32_commandline_copy (char *buffer, const char *string)
93 char *p = buffer;
94 const char *s;
96 if (!*string) /* Empty string. */
97 p = stpcpy (p, "\"\"");
98 else if (strpbrk (string, " \t\n\v\f\""))
100 /* Need top do some kind of quoting. */
101 p = stpcpy (p, "\"");
102 for (s=string; *s; s++)
104 *p++ = *s;
105 if (*s == '\"')
106 *p++ = *s;
108 *p++ = '\"';
109 *p = 0;
111 else
112 p = stpcpy (p, string);
114 return p;
117 /* Build a command line for use with W32's CreateProcess. On success
118 CMDLINE gets the address of a newly allocated string. */
119 static gpg_error_t
120 build_w32_commandline (const char *pgmname, const char * const *argv,
121 char **cmdline)
123 int i, n;
124 const char *s;
125 char *buf, *p;
127 *cmdline = NULL;
128 n = 0;
129 s = pgmname;
130 n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
131 for (; *s; s++)
132 if (*s == '\"')
133 n++; /* Need to double inner quotes. */
134 for (i=0; (s=argv[i]); i++)
136 n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
137 for (; *s; s++)
138 if (*s == '\"')
139 n++; /* Need to double inner quotes. */
141 n++;
143 buf = p = xtrymalloc (n);
144 if (!buf)
145 return gpg_error_from_syserror ();
147 p = build_w32_commandline_copy (p, pgmname);
148 for (i=0; argv[i]; i++)
150 *p++ = ' ';
151 p = build_w32_commandline_copy (p, argv[i]);
154 *cmdline= buf;
155 return 0;
157 #endif /*HAVE_W32_SYSTEM*/
160 #ifdef HAVE_W32_SYSTEM
161 /* Create pipe where the write end is inheritable. */
162 static int
163 create_inheritable_pipe (int filedes[2])
165 HANDLE r, w, h;
166 SECURITY_ATTRIBUTES sec_attr;
168 memset (&sec_attr, 0, sizeof sec_attr );
169 sec_attr.nLength = sizeof sec_attr;
170 sec_attr.bInheritHandle = FALSE;
172 if (!CreatePipe (&r, &w, &sec_attr, 0))
173 return -1;
175 if (!DuplicateHandle (GetCurrentProcess(), w,
176 GetCurrentProcess(), &h, 0,
177 TRUE, DUPLICATE_SAME_ACCESS ))
179 log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
180 CloseHandle (r);
181 CloseHandle (w);
182 return -1;
184 CloseHandle (w);
185 w = h;
187 filedes[0] = handle_to_fd (r);
188 filedes[1] = handle_to_fd (w);
189 return 0;
191 #endif /*HAVE_W32_SYSTEM*/
194 #ifdef HAVE_W32_SYSTEM
195 static HANDLE
196 w32_open_null (int for_write)
198 HANDLE hfile;
200 hfile = CreateFile ("nul",
201 for_write? GENERIC_WRITE : GENERIC_READ,
202 FILE_SHARE_READ | FILE_SHARE_WRITE,
203 NULL, OPEN_EXISTING, 0, NULL);
204 if (hfile == INVALID_HANDLE_VALUE)
205 log_debug ("can't open `nul': %s\n", w32_strerror (-1));
206 return hfile;
208 #endif /*HAVE_W32_SYSTEM*/
211 #ifndef HAVE_W32_SYSTEM
212 /* The exec core used right after the fork. This will never return. */
213 static void
214 do_exec (const char *pgmname, const char *argv[],
215 int fd_in, int fd_out, int fd_err,
216 void (*preexec)(void) )
218 char **arg_list;
219 int n, i, j;
220 int fds[3];
222 fds[0] = fd_in;
223 fds[1] = fd_out;
224 fds[2] = fd_err;
226 /* Create the command line argument array. */
227 i = 0;
228 if (argv)
229 while (argv[i])
230 i++;
231 arg_list = xcalloc (i+2, sizeof *arg_list);
232 arg_list[0] = strrchr (pgmname, '/');
233 if (arg_list[0])
234 arg_list[0]++;
235 else
236 arg_list[0] = xstrdup (pgmname);
237 if (argv)
238 for (i=0,j=1; argv[i]; i++, j++)
239 arg_list[j] = (char*)argv[i];
241 /* Assign /dev/null to unused FDs. */
242 for (i=0; i <= 2; i++)
244 if (fds[i] == -1 )
246 fds[i] = open ("/dev/null", i? O_WRONLY : O_RDONLY);
247 if (fds[i] == -1)
248 log_fatal ("failed to open `%s': %s\n",
249 "/dev/null", strerror (errno));
253 /* Connect the standard files. */
254 for (i=0; i <= 2; i++)
256 if (fds[i] != i && dup2 (fds[i], i) == -1)
257 log_fatal ("dup2 std%s failed: %s\n",
258 i==0?"in":i==1?"out":"err", strerror (errno));
261 /* Close all other files. */
262 n = sysconf (_SC_OPEN_MAX);
263 if (n < 0)
264 n = MAX_OPEN_FDS;
265 for (i=3; i < n; i++)
266 close(i);
267 errno = 0;
269 if (preexec)
270 preexec ();
271 execv (pgmname, arg_list);
272 /* No way to print anything, as we have closed all streams. */
273 _exit (127);
275 #endif /*!HAVE_W32_SYSTEM*/
278 /* Portable function to create a pipe. Under Windows the write end is
279 inheritable. */
280 gpg_error_t
281 gnupg_create_inbound_pipe (int filedes[2])
283 gpg_error_t err = 0;
284 #if HAVE_W32_SYSTEM
285 int fds[2];
287 filedes[0] = filedes[1] = -1;
288 err = gpg_error (GPG_ERR_GENERAL);
289 if (!create_inheritable_pipe (fds))
291 filedes[0] = _open_osfhandle (fds[0], 0);
292 if (filedes[0] == -1)
294 log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
295 CloseHandle (fd_to_handle (fds[1]));
297 else
299 filedes[1] = _open_osfhandle (fds[1], 1);
300 if (filedes[1] == -1)
302 log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
303 close (filedes[0]);
304 filedes[0] = -1;
305 CloseHandle (fd_to_handle (fds[1]));
307 else
308 err = 0;
311 #else
312 if (pipe (filedes) == -1)
314 err = gpg_error_from_syserror ();
315 filedes[0] = filedes[1] = -1;
317 #endif
318 return err;
322 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
323 stdin, write the output to OUTFILE, return a new stream in
324 STATUSFILE for stderr and the pid of the process in PID. The
325 arguments for the process are expected in the NULL terminated array
326 ARGV. The program name itself should not be included there. If
327 PREEXEC is not NULL, that function will be called right before the
328 exec. Calling gnupg_wait_process is required.
330 FLAGS is a bit vector with just one bit defined for now:
332 Bit 7: If set the process will be started as a background process.
333 This flag is only useful under W32 systems, so that no new
334 console is created and pops up a console window when
335 starting the server
337 Returns 0 on success or an error code. */
338 gpg_error_t
339 gnupg_spawn_process (const char *pgmname, const char *argv[],
340 FILE *infile, FILE *outfile,
341 void (*preexec)(void), unsigned int flags,
342 FILE **statusfile, pid_t *pid)
344 #ifdef HAVE_W32_SYSTEM
345 gpg_error_t err;
346 SECURITY_ATTRIBUTES sec_attr;
347 PROCESS_INFORMATION pi =
349 NULL, /* Returns process handle. */
350 0, /* Returns primary thread handle. */
351 0, /* Returns pid. */
352 0 /* Returns tid. */
354 STARTUPINFO si;
355 int cr_flags;
356 char *cmdline;
357 int fd, fdout, rp[2];
359 (void)preexec;
361 /* Setup return values. */
362 *statusfile = NULL;
363 *pid = (pid_t)(-1);
364 fflush (infile);
365 rewind (infile);
366 fd = _get_osfhandle (fileno (infile));
367 fdout = _get_osfhandle (fileno (outfile));
368 if (fd == -1 || fdout == -1)
369 log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
371 /* Prepare security attributes. */
372 memset (&sec_attr, 0, sizeof sec_attr );
373 sec_attr.nLength = sizeof sec_attr;
374 sec_attr.bInheritHandle = FALSE;
376 /* Build the command line. */
377 err = build_w32_commandline (pgmname, argv, &cmdline);
378 if (err)
379 return err;
381 /* Create a pipe. */
382 if (create_inheritable_pipe (rp))
384 err = gpg_error (GPG_ERR_GENERAL);
385 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
386 xfree (cmdline);
387 return err;
390 /* Start the process. Note that we can't run the PREEXEC function
391 because this would change our own environment. */
392 memset (&si, 0, sizeof si);
393 si.cb = sizeof (si);
394 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
395 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
396 si.hStdInput = fd_to_handle (fd);
397 si.hStdOutput = fd_to_handle (fdout);
398 si.hStdError = fd_to_handle (rp[1]);
400 cr_flags = (CREATE_DEFAULT_ERROR_MODE
401 | ((flags & 128)? DETACHED_PROCESS : 0)
402 | GetPriorityClass (GetCurrentProcess ())
403 | CREATE_SUSPENDED);
404 /* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
405 if (!CreateProcess (pgmname, /* Program to start. */
406 cmdline, /* Command line arguments. */
407 &sec_attr, /* Process security attributes. */
408 &sec_attr, /* Thread security attributes. */
409 TRUE, /* Inherit handles. */
410 cr_flags, /* Creation flags. */
411 NULL, /* Environment. */
412 NULL, /* Use current drive/directory. */
413 &si, /* Startup information. */
414 &pi /* Returns process information. */
417 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
418 xfree (cmdline);
419 CloseHandle (fd_to_handle (rp[0]));
420 CloseHandle (fd_to_handle (rp[1]));
421 return gpg_error (GPG_ERR_GENERAL);
423 xfree (cmdline);
424 cmdline = NULL;
426 /* Close the other end of the pipe. */
427 CloseHandle (fd_to_handle (rp[1]));
429 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
430 /* " dwProcessID=%d dwThreadId=%d\n", */
431 /* pi.hProcess, pi.hThread, */
432 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
434 /* Process has been created suspended; resume it now. */
435 ResumeThread (pi.hThread);
436 CloseHandle (pi.hThread);
439 int x;
441 x = _open_osfhandle (rp[0], 0);
442 if (x == -1)
443 log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
444 else
445 *statusfile = fdopen (x, "r");
447 if (!*statusfile)
449 err = gpg_error_from_syserror ();
450 log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err));
451 CloseHandle (pi.hProcess);
452 return err;
455 *pid = handle_to_pid (pi.hProcess);
456 return 0;
458 #else /* !HAVE_W32_SYSTEM */
459 gpg_error_t err;
460 int fd, fdout, rp[2];
462 (void)flags; /* Currently not used. */
464 *statusfile = NULL;
465 *pid = (pid_t)(-1);
466 fflush (infile);
467 rewind (infile);
468 fd = fileno (infile);
469 fdout = fileno (outfile);
470 if (fd == -1 || fdout == -1)
471 log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
473 if (pipe (rp) == -1)
475 err = gpg_error_from_syserror ();
476 log_error (_("error creating a pipe: %s\n"), strerror (errno));
477 return err;
480 #ifdef USE_GNU_PTH
481 *pid = pth_fork? pth_fork () : fork ();
482 #else
483 *pid = fork ();
484 #endif
485 if (*pid == (pid_t)(-1))
487 err = gpg_error_from_syserror ();
488 log_error (_("error forking process: %s\n"), strerror (errno));
489 close (rp[0]);
490 close (rp[1]);
491 return err;
494 if (!*pid)
496 gcry_control (GCRYCTL_TERM_SECMEM);
497 /* Run child. */
498 do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
499 /*NOTREACHED*/
502 /* Parent. */
503 close (rp[1]);
505 *statusfile = fdopen (rp[0], "r");
506 if (!*statusfile)
508 err = gpg_error_from_syserror ();
509 log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno));
510 kill (*pid, SIGTERM);
511 *pid = (pid_t)(-1);
512 return err;
515 return 0;
516 #endif /* !HAVE_W32_SYSTEM */
521 /* Simplified version of gnupg_spawn_process. This function forks and
522 then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
523 and ERRFD to stderr (any of them may be -1 to connect them to
524 /dev/null). The arguments for the process are expected in the NULL
525 terminated array ARGV. The program name itself should not be
526 included there. Calling gnupg_wait_process is required.
528 Returns 0 on success or an error code. */
529 gpg_error_t
530 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
531 int infd, int outfd, int errfd, pid_t *pid)
533 #ifdef HAVE_W32_SYSTEM
534 gpg_error_t err;
535 SECURITY_ATTRIBUTES sec_attr;
536 PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
537 STARTUPINFO si;
538 char *cmdline;
539 int i;
540 HANDLE stdhd[3];
542 /* Setup return values. */
543 *pid = (pid_t)(-1);
545 /* Prepare security attributes. */
546 memset (&sec_attr, 0, sizeof sec_attr );
547 sec_attr.nLength = sizeof sec_attr;
548 sec_attr.bInheritHandle = FALSE;
550 /* Build the command line. */
551 err = build_w32_commandline (pgmname, argv, &cmdline);
552 if (err)
553 return err;
555 memset (&si, 0, sizeof si);
556 si.cb = sizeof (si);
557 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
558 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
559 stdhd[0] = infd == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
560 stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
561 stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
562 si.hStdInput = infd == -1? stdhd[0] : (void*)_get_osfhandle (infd);
563 si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
564 si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
566 /* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
567 if (!CreateProcess (pgmname, /* Program to start. */
568 cmdline, /* Command line arguments. */
569 &sec_attr, /* Process security attributes. */
570 &sec_attr, /* Thread security attributes. */
571 TRUE, /* Inherit handles. */
572 (CREATE_DEFAULT_ERROR_MODE
573 | GetPriorityClass (GetCurrentProcess ())
574 | CREATE_SUSPENDED | DETACHED_PROCESS),
575 NULL, /* Environment. */
576 NULL, /* Use current drive/directory. */
577 &si, /* Startup information. */
578 &pi /* Returns process information. */
581 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
582 err = gpg_error (GPG_ERR_GENERAL);
584 else
585 err = 0;
586 xfree (cmdline);
587 for (i=0; i < 3; i++)
588 if (stdhd[i] != INVALID_HANDLE_VALUE)
589 CloseHandle (stdhd[i]);
590 if (err)
591 return err;
593 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
594 /* " dwProcessID=%d dwThreadId=%d\n", */
595 /* pi.hProcess, pi.hThread, */
596 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
598 /* Process has been created suspended; resume it now. */
599 ResumeThread (pi.hThread);
600 CloseHandle (pi.hThread);
602 *pid = handle_to_pid (pi.hProcess);
603 return 0;
605 #else /* !HAVE_W32_SYSTEM */
606 gpg_error_t err;
608 #ifdef USE_GNU_PTH
609 *pid = pth_fork? pth_fork () : fork ();
610 #else
611 *pid = fork ();
612 #endif
613 if (*pid == (pid_t)(-1))
615 err = gpg_error_from_syserror ();
616 log_error (_("error forking process: %s\n"), strerror (errno));
617 return err;
620 if (!*pid)
622 gcry_control (GCRYCTL_TERM_SECMEM);
623 /* Run child. */
624 do_exec (pgmname, argv, infd, outfd, errfd, NULL);
625 /*NOTREACHED*/
628 return 0;
629 #endif /* !HAVE_W32_SYSTEM */
633 /* Wait for the process identified by PID to terminate. PGMNAME should
634 be the same as supplied to the spawn function and is only used for
635 diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
636 for any failures of the spawned program or other error codes. If
637 EXITCODE is not NULL the exit code of the process is stored at this
638 address or -1 if it could not be retrieved. */
639 gpg_error_t
640 gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
642 gpg_err_code_t ec;
644 #ifdef HAVE_W32_SYSTEM
645 HANDLE proc = fd_to_handle (pid);
646 int code;
647 DWORD exc;
649 if (exitcode)
650 *exitcode = -1;
652 if (pid == (pid_t)(-1))
653 return gpg_error (GPG_ERR_INV_VALUE);
655 /* FIXME: We should do a pth_waitpid here. However this has not yet
656 been implemented. A special W32 pth system call would even be
657 better. */
658 code = WaitForSingleObject (proc, INFINITE);
659 switch (code)
661 case WAIT_FAILED:
662 log_error (_("waiting for process %d to terminate failed: %s\n"),
663 (int)pid, w32_strerror (-1));
664 ec = GPG_ERR_GENERAL;
665 break;
667 case WAIT_OBJECT_0:
668 if (!GetExitCodeProcess (proc, &exc))
670 log_error (_("error getting exit code of process %d: %s\n"),
671 (int)pid, w32_strerror (-1) );
672 ec = GPG_ERR_GENERAL;
674 else if (exc)
676 log_error (_("error running `%s': exit status %d\n"),
677 pgmname, (int)exc );
678 if (exitcode)
679 *exitcode = (int)exc;
680 ec = GPG_ERR_GENERAL;
682 else
684 if (exitcode)
685 *exitcode = 0;
686 ec = 0;
688 CloseHandle (proc);
689 break;
691 default:
692 log_error ("WaitForSingleObject returned unexpected "
693 "code %d for pid %d\n", code, (int)pid );
694 ec = GPG_ERR_GENERAL;
695 break;
698 #else /* !HAVE_W32_SYSTEM */
699 int i, status;
701 if (exitcode)
702 *exitcode = -1;
704 if (pid == (pid_t)(-1))
705 return gpg_error (GPG_ERR_INV_VALUE);
707 #ifdef USE_GNU_PTH
708 i = pth_waitpid ? pth_waitpid (pid, &status, 0) : waitpid (pid, &status, 0);
709 #else
710 while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
712 #endif
713 if (i == (pid_t)(-1))
715 log_error (_("waiting for process %d to terminate failed: %s\n"),
716 (int)pid, strerror (errno));
717 ec = gpg_err_code_from_errno (errno);
719 else if (WIFEXITED (status) && WEXITSTATUS (status) == 127)
721 log_error (_("error running `%s': probably not installed\n"), pgmname);
722 ec = GPG_ERR_CONFIGURATION;
724 else if (WIFEXITED (status) && WEXITSTATUS (status))
726 log_error (_("error running `%s': exit status %d\n"), pgmname,
727 WEXITSTATUS (status));
728 if (exitcode)
729 *exitcode = WEXITSTATUS (status);
730 ec = GPG_ERR_GENERAL;
732 else if (!WIFEXITED (status))
734 log_error (_("error running `%s': terminated\n"), pgmname);
735 ec = GPG_ERR_GENERAL;
737 else
739 if (exitcode)
740 *exitcode = 0;
741 ec = 0;
743 #endif /* !HAVE_W32_SYSTEM */
745 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
749 /* Spawn a new process and immediatley detach from it. The name of
750 the program to exec is PGMNAME and its arguments are in ARGV (the
751 programname is automatically passed as first argument).
752 Environment strings in ENVP are set. An error is returned if
753 pgmname is not executable; to make this work it is necessary to
754 provide an absolute file name. All standard file descriptors are
755 connected to /dev/null. */
756 gpg_error_t
757 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
758 const char *envp[] )
760 #ifdef HAVE_W32_SYSTEM
761 gpg_error_t err;
762 SECURITY_ATTRIBUTES sec_attr;
763 PROCESS_INFORMATION pi =
765 NULL, /* Returns process handle. */
766 0, /* Returns primary thread handle. */
767 0, /* Returns pid. */
768 0 /* Returns tid. */
770 STARTUPINFO si;
771 int cr_flags;
772 char *cmdline;
775 /* FIXME: We don't make use of ENVP yet. It is currently only used
776 to pass the GPG_AGENT_INFO variable to gpg-agent. As the default
777 on windows is to use a standard socket, this does not really
778 matter. */
779 (void)envp;
781 if (access (pgmname, X_OK))
782 return gpg_error_from_syserror ();
784 /* Prepare security attributes. */
785 memset (&sec_attr, 0, sizeof sec_attr );
786 sec_attr.nLength = sizeof sec_attr;
787 sec_attr.bInheritHandle = FALSE;
789 /* Build the command line. */
790 err = build_w32_commandline (pgmname, argv, &cmdline);
791 if (err)
792 return err;
794 /* Start the process. */
795 memset (&si, 0, sizeof si);
796 si.cb = sizeof (si);
797 si.dwFlags = STARTF_USESHOWWINDOW;
798 si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
800 cr_flags = (CREATE_DEFAULT_ERROR_MODE
801 | GetPriorityClass (GetCurrentProcess ())
802 | CREATE_NEW_PROCESS_GROUP
803 | DETACHED_PROCESS);
804 /* log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
805 /* pgmname, cmdline); */
806 if (!CreateProcess (pgmname, /* Program to start. */
807 cmdline, /* Command line arguments. */
808 &sec_attr, /* Process security attributes. */
809 &sec_attr, /* Thread security attributes. */
810 FALSE, /* Inherit handles. */
811 cr_flags, /* Creation flags. */
812 NULL, /* Environment. */
813 NULL, /* Use current drive/directory. */
814 &si, /* Startup information. */
815 &pi /* Returns process information. */
818 log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
819 xfree (cmdline);
820 return gpg_error (GPG_ERR_GENERAL);
822 xfree (cmdline);
823 cmdline = NULL;
825 /* log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
826 /* " dwProcessID=%d dwThreadId=%d\n", */
827 /* pi.hProcess, pi.hThread, */
828 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
830 CloseHandle (pi.hThread);
832 return 0;
834 #else
835 pid_t pid;
836 int i;
838 if (getuid() != geteuid())
839 return gpg_error (GPG_ERR_BUG);
841 if (access (pgmname, X_OK))
842 return gpg_error_from_syserror ();
844 #ifdef USE_GNU_PTH
845 pid = pth_fork? pth_fork () : fork ();
846 #else
847 pid = fork ();
848 #endif
849 if (pid == (pid_t)(-1))
851 log_error (_("error forking process: %s\n"), strerror (errno));
852 return gpg_error_from_syserror ();
854 if (!pid)
856 gcry_control (GCRYCTL_TERM_SECMEM);
857 if (setsid() == -1 || chdir ("/"))
858 _exit (1);
859 pid = fork (); /* Double fork to let init takes over the new child. */
860 if (pid == (pid_t)(-1))
861 _exit (1);
862 if (pid)
863 _exit (0); /* Let the parent exit immediately. */
865 if (envp)
866 for (i=0; envp[i]; i++)
867 putenv (xstrdup (envp[i]));
869 do_exec (pgmname, argv, -1, -1, -1, NULL);
871 /*NOTREACHED*/
874 if (waitpid (pid, NULL, 0) == -1)
875 log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
876 strerror (errno));
878 return 0;
879 #endif /* !HAVE_W32_SYSTEM*/