These few patches are preparations for the posix_spawn implementation for native Windows.
Note the NEWS entry: 2020-12-14 findprog-in The function 'find_in_given_path' now takes a 3rd argument 'const char *directory'. To maintain the previous behaviour, insert NULL as additional 3rd argument. Paul Smith: To accommodate for this change, a 1-liner patch is needed in GNU make. 2020-12-14 Bruno Haible <br...@clisp.org> findprog-in: Allow overriding the current directory. * lib/findprog.h (find_in_given_path): Add directory argument. * lib/findprog-in.c (find_in_given_path): Likewise. * lib/execute.c (execute): Update caller. * lib/spawn-pipe.c (create_pipe): Likewise. * lib/windows-spawn.c (spawnpvech): Likewise. * NEWS: Mention the change. 2020-12-14 Bruno Haible <br...@clisp.org> posix_spawn-internal: Make better use of 'const'. * lib/spawn_int.h (__spawni): Does not need write access to the elements of argv and envp. * lib/spawni.c (__spawni, script_execute): Likewise. * lib/spawn.c (posix_spawn): Update caller. * lib/spawnp.c (posix_spawnp): Likewise. 2020-12-14 Bruno Haible <br...@clisp.org> spawn: Make it compile on native Windows. * modules/spawn (Depends-on): Add signal-h. 2020-12-14 Bruno Haible <br...@clisp.org> windows-spawn: Avoid shadowing a variable. * lib/windows-spawn.c (spawnpvech): Rename local variable 'flags'.
>From 62514110dafb876059c4c3654fd200a022ad892c Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Mon, 14 Dec 2020 18:05:38 +0100 Subject: [PATCH 1/4] windows-spawn: Avoid shadowing a variable. * lib/windows-spawn.c (spawnpvech): Rename local variable 'flags'. --- ChangeLog | 5 +++++ lib/windows-spawn.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f9a021..865cc91 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-12-14 Bruno Haible <br...@clisp.org> + + windows-spawn: Avoid shadowing a variable. + * lib/windows-spawn.c (spawnpvech): Rename local variable 'flags'. + 2020-12-13 Paul Eggert <egg...@cs.ucla.edu> string: port memchr macro to AIX 7.2 XLC diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c index 88a6b4d..509727c 100644 --- a/lib/windows-spawn.c +++ b/lib/windows-spawn.c @@ -308,7 +308,7 @@ spawnpvech (int mode, /* Regarding handle inheritance, see <https://docs.microsoft.com/en-us/windows/win32/sysinfo/handle-inheritance> */ /* <https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags> */ - DWORD flags = (mode == P_DETACH ? DETACHED_PROCESS : 0); + DWORD process_creation_flags = (mode == P_DETACH ? DETACHED_PROCESS : 0); /* STARTUPINFO <https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa> */ STARTUPINFO sinfo; @@ -443,7 +443,8 @@ spawnpvech (int mode, PROCESS_INFORMATION pinfo; if (!CreateProcess (resolved_progname, command, NULL, NULL, TRUE, - flags, envblock, currdir, &sinfo, &pinfo)) + process_creation_flags, envblock, currdir, &sinfo, + &pinfo)) { DWORD error = GetLastError (); -- 2.7.4
>From 12c8567fcbe7e7baf89ba9fadc157e0a336705dc Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Mon, 14 Dec 2020 18:07:28 +0100 Subject: [PATCH 2/4] spawn: Make it compile on native Windows. * modules/spawn (Depends-on): Add signal-h. --- ChangeLog | 5 +++++ modules/spawn | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 865cc91..21cc216 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2020-12-14 Bruno Haible <br...@clisp.org> + spawn: Make it compile on native Windows. + * modules/spawn (Depends-on): Add signal-h. + +2020-12-14 Bruno Haible <br...@clisp.org> + windows-spawn: Avoid shadowing a variable. * lib/windows-spawn.c (spawnpvech): Rename local variable 'flags'. diff --git a/modules/spawn b/modules/spawn index f1b99ca..1828d37 100644 --- a/modules/spawn +++ b/modules/spawn @@ -9,6 +9,7 @@ m4/pid_t.m4 Depends-on: include_next sched +signal-h snippet/arg-nonnull snippet/c++defs snippet/warn-on-use -- 2.7.4
>From 29d55bf8c7d0c5a4a3b4aa2d93d897ff8463eb4c Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Mon, 14 Dec 2020 19:22:14 +0100 Subject: [PATCH 3/4] posix_spawn-internal: Make better use of 'const'. * lib/spawn_int.h (__spawni): Does not need write access to the elements of argv and envp. * lib/spawni.c (__spawni, script_execute): Likewise. * lib/spawn.c (posix_spawn): Update caller. * lib/spawnp.c (posix_spawnp): Likewise. --- ChangeLog | 9 +++++++++ lib/spawn.c | 3 ++- lib/spawn_int.h | 4 ++-- lib/spawni.c | 20 +++++++++++--------- lib/spawnp.c | 3 ++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 21cc216..f909f61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2020-12-14 Bruno Haible <br...@clisp.org> + posix_spawn-internal: Make better use of 'const'. + * lib/spawn_int.h (__spawni): Does not need write access to the elements + of argv and envp. + * lib/spawni.c (__spawni, script_execute): Likewise. + * lib/spawn.c (posix_spawn): Update caller. + * lib/spawnp.c (posix_spawnp): Likewise. + +2020-12-14 Bruno Haible <br...@clisp.org> + spawn: Make it compile on native Windows. * modules/spawn (Depends-on): Add signal-h. diff --git a/lib/spawn.c b/lib/spawn.c index c139b71..b658453 100644 --- a/lib/spawn.c +++ b/lib/spawn.c @@ -29,5 +29,6 @@ posix_spawn (pid_t *pid, const char *path, const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) { - return __spawni (pid, path, file_actions, attrp, argv, envp, 0); + return __spawni (pid, path, file_actions, attrp, + (const char * const *) argv, (const char * const *) envp, 0); } diff --git a/lib/spawn_int.h b/lib/spawn_int.h index 7c063b6..60a94dd 100644 --- a/lib/spawn_int.h +++ b/lib/spawn_int.h @@ -68,5 +68,5 @@ extern int __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t * #endif extern int __spawni (pid_t *pid, const char *path, const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *attrp, char *const argv[], - char *const envp[], int use_path); + const posix_spawnattr_t *attrp, const char *const argv[], + const char *const envp[], int use_path); diff --git a/lib/spawni.c b/lib/spawni.c index 07bbec7..1e20a97 100644 --- a/lib/spawni.c +++ b/lib/spawni.c @@ -109,7 +109,8 @@ __spawni (pid_t *pid, const char *file, the shell to interpret it as a script. */ static void internal_function -script_execute (const char *file, char *const argv[], char *const envp[]) +script_execute (const char *file, const char *const argv[], + const char *const envp[]) { /* Count the arguments. */ int argc = 0; @@ -118,9 +119,10 @@ script_execute (const char *file, char *const argv[], char *const envp[]) /* Construct an argument list for the shell. */ { - char **new_argv = (char **) alloca ((argc + 1) * sizeof (char *)); - new_argv[0] = (char *) _PATH_BSHELL; - new_argv[1] = (char *) file; + const char **new_argv = + (const char **) alloca ((argc + 1) * sizeof (const char *)); + new_argv[0] = _PATH_BSHELL; + new_argv[1] = file; while (argc > 1) { new_argv[argc] = argv[argc - 1]; @@ -128,7 +130,7 @@ script_execute (const char *file, char *const argv[], char *const envp[]) } /* Execute the shell. */ - execve (new_argv[0], new_argv, envp); + execve (new_argv[0], (char * const *) new_argv, (char * const *) envp); } } @@ -138,8 +140,8 @@ script_execute (const char *file, char *const argv[], char *const envp[]) int __spawni (pid_t *pid, const char *file, const posix_spawn_file_actions_t *file_actions, - const posix_spawnattr_t *attrp, char *const argv[], - char *const envp[], int use_path) + const posix_spawnattr_t *attrp, const char *const argv[], + const char *const envp[], int use_path) { pid_t new_pid; char *path, *p, *name; @@ -303,7 +305,7 @@ __spawni (pid_t *pid, const char *file, if (! use_path || strchr (file, '/') != NULL) { /* The FILE parameter is actually a path. */ - execve (file, argv, envp); + execve (file, (char * const *) argv, (char * const *) envp); if (errno == ENOEXEC) script_execute (file, argv, envp); @@ -354,7 +356,7 @@ __spawni (pid_t *pid, const char *file, startp = (char *) memcpy (name - (p - path), path, p - path); /* Try to execute this name. If it works, execv will not return. */ - execve (startp, argv, envp); + execve (startp, (char * const *) argv, (char * const *) envp); if (errno == ENOEXEC) script_execute (startp, argv, envp); diff --git a/lib/spawnp.c b/lib/spawnp.c index 0f03e79..91c54a1 100644 --- a/lib/spawnp.c +++ b/lib/spawnp.c @@ -29,5 +29,6 @@ posix_spawnp (pid_t *pid, const char *file, const posix_spawnattr_t *attrp, char *const argv[], char *const envp[]) { - return __spawni (pid, file, file_actions, attrp, argv, envp, 1); + return __spawni (pid, file, file_actions, attrp, + (const char * const *) argv, (const char * const *) envp, 1); } -- 2.7.4
>From 0299e540e47d71207081f87de6ec7aa2ceed5d25 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Mon, 14 Dec 2020 20:56:04 +0100 Subject: [PATCH 4/4] findprog-in: Allow overriding the current directory. * lib/findprog.h (find_in_given_path): Add directory argument. * lib/findprog-in.c (find_in_given_path): Likewise. * lib/execute.c (execute): Update caller. * lib/spawn-pipe.c (create_pipe): Likewise. * lib/windows-spawn.c (spawnpvech): Likewise. * NEWS: Mention the change. --- ChangeLog | 10 ++++++++++ NEWS | 5 +++++ lib/execute.c | 2 +- lib/findprog-in.c | 45 +++++++++++++++++++++++++++++++++++++++------ lib/findprog.h | 5 +++++ lib/spawn-pipe.c | 2 +- lib/windows-spawn.c | 2 +- 7 files changed, 62 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index f909f61..1a8e1a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2020-12-14 Bruno Haible <br...@clisp.org> + findprog-in: Allow overriding the current directory. + * lib/findprog.h (find_in_given_path): Add directory argument. + * lib/findprog-in.c (find_in_given_path): Likewise. + * lib/execute.c (execute): Update caller. + * lib/spawn-pipe.c (create_pipe): Likewise. + * lib/windows-spawn.c (spawnpvech): Likewise. + * NEWS: Mention the change. + +2020-12-14 Bruno Haible <br...@clisp.org> + posix_spawn-internal: Make better use of 'const'. * lib/spawn_int.h (__spawni): Does not need write access to the elements of argv and envp. diff --git a/NEWS b/NEWS index f484881..09d1987 100644 --- a/NEWS +++ b/NEWS @@ -60,6 +60,11 @@ User visible incompatible changes Date Modules Changes +2020-12-14 findprog-in The function 'find_in_given_path' now takes a 3rd + argument 'const char *directory'. To maintain the + previous behaviour, insert NULL as additional 3rd + argument. + 2020-12-11 sh-quote The argv argument of the 'shell_quote_argv' function is now of type 'const char * const *'. You no longer need to cast read-only strings to 'char *' diff --git a/lib/execute.c b/lib/execute.c index bdc0c0c..41a2239 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -126,7 +126,7 @@ execute (const char *progname, if (! IS_ABSOLUTE_FILE_NAME (prog_path)) { const char *resolved_prog = - find_in_given_path (prog_path, getenv ("PATH"), false); + find_in_given_path (prog_path, getenv ("PATH"), NULL, false); if (resolved_prog == NULL) goto fail_with_errno; if (resolved_prog != prog_path) diff --git a/lib/findprog-in.c b/lib/findprog-in.c index 863f67e..63b8419 100644 --- a/lib/findprog-in.c +++ b/lib/findprog-in.c @@ -73,7 +73,7 @@ static const char * const suffixes[] = const char * find_in_given_path (const char *progname, const char *path, - bool optimize_for_exec) + const char *directory, bool optimize_for_exec) { { bool has_slash = false; @@ -101,6 +101,12 @@ find_in_given_path (const char *progname, const char *path, with such a suffix is actually executable. */ int failure_errno; size_t i; + + const char *directory_as_prefix = + (directory != NULL && IS_RELATIVE_FILE_NAME (progname) + ? directory + : ""); + #if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */ const char *progbasename; @@ -126,9 +132,10 @@ find_in_given_path (const char *progname, const char *path, if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL)) #endif { - /* Concatenate progname and suffix. */ + /* Concatenate directory_as_prefix, progname, suffix. */ char *progpathname = - concatenated_filename ("", progname, suffix); + concatenated_filename (directory_as_prefix, progname, + suffix); if (progpathname == NULL) return NULL; /* errno is set here */ @@ -194,6 +201,8 @@ find_in_given_path (const char *progname, const char *path, { const char *dir; bool last; + char *dir_as_prefix_to_free; + const char *dir_as_prefix; size_t i; /* Extract next directory in PATH. */ @@ -207,6 +216,25 @@ find_in_given_path (const char *progname, const char *path, if (dir == cp) dir = "."; + /* Concatenate directory and dir. */ + if (directory != NULL && IS_RELATIVE_FILE_NAME (dir)) + { + dir_as_prefix_to_free = + concatenated_filename (directory, dir, NULL); + if (dir_as_prefix_to_free == NULL) + { + /* errno is set here. */ + failure_errno = errno; + goto failed; + } + dir_as_prefix = dir_as_prefix_to_free; + } + else + { + dir_as_prefix_to_free = NULL; + dir_as_prefix = dir; + } + /* Try all platform-dependent suffixes. */ for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++) { @@ -218,14 +246,15 @@ find_in_given_path (const char *progname, const char *path, if ((*suffix != '\0') != (strchr (progname, '.') != NULL)) #endif { - /* Concatenate dir, progname, and suffix. */ + /* Concatenate dir_as_prefix, progname, and suffix. */ char *progpathname = - concatenated_filename (dir, progname, suffix); + concatenated_filename (dir_as_prefix, progname, suffix); if (progpathname == NULL) { /* errno is set here. */ failure_errno = errno; + free (dir_as_prefix_to_free); goto failed; } @@ -249,7 +278,7 @@ find_in_given_path (const char *progname, const char *path, free (progpathname); /* Add the "./" prefix for real, that - xconcatenated_filename() optimized away. + concatenated_filename() optimized away. This avoids a second PATH search when the caller uses execl/execv/execlp/execvp. */ progpathname = @@ -258,6 +287,7 @@ find_in_given_path (const char *progname, const char *path, { /* errno is set here. */ failure_errno = errno; + free (dir_as_prefix_to_free); goto failed; } progpathname[0] = '.'; @@ -266,6 +296,7 @@ find_in_given_path (const char *progname, const char *path, strlen (progname) + 1); } + free (dir_as_prefix_to_free); free (path_copy); return progpathname; } @@ -281,6 +312,8 @@ find_in_given_path (const char *progname, const char *path, } } + free (dir_as_prefix_to_free); + if (last) break; } diff --git a/lib/findprog.h b/lib/findprog.h index c020290..6e21aa2 100644 --- a/lib/findprog.h +++ b/lib/findprog.h @@ -42,6 +42,10 @@ extern const char *find_in_path (const char *progname); directory. A null PATH is equivalent to an empty PATH, that is, to the singleton list that contains only the current directory. + If DIRECTORY is not NULL, all relative filenames (i.e. PROGNAME when it + contains a slash, and the PATH elements) are considered relative to + DIRECTORY instead of relative to the current directory of this process. + Determines the pathname that would be called by execlp/execvp of PROGNAME. - If successful, it returns a pathname containing a slash (either absolute or relative to the current directory). The returned string can be used @@ -62,6 +66,7 @@ extern const char *find_in_path (const char *progname); - On POSIX systems excluding Cygwin: a '/', - On Windows, OS/2, DOS platforms: a '/' or '\'. */ extern const char *find_in_given_path (const char *progname, const char *path, + const char *directory, bool optimize_for_exec); diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c index bd34959..d483520 100644 --- a/lib/spawn-pipe.c +++ b/lib/spawn-pipe.c @@ -154,7 +154,7 @@ create_pipe (const char *progname, if (! IS_ABSOLUTE_FILE_NAME (prog_path)) { const char *resolved_prog = - find_in_given_path (prog_path, getenv ("PATH"), false); + find_in_given_path (prog_path, getenv ("PATH"), NULL, false); if (resolved_prog == NULL) goto fail_with_errno; if (resolved_prog != prog_path) diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c index 509727c..19251ae 100644 --- a/lib/windows-spawn.c +++ b/lib/windows-spawn.c @@ -223,7 +223,7 @@ spawnpvech (int mode, /* Implement the 'p' letter: search for PROGNAME in getenv ("PATH"). */ const char *resolved_progname = - find_in_given_path (progname, getenv ("PATH"), false); + find_in_given_path (progname, getenv ("PATH"), NULL, false); if (resolved_progname == NULL) return -1; -- 2.7.4