bunpen: bind execvpe

This commit is contained in:
2024-09-05 23:21:31 +00:00
parent 4123d2d92e
commit 05b8352b4d

View File

@@ -1,10 +1,13 @@
// vim: set shiftwidth=2 :
use log;
use os;
use path;
use rt;
use strings;
use types::c;
export fn execve(path: str, argv: []str, envp: []str = []) (rt::errno | void) = {
export fn execve(path: str, argv: []str, envp: []str = []) rt::errno = {
let path_buf: [path::MAX]c::char = [0...];
syscall(
@@ -14,6 +17,21 @@ export fn execve(path: str, argv: []str, envp: []str = []) (rt::errno | void) =
to_cstr_array(argv): *[*]nullable *const c::char: uintptr: u64,
to_cstr_array(envp): *[*]nullable *const c::char: uintptr: u64,
)?;
log::fatal("[exec] unexpectedly returned without error");
};
// if `name` contains a slash, proceed as per `execve`.
// otherwise, crawl $PATH and try executing until we succeed.
export fn execvpe(name: str, argv: []str, envp: []str = []) rt::errno = {
return if (strings::contains(name, "/")) {
yield execve(name, argv, envp);
} else {
yield match (os::getenv("PATH")) {
case let p: str => yield _execvpe(p, name, argv, envp);
case void => yield execve(name, argv, envp);
};
};
};
// allocate and return a NULL-terminated array of pointers to c strings.
@@ -26,3 +44,19 @@ fn to_cstr_array(strs: []str) []nullable *const c::char = {
append(cstrs, null);
return cstrs;
};
// split `path` on `:`, crawl it, and try executing until we succeed.
// note that 1:1 parity with libc's execvpe is probably not what we have here.
fn _execvpe(path: str, name: str, argv: []str, envp: []str = []) rt::errno = {
let status = rt::ENOENT;
let pieces = strings::split(path, ":");
defer free(pieces);
for (let p .. pieces) {
let this_path = strings::join("/", p, name);
defer free(this_path);
status = execve(this_path, argv, envp);
// try the next item, or return the status if this is the last one.
};
return status;
};