hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Mos/exec/cmd.ha | 9++++++++-
Mos/exec/exec+freebsd.ha | 4++++
Mos/exec/exec+linux.ha | 4++++
Mos/exec/types.ha | 6+++++-
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); }; };