commit 380529eb5ac3325ea7cc741f00ba76b754d70d7c
parent 57e083e59ff9bd4e4d8db0f628aaf43172066762
Author: Ember Sawady <ecs@d2evs.net>
Date: Wed, 18 Jan 2023 15:14:05 +0000
os::exec: add chdir
Signed-off-by: Ember Sawady <ecs@d2evs.net>
Diffstat:
4 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/os/exec/cmd.ha b/os/exec/cmd.ha
@@ -42,7 +42,7 @@ export fn cmd(name: str, args: str...) (command | error) = {
argv = alloc([], len(args) + 1),
env = strings::dupall(os::getenvs()),
files = [],
- ...
+ dir = "",
};
append(cmd.argv, name);
append(cmd.argv, args...);
@@ -177,6 +177,13 @@ export fn nullstd(cmd: *command) void = {
addfile(cmd, os::stderr, nullfd);
};
+// Configures the child process's working directory. This does not affect the
+// process environment. The path is borrowed from the input, and must outlive
+// the command.
+export fn chdir(cmd: *command, dir: str) void = {
+ cmd.dir = dir;
+};
+
fn lookup(name: str) (platform_cmd | void | error) = {
const path = match (os::getenv("PATH")) {
case void =>
diff --git a/os/exec/exec+freebsd.ha b/os/exec/exec+freebsd.ha
@@ -138,6 +138,10 @@ fn platform_exec(cmd: *command) error = {
};
};
+ if (cmd.dir != "") {
+ os::chdir(cmd.dir)?;
+ };
+
return errors::errno(rt::fexecve(cmd.platform,
argv: *[*]nullable *const char, envp: *[*]nullable *const char));
};
diff --git a/os/exec/exec+linux.ha b/os/exec/exec+linux.ha
@@ -150,6 +150,10 @@ fn platform_exec(cmd: *command) error = {
};
};
+ if (cmd.dir != "") {
+ os::chdir(cmd.dir)?;
+ };
+
return errors::errno(rt::execveat(cmd.platform,
"\0", argv: *[*]nullable *const char,
envp: *[*]nullable *const char, rt::AT_EMPTY_PATH));
diff --git a/os/exec/types.ha b/os/exec/types.ha
@@ -2,6 +2,7 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use errors;
+use fs;
use io;
// Represents a "null" file descriptor, e.g. /dev/null.
@@ -15,13 +16,14 @@ export type command = struct {
argv: []str,
env: []str,
files: []((io::file | nullfd | closefd), io::file),
+ dir: str,
};
// Returned when path resolution fails to find a command by its name.
export type nocmd = !void;
// All errors that can be returned from os::exec.
-export type error = !(nocmd | ...errors::error | io::error);
+export type error = !(nocmd | ...errors::error | io::error | fs::error);
// Returns a human-readable message for the given error.
export fn strerror(err: error) const str = {
@@ -32,6 +34,8 @@ export fn strerror(err: error) const str = {
return errors::strerror(err);
case let err: io::error =>
return io::strerror(err);
+ case let err: fs::error =>
+ return fs::strerror(err);
};
};