pipe_new() creates a unidirectional pipe returning [read_fd, write_fd]. Combined with fork, dup2, and execvp, this lets you capture the output of an external command — the same mechanism Unix shells use for | (pipe).
// Pipes — connecting two processes via pipe // Pipes — conectar dos procesos via pipe fn main() -> int { // pipe_new() returns [read_fd, write_fd] let fds: Array = pipe_new() let read_fd: int = fds[0] let write_fd: int = fds[1] let pid: int = fork() if pid == 0 { // Child: redirect stdout to write end of pipe close_fd(read_fd) dup2(write_fd, 1) close_fd(write_fd) // exec ls — output goes into pipe let args: Array = ["ls", "/tmp"] execvp("ls", args) return 1 } // Parent: read from pipe close_fd(write_fd) let output: String = tcp_read(read_fd, 4096) close_fd(read_fd) waitpid(pid, 0) print("ls output (first 200 chars):") if output.length() > 200 { print(output.substring(0, 200)) } else { print(output) } return 0 }
ls output (first 200 chars): ...
How it works
pipe_new() creates a unidirectional byte stream and returns an array of two file descriptors: [read_fd, write_fd]. Data written to write_fd can be read from read_fd.
After fork(), the child closes the read end, uses dup2(write_fd, 1) to redirect its stdout to the pipe's write end, then calls execvp to run ls. The child's output flows through the pipe instead of the terminal.
The parent closes the write end (so reads will see EOF when the child exits), reads the pipe contents with tcp_read, and waits for the child with waitpid. This is exactly how Unix shells implement the | operator.