diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-02-17 12:11:15 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-02-17 12:11:15 -0800 |
commit | 3080fb5f28e0337b5859f4d6eb19bda9207a65fa (patch) | |
tree | a5db86f189fa8aa638ef82285668d387cb3dd500 /stream.c | |
parent | 4247fc89d9dba503a1eb6e211eae604835d782f7 (diff) | |
download | txr-3080fb5f28e0337b5859f4d6eb19bda9207a65fa.tar.gz txr-3080fb5f28e0337b5859f4d6eb19bda9207a65fa.tar.bz2 txr-3080fb5f28e0337b5859f4d6eb19bda9207a65fa.zip |
cygwin: use spawnvp for run and sh.
We revive the dead _wspawnvp code that was used on MinGW, a
platform that has not been supported for years, adapting it
for Cygwin.
* configure: Correct the _wspawnlp test; it should have been
testing for _wspawnvp function, which is what is is actually
used by the matching code. Moreover, the broken test was
calling _wspawnlp with _wspawnvp style arguments. Anyway, this
is moot because we will never detect this function in the
foreseeable future. More importantly, adding a test for
spawnvp, which exists on Cygwin.
* stream.c: Include the <process.h> header if HAVE_WSPAWN or
HAVE_SPAWN. This was missing before; how did the _wspawnvp
call ever compile?
(w_spawnvp): New static function.
(run): spawn version now calls either _wspawwnvp or w_spawnvp
if that is not available. We test for HAVE_WSPAWN or
HAVE_SPAWN first, before HAVE_FORK_STUFF, so that we use the
spawn function preferentially. On Cygwin, we have the fork
stuff.
Diffstat (limited to 'stream.c')
-rw-r--r-- | stream.c | 127 |
1 files changed, 81 insertions, 46 deletions
@@ -56,6 +56,9 @@ #if HAVE_SOCKETS #include <sys/socket.h> #endif +#if HAVE_WSPAWN || HAVE_SPAWN +#include <process.h> +#endif #include "alloca.h" #include "lib.h" #include "gc.h" @@ -4379,7 +4382,84 @@ val open_process(val name, val mode_str, val args) } #endif -#if HAVE_FORK_STUFF +#if HAVE_WSPAWN || HAVE_SPAWN + +#if !HAVE_WSPAWN +static int w_spawnvp(int mode, const wchar_t *wpath, int wargc, + const wchar_t **wargv) +{ + char *path = utf8_dup_to(wpath); + const char **argv = coerce(const char **, + chk_malloc(sizeof *argv * (wargc + 1))); + int i, res; + + for (i = 0; i < wargc; i++) + argv[i] = utf8_dup_to(wargv[i]); + argv[i] = 0; + + res = spawnvp(mode, path, argv); + + for (i = 0; i < wargc; i++) + free(strip_qual(char *, argv[i])); + free(argv); + free(path); + + return res; +} +#endif + +static val run(val command, val args) +{ + val self = lit("run"); + const wchar_t **wargv = 0; + val iter; + int i, nargs, status = 0; + struct save_fds sfds; + + args = default_null_arg(args); + nargs = c_num(length(args)) + 1; + + fds_init(&sfds); + + uw_simple_catch_begin; + + fds_swizzle(&sfds, FDS_IN | FDS_OUT | FDS_ERR); + + if (nargs < 0 || nargs == INT_MAX) + uw_throwf(error_s, lit("~a: argument list overflow"), self, nao); + + wargv = coerce(const wchar_t **, chk_xalloc(nargs + 1, sizeof *wargv, self)); + + for (i = 0, iter = cons(command, args); iter; i++, iter = cdr(iter)) + wargv[i] = c_str(car(iter)); + wargv[i] = 0; + +#if HAVE_WSPAWN + status = _wspawnvp(_P_WAIT, c_str(command), wargv); +#else + status = w_spawnvp(_P_WAIT, c_str(command), nargs, wargv); +#endif + + free(strip_qual(wchar_t **, wargv)); + + gc_hint(args); + + uw_unwind { + fds_restore(&sfds); + } + + uw_catch_end; + + return (status < 0) ? nil : num(status); +} + +static val sh(val command) +{ + return run(lit("cmd.exe"), list(lit("/C"), command, nao)); +} + +#elif HAVE_FORK_STUFF + static val run(val name, val args) { val self = lit("run"); @@ -4456,52 +4536,7 @@ static val sh(val command) { return run(shell, list(shell_arg, command, nao)); } -#elif HAVE_WSPAWN -static val run(val command, val args) -{ - val self = lit("run"); - const wchar_t **wargv = 0; - val iter; - int i, nargs, status; - struct save_fds sfds; - - args = default_null_arg(args); - nargs = c_num(length(args)) + 1; - - fds_init(&sfds); - - uw_simple_catch_begin; - - fds_swizzle(&sfds, FDS_IN | FDS_OUT | FDS_ERR); - - if (nargs < 0 || nargs == INT_MAX) - uw_throwf(error_s, lit("~a: argument list overflow"), self, nao); - wargv = coerce(const wchar_t **, chk_xalloc(nargs + 1, sizeof *wargv, self)); - - for (i = 0, iter = cons(command, args); iter; i++, iter = cdr(iter)) - wargv[i] = c_str(car(iter)); - wargv[i] = 0; - - status = _wspawnvp(_P_WAIT, c_str(command), wargv); - - free(strip_qual(wchar_t **, wargv)); - - gc_hint(args); - - uw_unwind { - fds_restore(&sfds); - } - - uw_catch_end; - - return (status < 0) ? nil : num(status); -} - -static val sh(val command) -{ - return run(lit("cmd.exe"), list(lit("/C"), command, nao)); -} #else #error port me! #endif |