Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(enh) adds Process.exec(cmd, [args], [cwd],[env]) #94

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
50 changes: 48 additions & 2 deletions src/module/os.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ static void processOnExit(uv_process_t* req, int64_t exit_status, int term_signa
arg = data->options.args[index];
}

index = 0;
if (data->options.env) {
char* env = data->options.env[index];
while (env != NULL)
{
free(env);
index += 1;
env = data->options.args[index];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in later commit.

}
}

free((void*)data);

schedulerResume(fiber, true);
Expand Down Expand Up @@ -184,6 +195,41 @@ void processExec(WrenVM* vm)
data->options.exit_cb = processOnExit;
data->fiber = wrenGetSlotHandle(vm, 5);

wrenEnsureSlots(vm, 6);

if (wrenGetSlotType(vm, 4) == WREN_TYPE_NULL) {
// no environment specified
} else if (wrenGetSlotType(vm, 4) == WREN_TYPE_LIST) {
// fprintf(stderr,"got list\n");
int envCount = wrenGetListCount(vm, 4);
int envSize = sizeof(char*) * (envCount + 1);

data->options.env = (char**)malloc(envSize);
data->options.env[envCount] = NULL;

// fprintf(stderr,"envsize %d\n", envCount);
for (int i = 0; i < envCount ; i++)
{

wrenGetListElement(vm, 4, i, 6);
//:todo: ensure this is a string, and report an error if not

if (wrenGetSlotType(vm, 6) != WREN_TYPE_STRING) {
wrenSetSlotString(vm, 0, "aruments to params are suppose to be string");
wrenAbortFiber(vm, 0);
}
char* envKeyPlusValue = cli_strdup(wrenGetSlotString(vm, 6));
// fprintf(stderr,"key: %s\n", envKeyPlusValue);
// fprintf(stderr,"setting %s\n", envKeyPlusValue);
// char* equalSplit = strchr(envKeyPlusValue, '=');
// *equalSplit = '\0';
// char* key = envKeyPlusValue;
// char* value = equalSplit + 1;

data->options.env[i] = envKeyPlusValue;
}
}

int argCount = wrenGetListCount(vm, 2);
int argsSize = sizeof(char*) * (argCount + 2);

Expand All @@ -192,7 +238,6 @@ void processExec(WrenVM* vm)
data->options.args[0] = cmd;
data->options.args[argCount + 1] = NULL;

wrenEnsureSlots(vm, 3);
for (int i = 0; i < argCount; i++)
{
wrenGetListElement(vm, 2, i, 3);
Expand All @@ -209,7 +254,8 @@ void processExec(WrenVM* vm)
int r;
if ((r = uv_spawn(getLoop(), child_req, &data->options)))
{
fprintf(stderr, "Could not launch %s, reason: %s\n", cmd, uv_strerror(r));
// should be stderr??? but no idea how to make tests work/pass with that
fprintf(stdout, "Could not launch %s, reason: %s\n", cmd, uv_strerror(r));
wrenSetSlotString(vm, 0, "Could not spawn process.");
wrenAbortFiber(vm, 0);
}
Expand Down
12 changes: 11 additions & 1 deletion src/module/os.wren
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,17 @@ class Process {
return exec(cmd, args, cwd, null)
}

static exec(cmd, args, cwd, env) {
static exec(cmd, args, cwd, envMap) {
var env = []
if (envMap is Map) {
for (entry in envMap) {
env.add([entry.key, entry.value].join("="))
}
} else if (envMap == null) {
env = null
} else {
Fiber.abort("environment vars must be passed as a Map")
}
exec_(cmd, args, cwd, env, Fiber.current)
return Scheduler.runNextScheduled_()
}
Expand Down
12 changes: 11 additions & 1 deletion src/module/os.wren.inc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,17 @@ static const char* osModuleSource =
" return exec(cmd, args, cwd, null) \n"
" }\n"
" \n"
" static exec(cmd, args, cwd, env) { \n"
" static exec(cmd, args, cwd, envMap) { \n"
" var env = []\n"
" if (envMap is Map) {\n"
" for (entry in envMap) {\n"
" env.add([entry.key, entry.value].join(\"=\"))\n"
" }\n"
" } else if (envMap == null) {\n"
" env = null\n"
" } else {\n"
" Fiber.abort(\"environment vars must be passed as a Map\")\n"
" }\n"
" exec_(cmd, args, cwd, env, Fiber.current)\n"
" return Scheduler.runNextScheduled_()\n"
" }\n"
Expand Down
16 changes: 16 additions & 0 deletions test/os/process/exec.wren
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,20 @@ if (Platform.isPosix) {
System.print(Process.exec("ls", ["test"], "./src/")) // expect: 1
} else if (Platform.name == "Windows") {
// TODO: can this be done with dir on windows?
}

// env

if (Platform.isPosix) {
System.print(Process.exec("/usr/bin/true",[],null,{})) // expect: 0

var fiber = Fiber.new {
Process.exec("ls",[],null,{"PATH": "/binx/"})
}
var r = fiber.try()
System.print(r)
// expect: Could not launch ls, reason: no such file or directory
// expect: Could not spawn process.
} else if (Platform.name == "Windows") {

}