summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-02-17 12:11:15 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-02-17 12:11:15 -0800
commit3080fb5f28e0337b5859f4d6eb19bda9207a65fa (patch)
treea5db86f189fa8aa638ef82285668d387cb3dd500
parent4247fc89d9dba503a1eb6e211eae604835d782f7 (diff)
downloadtxr-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.
-rwxr-xr-xconfigure23
-rw-r--r--stream.c127
2 files changed, 102 insertions, 48 deletions
diff --git a/configure b/configure
index 4198718d..18390a21 100755
--- a/configure
+++ b/configure
@@ -2506,7 +2506,7 @@ else
printf "no\n"
fi
-printf "Checking for _wspawnlp ... "
+printf "Checking for _wspawnvp ... "
cat > conftest.c <<!
#include "config.h"
@@ -2516,7 +2516,7 @@ cat > conftest.c <<!
int main(int argc, char **argv)
{
wchar_t *wargv[] = { L"foo", L"bar", 0 };
- int r = _wspawnlp(_P_WAIT, L"foo", wargv);
+ int r = _wspawnvp(_P_WAIT, L"foo", wargv);
return 0;
}
!
@@ -2527,6 +2527,25 @@ else
printf "no\n"
fi
+printf "Checking for spawnvp ... "
+
+cat > conftest.c <<!
+#include "config.h"
+#include <process.h>
+
+int main(int argc, char **argv)
+{
+ int r = spawnvp(_P_WAIT, "foo", argv);
+ return 0;
+}
+!
+if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_SPAWN 1\n" >> config.h
+else
+ printf "no\n"
+fi
+
printf "Checking for chsize ... "
cat > conftest.c <<!
#include <unistd.h>
diff --git a/stream.c b/stream.c
index 0c6af9ec..7acabe82 100644
--- a/stream.c
+++ b/stream.c
@@ -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