diff --git a/CHANGELOG.md b/CHANGELOG.md index f421a82d..9b411a0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ All notable changes to this project will be documented in this file. ## Unreleased - ??? +- Expose `janet_cfuns_prefix` in C API. - Add `os/proc-wait` and `os/proc-kill` for interacting with processes. - Add `janet_getjfile` to C API. -- Allow redirection of stdin, stdout, and stderr by passing keywords in the env table. -- Add `:a` flag to `os/execute` to get a core/process back instead of an exit code. +- Allow redirection of stdin, stdout, and stderr by passing keywords in the env table in `os/spawn` and `os/execute`. +- Add `os/spawn` to get a core/process back instead of an exit code as in `os/execute`. When called like this, `os/execute` returns immediately. - Add `:x` flag to os/execute to raise error when exit code is non-zero. - Don't run `main` when flychecking. diff --git a/src/core/os.c b/src/core/os.c index ac24bad5..46f5f638 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -428,13 +428,13 @@ static const JanetAbstractType ProcAT = { JANET_ATEND_GET }; -static Janet os_execute(int32_t argc, Janet *argv) { +static Janet os_execute_impl(int32_t argc, Janet *argv, int is_async) { janet_arity(argc, 1, 3); /* Get flags */ uint64_t flags = 0; if (argc > 1) { - flags = janet_getflags(argv, 1, "epxa"); + flags = janet_getflags(argv, 1, "epx"); } /* Get environment */ @@ -462,7 +462,6 @@ static Janet os_execute(int32_t argc, Janet *argv) { /* Result */ int status = 0; - int is_async = janet_flag_at(flags, 3); #ifdef JANET_WINDOWS @@ -569,7 +568,7 @@ static Janet os_execute(int32_t argc, Janet *argv) { if (status) { os_execute_cleanup(envp, child_argv); janet_panicf("%p: %s", argv[0], strerror(errno)); - } else if (janet_flag_at(flags, 3)) { + } else if (is_async) { /* Get process handle */ os_execute_cleanup(envp, child_argv); } else { @@ -608,6 +607,14 @@ static Janet os_execute(int32_t argc, Janet *argv) { } } +static Janet os_execute(int32_t argc, Janet *argv) { + return os_execute_impl(argc, argv, 1); +} + +static Janet os_spawn(int32_t argc, Janet *argv) { + return os_execute_impl(argc, argv, 0); +} + static Janet os_shell(int32_t argc, Janet *argv) { janet_arity(argc, 0, 1); const char *cmd = argc @@ -1522,11 +1529,16 @@ static const JanetReg os_cfuns[] = { "\t:p - allows searching the current PATH for the binary to execute. " "Without this flag, binaries must use absolute paths.\n" "\t:x - raise error if exit code is non-zero.\n" - "\t:a - Runs the process asynchronously and returns a core/process.\n\n" "env is a table or struct mapping environment variables to values. It can also " "contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. " "These arguments should be core/file values. " - "Returns the exit status of the program, or a core/process object if the :a flag is given.") + "Returns the exit status of the program.") + }, + { + "os/spawn", os_spawn, + JDOC("(os/spawn args &opts flags env)\n\n" + "Execute a program on the system and return a handle to the process. Otherwise, the " + "same arguments as os/execute. Does not wait for the process.") }, { "os/shell", os_shell, diff --git a/src/include/janet.h b/src/include/janet.h index 443cef4e..e90cc423 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1439,6 +1439,7 @@ typedef enum { JANET_API void janet_def(JanetTable *env, const char *name, Janet val, const char *documentation); JANET_API void janet_var(JanetTable *env, const char *name, Janet val, const char *documentation); JANET_API void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns); +JANET_API void janet_cfuns_prefix(JanetTable *env, const char *regprefix, const JanetReg *cfuns); JANET_API JanetBindingType janet_resolve(JanetTable *env, JanetSymbol sym, Janet *out); JANET_API void janet_register(const char *name, JanetCFunction cfun);