summaryrefslogtreecommitdiffstats
path: root/stream.c
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 /stream.c
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.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c127
1 files changed, 81 insertions, 46 deletions
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