summaryrefslogtreecommitdiffstats
path: root/stream.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-03-13 01:07:49 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-03-13 01:07:49 -0700
commit5251ac1ca49b5abc0d68f77291eb463f2040eb31 (patch)
treeae9b60f56270a79931ffe6c8c1a3cd9b5c7198e4 /stream.c
parent03e6fc5649ab4548fc331a0fe8bb5ed93eb296db (diff)
downloadtxr-5251ac1ca49b5abc0d68f77291eb463f2040eb31.tar.gz
txr-5251ac1ca49b5abc0d68f77291eb463f2040eb31.tar.bz2
txr-5251ac1ca49b5abc0d68f77291eb463f2040eb31.zip
* stream.c (open_process): If execvp fails, use errno as the
exit status. (sh, run): New static functions. (stream_init): sh and run registered as intrinsics.
Diffstat (limited to 'stream.c')
-rw-r--r--stream.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/stream.c b/stream.c
index 8e049212..1744c28c 100644
--- a/stream.c
+++ b/stream.c
@@ -2176,7 +2176,7 @@ val open_process(val name, val mode_str, val args)
}
execvp(utf8name, argv);
- _exit(1);
+ _exit(errno);
} else {
int whichfd;
char *utf8mode = utf8_dup_to(c_str(mode_str));
@@ -2271,6 +2271,81 @@ val open_process(val name, val mode_str, val args)
}
#endif
+static val sh(val command)
+{
+ char *cmd = utf8_dup_to(c_str(command));
+ int status = system(cmd);
+ if (status < 0)
+ return nil;
+#if HAVE_SYS_WAIT
+ if (WIFEXITED(status)) {
+ int exitstatus = WEXITSTATUS(status);
+ return num(exitstatus);
+ }
+#endif
+ return status == 0 ? zero : nil;
+}
+
+#if HAVE_FORK_STUFF
+static val run(val name, val args)
+{
+ pid_t pid;
+ char **argv = 0, *utf8name = 0;
+ val iter;
+ int i, nargs;
+
+ args = default_bool_arg(args);
+ nargs = c_num(length(args)) + 1;
+
+ argv = (char **) chk_malloc((nargs + 2) * sizeof *argv);
+
+ for (i = 0, iter = cons(name, args); iter; i++, iter = cdr(iter)) {
+ val arg = car(iter);
+ argv[i] = utf8_dup_to(c_str(arg));
+ }
+ argv[i] = 0;
+
+ utf8name = utf8_dup_to(c_str(name));
+
+ pid = fork();
+
+ if (pid == -1) {
+ for (i = 0; i < nargs; i++)
+ free(argv[i]);
+ free(argv);
+ uw_throwf(file_error_s, lit("opening process ~a, fork syscall failed: ~a/~s"),
+ name, num(errno), string_utf8(strerror(errno)), nao);
+ }
+
+ if (pid == 0) {
+ execvp(utf8name, argv);
+ _exit(errno);
+ } else {
+ int status;
+ for (i = 0; i < nargs; i++)
+ free(argv[i]);
+ free(argv);
+ while (waitpid(pid, &status, 0) == -1 && errno == EINTR)
+ ;
+ if (status < 0)
+ return nil;
+#if HAVE_SYS_WAIT
+ if (WIFEXITED(status)) {
+ int exitstatus = WEXITSTATUS(status);
+ return num(exitstatus);
+ }
+#endif
+ return status == 0 ? zero : nil;
+ }
+}
+#else
+static val run(val command, val args)
+{
+ val win_cmdline = win_make_cmdline(cons(name, args));
+ return sh(win_cmdline);
+}
+#endif
+
static void cat_stream_print(val stream, val out)
{
val streams = (val) stream->co.handle;
@@ -2748,6 +2823,8 @@ void stream_init(void)
reg_fun(intern(lit("open-command"), user_package), func_n2o(open_command, 1));
reg_fun(intern(lit("open-pipe"), user_package), func_n2(open_command));
reg_fun(intern(lit("open-process"), user_package), func_n3o(open_process, 2));
+ reg_fun(intern(lit("sh"), user_package), func_n1(sh));
+ reg_fun(intern(lit("run"), user_package), func_n2o(run, 1));
reg_fun(intern(lit("remove-path"), user_package), func_n1(remove_path));
reg_fun(intern(lit("rename-path"), user_package), func_n2(rename_path));
reg_fun(intern(lit("open-files"), user_package), func_n2o(open_files, 1));