(root)/
gettext-0.22.4/
gettext-tools/
gnulib-lib/
windows-spawn.h
       1  /* Auxiliary functions for the creation of subprocesses.  Native Windows API.
       2     Copyright (C) 2001, 2003-2023 Free Software Foundation, Inc.
       3     Written by Bruno Haible <bruno@clisp.org>, 2003.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file 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 Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  #ifndef _WINDOWS_SPAWN_H
      19  #define _WINDOWS_SPAWN_H
      20  
      21  /* This file uses _GL_ATTRIBUTE_MALLOC.  */
      22  #if !_GL_CONFIG_H_INCLUDED
      23   #error "Please include config.h first."
      24  #endif
      25  
      26  #include <stdint.h>
      27  #include <stdlib.h>
      28  
      29  /* Get declarations of the native Windows API functions.  */
      30  #define WIN32_LEAN_AND_MEAN
      31  #include <windows.h>
      32  
      33  
      34  /* Prepares an argument vector before calling spawn().
      35  
      36     Note that spawn() does not by itself call the command interpreter
      37       (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
      38        ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
      39           GetVersionEx(&v);
      40           v.dwPlatformId == VER_PLATFORM_WIN32_NT;
      41        }) ? "cmd.exe" : "command.com").
      42     Instead it simply concatenates the arguments, separated by ' ', and calls
      43     CreateProcess().  We must quote the arguments since Windows CreateProcess()
      44     interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
      45     special way:
      46     - Space and tab are interpreted as delimiters. They are not treated as
      47       delimiters if they are surrounded by double quotes: "...".
      48     - Unescaped double quotes are removed from the input. Their only effect is
      49       that within double quotes, space and tab are treated like normal
      50       characters.
      51     - Backslashes not followed by double quotes are not special.
      52     - But 2*n+1 backslashes followed by a double quote become
      53       n backslashes followed by a double quote (n >= 0):
      54         \" -> "
      55         \\\" -> \"
      56         \\\\\" -> \\"
      57     - '*', '?' characters may get expanded through wildcard expansion in the
      58       callee: By default, in the callee, the initialization code before main()
      59       takes the result of GetCommandLine(), wildcard-expands it, and passes it
      60       to main(). The exceptions to this rule are:
      61         - programs that inspect GetCommandLine() and ignore argv,
      62         - mingw programs that have a global variable 'int _CRT_glob = 0;',
      63         - Cygwin programs, when invoked from a Cygwin program.
      64  
      65     prepare_spawn creates and returns a new argument vector, where the arguments
      66     are appropriately quoted and an additional argument "sh.exe" has been added
      67     at the beginning.  The new argument vector is freshly allocated.  The memory
      68     for all its elements is allocated within *MEM_TO_FREE, which is freshly
      69     allocated as well.  In case of memory allocation failure, NULL is returned,
      70     with errno set.
      71   */
      72  extern const char ** prepare_spawn (const char * const *argv,
      73                                      char **mem_to_free);
      74  
      75  /* Composes the command to be passed to CreateProcess().
      76     ARGV must contain appropriately quoted arguments, as returned by
      77     prepare_spawn.
      78     Returns a freshly allocated string.  In case of memory allocation failure,
      79     NULL is returned, with errno set.  */
      80  extern char * compose_command (const char * const *argv)
      81    _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
      82  
      83  /* Composes the block of memory that contains the environment variables.
      84     ENVP must contain an environment (a NULL-terminated array of string of the
      85     form VARIABLE=VALUE).
      86     Returns a freshly allocated block of memory.  In case of memory allocation
      87     failure, NULL is returned, with errno set.  */
      88  extern char * compose_envblock (const char * const *envp)
      89    _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
      90  
      91  
      92  /* An inheritable handle with some additional information.  */
      93  struct IHANDLE
      94  {
      95    /* Either INVALID_HANDLE_VALUE or an inheritable handle.  */
      96    HANDLE handle;
      97    /* Only relevant if handle != INVALID_HANDLE_VALUE.
      98       It is a bit mask consisting of:
      99         - 32 for O_APPEND.
     100         - KEEP_OPEN_IN_CHILD if the handle is scheduled to be preserved in the
     101           child process.
     102         - KEEP_OPEN_IN_PARENT if the handle is shared with (and needs to be kept
     103           open in) the parent process.
     104         - DELAYED_DUP2_OLDFD if there is a delayed dup2 (oldfd, newfd) and
     105           this IHANDLE is at position oldfd.
     106         - DELAYED_DUP2_NEWFD if there is a delayed dup2 (oldfd, newfd) and
     107           this IHANDLE is at position newfd.
     108       Note that DELAYED_DUP2_OLDFD and DELAYED_DUP2_NEWFD cannot be set in the
     109       same IHANDLE.  */
     110    unsigned short flags;
     111    #define KEEP_OPEN_IN_CHILD 0x100
     112    #define KEEP_OPEN_IN_PARENT 0x200
     113    #define DELAYED_DUP2_OLDFD 0x400
     114    #define DELAYED_DUP2_NEWFD 0x800
     115    /* Only relevant if handle != INVALID_HANDLE_VALUE and flags contains
     116       either DELAYED_DUP2_OLDFD or DELAYED_DUP2_NEWFD.
     117       It is the other fd of the delayed dup2 (oldfd, newfd), i.e.
     118         - for DELAYED_DUP2_OLDFD, the newfd,
     119         - for DELAYED_DUP2_NEWFD, the oldfd.  */
     120    int linked_fd;
     121  };
     122  
     123  /* This struct keeps track of which handles to potentially pass to a subprocess,
     124     and with which flags.  All of the handles here are inheritable.
     125     Regarding handle inheritance, see
     126     <https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance>.
     127     Whether a handle is actually scheduled for being preserved in the child
     128     process is determined by the KEEP_OPEN_IN_CHILD bit in the flags.  */
     129  struct inheritable_handles
     130  {
     131    /* The number of occupied entries in the two arrays below.
     132       3 <= count <= allocated.  */
     133    size_t count;
     134    /* The number of allocated entries in the two arrays below.  */
     135    size_t allocated;
     136    /* ih[0..count-1] are the occupied entries.  */
     137    struct IHANDLE *ih;
     138  };
     139  
     140  /* Initializes a set of inheritable handles, filling in all or part of the
     141     file descriptors of the current process.
     142     If DUPLICATE is true, the handles stored are those of all file descriptors,
     143     and we use DuplicateHandle to make sure that they are all inheritable.
     144     If DUPLICATE is false, the handles stored are only the inheritables ones;
     145     this is a shortcut for spawnpvech().
     146     Returns 0 upon success.  In case of failure, -1 is returned, with errno set.
     147   */
     148  extern int init_inheritable_handles (struct inheritable_handles *inh_handles,
     149                                       bool duplicate);
     150  
     151  /* Fills a set of inheritable handles into a STARTUPINFO for CreateProcess().
     152     Returns 0 upon success.  In case of failure, -1 is returned, with errno set.
     153   */
     154  extern int compose_handles_block (const struct inheritable_handles *inh_handles,
     155                                    STARTUPINFOA *sinfo);
     156  
     157  /* Frees the memory held by a set of inheritable handles.  */
     158  extern void free_inheritable_handles (struct inheritable_handles *inh_handles);
     159  
     160  
     161  /* Converts a CreateProcess() error code (retrieved through GetLastError()) to
     162     an errno value.  */
     163  extern int convert_CreateProcess_error (DWORD error);
     164  
     165  
     166  /* Creates a subprocess.
     167     MODE is either P_WAIT or P_NOWAIT.
     168     PROGNAME is the program to invoke.
     169     ARGV is the NULL-terminated array of arguments, ARGV[0] being PROGNAME by
     170     convention.
     171     ENVP is the NULL-terminated set of environment variable assignments, or NULL
     172     to inherit the initial environ variable assignments from the caller and
     173     ignore all calls to putenv(), setenv(), unsetenv() done in the caller.
     174     CURRDIR is the directory in which to start the program, or NULL to inherit
     175     the working directory from the caller.
     176     STDIN_HANDLE, STDOUT_HANDLE, STDERR_HANDLE are the handles to use for the
     177     first three file descriptors in the callee process.
     178     Returns
     179       - 0 for success (if MODE is P_WAIT), or
     180       - a handle that be passed to _cwait (on Windows) or waitpid (on OS/2), or
     181       - -1 upon error, with errno set.
     182   */
     183  extern intptr_t spawnpvech (int mode,
     184                              const char *progname, const char * const *argv,
     185                              const char * const *envp,
     186                              const char *currdir,
     187                              HANDLE stdin_handle, HANDLE stdout_handle,
     188                              HANDLE stderr_handle);
     189  
     190  #endif /* _WINDOWS_SPAWN_H */