1 /* exechelp.c - fork and exec helpers
2 * Copyright (C) 2004, 2007, 2008, 2009 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/>.
31 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
39 #ifndef HAVE_W32_SYSTEM
45 #include <sys/resource.h>
46 #endif /*HAVE_GETRLIMIT*/
49 # include <sys/stat.h>
58 /* Define to 1 do enable debugging. */
59 #define DEBUG_W32_SPAWN 1
62 /* We have the usual problem here: Some modules are linked against pth
63 and some are not. However we want to use pth_fork and pth_waitpid
64 here. Using a weak symbol works but is not portable - we should
65 provide a an explicit dummy pth module instead of using the
69 #pragma weak pth_waitpid
72 #ifdef HAVE_W32_SYSTEM
73 /* It seems Vista doesn't grok X_OK and so fails access() tests.
74 Previous versions interpreted X_OK as F_OK anyway, so we'll just
78 #endif /* HAVE_W32_SYSTEM */
81 #ifdef HAVE_W32_SYSTEM
82 /* We assume that a HANDLE can be represented by an int which should
83 be true for all i386 systems (HANDLE is defined as void *) and
84 these are the only systems for which Windows is available. Further
85 we assume that -1 denotes an invalid handle. */
86 # define fd_to_handle(a) ((HANDLE)(a))
87 # define handle_to_fd(a) ((int)(a))
88 # define pid_to_handle(a) ((HANDLE)(a))
89 # define handle_to_pid(a) ((int)(a))
93 /* Return the maximum number of currently allowed open file
94 descriptors. Only useful on POSIX systems but returns a value on
100 #ifdef HAVE_GETRLIMIT
103 # ifdef RLIMIT_NOFILE
104 if (!getrlimit (RLIMIT_NOFILE
, &rl
))
105 max_fds
= rl
.rlim_max
;
109 if (max_fds
== -1 && !getrlimit (RLIMIT_OFILE
, &rl
))
110 max_fds
= rl
.rlim_max
;
113 #endif /*HAVE_GETRLIMIT*/
118 long int scres
= sysconf (_SC_OPEN_MAX
);
124 #ifdef _POSIX_OPEN_MAX
126 max_fds
= _POSIX_OPEN_MAX
;
135 max_fds
= 256; /* Arbitrary limit. */
141 /* Close all file descriptors starting with descriptor FIRST. If
142 EXCEPT is not NULL, it is expected to be a list of file descriptors
143 which shall not be closed. This list shall be sorted in ascending
144 order with the end marked by -1. */
146 close_all_fds (int first
, int *except
)
148 int max_fd
= get_max_fds ();
149 int fd
, i
, except_start
;
154 for (fd
=first
; fd
< max_fd
; fd
++)
156 for (i
=except_start
; except
[i
] != -1; i
++)
160 /* If we found the descriptor in the exception list
161 we can start the next compare run at the next
162 index because the exception list is ordered. */
163 except_start
= i
+ 1;
173 for (fd
=first
; fd
< max_fd
; fd
++)
181 /* Returns an array with all currently open file descriptors. The end
182 of the array is marked by -1. The caller needs to release this
183 array using the *standard free* and not with xfree. This allow the
184 use of this fucntion right at startup even before libgcrypt has
185 been initialized. Returns NULL on error and sets ERRNO
188 get_all_open_fds (void)
194 array
= calloc (1, sizeof *array
);
200 max_fd
= get_max_fds ();
201 narray
= 32; /* If you change this change also t-exechelp.c. */
202 array
= calloc (narray
, sizeof *array
);
206 /* Note: The list we return is ordered. */
207 for (idx
=0, fd
=0; fd
< max_fd
; fd
++)
208 if (!(fstat (fd
, &statbuf
) == -1 && errno
== EBADF
))
214 narray
+= (narray
< 256)? 32:256;
215 tmp
= realloc (array
, narray
* sizeof *array
);
232 #ifdef HAVE_W32_SYSTEM
233 /* Helper function to build_w32_commandline. */
235 build_w32_commandline_copy (char *buffer
, const char *string
)
240 if (!*string
) /* Empty string. */
241 p
= stpcpy (p
, "\"\"");
242 else if (strpbrk (string
, " \t\n\v\f\""))
244 /* Need top do some kind of quoting. */
245 p
= stpcpy (p
, "\"");
246 for (s
=string
; *s
; s
++)
256 p
= stpcpy (p
, string
);
261 /* Build a command line for use with W32's CreateProcess. On success
262 CMDLINE gets the address of a newly allocated string. */
264 build_w32_commandline (const char *pgmname
, const char * const *argv
,
274 n
+= strlen (s
) + 1 + 2; /* (1 space, 2 quoting */
277 n
++; /* Need to double inner quotes. */
278 for (i
=0; (s
=argv
[i
]); i
++)
280 n
+= strlen (s
) + 1 + 2; /* (1 space, 2 quoting */
283 n
++; /* Need to double inner quotes. */
287 buf
= p
= xtrymalloc (n
);
289 return gpg_error_from_syserror ();
291 p
= build_w32_commandline_copy (p
, pgmname
);
292 for (i
=0; argv
[i
]; i
++)
295 p
= build_w32_commandline_copy (p
, argv
[i
]);
301 #endif /*HAVE_W32_SYSTEM*/
304 #ifdef HAVE_W32_SYSTEM
305 /* Create pipe where the write end is inheritable. */
307 create_inheritable_pipe (int filedes
[2])
310 SECURITY_ATTRIBUTES sec_attr
;
312 memset (&sec_attr
, 0, sizeof sec_attr
);
313 sec_attr
.nLength
= sizeof sec_attr
;
314 sec_attr
.bInheritHandle
= FALSE
;
316 if (!CreatePipe (&r
, &w
, &sec_attr
, 0))
319 if (!DuplicateHandle (GetCurrentProcess(), w
,
320 GetCurrentProcess(), &h
, 0,
321 TRUE
, DUPLICATE_SAME_ACCESS
))
323 log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
331 filedes
[0] = handle_to_fd (r
);
332 filedes
[1] = handle_to_fd (w
);
335 #endif /*HAVE_W32_SYSTEM*/
338 #ifdef HAVE_W32_SYSTEM
340 w32_open_null (int for_write
)
344 hfile
= CreateFile ("nul",
345 for_write
? GENERIC_WRITE
: GENERIC_READ
,
346 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
347 NULL
, OPEN_EXISTING
, 0, NULL
);
348 if (hfile
== INVALID_HANDLE_VALUE
)
349 log_debug ("can't open `nul': %s\n", w32_strerror (-1));
352 #endif /*HAVE_W32_SYSTEM*/
355 #ifndef HAVE_W32_SYSTEM
356 /* The exec core used right after the fork. This will never return. */
358 do_exec (const char *pgmname
, const char *argv
[],
359 int fd_in
, int fd_out
, int fd_err
,
360 void (*preexec
)(void) )
370 /* Create the command line argument array. */
375 arg_list
= xcalloc (i
+2, sizeof *arg_list
);
376 arg_list
[0] = strrchr (pgmname
, '/');
380 arg_list
[0] = xstrdup (pgmname
);
382 for (i
=0,j
=1; argv
[i
]; i
++, j
++)
383 arg_list
[j
] = (char*)argv
[i
];
385 /* Assign /dev/null to unused FDs. */
386 for (i
=0; i
<= 2; i
++)
390 fds
[i
] = open ("/dev/null", i
? O_WRONLY
: O_RDONLY
);
392 log_fatal ("failed to open `%s': %s\n",
393 "/dev/null", strerror (errno
));
397 /* Connect the standard files. */
398 for (i
=0; i
<= 2; i
++)
400 if (fds
[i
] != i
&& dup2 (fds
[i
], i
) == -1)
401 log_fatal ("dup2 std%s failed: %s\n",
402 i
==0?"in":i
==1?"out":"err", strerror (errno
));
405 /* Close all other files. */
406 close_all_fds (3, NULL
);
410 execv (pgmname
, arg_list
);
411 /* No way to print anything, as we have closed all streams. */
414 #endif /*!HAVE_W32_SYSTEM*/
417 /* Portable function to create a pipe. Under Windows the write end is
420 gnupg_create_inbound_pipe (int filedes
[2])
426 filedes
[0] = filedes
[1] = -1;
427 err
= gpg_error (GPG_ERR_GENERAL
);
428 if (!create_inheritable_pipe (fds
))
430 filedes
[0] = _open_osfhandle (fds
[0], 0);
431 if (filedes
[0] == -1)
433 log_error ("failed to translate osfhandle %p\n", (void*)fds
[0]);
434 CloseHandle (fd_to_handle (fds
[1]));
438 filedes
[1] = _open_osfhandle (fds
[1], 1);
439 if (filedes
[1] == -1)
441 log_error ("failed to translate osfhandle %p\n", (void*)fds
[1]);
444 CloseHandle (fd_to_handle (fds
[1]));
451 if (pipe (filedes
) == -1)
453 err
= gpg_error_from_syserror ();
454 filedes
[0] = filedes
[1] = -1;
461 /* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
462 stdin, write the output to OUTFILE, return a new stream in
463 STATUSFILE for stderr and the pid of the process in PID. The
464 arguments for the process are expected in the NULL terminated array
465 ARGV. The program name itself should not be included there. If
466 PREEXEC is not NULL, that function will be called right before the
467 exec. Calling gnupg_wait_process is required.
469 FLAGS is a bit vector with just one bit defined for now:
471 Bit 7: If set the process will be started as a background process.
472 This flag is only useful under W32 systems, so that no new
473 console is created and pops up a console window when
476 Bit 6: On W32 run AllowSetForegroundWindow for the child. Due to
477 error problems this actually allows SetForegroundWindow for
478 childs of this process.
480 Returns 0 on success or an error code. */
482 gnupg_spawn_process (const char *pgmname
, const char *argv
[],
483 FILE *infile
, FILE *outfile
,
484 void (*preexec
)(void), unsigned int flags
,
485 FILE **statusfile
, pid_t
*pid
)
487 #ifdef HAVE_W32_SYSTEM
489 SECURITY_ATTRIBUTES sec_attr
;
490 PROCESS_INFORMATION pi
=
492 NULL
, /* Returns process handle. */
493 0, /* Returns primary thread handle. */
494 0, /* Returns pid. */
500 int fd
, fdout
, rp
[2];
504 /* Setup return values. */
509 fd
= _get_osfhandle (fileno (infile
));
510 fdout
= _get_osfhandle (fileno (outfile
));
511 if (fd
== -1 || fdout
== -1)
512 log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
514 /* Prepare security attributes. */
515 memset (&sec_attr
, 0, sizeof sec_attr
);
516 sec_attr
.nLength
= sizeof sec_attr
;
517 sec_attr
.bInheritHandle
= FALSE
;
519 /* Build the command line. */
520 err
= build_w32_commandline (pgmname
, argv
, &cmdline
);
525 if (create_inheritable_pipe (rp
))
527 err
= gpg_error (GPG_ERR_GENERAL
);
528 log_error (_("error creating a pipe: %s\n"), gpg_strerror (err
));
533 /* Start the process. Note that we can't run the PREEXEC function
534 because this would change our own environment. */
535 memset (&si
, 0, sizeof si
);
537 si
.dwFlags
= STARTF_USESTDHANDLES
| STARTF_USESHOWWINDOW
;
538 si
.wShowWindow
= DEBUG_W32_SPAWN
? SW_SHOW
: SW_MINIMIZE
;
539 si
.hStdInput
= fd_to_handle (fd
);
540 si
.hStdOutput
= fd_to_handle (fdout
);
541 si
.hStdError
= fd_to_handle (rp
[1]);
543 cr_flags
= (CREATE_DEFAULT_ERROR_MODE
544 | ((flags
& 128)? DETACHED_PROCESS
: 0)
545 | GetPriorityClass (GetCurrentProcess ())
547 /* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
548 if (!CreateProcess (pgmname
, /* Program to start. */
549 cmdline
, /* Command line arguments. */
550 &sec_attr
, /* Process security attributes. */
551 &sec_attr
, /* Thread security attributes. */
552 TRUE
, /* Inherit handles. */
553 cr_flags
, /* Creation flags. */
554 NULL
, /* Environment. */
555 NULL
, /* Use current drive/directory. */
556 &si
, /* Startup information. */
557 &pi
/* Returns process information. */
560 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
562 CloseHandle (fd_to_handle (rp
[0]));
563 CloseHandle (fd_to_handle (rp
[1]));
564 return gpg_error (GPG_ERR_GENERAL
);
569 /* Close the other end of the pipe. */
570 CloseHandle (fd_to_handle (rp
[1]));
572 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
573 /* " dwProcessID=%d dwThreadId=%d\n", */
574 /* pi.hProcess, pi.hThread, */
575 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
577 /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
578 invalid argument error if we pass the the correct processID to
579 it. As a workaround we use -1 (ASFW_ANY). */
581 gnupg_allow_set_foregound_window ((pid_t
)(-1)/*pi.dwProcessId*/);
583 /* Process has been created suspended; resume it now. */
584 ResumeThread (pi
.hThread
);
585 CloseHandle (pi
.hThread
);
590 x
= _open_osfhandle (rp
[0], 0);
592 log_error ("failed to translate osfhandle %p\n", (void*)rp
[0] );
594 *statusfile
= fdopen (x
, "r");
598 err
= gpg_error_from_syserror ();
599 log_error (_("can't fdopen pipe for reading: %s\n"), gpg_strerror (err
));
600 CloseHandle (pi
.hProcess
);
604 *pid
= handle_to_pid (pi
.hProcess
);
607 #else /* !HAVE_W32_SYSTEM */
609 int fd
, fdout
, rp
[2];
611 (void)flags
; /* Currently not used. */
617 fd
= fileno (infile
);
618 fdout
= fileno (outfile
);
619 if (fd
== -1 || fdout
== -1)
620 log_fatal ("no file descriptor for file passed to gnupg_spawn_process\n");
624 err
= gpg_error_from_syserror ();
625 log_error (_("error creating a pipe: %s\n"), strerror (errno
));
630 *pid
= pth_fork
? pth_fork () : fork ();
634 if (*pid
== (pid_t
)(-1))
636 err
= gpg_error_from_syserror ();
637 log_error (_("error forking process: %s\n"), strerror (errno
));
645 gcry_control (GCRYCTL_TERM_SECMEM
);
647 do_exec (pgmname
, argv
, fd
, fdout
, rp
[1], preexec
);
654 *statusfile
= fdopen (rp
[0], "r");
657 err
= gpg_error_from_syserror ();
658 log_error (_("can't fdopen pipe for reading: %s\n"), strerror (errno
));
659 kill (*pid
, SIGTERM
);
665 #endif /* !HAVE_W32_SYSTEM */
670 /* Simplified version of gnupg_spawn_process. This function forks and
671 then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
672 and ERRFD to stderr (any of them may be -1 to connect them to
673 /dev/null). The arguments for the process are expected in the NULL
674 terminated array ARGV. The program name itself should not be
675 included there. Calling gnupg_wait_process is required.
677 Returns 0 on success or an error code. */
679 gnupg_spawn_process_fd (const char *pgmname
, const char *argv
[],
680 int infd
, int outfd
, int errfd
, pid_t
*pid
)
682 #ifdef HAVE_W32_SYSTEM
684 SECURITY_ATTRIBUTES sec_attr
;
685 PROCESS_INFORMATION pi
= { NULL
, 0, 0, 0 };
691 /* Setup return values. */
694 /* Prepare security attributes. */
695 memset (&sec_attr
, 0, sizeof sec_attr
);
696 sec_attr
.nLength
= sizeof sec_attr
;
697 sec_attr
.bInheritHandle
= FALSE
;
699 /* Build the command line. */
700 err
= build_w32_commandline (pgmname
, argv
, &cmdline
);
704 memset (&si
, 0, sizeof si
);
706 si
.dwFlags
= STARTF_USESTDHANDLES
| STARTF_USESHOWWINDOW
;
707 si
.wShowWindow
= DEBUG_W32_SPAWN
? SW_SHOW
: SW_MINIMIZE
;
708 stdhd
[0] = infd
== -1? w32_open_null (0) : INVALID_HANDLE_VALUE
;
709 stdhd
[1] = outfd
== -1? w32_open_null (1) : INVALID_HANDLE_VALUE
;
710 stdhd
[2] = errfd
== -1? w32_open_null (1) : INVALID_HANDLE_VALUE
;
711 si
.hStdInput
= infd
== -1? stdhd
[0] : (void*)_get_osfhandle (infd
);
712 si
.hStdOutput
= outfd
== -1? stdhd
[1] : (void*)_get_osfhandle (outfd
);
713 si
.hStdError
= errfd
== -1? stdhd
[2] : (void*)_get_osfhandle (errfd
);
715 /* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
716 if (!CreateProcess (pgmname
, /* Program to start. */
717 cmdline
, /* Command line arguments. */
718 &sec_attr
, /* Process security attributes. */
719 &sec_attr
, /* Thread security attributes. */
720 TRUE
, /* Inherit handles. */
721 (CREATE_DEFAULT_ERROR_MODE
722 | GetPriorityClass (GetCurrentProcess ())
723 | CREATE_SUSPENDED
| DETACHED_PROCESS
),
724 NULL
, /* Environment. */
725 NULL
, /* Use current drive/directory. */
726 &si
, /* Startup information. */
727 &pi
/* Returns process information. */
730 log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
731 err
= gpg_error (GPG_ERR_GENERAL
);
736 for (i
=0; i
< 3; i
++)
737 if (stdhd
[i
] != INVALID_HANDLE_VALUE
)
738 CloseHandle (stdhd
[i
]);
742 /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
743 /* " dwProcessID=%d dwThreadId=%d\n", */
744 /* pi.hProcess, pi.hThread, */
745 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
747 /* Process has been created suspended; resume it now. */
748 ResumeThread (pi
.hThread
);
749 CloseHandle (pi
.hThread
);
751 *pid
= handle_to_pid (pi
.hProcess
);
754 #else /* !HAVE_W32_SYSTEM */
758 *pid
= pth_fork
? pth_fork () : fork ();
762 if (*pid
== (pid_t
)(-1))
764 err
= gpg_error_from_syserror ();
765 log_error (_("error forking process: %s\n"), strerror (errno
));
771 gcry_control (GCRYCTL_TERM_SECMEM
);
773 do_exec (pgmname
, argv
, infd
, outfd
, errfd
, NULL
);
778 #endif /* !HAVE_W32_SYSTEM */
782 /* Wait for the process identified by PID to terminate. PGMNAME should
783 be the same as supplied to the spawn function and is only used for
784 diagnostics. Returns 0 if the process succeeded, GPG_ERR_GENERAL
785 for any failures of the spawned program or other error codes. If
786 EXITCODE is not NULL the exit code of the process is stored at this
787 address or -1 if it could not be retrieved. */
789 gnupg_wait_process (const char *pgmname
, pid_t pid
, int *exitcode
)
793 #ifdef HAVE_W32_SYSTEM
794 HANDLE proc
= fd_to_handle (pid
);
801 if (pid
== (pid_t
)(-1))
802 return gpg_error (GPG_ERR_INV_VALUE
);
804 /* FIXME: We should do a pth_waitpid here. However this has not yet
805 been implemented. A special W32 pth system call would even be
807 code
= WaitForSingleObject (proc
, INFINITE
);
811 log_error (_("waiting for process %d to terminate failed: %s\n"),
812 (int)pid
, w32_strerror (-1));
813 ec
= GPG_ERR_GENERAL
;
817 if (!GetExitCodeProcess (proc
, &exc
))
819 log_error (_("error getting exit code of process %d: %s\n"),
820 (int)pid
, w32_strerror (-1) );
821 ec
= GPG_ERR_GENERAL
;
825 log_error (_("error running `%s': exit status %d\n"),
828 *exitcode
= (int)exc
;
829 ec
= GPG_ERR_GENERAL
;
841 log_error ("WaitForSingleObject returned unexpected "
842 "code %d for pid %d\n", code
, (int)pid
);
843 ec
= GPG_ERR_GENERAL
;
847 #else /* !HAVE_W32_SYSTEM */
853 if (pid
== (pid_t
)(-1))
854 return gpg_error (GPG_ERR_INV_VALUE
);
857 i
= pth_waitpid
? pth_waitpid (pid
, &status
, 0) : waitpid (pid
, &status
, 0);
859 while ( (i
=waitpid (pid
, &status
, 0)) == -1 && errno
== EINTR
)
862 if (i
== (pid_t
)(-1))
864 log_error (_("waiting for process %d to terminate failed: %s\n"),
865 (int)pid
, strerror (errno
));
866 ec
= gpg_err_code_from_errno (errno
);
868 else if (WIFEXITED (status
) && WEXITSTATUS (status
) == 127)
870 log_error (_("error running `%s': probably not installed\n"), pgmname
);
871 ec
= GPG_ERR_CONFIGURATION
;
873 else if (WIFEXITED (status
) && WEXITSTATUS (status
))
875 log_error (_("error running `%s': exit status %d\n"), pgmname
,
876 WEXITSTATUS (status
));
878 *exitcode
= WEXITSTATUS (status
);
879 ec
= GPG_ERR_GENERAL
;
881 else if (!WIFEXITED (status
))
883 log_error (_("error running `%s': terminated\n"), pgmname
);
884 ec
= GPG_ERR_GENERAL
;
892 #endif /* !HAVE_W32_SYSTEM */
894 return gpg_err_make (GPG_ERR_SOURCE_DEFAULT
, ec
);
898 /* Spawn a new process and immediatley detach from it. The name of
899 the program to exec is PGMNAME and its arguments are in ARGV (the
900 programname is automatically passed as first argument).
901 Environment strings in ENVP are set. An error is returned if
902 pgmname is not executable; to make this work it is necessary to
903 provide an absolute file name. All standard file descriptors are
904 connected to /dev/null. */
906 gnupg_spawn_process_detached (const char *pgmname
, const char *argv
[],
909 #ifdef HAVE_W32_SYSTEM
911 SECURITY_ATTRIBUTES sec_attr
;
912 PROCESS_INFORMATION pi
=
914 NULL
, /* Returns process handle. */
915 0, /* Returns primary thread handle. */
916 0, /* Returns pid. */
924 /* FIXME: We don't make use of ENVP yet. It is currently only used
925 to pass the GPG_AGENT_INFO variable to gpg-agent. As the default
926 on windows is to use a standard socket, this does not really
930 if (access (pgmname
, X_OK
))
931 return gpg_error_from_syserror ();
933 /* Prepare security attributes. */
934 memset (&sec_attr
, 0, sizeof sec_attr
);
935 sec_attr
.nLength
= sizeof sec_attr
;
936 sec_attr
.bInheritHandle
= FALSE
;
938 /* Build the command line. */
939 err
= build_w32_commandline (pgmname
, argv
, &cmdline
);
943 /* Start the process. */
944 memset (&si
, 0, sizeof si
);
946 si
.dwFlags
= STARTF_USESHOWWINDOW
;
947 si
.wShowWindow
= DEBUG_W32_SPAWN
? SW_SHOW
: SW_MINIMIZE
;
949 cr_flags
= (CREATE_DEFAULT_ERROR_MODE
950 | GetPriorityClass (GetCurrentProcess ())
951 | CREATE_NEW_PROCESS_GROUP
953 /* log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
954 /* pgmname, cmdline); */
955 if (!CreateProcess (pgmname
, /* Program to start. */
956 cmdline
, /* Command line arguments. */
957 &sec_attr
, /* Process security attributes. */
958 &sec_attr
, /* Thread security attributes. */
959 FALSE
, /* Inherit handles. */
960 cr_flags
, /* Creation flags. */
961 NULL
, /* Environment. */
962 NULL
, /* Use current drive/directory. */
963 &si
, /* Startup information. */
964 &pi
/* Returns process information. */
967 log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
969 return gpg_error (GPG_ERR_GENERAL
);
974 /* log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
975 /* " dwProcessID=%d dwThreadId=%d\n", */
976 /* pi.hProcess, pi.hThread, */
977 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
979 CloseHandle (pi
.hThread
);
987 if (getuid() != geteuid())
988 return gpg_error (GPG_ERR_BUG
);
990 if (access (pgmname
, X_OK
))
991 return gpg_error_from_syserror ();
994 pid
= pth_fork
? pth_fork () : fork ();
998 if (pid
== (pid_t
)(-1))
1000 log_error (_("error forking process: %s\n"), strerror (errno
));
1001 return gpg_error_from_syserror ();
1005 gcry_control (GCRYCTL_TERM_SECMEM
);
1006 if (setsid() == -1 || chdir ("/"))
1008 pid
= fork (); /* Double fork to let init takes over the new child. */
1009 if (pid
== (pid_t
)(-1))
1012 _exit (0); /* Let the parent exit immediately. */
1015 for (i
=0; envp
[i
]; i
++)
1016 putenv (xstrdup (envp
[i
]));
1018 do_exec (pgmname
, argv
, -1, -1, -1, NULL
);
1023 if (waitpid (pid
, NULL
, 0) == -1)
1024 log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
1028 #endif /* !HAVE_W32_SYSTEM*/