Plasma GitLab Archive
Projects Blog Knowledge

{2 The [shell] library: Pipelines and redirections}

The [shell] library provides some of the functionality of a Unix shell; in
particular the library supports starting simple commands, executing
pipelined commands, and arranging redirections.

{3 Module [Shell]: The comfortable layer}

This module is designed for the average user who does not know very
much about the Unix process model, and just wants to start external commands.
A simple command can be executed by a statement like

{[ call [ cmd "ls" [ "/dir1"; "/dir2" ]] ]}

This statement searches "ls" in the current search PATH, launches the
new process, and passes the arguments "/dir1" and /dir2" to the process.
Nothing special is done with the file descriptors; the new process shares
stdin, stdout and stderr with the current process (all other descriptors
are automatically closed).

A pipeline can be constructed by [call] as well. For example:

{[ call [ cmd "find" [ "/dir" ]; cmd "grep" [ "something" ] ] ]}

The output of "find" is redirected to the input of "grep".

You can redirect stdin, stdout, stderr (and every other descriptor)
by assigning them to other descriptors, or by opening and reading from or
writing to them. In the latter case, multiple descriptors can be served
parallely. For example:

{[
let s = "d\na\nc\nb\n" in
let b = Buffer.create 20 in
call ~stdin:(from_string s) ~stdout:(to_buffer b) [ cmd "sort" [] ]
]}

Here, "sort" reads the contents of s and writes the result to b.

Unlike the Unix shell, this module reports errors from all components
of a pipeline. For example:

{[
call [ cmd "cat" [ "/notfound" ]; cmd "ls" [ "/notfound.too" ] ]
]}

This will raise an exception

{[
Subprocess_error [ "/bin/cat", Unix.WEXITED 1; "/bin/ls", Unix.WEXITED 1 ]
]}

There is another subtle difference to many Unix shells (and normally
also the [system] function in libc). This module reports errors occuring
between [fork] and [exec]; for instance if the file "fail" refers to
a non-existing interpreter

{[
#! /not/found
]}

but is executable, this special error can only be detected by the "exec"
call. Unix shells print an error message to stderr, and return an exit code
of 127 (which is reserved for this case):

{[
Sys.command "fail";;
sh: ./fail: No such file or directory
~ : int = 127
]}

However, the true reason isn't reported. In contrast to this, the Shell
module is able to pass the real error condition back to the calling
program:

{[
call [ command "fail" ];;
Uncaught exception: Unix.Unix_error(20, "execve", "./fail").
]}


{3 Module [Shell_sys]: The fundamental layer}

The module [Shell] is a simple application of the functions defined in
[Shell_sys], the more fundamental module. [Shell_sys] allows a more
fine-grained control of the execution of external commands; however, it is more
difficult to use.

[Shell_sys] allows it to run processes both synchronously and asynchronously,
to form pipelines with arbitrary topology, to create user-defined handlers
serving file descriptors, and to control signal handling.


{3 Module [Unix_exts]: The missing system calls}

This module contains some system calls missing in the Unix library distributed
with O'Caml.

This web site is published by Informatikbüro Gerd Stolpmann
Powered by Caml