#unix #pipe #fork #exec #posix

bin+lib unix_exec_piper

unix_exec_piper helps you to exec multiple commands where STDOUT of one process is connected to STDIN of the next process. This is what a shell (like bash) does internally.

5 releases

0.1.4 Sep 20, 2020
0.1.3 Sep 20, 2020
0.1.2 Sep 20, 2020
0.1.1 Sep 20, 2020
0.1.0 Sep 20, 2020

#292 in Unix APIs

MIT license

536 lines

unix_exec_piper: A library written in Rust that execs multiple commands and connects them with pipes.


My library basically does the functionality that happens when you type cat file.txt | grep -i | wc -l into a shell like bash. unix_exec_piper does no parsing, but only the actual execution and connection between the (child) processes via unix pipes.

Important main parts of the library are pipe.rs and lib.rs :: execute_piped_cmd_chain().

The main purpose of this library is educational and to show people who are interested in this how it's done.

You might build a shell around this library (if it gets more functionality in the future).

Basics you need to know

Please make yourself familiar with the UNIX/Posix concepts:

  • pipe()
  • fork()
  • file descriptors and "Everything is a file"
  • exec()

Supported features

  • Creating pipes between processes where STDOUT of one process gets connected to STDIN of the next process.
    ($ cat file.txt | grep -i | wc -l)
  • I/O redirection into files
    $ cat < file.txt | grep -i | wc -l > out.txt

not (yet) supported features


See src/bin/example.rs.

Basic idea

The parent process loops n times (for n commands) and creates n-1 Pipes. Therefore n child processes are created through fork(). Each child process has two variables in its address space:

let mut pipe_to_current: Option<Pipe>;
let mut pipe_to_next: Option<Pipe>;

Pipes communicates across process boundaries in the following way:

child process 0    child process 1    child process n
_______________    _______________    _________
| cat foo.txt |    | grep -i abc |    | wc -l |
---------------    ---------------    ---------
            ^        ^         ^        ^
      WRITE |--------|  R / W  |--------| READ
      END               E   E             END
                   (current child)
        -Pipe to Current-   -Pipe to Next-

Each process uses pipe_to_current (if present) as "read end" (as it's stdin) and pipe_to_current (if present) as "write end" (duplicate it's STDOUT file descriptor into the write end of the pipe).