(sigil process)
(sigil process) - Process Management Library
Process management operations including spawning subprocesses, environment variable access, and command execution. Native functions are implemented in C with higher-level utilities defined here.
Running Commands
(import (sigil process))
;; Run and wait for completion
(process-run "ls" "-l")
;; Capture output as string
(process-output->string "date") ; => "Thu Jan 15 14:30:00 2025"
;; Capture output as lines
(process-lines "ls") ; => ("file1" "file2" ...)Spawning Processes
(let ((p (process-spawn "cat")))
(display "Hello\n" (process-stdin p))
(close-output-port (process-stdin p))
(display (read-line (process-stdout p)))
(process-wait p))Environment
(getenv "HOME") ; => "/home/user"
(setenv! "MY_VAR" "value")Exports
process-runprocedureRun a command and wait for it to complete.
Returns the exit status (0 for success; 128+N when the child died from signal N). Raises an io-error when the process cannot be started or waited on (for example, fork failing under process pressure) -- it never returns a non-integer.
(process-run "ls" "-l") ; => 0process-spawnprocedureSpawn a subprocess without waiting.
Returns a process object, or #f if the process cannot be started. Use process-wait to wait for completion and retrieve the exit status.
With die-with-parent: #t, the child is killed automatically when this (parent) process dies, even on an uncatchable SIGKILL. On Linux this uses PR_SET_PDEATHSIG; on other platforms it is a no-op.
(let ((p (process-spawn "sleep" "10")))
(process-kill! p))
;; Child dies on its own if this process is killed:
(process-spawn "my-worker" "--serve" die-with-parent: #t)process-spawn-ptyprocedureSpawn a subprocess on a pseudo-terminal (Unix only).
Allocates a pty, forks, and runs the command as a session leader with the pty slave as its controlling terminal wired to stdin/stdout/stderr. All fork discipline is handled in C; do not attempt fork or forkpty from Scheme.
Returns a process object whose I/O rides the pty MASTER, not pipes: use process-pty-read / process-pty-write (guarded by await-readable-fd / await-writable-fd on process-pty-fd in async code), NOT process-stdout / process-stdin.
The master fd is non-blocking. process-pty-read returns an empty bytevector when no data is ready and an eof-object once the child exited and the stream drained. cwd: sets the child's working directory; term: sets its TERM (default "xterm-256color"; pass #f to inherit).
(let ((p (process-spawn-pty "sh" cols: 120 rows: 40)))
(process-pty-write p "ls\n")
...
(process-pty-close! p)
(process-wait p))process-spawn-pipeprocedureSpawn a subprocess on non-blocking pipes for a stream session (Unix only).
The pipe analog of process-spawn-pty, for a child that speaks a line/byte protocol over stdin/stdout rather than a terminal — e.g. tmux -C, which hard-fails on a tty. stdin and stdout are NON-BLOCKING pipes; the child's stderr is inherited (not captured), keeping the stdout stream clean for a strict control protocol.
Returns a process object whose I/O rides raw pipe fds: use process-pipe-read / process-pipe-write (guarded by await-readable-fd / await-writable-fd on process-stdout-fd / process-stdin-fd), NOT process-stdout / process-stdin. process-pipe-read returns an empty bytevector when no data is ready and an eof-object once the child closes stdout. cwd: sets the child's working directory.
(let ((p (process-spawn-pipe "tmux" "-C" "new-session")))
(process-pipe-write p "list-sessions\n")
...
(process-pipe-close-stdin! p)
(process-wait p))process-signal!procedureSend a signal to a spawned process.
Accepts a signal name symbol ('hup 'int 'quit 'kill 'usr1 'usr2 'term 'cont 'stop 'tstp 'winch) or a raw signal number. For pty-spawned processes the signal goes to the child's whole process group (the child is a session leader), matching terminal semantics; plain-spawned processes are signalled individually. Returns #t if the signal was delivered.
(process-signal! p 'int) ; like Ctrl-C
(process-signal! p 'term)process-waitprocedureWait for a process to complete.
Returns the exit status.
(process-wait p) ; => 0process-kill!procedureKill a running process.
(process-kill! p)process?procedureCheck if a value is a process object.
process-pty?procedureCheck if a process was spawned with a pty (via process-spawn-pty).
process-pty-fdprocedureGet the raw pty master file descriptor of a pty-spawned process.
Feed this to await-readable-fd / await-writable-fd from (sigil async) before calling process-pty-read / process-pty-write so the single-threaded VM never blocks.
process-pty-readprocedureRead available bytes from the pty master.
Returns a bytevector (EMPTY when no data is ready — the fd is non-blocking) or an eof-object once the child exited and the stream is drained. Optional second argument caps the read size (default 4096).
process-pty-writeprocedureWrite a string or bytevector to the pty master (child input).
Returns the number of bytes actually written; may be 0 (kernel buffer full) or partial. Await writability and retry with the remainder.
process-pty-resize!procedureSet the pty window size. The kernel delivers SIGWINCH to the child's foreground process group automatically.
process-pty-close!procedureClose the pty master fd (idempotent). A still-running child sees terminal hangup.
process-stdout-fdprocedureGet the raw stdout (read) pipe fd of a pipe-spawned process.
Feed this to await-readable-fd from (sigil async) before calling process-pipe-read so the single-threaded VM never blocks. The fd is non-blocking.
process-stdin-fdprocedureGet the raw stdin (write) pipe fd of a pipe-spawned process.
Feed this to await-writable-fd from (sigil async) before calling process-pipe-write. The fd is non-blocking.
process-pipe-readprocedureRead available bytes from the child's stdout pipe.
Returns a bytevector (EMPTY when no data is ready — the fd is non-blocking) or an eof-object once the child closes its stdout. Optional second argument caps the read size (default 4096).
process-pipe-writeprocedureWrite a string or bytevector to the child's stdin pipe.
Returns the number of bytes actually written; may be 0 (kernel buffer full) or partial. Await writability and retry with the remainder. Raises an io-error if the child has closed its stdin.
process-pipe-close-stdin!procedureClose the child's stdin pipe (idempotent), delivering EOF to the child.
process-pidprocedureGet the OS process id of a spawned process.
process-alive?procedureCheck if a process is still running.
(process-alive? p) ; => #t or #fprocess-stdinprocedureGet the stdin port of a spawned process.
Returns an output port for writing to the process.
process-stdoutprocedureGet the stdout port of a spawned process.
Returns an input port for reading the process output.
process-stderrprocedureGet the stderr port of a spawned process.
Returns an input port for reading error output.
getenvprocedureGet an environment variable.
Returns the value as a string, or #f if not set.
(getenv "HOME") ; => "/home/user"
(getenv "MISSING") ; => #fsetenv!procedureSet an environment variable.
(setenv! "MY_VAR" "my-value")command-lineprocedureGet the command-line arguments.
Returns a list where the first element is the program name.
(command-line) ; => ("./my-program" "arg1" "arg2")exitprocedureExit the process with a status code.
(exit 0) ; success
(exit 1) ; failureprocess-idprocedureGet the current process ID.
(process-id) ; => 12345command-exists?procedureCheck if a command exists in PATH.
(command-exists? "ls") ; => #t
(command-exists? "foo") ; => #fcall-with-processprocedureCall a procedure with a spawned process.
The process is automatically waited for when proc returns.
(call-with-process "ls" '("-l")
(lambda (p)
(read-line (process-stdout p))))process-output->stringprocedureRun a command and capture its stdout as a string.
Returns #f if the process cannot be started.
(process-output->string "echo" "hello") ; => "hello"
(process-output->string "date") ; => "Thu Jan 15..."read-all-stringprocedureRead all content from a port as a string. Helper for process-output->string.
process-linesprocedureRun a command and return its stdout as a list of lines.
Returns #f if the process cannot be started.
(process-lines "ls") ; => ("file1" "file2" ...)
(process-lines "ls" "-la") ; => ("total 42" "drwxr-x..." ...)read-all-linesprocedureRead all lines from a port. Helper for process-lines.
%process-spawn-optsvariable(No description)
%process-spawn-errorvariable(No description)
%process-wait-resultvariable(No description)
%process-signalvariable(No description)
process-pgidvariable(No description)
%process-spawn-ptyvariable(No description)
%process-spawn-pipevariable(No description)
%process-pipe-write-or-closedvariable(No description)
%set-exit-hook!variable(No description)
%set-exit-trap!variable(No description)
%last-trapped-exit-statusvariable(No description)
emergency-exitvariable(No description)
get-environment-variablesvariable(No description)
executable-pathvariable(No description)