std::process
Process
Safe, owned process helpers on supported POSIX hosts.
Overview
The Process namespace exposes startup argument access, process identifiers,
host shell execution, and an owned Command builder for child processes.
Argument helpers copy host argv data into owned String values so callers
do not depend on raw C pointers.
The compiler-generated C main wrapper bootstraps runtime access to argc
and argv. Runtime C does not own command-builder state; Process::Command
stores owned Ignis data and drives POSIX fork, execvp, pipe, dup2,
waitpid, and related calls through std::libc.
C entrypoint
┌──────────────────────────────────────────────────────────────┐
│ int main(int argc, char** argv) │
└───────────────────────┬──────────────────────────────────────┘
│ stores argc/argv in runtime slots
▼
__process_rt
┌──────────────────────────────────────────────────────────────┐
│ ignis_process_arg_count() -> argc │
│ ignis_process_arg_at(i) -> argv[i] or null │
└───────────────────────┬──────────────────────────────────────┘
│ copied into owned String values
▼
Process::args() -> Vector<String>
APIs
| API | Description |
|---|---|
Process::args |
Owned startup arguments, including argv[0] |
Process::argCount |
Raw startup argument count |
Process::id |
Current process identifier |
Process::parentId |
Parent process identifier |
Process::system |
Execute a command through the host shell |
Process::Command |
Owned child-process builder backed by POSIX APIs |
Process::command |
Convenience constructor for Command |
Process::ExitStatus |
Normalized wait-status view |
Process::Output |
Captured stdout/stderr and status |
Raw Status Values
Process::system returns the raw integer status produced by the host C
library. This value is not normalized to an exit code; POSIX hosts encode
signal and exit information in the wait status. Callers that need portable
exit-code handling should prefer Process::Command::run or
Process::Command::output, which return Process::ExitStatus.
Shell and Security Notes
Process::system delegates to the host shell. Shell expansion, quoting,
environment inheritance, current working directory, and PATH lookup all follow
host behavior. Do not pass untrusted text into system without explicit
validation or quoting for the target shell.
Process::Command bypasses the shell unless the selected program is itself a
shell. Arguments are passed as distinct argv entries to execvp.
Platform Notes
These APIs are currently enabled on Linux and macOS. system returns the raw
host status and inherits the shell’s quoting and security behavior.
Example
import Process from "std::process";
import String from "std::string";
import Vector from "std::vector";
function main(): i32 {
let args: Vector<String> = Process::args();
return args.length() > 0 ? 0 : 1;
}
Command Example
import Path from "std::path";
import Process from "std::process";
import String from "std::string";
import Vector from "std::vector";
function main(): i32 {
let mut command: Process::Command = Process::command("/bin/sh");
command.arg("-c");
command.arg("printf '%s' \"$IGNIS_EXAMPLE\"");
command.env("IGNIS_EXAMPLE", "ok");
command.cwd(&Path::PathBuf::create("/tmp"));
match (command.output()) {
Result::OK(output) -> {
let status: Process::ExitStatus = output.status();
let stdout: String = output.stdout();
if status.success && stdout.equalsStr("ok") {
return 0;
}
return status.code;
},
Result::ERROR(_) -> return 1,
};
}
namespace __process_rtFunctions
function ignis_process_arg_at(index: i32): *mut u8Returns a borrowed argv[index] pointer captured by the runtime.
function ignis_process_arg_count(): i32Returns the argc value captured by the generated runtime entrypoint.
namespace ProcessProcess inspection and command execution helpers.
This namespace wraps runtime-provided startup arguments and selected POSIX
process calls. Argument APIs return owned strings detached from the raw C
argv storage captured when the generated program starts.
Records
record CommandOwned child-process builder implemented in Ignis std.
The builder keeps owned program, argument, environment, and cwd state in
nongeneric storage so the std module can drive POSIX fork/execvp
directly through std::libc without relying on dedicated runtime helpers.
Example
import Path from "std::path";
import Process from "std::process";
import String from "std::string";
import Vector from "std::vector";
let mut extra: Vector<String> = Vector::new<String>();
extra.push(String::create("-c"));
extra.push(String::create("printf done"));
let mut command: Process::Command = Process::Command::new("/bin/sh");
command.args(extra);
command.env("IGNIS_CHILD", "1");
command.cwd(&Path::PathBuf::create("/tmp"));
match (command.run()) {
Result::OK(status) -> {
let ok: boolean = status.success;
},
Result::ERROR(_) -> {},
};
program: StringProgram path or command name used for execvp.
args(&mut self, values: Vector<String>): voidAppends multiple arguments in order.
Each vector element is appended as one argv entry, preserving order.
argsLength: u64Number of initialized entries in args.
argsCapacity: u64Allocated capacity of args.
envKeys: *mut StringOwned child-only environment keys.
envValues: *mut StringOwned child-only environment values.
envLength: u64Number of initialized key/value pairs in envKeys and envValues.
envCapacity: u64Allocated capacity of envKeys and envValues.
cwd(&mut self, path: &PathBuf): voidSets the child working directory without mutating the parent process.
The directory change runs after fork and before execvp, so it applies
only to the child process.
hasCwd: booleanTrue when cwd should be applied in the child after fork.
static new(program: str): CommandCreates a new child-process command builder.
program is copied into owned storage and is also inserted as argv[0].
arg(&mut self, value: str): voidAppends one argument to the child command line.
Arguments are not parsed by a shell. Each call appends one exact argv
entry for the eventual execvp call.
args(&mut self, values: Vector<String>): voidAppends multiple arguments in order.
Each vector element is appended as one argv entry, preserving order.
buildArgv(&self): *mut strBuilds the null-terminated borrowed argv array required by execvp.
The returned array owns only the pointer vector, not the pointed-to string
bytes. The parent frees the vector after fork; the child only uses it
until execvp succeeds or processCommandChildFail exits.
cwd(&mut self, path: &PathBuf): voidSets the child working directory without mutating the parent process.
The directory change runs after fork and before execvp, so it applies
only to the child process.
drop(&mut self): voidReleases the owned builder storage.
dropArgsStorage(&mut self): voidDrops all initialized argv strings and frees argv storage.
dropEnvStorage(&mut self): voidDrops all initialized environment strings and frees environment storage.
env(&mut self, key: str, value: str): voidAdds or replaces one environment variable for the child only.
The parent process environment is not changed. Reusing the same key updates the child override instead of adding a duplicate entry.
growArgs(&mut self, minCapacity: u64): voidEnsures argv storage can hold at least minCapacity initialized entries.
growEnv(&mut self, minCapacity: u64): voidEnsures environment key/value storage can hold minCapacity entries.
output(&self): Result<Output, IoError>Runs the child process and captures stdout/stderr into owned Strings.
Captured output is stored in temporary files created with mkstemp and
unlinked before the child runs, avoiding visible leftover paths when the
process completes normally.
Example
import Process from "std::process";
import String from "std::string";
let mut command: Process::Command = Process::Command::new("/bin/sh");
command.arg("-c");
command.arg("printf stdout; printf stderr 1>&2");
match (command.output()) {
Result::OK(output) -> {
let status: Process::ExitStatus = output.status();
let stdout: String = output.stdout();
let stderr: String = output.stderr();
},
Result::ERROR(_) -> {},
};
prepareChild(&self, errorFd: i32): voidApplies child-only cwd and environment state after fork.
This function must run in the child. On failure it reports errno through
errorFd and exits, because returning into shared parent control flow
after partial child setup would be unsafe.
pushArgValue(&mut self, value: str): voidCopies value into owned argv storage.
run(&self): Result<ExitStatus, IoError>Runs the child process without capturing stdout or stderr.
Example
import Process from "std::process";
let mut command: Process::Command = Process::command("/bin/sh");
command.arg("-c");
command.arg("exit 7");
match (command.run()) {
Result::OK(status) -> {
let code: i32 = status.code;
let ok: boolean = status.success;
},
Result::ERROR(_) -> {},
};
setEnvValue(&mut self, key: str, value: str): voidAdds or replaces one child environment override in owned storage.
spawn(&self, stdoutFd: i32, stderrFd: i32, rawStatusOut: &mut i32): i32Forks, optionally redirects output fds, execs the program, and waits.
Returns 0 on successful spawn/wait and writes the raw wait status to
rawStatusOut. A nonzero return value is a raw errno suitable for
Io::IoError::fromErrno.
record ExitStatusNormalized child-process status derived from a POSIX wait status.
raw preserves the host wait status. code contains a shell-like exit
code: regular exits use the child exit code and signal exits use
128 + signal. success is true only when the child exited with code 0.
raw: i32Raw host wait status returned by the runtime.
code: i32Normalized exit-code-like value.
success: booleanTrue when the command exited successfully.
record OutputCaptured child-process output plus exit status.
Example
import Process from "std::process";
import String from "std::string";
let command: Process::Command = Process::Command::new("/bin/echo");
match (command.output()) {
Result::OK(output) -> {
let status: Process::ExitStatus = output.status();
let stdout: String = output.stdout();
},
Result::ERROR(_) -> {},
};
status(&self): ExitStatusReturns the child exit status.
stdout(&self): StringReturns a cloned copy of captured stdout.
stderr(&self): StringReturns a cloned copy of captured stderr.
status(&self): ExitStatusReturns the child exit status.
stderr(&self): StringReturns a cloned copy of captured stderr.
stdout(&self): StringReturns a cloned copy of captured stdout.
Functions
function argCount(): i32Returns the host startup argument count, including argv[0].
The count comes from the runtime bootstrap created by the compiler’s C
main wrapper. It is the same count used by Process::args.
Returns
Number of startup arguments captured by the runtime, including argv[0].
Invariants
argCount() should match Process::args().length() as long as runtime
initialization happened before the call and the runtime bridge remains
unchanged.
Example
import Process from "std::process";
let count: i32 = Process::argCount();
let hasProgramName: boolean = count > 0;
function args(): Vector<String>Returns owned copies of the startup arguments, including argv[0].
The returned vector owns every string. Mutating or storing the returned
values is safe because they no longer borrow from the runtime argv array.
Ordering
The result preserves host argv order exactly:
args()[0] -> argv[0] // program/test binary path
args()[1] -> argv[1]
args()[2] -> argv[2]
The std test runner invokes individual tests through its own harness, so
argv[0] is the generated std test binary in that context.
Returns
A vector with Process::argCount() entries. The first entry is the program
path or command name as supplied by the host process launcher.
Example
import Process from "std::process";
let args = Process::args();
let hasUserArg: boolean = args.length() > 1;
function command(program: str): CommandConvenience helper mirroring common builder-style construction.
Example
import Process from "std::process";
let mut command: Process::Command = Process::command("/bin/echo");
command.arg("hello");
function id(): i32Returns the current process identifier.
This is the host PID returned by getpid(2) on POSIX platforms. The value
is useful for diagnostics, logs, temporary file names, and process-aware
integration tests.
Returns
Positive host process identifier for the currently running test or program.
Notes
PIDs are host resources. They are not deterministic between runs and should only be used for diagnostics, uniqueness, or sanity checks.
Example
import Process from "std::process";
let pid: i32 = Process::id();
let valid: boolean = pid > 0;
function parentId(): i32Returns the parent process identifier.
This is the host parent PID returned by getppid(2). Parent process IDs
can change if the original parent exits and the process is reparented by
the operating system.
Returns
Host process identifier for the current process parent.
Notes
POSIX can reparent processes when the original parent exits. Do not use this value as a stable identity across long-running programs.
Example
import Process from "std::process";
let parent: i32 = Process::parentId();
let hasParent: boolean = parent > 0;
function system(command: str): i32Executes command through the host shell and returns the raw host status.
The command is passed to the platform C library system(3). The shell is
responsible for parsing, expansion, redirection, PATH lookup, and process
creation. The returned value is the raw host status, not a normalized exit
code.
Security
Avoid building command from untrusted input. Shell metacharacters can
change the executed program or add additional commands.
Arguments
command: shell command text passed directly tosystem(3).
Returns
Raw host status returned by the C library. On POSIX this is a wait status, not just the child exit code.
Status Encoding
A command that exits with code 1 may return an encoded value such as
256, depending on the platform. Prefer Process::Command::run when you
need the normalized Process::ExitStatus view.
Example
import Process from "std::process";
let status: i32 = Process::system("true");
let succeededExactly: boolean = status == 0;
Functions
function processCommandChildFail(errorFd: i32, rawErrno: i32): voidReports child setup or exec failure to the parent, then exits the child.
This helper must only run after fork in the child process. It writes a raw
errno value to the close-on-exec error pipe so the parent can distinguish
successful execvp from setup failures before returning an IoError.
function processCommandReadAll(fd: i32): Result<String, IoError>Reads a seekable temporary output file into an owned String.
The caller retains ownership of fd and must close it after this helper
returns. The temporary file has already been unlinked by Command::output,
so reading consumes only the anonymous open descriptor.
function processCommandSetCloseOnExec(fd: i32): i32Marks fd close-on-exec so parent-only descriptors do not leak into children.
function processCommandWaitForExec(pid: i32, errorReadFd: i32, rawStatusOut: &mut i32): i32Waits for child startup completion and then reaps the child process.
The error pipe is close-on-exec. EOF therefore means execvp succeeded,
while bytes on the pipe contain the child setup/exec errno. This function
owns and closes errorReadFd before returning.
function processExitStatusFromRaw(rawStatus: i32): ExitStatusConverts a raw host wait status into the public ExitStatus record.
function processOwnedArgAt(index: i32): StringCopies one runtime argument into an owned String.
A null runtime pointer is treated as an empty string to keep Process::args
total over the range 0..Process::argCount().
Runtime Contract
The generated C wrapper must call ignis_runtime_init(argc, argv) before any
user or test code calls this helper. Without runtime initialization, argument
count and pointer reads fall back to whatever the runtime bridge reports.
Arguments
index: zero-based runtime argument index.
Returns
An owned String copy of argv[index], or an empty String if the runtime
reports a null pointer. Callers normally use Process::args instead of this
helper.
function processWaitStatusCode(rawStatus: i32): i32Converts a POSIX wait status into a shell-like status code.
function processWaitStatusExited(rawStatus: i32): booleanReturns true when a POSIX wait status represents normal child exit.
function processWaitStatusStopped(rawStatus: i32): booleanReturns true when a POSIX wait status represents a stopped child.
function processWaitStatusSuccess(rawStatus: i32): booleanReturns true only for normal exit with status code 0.
Constants
const PROCESS_EXEC_FAILURE_EXIT: i32const PROCESS_SIGNAL_MASK: i32const PROCESS_STOPPED_MASK: i32const PROCESS_STOPPED_VALUE: i32