Bump to 2.4.3
[platform/upstream/gpg2.git] / common / exechelp-w32.c
1 /* exechelp-w32.c - Fork and exec helpers for W32.
2  * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc.
3  * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH
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 <https://www.gnu.org/licenses/>.
29  * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
30  */
31
32 #include <config.h>
33
34 #if !defined(HAVE_W32_SYSTEM)
35 #error This code is only used on W32.
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.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
58 #ifdef HAVE_STAT
59 # include <sys/stat.h>
60 #endif
61
62
63 #include "util.h"
64 #include "i18n.h"
65 #include "sysutils.h"
66 #include "exechelp.h"
67
68 #include <windows.h>
69
70 /* Define to 1 do enable debugging.  */
71 #define DEBUG_W32_SPAWN 0
72
73
74 /* It seems Vista doesn't grok X_OK and so fails access() tests.
75    Previous versions interpreted X_OK as F_OK anyway, so we'll just
76    use F_OK directly. */
77 #undef X_OK
78 #define X_OK F_OK
79
80 /* We assume that a HANDLE can be represented by an intptr_t which
81    should be true for all systems (HANDLE is defined as void *).
82    Further we assume that -1 denotes an invalid handle.  */
83 # define fd_to_handle(a)  ((HANDLE)(a))
84 # define handle_to_fd(a)  ((intptr_t)(a))
85 # define pid_to_handle(a) ((HANDLE)(a))
86 # define handle_to_pid(a) ((int)(a))
87
88
89 /* Helper */
90 static inline gpg_error_t
91 my_error_from_syserror (void)
92 {
93   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
94 }
95
96 static inline gpg_error_t
97 my_error (int errcode)
98 {
99   return gpg_err_make (default_errsource, errcode);
100 }
101
102
103 /* Return the maximum number of currently allowed open file
104    descriptors.  Only useful on POSIX systems but returns a value on
105    other systems too.  */
106 int
107 get_max_fds (void)
108 {
109   int max_fds = -1;
110
111 #ifdef OPEN_MAX
112   if (max_fds == -1)
113     max_fds = OPEN_MAX;
114 #endif
115
116   if (max_fds == -1)
117     max_fds = 256;  /* Arbitrary limit.  */
118
119   return max_fds;
120 }
121
122
123 /* Under Windows this is a dummy function.  */
124 void
125 close_all_fds (int first, int *except)
126 {
127   (void)first;
128   (void)except;
129 }
130
131
132 /* Returns an array with all currently open file descriptors.  The end
133  * of the array is marked by -1.  The caller needs to release this
134  * array using the *standard free* and not with xfree.  This allow the
135  * use of this function right at startup even before libgcrypt has
136  * been initialized.  Returns NULL on error and sets ERRNO
137  * accordingly.  Note that fstat prints a warning to DebugView for all
138  * invalid fds which is a bit annoying.  We actually do not need this
139  * function in real code (close_all_fds is a dummy anyway) but we keep
140  * it for use by t-exechelp.c.  */
141 int *
142 get_all_open_fds (void)
143 {
144   int *array;
145   size_t narray;
146   int fd, max_fd, idx;
147 #ifndef HAVE_STAT
148   array = calloc (1, sizeof *array);
149   if (array)
150     array[0] = -1;
151 #else /*HAVE_STAT*/
152   struct stat statbuf;
153
154   max_fd = get_max_fds ();
155   narray = 32;  /* If you change this change also t-exechelp.c.  */
156   array = calloc (narray, sizeof *array);
157   if (!array)
158     return NULL;
159
160   /* Note:  The list we return is ordered.  */
161   for (idx=0, fd=0; fd < max_fd; fd++)
162     if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
163       {
164         if (idx+1 >= narray)
165           {
166             int *tmp;
167
168             narray += (narray < 256)? 32:256;
169             tmp = realloc (array, narray * sizeof *array);
170             if (!tmp)
171               {
172                 free (array);
173                 return NULL;
174               }
175             array = tmp;
176           }
177         array[idx++] = fd;
178       }
179   array[idx] = -1;
180 #endif /*HAVE_STAT*/
181   return array;
182 }
183
184
185 /* Helper function to build_w32_commandline. */
186 static char *
187 build_w32_commandline_copy (char *buffer, const char *string)
188 {
189   char *p = buffer;
190   const char *s;
191
192   if (!*string) /* Empty string. */
193     p = stpcpy (p, "\"\"");
194   else if (strpbrk (string, " \t\n\v\f\""))
195     {
196       /* Need to do some kind of quoting.  */
197       p = stpcpy (p, "\"");
198       for (s=string; *s; s++)
199         {
200           *p++ = *s;
201           if (*s == '\"')
202             *p++ = *s;
203         }
204       *p++ = '\"';
205       *p = 0;
206     }
207   else
208     p = stpcpy (p, string);
209
210   return p;
211 }
212
213 /* Build a command line for use with W32's CreateProcess.  On success
214    CMDLINE gets the address of a newly allocated string.  */
215 static gpg_error_t
216 build_w32_commandline (const char *pgmname, const char * const *argv,
217                        char **cmdline)
218 {
219   int i, n;
220   const char *s;
221   char *buf, *p;
222
223   *cmdline = NULL;
224   n = 0;
225   s = pgmname;
226   n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
227   for (; *s; s++)
228     if (*s == '\"')
229       n++;  /* Need to double inner quotes.  */
230   for (i=0; (s=argv[i]); i++)
231     {
232       n += strlen (s) + 1 + 2;  /* (1 space, 2 quoting */
233       for (; *s; s++)
234         if (*s == '\"')
235           n++;  /* Need to double inner quotes.  */
236     }
237   n++;
238
239   buf = p = xtrymalloc (n);
240   if (!buf)
241     return my_error_from_syserror ();
242
243   p = build_w32_commandline_copy (p, pgmname);
244   for (i=0; argv[i]; i++)
245     {
246       *p++ = ' ';
247       p = build_w32_commandline_copy (p, argv[i]);
248     }
249
250   *cmdline= buf;
251   return 0;
252 }
253
254
255 #define INHERIT_READ    1
256 #define INHERIT_WRITE   2
257 #define INHERIT_BOTH    (INHERIT_READ|INHERIT_WRITE)
258
259 /* Create pipe.  FLAGS indicates which ends are inheritable.  */
260 static int
261 create_inheritable_pipe (HANDLE filedes[2], int flags)
262 {
263   HANDLE r, w;
264   SECURITY_ATTRIBUTES sec_attr;
265
266   memset (&sec_attr, 0, sizeof sec_attr );
267   sec_attr.nLength = sizeof sec_attr;
268   sec_attr.bInheritHandle = TRUE;
269
270   if (!CreatePipe (&r, &w, &sec_attr, 0))
271     return -1;
272
273   if ((flags & INHERIT_READ) == 0)
274     if (! SetHandleInformation (r, HANDLE_FLAG_INHERIT, 0))
275       goto fail;
276
277   if ((flags & INHERIT_WRITE) == 0)
278     if (! SetHandleInformation (w, HANDLE_FLAG_INHERIT, 0))
279       goto fail;
280
281   filedes[0] = r;
282   filedes[1] = w;
283   return 0;
284
285  fail:
286   log_error ("SetHandleInformation failed: %s\n", w32_strerror (-1));
287   CloseHandle (r);
288   CloseHandle (w);
289   return -1;
290 }
291
292
293 static HANDLE
294 w32_open_null (int for_write)
295 {
296   HANDLE hfile;
297
298   hfile = CreateFileW (L"nul",
299                        for_write? GENERIC_WRITE : GENERIC_READ,
300                        FILE_SHARE_READ | FILE_SHARE_WRITE,
301                        NULL, OPEN_EXISTING, 0, NULL);
302   if (hfile == INVALID_HANDLE_VALUE)
303     log_debug ("can't open 'nul': %s\n", w32_strerror (-1));
304   return hfile;
305 }
306
307
308 static gpg_error_t
309 create_pipe_and_estream (int filedes[2], int flags,
310                          estream_t *r_fp, int outbound, int nonblock)
311 {
312   gpg_error_t err = 0;
313   HANDLE fds[2];
314   es_syshd_t syshd;
315
316   filedes[0] = filedes[1] = -1;
317   err = my_error (GPG_ERR_GENERAL);
318   if (!create_inheritable_pipe (fds, flags))
319     {
320       filedes[0] = _open_osfhandle (handle_to_fd (fds[0]), O_RDONLY);
321       if (filedes[0] == -1)
322         {
323           log_error ("failed to translate osfhandle %p\n", fds[0]);
324           CloseHandle (fds[1]);
325         }
326       else
327         {
328           filedes[1] = _open_osfhandle (handle_to_fd (fds[1]), O_APPEND);
329           if (filedes[1] == -1)
330             {
331               log_error ("failed to translate osfhandle %p\n", fds[1]);
332               close (filedes[0]);
333               filedes[0] = -1;
334               CloseHandle (fds[1]);
335             }
336           else
337             err = 0;
338         }
339     }
340
341   if (! err && r_fp)
342     {
343       syshd.type = ES_SYSHD_HANDLE;
344       if (!outbound)
345         {
346           syshd.u.handle = fds[0];
347           *r_fp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
348         }
349       else
350         {
351           syshd.u.handle = fds[1];
352           *r_fp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
353         }
354       if (!*r_fp)
355         {
356           err = my_error_from_syserror ();
357           log_error (_("error creating a stream for a pipe: %s\n"),
358                      gpg_strerror (err));
359           close (filedes[0]);
360           close (filedes[1]);
361           filedes[0] = filedes[1] = -1;
362           return err;
363         }
364     }
365
366   return err;
367 }
368
369 /* Portable function to create a pipe.  Under Windows the write end is
370    inheritable.  If R_FP is not NULL, an estream is created for the
371    read end and stored at R_FP.  */
372 gpg_error_t
373 gnupg_create_inbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
374 {
375   return create_pipe_and_estream (filedes, INHERIT_WRITE,
376                                   r_fp, 0, nonblock);
377 }
378
379
380 /* Portable function to create a pipe.  Under Windows the read end is
381    inheritable.  If R_FP is not NULL, an estream is created for the
382    write end and stored at R_FP.  */
383 gpg_error_t
384 gnupg_create_outbound_pipe (int filedes[2], estream_t *r_fp, int nonblock)
385 {
386   return create_pipe_and_estream (filedes, INHERIT_READ,
387                                   r_fp, 1, nonblock);
388 }
389
390
391 /* Portable function to create a pipe.  Under Windows both ends are
392    inheritable.  */
393 gpg_error_t
394 gnupg_create_pipe (int filedes[2])
395 {
396   return create_pipe_and_estream (filedes, INHERIT_BOTH,
397                                   NULL, 0, 0);
398 }
399
400
401 /* Close the end of a pipe.  */
402 void
403 gnupg_close_pipe (int fd)
404 {
405   if (fd != -1)
406     close (fd);
407 }
408
409
410 /* Fork and exec the PGMNAME, see exechelp.h for details.  */
411 gpg_error_t
412 gnupg_spawn_process (const char *pgmname, const char *argv[],
413                      int *except, unsigned int flags,
414                      estream_t *r_infp,
415                      estream_t *r_outfp,
416                      estream_t *r_errfp,
417                      pid_t *pid)
418 {
419   gpg_error_t err;
420   SECURITY_ATTRIBUTES sec_attr;
421   PROCESS_INFORMATION pi =
422     {
423       NULL,      /* Returns process handle.  */
424       0,         /* Returns primary thread handle.  */
425       0,         /* Returns pid.  */
426       0          /* Returns tid.  */
427     };
428   STARTUPINFOW si;
429   int cr_flags;
430   char *cmdline;
431   wchar_t *wcmdline = NULL;
432   wchar_t *wpgmname = NULL;
433   HANDLE inpipe[2]  = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
434   HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
435   HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
436   estream_t infp = NULL;
437   estream_t outfp = NULL;
438   estream_t errfp = NULL;
439   HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
440                       INVALID_HANDLE_VALUE,
441                       INVALID_HANDLE_VALUE};
442   int i, rc;
443   es_syshd_t syshd;
444   gpg_err_source_t errsource = default_errsource;
445   int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
446
447   (void)except; /* Not yet used.  */
448
449   if (r_infp)
450     *r_infp = NULL;
451   if (r_outfp)
452     *r_outfp = NULL;
453   if (r_errfp)
454     *r_errfp = NULL;
455   *pid = (pid_t)(-1); /* Always required.  */
456
457   if (r_infp)
458     {
459       if (create_inheritable_pipe (inpipe, INHERIT_READ))
460         {
461           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
462           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
463           return err;
464         }
465
466       syshd.type = ES_SYSHD_HANDLE;
467       syshd.u.handle = inpipe[1];
468       infp = es_sysopen (&syshd, nonblock? "w,nonblock" : "w");
469       if (!infp)
470         {
471           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
472           log_error (_("error creating a stream for a pipe: %s\n"),
473                      gpg_strerror (err));
474           CloseHandle (inpipe[0]);
475           CloseHandle (inpipe[1]);
476           inpipe[0] = inpipe[1] = INVALID_HANDLE_VALUE;
477           return err;
478         }
479     }
480
481   if (r_outfp)
482     {
483       if (create_inheritable_pipe (outpipe, INHERIT_WRITE))
484         {
485           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
486           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
487           return err;
488         }
489
490       syshd.type = ES_SYSHD_HANDLE;
491       syshd.u.handle = outpipe[0];
492       outfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
493       if (!outfp)
494         {
495           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
496           log_error (_("error creating a stream for a pipe: %s\n"),
497                      gpg_strerror (err));
498           CloseHandle (outpipe[0]);
499           CloseHandle (outpipe[1]);
500           outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
501           if (infp)
502             es_fclose (infp);
503           else if (inpipe[1] != INVALID_HANDLE_VALUE)
504             CloseHandle (inpipe[1]);
505           if (inpipe[0] != INVALID_HANDLE_VALUE)
506             CloseHandle (inpipe[0]);
507           return err;
508         }
509     }
510
511   if (r_errfp)
512     {
513       if (create_inheritable_pipe (errpipe, INHERIT_WRITE))
514         {
515           err = gpg_err_make (errsource, GPG_ERR_GENERAL);
516           log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
517           return err;
518         }
519
520       syshd.type = ES_SYSHD_HANDLE;
521       syshd.u.handle = errpipe[0];
522       errfp = es_sysopen (&syshd, nonblock? "r,nonblock" : "r");
523       if (!errfp)
524         {
525           err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
526           log_error (_("error creating a stream for a pipe: %s\n"),
527                      gpg_strerror (err));
528           CloseHandle (errpipe[0]);
529           CloseHandle (errpipe[1]);
530           errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
531           if (outfp)
532             es_fclose (outfp);
533           else if (outpipe[0] != INVALID_HANDLE_VALUE)
534             CloseHandle (outpipe[0]);
535           if (outpipe[1] != INVALID_HANDLE_VALUE)
536             CloseHandle (outpipe[1]);
537           if (infp)
538             es_fclose (infp);
539           else if (inpipe[1] != INVALID_HANDLE_VALUE)
540             CloseHandle (inpipe[1]);
541           if (inpipe[0] != INVALID_HANDLE_VALUE)
542             CloseHandle (inpipe[0]);
543           return err;
544         }
545     }
546
547   /* Prepare security attributes.  */
548   memset (&sec_attr, 0, sizeof sec_attr );
549   sec_attr.nLength = sizeof sec_attr;
550   sec_attr.bInheritHandle = FALSE;
551
552   /* Build the command line.  */
553   err = build_w32_commandline (pgmname, argv, &cmdline);
554   if (err)
555     return err;
556
557   if (inpipe[0] == INVALID_HANDLE_VALUE)
558     nullhd[0] = ((flags & GNUPG_SPAWN_KEEP_STDIN)?
559                  GetStdHandle (STD_INPUT_HANDLE) : w32_open_null (0));
560   if (outpipe[1] == INVALID_HANDLE_VALUE)
561     nullhd[1] = ((flags & GNUPG_SPAWN_KEEP_STDOUT)?
562                  GetStdHandle (STD_OUTPUT_HANDLE) : w32_open_null (1));
563   if (errpipe[1] == INVALID_HANDLE_VALUE)
564     nullhd[2] = ((flags & GNUPG_SPAWN_KEEP_STDOUT)?
565                  GetStdHandle (STD_ERROR_HANDLE) : w32_open_null (1));
566
567   memset (&si, 0, sizeof si);
568   si.cb = sizeof (si);
569   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
570   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE;
571   si.hStdInput  = inpipe[0]  == INVALID_HANDLE_VALUE? nullhd[0] : inpipe[0];
572   si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
573   si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];
574
575   cr_flags = (CREATE_DEFAULT_ERROR_MODE
576               | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0)
577               | GetPriorityClass (GetCurrentProcess ())
578               | CREATE_SUSPENDED);
579   /*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", */
580   /*              pgmname, cmdline); */
581   /* Take care: CreateProcessW may modify wpgmname */
582   if (!(wpgmname = utf8_to_wchar (pgmname)))
583     rc = 0;
584   else if (!(wcmdline = utf8_to_wchar (cmdline)))
585     rc = 0;
586   else
587     rc = CreateProcessW (wpgmname,      /* Program to start.  */
588                          wcmdline,      /* Command line arguments.  */
589                          &sec_attr,     /* Process security attributes.  */
590                          &sec_attr,     /* Thread security attributes.  */
591                          TRUE,          /* Inherit handles.  */
592                          cr_flags,      /* Creation flags.  */
593                          NULL,          /* Environment.  */
594                          NULL,          /* Use current drive/directory.  */
595                          &si,           /* Startup information. */
596                          &pi            /* Returns process information.  */
597                          );
598   if (!rc)
599     {
600       if (!wpgmname || !wcmdline)
601         log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
602                    strerror (errno));
603       else
604         log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
605       xfree (wpgmname);
606       xfree (wcmdline);
607       xfree (cmdline);
608       if (infp)
609         es_fclose (infp);
610       else if (inpipe[1] != INVALID_HANDLE_VALUE)
611         CloseHandle (outpipe[1]);
612       if (inpipe[0] != INVALID_HANDLE_VALUE)
613         CloseHandle (inpipe[0]);
614       if (outfp)
615         es_fclose (outfp);
616       else if (outpipe[0] != INVALID_HANDLE_VALUE)
617         CloseHandle (outpipe[0]);
618       if (outpipe[1] != INVALID_HANDLE_VALUE)
619         CloseHandle (outpipe[1]);
620       if (errfp)
621         es_fclose (errfp);
622       else if (errpipe[0] != INVALID_HANDLE_VALUE)
623         CloseHandle (errpipe[0]);
624       if (errpipe[1] != INVALID_HANDLE_VALUE)
625         CloseHandle (errpipe[1]);
626       return gpg_err_make (errsource, GPG_ERR_GENERAL);
627     }
628   xfree (wpgmname);
629   xfree (wcmdline);
630   xfree (cmdline);
631   cmdline = NULL;
632
633   /* Close the inherited handles to /dev/null.  */
634   for (i=0; i < DIM (nullhd); i++)
635     if (nullhd[i] != INVALID_HANDLE_VALUE)
636       CloseHandle (nullhd[i]);
637
638   /* Close the inherited ends of the pipes.  */
639   if (inpipe[0] != INVALID_HANDLE_VALUE)
640     CloseHandle (inpipe[0]);
641   if (outpipe[1] != INVALID_HANDLE_VALUE)
642     CloseHandle (outpipe[1]);
643   if (errpipe[1] != INVALID_HANDLE_VALUE)
644     CloseHandle (errpipe[1]);
645
646   /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
647   /*            " dwProcessID=%d dwThreadId=%d\n", */
648   /*            pi.hProcess, pi.hThread, */
649   /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
650   /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */
651
652   /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
653      invalid argument error if we pass it the correct processID.  As a
654      workaround we use -1 (ASFW_ANY).  */
655   if ((flags & GNUPG_SPAWN_RUN_ASFW))
656     gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);
657
658   /* Process has been created suspended; resume it now. */
659   ResumeThread (pi.hThread);
660   CloseHandle (pi.hThread);
661
662   if (r_infp)
663     *r_infp = infp;
664   if (r_outfp)
665     *r_outfp = outfp;
666   if (r_errfp)
667     *r_errfp = errfp;
668
669   *pid = handle_to_pid (pi.hProcess);
670   return 0;
671
672 }
673
674
675
676 /* Simplified version of gnupg_spawn_process.  This function forks and
677    then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
678    and ERRFD to stderr (any of them may be -1 to connect them to
679    /dev/null).  The arguments for the process are expected in the NULL
680    terminated array ARGV.  The program name itself should not be
681    included there.  Calling gnupg_wait_process is required.
682
683    Returns 0 on success or an error code. */
684 gpg_error_t
685 gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
686                         int infd, int outfd, int errfd, pid_t *pid)
687 {
688   gpg_error_t err;
689   SECURITY_ATTRIBUTES sec_attr;
690   PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
691   STARTUPINFOW si;
692   char *cmdline;
693   wchar_t *wcmdline = NULL;
694   wchar_t *wpgmname = NULL;
695   int i, rc;
696   HANDLE stdhd[3];
697
698   /* Setup return values.  */
699   *pid = (pid_t)(-1);
700
701   /* Prepare security attributes.  */
702   memset (&sec_attr, 0, sizeof sec_attr );
703   sec_attr.nLength = sizeof sec_attr;
704   sec_attr.bInheritHandle = FALSE;
705
706   /* Build the command line.  */
707   err = build_w32_commandline (pgmname, argv, &cmdline);
708   if (err)
709     return err;
710
711   memset (&si, 0, sizeof si);
712   si.cb = sizeof (si);
713   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
714   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
715   stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
716   stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
717   stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
718   si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
719   si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
720   si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
721
722 /*   log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
723   /* Take care: CreateProcessW may modify wpgmname */
724   if (!(wpgmname = utf8_to_wchar (pgmname)))
725     rc = 0;
726   else if (!(wcmdline = utf8_to_wchar (cmdline)))
727     rc = 0;
728   else
729     rc = CreateProcessW (wpgmname,      /* Program to start.  */
730                          wcmdline,      /* Command line arguments.  */
731                          &sec_attr,     /* Process security attributes.  */
732                          &sec_attr,     /* Thread security attributes.  */
733                          TRUE,          /* Inherit handles.  */
734                          (CREATE_DEFAULT_ERROR_MODE
735                           | GetPriorityClass (GetCurrentProcess ())
736                           | CREATE_SUSPENDED | DETACHED_PROCESS),
737                          NULL,          /* Environment.  */
738                          NULL,          /* Use current drive/directory.  */
739                          &si,           /* Startup information. */
740                          &pi            /* Returns process information.  */
741                          );
742   if (!rc)
743     {
744       if (!wpgmname || !wcmdline)
745         log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
746                    strerror (errno));
747       else
748         log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
749       err = my_error (GPG_ERR_GENERAL);
750     }
751   else
752     err = 0;
753   xfree (wpgmname);
754   xfree (wcmdline);
755   xfree (cmdline);
756   for (i=0; i < 3; i++)
757     if (stdhd[i] != INVALID_HANDLE_VALUE)
758       CloseHandle (stdhd[i]);
759   if (err)
760     return err;
761
762 /*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
763 /*              " dwProcessID=%d dwThreadId=%d\n", */
764 /*              pi.hProcess, pi.hThread, */
765 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
766
767   /* Process has been created suspended; resume it now. */
768   ResumeThread (pi.hThread);
769   CloseHandle (pi.hThread);
770
771   *pid = handle_to_pid (pi.hProcess);
772   return 0;
773
774 }
775
776
777 /* See exechelp.h for a description.  */
778 gpg_error_t
779 gnupg_wait_process (const char *pgmname, pid_t pid, int hang, int *r_exitcode)
780 {
781   return gnupg_wait_processes (&pgmname, &pid, 1, hang, r_exitcode);
782 }
783
784 /* See exechelp.h for a description.  */
785 gpg_error_t
786 gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
787                       int hang, int *r_exitcodes)
788 {
789   gpg_err_code_t ec = 0;
790   size_t i;
791   HANDLE *procs;
792   int code;
793
794   procs = xtrycalloc (count, sizeof *procs);
795   if (procs == NULL)
796     return my_error_from_syserror ();
797
798   for (i = 0; i < count; i++)
799     {
800       if (r_exitcodes)
801         r_exitcodes[i] = -1;
802
803       if (pids[i] == (pid_t)(-1))
804         return my_error (GPG_ERR_INV_VALUE);
805
806       procs[i] = pid_to_handle (pids[i]);
807     }
808
809   /* FIXME: We should do a pth_waitpid here.  However this has not yet
810      been implemented.  A special W32 pth system call would even be
811      better.  */
812   code = WaitForMultipleObjects (count, procs, TRUE, hang? INFINITE : 0);
813   switch (code)
814     {
815     case WAIT_TIMEOUT:
816       ec = GPG_ERR_TIMEOUT;
817       goto leave;
818
819     case WAIT_FAILED:
820       log_error (_("waiting for processes to terminate failed: %s\n"),
821                  w32_strerror (-1));
822       ec = GPG_ERR_GENERAL;
823       goto leave;
824
825     case WAIT_OBJECT_0:
826       for (i = 0; i < count; i++)
827         {
828           DWORD exc;
829
830           if (! GetExitCodeProcess (procs[i], &exc))
831             {
832               log_error (_("error getting exit code of process %d: %s\n"),
833                          (int) pids[i], w32_strerror (-1) );
834               ec = GPG_ERR_GENERAL;
835             }
836           else if (exc)
837             {
838               if (!r_exitcodes)
839                 log_error (_("error running '%s': exit status %d\n"),
840                            pgmnames[i], (int)exc);
841               else
842                 r_exitcodes[i] = (int)exc;
843               ec = GPG_ERR_GENERAL;
844             }
845           else
846             {
847               if (r_exitcodes)
848                 r_exitcodes[i] = 0;
849             }
850         }
851       break;
852
853     default:
854       log_error ("WaitForMultipleObjects returned unexpected "
855                  "code %d\n", code);
856       ec = GPG_ERR_GENERAL;
857       break;
858     }
859
860  leave:
861   return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
862 }
863
864
865
866 void
867 gnupg_release_process (pid_t pid)
868 {
869   if (pid != (pid_t)INVALID_HANDLE_VALUE)
870     {
871       HANDLE process = (HANDLE)pid;
872
873       CloseHandle (process);
874     }
875 }
876
877
878 /* Spawn a new process and immediately detach from it.  The name of
879    the program to exec is PGMNAME and its arguments are in ARGV (the
880    programname is automatically passed as first argument).
881    Environment strings in ENVP are set.  An error is returned if
882    pgmname is not executable; to make this work it is necessary to
883    provide an absolute file name.  All standard file descriptors are
884    connected to /dev/null. */
885 gpg_error_t
886 gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
887                               const char *envp[] )
888 {
889   gpg_error_t err;
890   SECURITY_ATTRIBUTES sec_attr;
891   PROCESS_INFORMATION pi =
892     {
893       NULL,      /* Returns process handle.  */
894       0,         /* Returns primary thread handle.  */
895       0,         /* Returns pid.  */
896       0          /* Returns tid.  */
897     };
898   STARTUPINFOW si;
899   int cr_flags;
900   char *cmdline;
901   wchar_t *wcmdline = NULL;
902   wchar_t *wpgmname = NULL;
903   BOOL in_job = FALSE;
904   gpg_err_code_t ec;
905   int rc;
906   int jobdebug;
907
908   /* We don't use ENVP.  */
909   (void)envp;
910
911   cmdline = getenv ("GNUPG_EXEC_DEBUG_FLAGS");
912   jobdebug = (cmdline && (atoi (cmdline) & 1));
913
914   if ((ec = gnupg_access (pgmname, X_OK)))
915     return gpg_err_make (default_errsource, ec);
916
917   /* Prepare security attributes.  */
918   memset (&sec_attr, 0, sizeof sec_attr );
919   sec_attr.nLength = sizeof sec_attr;
920   sec_attr.bInheritHandle = FALSE;
921
922   /* Build the command line.  */
923   err = build_w32_commandline (pgmname, argv, &cmdline);
924   if (err)
925     return err;
926
927   /* Start the process.  */
928   memset (&si, 0, sizeof si);
929   si.cb = sizeof (si);
930   si.dwFlags = STARTF_USESHOWWINDOW;
931   si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
932
933   cr_flags = (CREATE_DEFAULT_ERROR_MODE
934               | GetPriorityClass (GetCurrentProcess ())
935               | CREATE_NEW_PROCESS_GROUP
936               | DETACHED_PROCESS);
937
938   /* Check if we were spawned as part of a Job.
939    * In a job we need to add CREATE_BREAKAWAY_FROM_JOB
940    * to the cr_flags, otherwise our child processes
941    * are killed when we terminate. */
942   if (!IsProcessInJob (GetCurrentProcess(), NULL, &in_job))
943     {
944       log_error ("IsProcessInJob() failed: %s\n", w32_strerror (-1));
945       in_job = FALSE;
946     }
947
948   if (in_job)
949     {
950       /* Only try to break away from job if it is allowed, otherwise
951        * CreateProcess() would fail with an "Access is denied" error. */
952       JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
953       if (!QueryInformationJobObject (NULL, JobObjectExtendedLimitInformation,
954                                       &info, sizeof info, NULL))
955         {
956           log_error ("QueryInformationJobObject() failed: %s\n",
957                      w32_strerror (-1));
958         }
959       else if ((info.BasicLimitInformation.LimitFlags &
960                 JOB_OBJECT_LIMIT_BREAKAWAY_OK))
961         {
962           if (jobdebug)
963             log_debug ("Using CREATE_BREAKAWAY_FROM_JOB flag\n");
964           cr_flags |= CREATE_BREAKAWAY_FROM_JOB;
965         }
966       else if ((info.BasicLimitInformation.LimitFlags &
967                 JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK))
968         {
969           /* The child process should automatically detach from the job. */
970           if (jobdebug)
971             log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag; "
972                        "JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK is set\n");
973         }
974       else
975         {
976           /* It seems that the child process must remain in the job.
977            * This is not necessarily an error, although it can cause premature
978            * termination of the child process when the job is closed. */
979           if (jobdebug)
980             log_debug ("Not using CREATE_BREAKAWAY_FROM_JOB flag\n");
981         }
982     }
983   else
984     {
985       if (jobdebug)
986         log_debug ("Process is not in a Job\n");
987     }
988
989   /*   log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
990   /*              pgmname, cmdline); */
991   /* Take care: CreateProcessW may modify wpgmname */
992   if (!(wpgmname = utf8_to_wchar (pgmname)))
993     rc = 0;
994   else if (!(wcmdline = utf8_to_wchar (cmdline)))
995     rc = 0;
996   else
997     rc = CreateProcessW (wpgmname,      /* Program to start.  */
998                          wcmdline,      /* Command line arguments.  */
999                          &sec_attr,     /* Process security attributes.  */
1000                          &sec_attr,     /* Thread security attributes.  */
1001                          FALSE,         /* Inherit handles.  */
1002                          cr_flags,      /* Creation flags.  */
1003                          NULL,          /* Environment.  */
1004                          NULL,          /* Use current drive/directory.  */
1005                          &si,           /* Startup information. */
1006                          &pi            /* Returns process information.  */
1007                          );
1008   if (!rc)
1009     {
1010       if (!wpgmname || !wcmdline)
1011         log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
1012                    strerror (errno));
1013       else
1014         log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
1015       xfree (wpgmname);
1016       xfree (wcmdline);
1017       xfree (cmdline);
1018       return my_error (GPG_ERR_GENERAL);
1019     }
1020   xfree (wpgmname);
1021   xfree (wcmdline);
1022   xfree (cmdline);
1023   cmdline = NULL;
1024
1025 /*   log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */
1026 /*              " dwProcessID=%d dwThreadId=%d\n", */
1027 /*              pi.hProcess, pi.hThread, */
1028 /*              (int) pi.dwProcessId, (int) pi.dwThreadId); */
1029
1030   CloseHandle (pi.hThread);
1031   CloseHandle (pi.hProcess);
1032
1033   return 0;
1034 }
1035
1036
1037 /* Kill a process; that is send an appropriate signal to the process.
1038    gnupg_wait_process must be called to actually remove the process
1039    from the system.  An invalid PID is ignored.  */
1040 void
1041 gnupg_kill_process (pid_t pid)
1042 {
1043   if (pid != (pid_t) INVALID_HANDLE_VALUE)
1044     {
1045       HANDLE process = (HANDLE) pid;
1046
1047       /* Arbitrary error code.  */
1048       TerminateProcess (process, 1);
1049     }
1050 }