bunpen: bind execvpe
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
Reference in New Issue
Block a user