Bump to m4 1.4.19
[platform/upstream/m4.git] / lib / windows-spawn.c
1 /* Auxiliary functions for the creation of subprocesses.  Native Windows API.
2    Copyright (C) 2001, 2003-2021 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 /* Specification.  */
21 #include "windows-spawn.h"
22
23 /* Get declarations of the native Windows API functions.  */
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32
33 /* Get _get_osfhandle().  */
34 #if GNULIB_MSVC_NOTHROW
35 # include "msvc-nothrow.h"
36 #else
37 # include <io.h>
38 #endif
39 #include <process.h>
40
41 #include "findprog.h"
42
43 /* Don't assume that UNICODE is not defined.  */
44 #undef STARTUPINFO
45 #define STARTUPINFO STARTUPINFOA
46 #undef CreateProcess
47 #define CreateProcess CreateProcessA
48
49 #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*?"
50 #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
51
52 /* Returns the length of a quoted argument string.  */
53 static size_t
54 quoted_arg_length (const char *string)
55 {
56   bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
57   size_t length;
58   unsigned int backslashes;
59   const char *s;
60
61   length = 0;
62   backslashes = 0;
63   if (quote_around)
64     length++;
65   for (s = string; *s != '\0'; s++)
66     {
67       char c = *s;
68       if (c == '"')
69         length += backslashes + 1;
70       length++;
71       if (c == '\\')
72         backslashes++;
73       else
74         backslashes = 0;
75     }
76   if (quote_around)
77     length += backslashes + 1;
78
79   return length;
80 }
81
82 /* Produces a quoted argument string.
83    Stores exactly quoted_arg_length (STRING) + 1 bytes, including the final
84    NUL byte, at MEM.
85    Returns a pointer past the stored quoted argument string.  */
86 static char *
87 quoted_arg_string (const char *string, char *mem)
88 {
89   bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
90   char *p;
91   unsigned int backslashes;
92   const char *s;
93
94   p = mem;
95   backslashes = 0;
96   if (quote_around)
97     *p++ = '"';
98   for (s = string; *s != '\0'; s++)
99     {
100       char c = *s;
101       if (c == '"')
102         {
103           unsigned int j;
104           for (j = backslashes + 1; j > 0; j--)
105             *p++ = '\\';
106         }
107       *p++ = c;
108       if (c == '\\')
109         backslashes++;
110       else
111         backslashes = 0;
112     }
113   if (quote_around)
114     {
115       unsigned int j;
116       for (j = backslashes; j > 0; j--)
117         *p++ = '\\';
118       *p++ = '"';
119     }
120   *p++ = '\0';
121
122   return p;
123 }
124
125 const char **
126 prepare_spawn (const char * const *argv, char **mem_to_free)
127 {
128   size_t argc;
129   const char **new_argv;
130   size_t i;
131
132   /* Count number of arguments.  */
133   for (argc = 0; argv[argc] != NULL; argc++)
134     ;
135
136   /* Allocate new argument vector.  */
137   new_argv = (const char **) malloc ((1 + argc + 1) * sizeof (const char *));
138
139   /* Add an element upfront that can be used when argv[0] turns out to be a
140      script, not a program.
141      On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
142      "sh.exe".  We have to omit the directory part and rely on the search in
143      PATH, because the mingw "mount points" are not visible inside Windows
144      CreateProcess().  */
145   new_argv[0] = "sh.exe";
146
147   /* Put quoted arguments into the new argument vector.  */
148   size_t needed_size = 0;
149   for (i = 0; i < argc; i++)
150     {
151       const char *string = argv[i];
152       size_t length;
153
154       if (string[0] == '\0')
155         length = strlen ("\"\"");
156       else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
157         length = quoted_arg_length (string);
158       else
159         length = strlen (string);
160       needed_size += length + 1;
161     }
162
163   char *mem;
164   if (needed_size == 0)
165     mem = NULL;
166   else
167     {
168       mem = (char *) malloc (needed_size);
169       if (mem == NULL)
170         {
171           /* Memory allocation failure.  */
172           free (new_argv);
173           errno = ENOMEM;
174           return NULL;
175         }
176     }
177   *mem_to_free = mem;
178
179   for (i = 0; i < argc; i++)
180     {
181       const char *string = argv[i];
182
183       new_argv[1 + i] = mem;
184       if (string[0] == '\0')
185         {
186           size_t length = strlen ("\"\"");
187           memcpy (mem, "\"\"", length + 1);
188           mem += length + 1;
189         }
190       else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
191         {
192           mem = quoted_arg_string (string, mem);
193         }
194       else
195         {
196           size_t length = strlen (string);
197           memcpy (mem, string, length + 1);
198           mem += length + 1;
199         }
200     }
201   new_argv[1 + argc] = NULL;
202
203   return new_argv;
204 }
205
206 char *
207 compose_command (const char * const *argv)
208 {
209   /* Just concatenate the argv[] strings, separated by spaces.  */
210   char *command;
211
212   /* Determine the size of the needed block of memory.  */
213   size_t total_size = 0;
214   const char * const *ap;
215   const char *p;
216   for (ap = argv; (p = *ap) != NULL; ap++)
217     total_size += strlen (p) + 1;
218   size_t command_size = (total_size > 0 ? total_size : 1);
219
220   /* Allocate the block of memory.  */
221   command = (char *) malloc (command_size);
222   if (command == NULL)
223     {
224       errno = ENOMEM;
225       return NULL;
226     }
227
228   /* Fill it.  */
229   if (total_size > 0)
230     {
231       char *cp = command;
232       for (ap = argv; (p = *ap) != NULL; ap++)
233         {
234           size_t size = strlen (p) + 1;
235           memcpy (cp, p, size - 1);
236           cp += size;
237           cp[-1] = ' ';
238         }
239       cp[-1] = '\0';
240     }
241   else
242     *command = '\0';
243
244   return command;
245 }
246
247 char *
248 compose_envblock (const char * const *envp)
249 {
250   /* This is a bit hairy, because we don't have a lock that would prevent other
251      threads from making modifications in ENVP.  So, just make sure we don't
252      crash; but if other threads are making modifications, part of the result
253      may be wrong.  */
254  retry:
255   {
256     /* Guess the size of the needed block of memory.
257        The guess will be exact if other threads don't make modifications.  */
258     size_t total_size = 0;
259     const char * const *ep;
260     const char *p;
261     for (ep = envp; (p = *ep) != NULL; ep++)
262       total_size += strlen (p) + 1;
263     size_t envblock_size = total_size;
264
265     /* Allocate the block of memory.  */
266     char *envblock = (char *) malloc (envblock_size + 1);
267     if (envblock == NULL)
268       {
269         errno = ENOMEM;
270         return NULL;
271       }
272     size_t envblock_used = 0;
273     for (ep = envp; (p = *ep) != NULL; ep++)
274       {
275         size_t size = strlen (p) + 1;
276         if (envblock_used + size > envblock_size)
277           {
278             /* Other threads did modifications.  Need more memory.  */
279             envblock_size += envblock_size / 2;
280             if (envblock_used + size > envblock_size)
281               envblock_size = envblock_used + size;
282
283             char *new_envblock = (char *) realloc (envblock, envblock_size + 1);
284             if (new_envblock == NULL)
285               {
286                 free (envblock);
287                 errno = ENOMEM;
288                 return NULL;
289               }
290             envblock = new_envblock;
291           }
292         memcpy (envblock + envblock_used, p, size);
293         envblock_used += size;
294         if (envblock[envblock_used - 1] != '\0')
295           {
296             /* Other threads did modifications.  Restart.  */
297             free (envblock);
298             goto retry;
299           }
300       }
301     envblock[envblock_used] = '\0';
302     return envblock;
303   }
304 }
305
306 int
307 init_inheritable_handles (struct inheritable_handles *inh_handles,
308                           bool duplicate)
309 {
310   /* Determine the minimal count of handles we need to care about.  */
311   size_t handles_count;
312   {
313     /* _getmaxstdio
314        <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/getmaxstdio>
315        Default value is 512.  */
316     unsigned int fdmax = _getmaxstdio ();
317     if (fdmax < 3)
318       fdmax = 3;
319     for (; fdmax > 3; fdmax--)
320       {
321         unsigned int fd = fdmax - 1;
322         /* _get_osfhandle
323            <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle>  */
324         HANDLE handle = (HANDLE) _get_osfhandle (fd);
325         if (handle != INVALID_HANDLE_VALUE)
326           {
327             DWORD hflags;
328             /* GetHandleInformation
329                <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation>  */
330             if (GetHandleInformation (handle, &hflags))
331               {
332                 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
333                   /* fd denotes an inheritable descriptor.  */
334                   break;
335               }
336           }
337       }
338     handles_count = fdmax;
339   }
340   /* Note: handles_count >= 3.  */
341
342   /* Allocate the arrays.  */
343   size_t handles_allocated = handles_count;
344   HANDLE *handles_array =
345     (HANDLE *) malloc (handles_allocated * sizeof (HANDLE));
346   if (handles_array == NULL)
347     {
348       errno = ENOMEM;
349       return -1;
350     }
351   unsigned char *flags_array =
352     (unsigned char *) malloc (handles_allocated * sizeof (unsigned char));
353   if (flags_array == NULL)
354     {
355       free (handles_array);
356       errno = ENOMEM;
357       return -1;
358     }
359
360   /* Fill in the two arrays.  */
361   {
362     HANDLE curr_process = (duplicate ? GetCurrentProcess () : INVALID_HANDLE_VALUE);
363     unsigned int fd;
364     for (fd = 0; fd < handles_count; fd++)
365       {
366         handles_array[fd] = INVALID_HANDLE_VALUE;
367         /* _get_osfhandle
368            <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/get-osfhandle>  */
369         HANDLE handle = (HANDLE) _get_osfhandle (fd);
370         if (handle != INVALID_HANDLE_VALUE)
371           {
372             DWORD hflags;
373             /* GetHandleInformation
374                <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation>  */
375             if (GetHandleInformation (handle, &hflags))
376               {
377                 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
378                   {
379                     /* fd denotes an inheritable descriptor.  */
380                     if (duplicate)
381                       {
382                         if (!DuplicateHandle (curr_process, handle,
383                                               curr_process, &handles_array[fd],
384                                               0, TRUE, DUPLICATE_SAME_ACCESS))
385                           {
386                             unsigned int i;
387                             for (i = 0; i < fd; i++)
388                               if (handles_array[i] != INVALID_HANDLE_VALUE)
389                                 CloseHandle (handles_array[i]);
390                             free (flags_array);
391                             free (handles_array);
392                             errno = EBADF; /* arbitrary */
393                             return -1;
394                           }
395                       }
396                     else
397                       handles_array[fd] = handle;
398
399                     flags_array[fd] = 0;
400                   }
401               }
402           }
403       }
404   }
405
406   /* Return the result.  */
407   inh_handles->count = handles_count;
408   inh_handles->allocated = handles_allocated;
409   inh_handles->handles = handles_array;
410   inh_handles->flags = flags_array;
411   return 0;
412 }
413
414 int
415 compose_handles_block (const struct inheritable_handles *inh_handles,
416                        STARTUPINFO *sinfo)
417 {
418   /* STARTUPINFO
419      <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa>  */
420   sinfo->dwFlags = STARTF_USESTDHANDLES;
421   sinfo->hStdInput  = inh_handles->handles[0];
422   sinfo->hStdOutput = inh_handles->handles[1];
423   sinfo->hStdError  = inh_handles->handles[2];
424
425   /* On newer versions of Windows, more file descriptors / handles than the
426      first three can be passed.
427      The format is as follows: Let N be an exclusive upper bound for the file
428      descriptors to be passed. Two arrays are constructed in memory:
429        - flags[0..N-1], of element type 'unsigned char',
430        - handles[0..N-1], of element type 'HANDLE' or 'intptr_t'.
431      For used entries, handles[i] is the handle, and flags[i] is a set of flags,
432      a combination of:
433         1 for open file descriptors,
434        64 for handles of type FILE_TYPE_CHAR,
435         8 for handles of type FILE_TYPE_PIPE,
436        32 for O_APPEND.
437      For unused entries - this may include any of the first three, since they
438      are already passed above -, handles[i] is INVALID_HANDLE_VALUE and flags[i]
439      is zero.
440      lpReserved2 now is a pointer to the concatenation (without padding) of:
441        - an 'unsigned int' whose value is N,
442        - the contents of the flags[0..N-1] array,
443        - the contents of the handles[0..N-1] array.
444      cbReserved2 is the size (in bytes) of the object at lpReserved2.  */
445
446   size_t handles_count = inh_handles->count;
447
448   sinfo->cbReserved2 =
449     sizeof (unsigned int)
450     + handles_count * sizeof (unsigned char)
451     + handles_count * sizeof (HANDLE);
452   /* Add some padding, so that we can work with a properly aligned HANDLE
453      array.  */
454   char *hblock = (char *) malloc (sinfo->cbReserved2 + (sizeof (HANDLE) - 1));
455   if (hblock == NULL)
456     {
457       errno = ENOMEM;
458       return -1;
459     }
460   unsigned char *flags = (unsigned char *) (hblock + sizeof (unsigned int));
461   char *handles = (char *) (flags + handles_count);
462   HANDLE *handles_aligned =
463     (HANDLE *) (((uintptr_t) handles + (sizeof (HANDLE) - 1))
464                 & - (uintptr_t) sizeof (HANDLE));
465
466   * (unsigned int *) hblock = handles_count;
467   {
468     unsigned int fd;
469     for (fd = 0; fd < handles_count; fd++)
470       {
471         handles_aligned[fd] = INVALID_HANDLE_VALUE;
472         flags[fd] = 0;
473
474         HANDLE handle = inh_handles->handles[fd];
475         if (handle != INVALID_HANDLE_VALUE
476             /* The first three are possibly already passed above.
477                But they need to passed here as well, if they have some flags.  */
478             && (fd >= 3 || inh_handles->flags[fd] != 0))
479           {
480             DWORD hflags;
481             /* GetHandleInformation
482                <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-gethandleinformation>  */
483             if (GetHandleInformation (handle, &hflags))
484               {
485                 if ((hflags & HANDLE_FLAG_INHERIT) != 0)
486                   {
487                     /* fd denotes an inheritable descriptor.  */
488                     handles_aligned[fd] = handle;
489                     /* On Microsoft Windows, it would be sufficient to set
490                        flags[fd] = 1.  But on ReactOS or Wine, adding the bit
491                        that indicates the handle type may be necessary.  So,
492                        just do it everywhere.  */
493                     flags[fd] = 1 | inh_handles->flags[fd];
494                     switch (GetFileType (handle))
495                       {
496                       case FILE_TYPE_CHAR:
497                         flags[fd] |= 64;
498                         break;
499                       case FILE_TYPE_PIPE:
500                         flags[fd] |= 8;
501                         break;
502                       default:
503                         break;
504                       }
505                   }
506                 else
507                   /* We shouldn't have any non-inheritable handles in
508                      inh_handles->handles.  */
509                   abort ();
510               }
511           }
512       }
513   }
514   if (handles != (char *) handles_aligned)
515     memmove (handles, (char *) handles_aligned, handles_count * sizeof (HANDLE));
516
517   sinfo->lpReserved2 = (BYTE *) hblock;
518
519   return 0;
520 }
521
522 void
523 free_inheritable_handles (struct inheritable_handles *inh_handles)
524 {
525   free (inh_handles->flags);
526   free (inh_handles->handles);
527 }
528
529 int
530 convert_CreateProcess_error (DWORD error)
531 {
532   /* Some of these errors probably cannot happen.  But who knows...  */
533   switch (error)
534     {
535     case ERROR_FILE_NOT_FOUND:
536     case ERROR_PATH_NOT_FOUND:
537     case ERROR_BAD_PATHNAME:
538     case ERROR_BAD_NET_NAME:
539     case ERROR_INVALID_NAME:
540     case ERROR_DIRECTORY:
541       return ENOENT;
542       break;
543
544     case ERROR_ACCESS_DENIED:
545     case ERROR_SHARING_VIOLATION:
546       return EACCES;
547       break;
548
549     case ERROR_OUTOFMEMORY:
550       return ENOMEM;
551       break;
552
553     case ERROR_BUFFER_OVERFLOW:
554     case ERROR_FILENAME_EXCED_RANGE:
555       return ENAMETOOLONG;
556       break;
557
558     case ERROR_BAD_FORMAT:
559     case ERROR_BAD_EXE_FORMAT:
560       return ENOEXEC;
561       break;
562
563     default:
564       return EINVAL;
565       break;
566     }
567 }
568
569 intptr_t
570 spawnpvech (int mode,
571             const char *progname, const char * const *argv,
572             const char * const *envp,
573             const char *currdir,
574             HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle)
575 {
576   /* Validate the arguments.  */
577   if (!(mode == P_WAIT
578         || mode == P_NOWAIT
579         || mode == P_DETACH
580         || mode == P_OVERLAY)
581       || progname == NULL || argv == NULL)
582     {
583       errno = EINVAL;
584       return -1;
585     }
586
587   /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH").  */
588   const char *resolved_progname =
589     find_in_given_path (progname, getenv ("PATH"), NULL, false);
590   if (resolved_progname == NULL)
591     return -1;
592
593   /* Compose the command.  */
594   char *command = compose_command (argv);
595   if (command == NULL)
596     goto out_of_memory_1;
597
598   /* Copy *ENVP into a contiguous block of memory.  */
599   char *envblock;
600   if (envp == NULL)
601     envblock = NULL;
602   else
603     {
604       envblock = compose_envblock (envp);
605       if (envblock == NULL)
606         goto out_of_memory_2;
607     }
608
609   /* Collect the inheritable handles.  */
610   struct inheritable_handles inh_handles;
611   if (init_inheritable_handles (&inh_handles, false) < 0)
612     {
613       int saved_errno = errno;
614       if (envblock != NULL)
615         free (envblock);
616       free (command);
617       if (resolved_progname != progname)
618         free ((char *) resolved_progname);
619       errno = saved_errno;
620       return -1;
621     }
622   inh_handles.handles[0] = stdin_handle;  inh_handles.flags[0] = 0;
623   inh_handles.handles[1] = stdout_handle; inh_handles.flags[1] = 0;
624   inh_handles.handles[2] = stderr_handle; inh_handles.flags[2] = 0;
625
626   /* CreateProcess
627      <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa>  */
628   /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags>  */
629   DWORD process_creation_flags = (mode == P_DETACH ? DETACHED_PROCESS : 0);
630   /* STARTUPINFO
631      <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa>  */
632   STARTUPINFO sinfo;
633   sinfo.cb = sizeof (STARTUPINFO);
634   sinfo.lpReserved = NULL;
635   sinfo.lpDesktop = NULL;
636   sinfo.lpTitle = NULL;
637   if (compose_handles_block (&inh_handles, &sinfo) < 0)
638     {
639       int saved_errno = errno;
640       free_inheritable_handles (&inh_handles);
641       if (envblock != NULL)
642         free (envblock);
643       free (command);
644       if (resolved_progname != progname)
645         free ((char *) resolved_progname);
646       errno = saved_errno;
647       return -1;
648     }
649
650   PROCESS_INFORMATION pinfo;
651   if (!CreateProcess (resolved_progname, command, NULL, NULL, TRUE,
652                       process_creation_flags, envblock, currdir, &sinfo,
653                       &pinfo))
654     {
655       DWORD error = GetLastError ();
656
657       free (sinfo.lpReserved2);
658       free_inheritable_handles (&inh_handles);
659       if (envblock != NULL)
660         free (envblock);
661       free (command);
662       if (resolved_progname != progname)
663         free ((char *) resolved_progname);
664
665       errno = convert_CreateProcess_error (error);
666       return -1;
667     }
668
669   if (pinfo.hThread)
670     CloseHandle (pinfo.hThread);
671   free (sinfo.lpReserved2);
672   free_inheritable_handles (&inh_handles);
673   if (envblock != NULL)
674     free (envblock);
675   free (command);
676   if (resolved_progname != progname)
677     free ((char *) resolved_progname);
678
679   switch (mode)
680     {
681     case P_WAIT:
682       {
683         /* Wait until it terminates.  Then get its exit status code.  */
684         switch (WaitForSingleObject (pinfo.hProcess, INFINITE))
685           {
686           case WAIT_OBJECT_0:
687             break;
688           case WAIT_FAILED:
689             errno = ECHILD;
690             return -1;
691           default:
692             abort ();
693           }
694
695         DWORD exit_code;
696         if (!GetExitCodeProcess (pinfo.hProcess, &exit_code))
697           {
698             errno = ECHILD;
699             return -1;
700           }
701         CloseHandle (pinfo.hProcess);
702         return exit_code;
703       }
704
705     case P_NOWAIT:
706       /* Return pinfo.hProcess, not pinfo.dwProcessId.  */
707       return (intptr_t) pinfo.hProcess;
708
709     case P_DETACH:
710     case P_OVERLAY:
711       CloseHandle (pinfo.hProcess);
712       return 0;
713
714     default:
715       /* Already checked above.  */
716       abort ();
717     }
718
719   /*NOTREACHED*/
720  out_of_memory_2:
721   free (command);
722  out_of_memory_1:
723   if (resolved_progname != progname)
724     free ((char *) resolved_progname);
725   errno = ENOMEM;
726   return -1;
727 }