Chicken » Module (chicken process)

## Module (chicken process)

This module offers procedures for interacting with subprocesses.

- New in CHICKEN 5.4.0: Errors caused by underlying C calls that change errno will produce a condition object with an `errno` property, which can be accessed with `(get-condition-property <the-condition-object> 'exn 'errno)`.

### Processes

#### process-execute

process-execute PATHNAME #!optional ARGUMENT-LIST ENVIRONMENT-ALISTprocedure

  Replaces the running process with a new process image from the program stored at PATHNAME, using the C library function `execvp(3)`. If the optional argument ARGUMENT-LIST is given, then it should contain a list of strings which are passed as arguments to the subprocess. If the optional argument ENVIRONMENT-ALIST is supplied, then the library function `execve(2)` is used, and the environment passed in ENVIRONMENT-ALIST (which should be of the form `(("<NAME>" . "<VALUE>") ...)`) is given to the invoked process. Note that `execvp(3)` respects the current setting of the `PATH` environment variable while `execve(3)` does not.

  This procedure never returns; it either replaces the process with a new one or it raises an exception in case something went wrong executing the program.

  On Windows, these procedures all have an additional optional parameter `EXACT-FLAG`, which defaults to `#f`. When `#f` is passed, any argument string with embedded whitespace will be wrapped in quotes. When `#t` no such wrapping occurs.

#### process-fork

process-fork #!optional THUNK KILLOTHERS? procedure

  Creates a new child process with the UNIX system call `fork()`. Returns either the PID of the child process or 0. If THUNK is given, then the child process calls it as a procedure with no arguments and terminates. If THUNK is given and the optional argument KILLOTHERS? is true, then kill all other existing threads in the child process, leaving only the current thread to run THUNK and terminate.

  NOTE: On native Windows builds (all except cygwin), this procedure is unimplemented and will raise an error.

#### process-run

process-run COMMANDLINEprocedure
process-run COMMAND ARGUMENT-LISTprocedure

  Creates a new child process. The PID of the new process is returned.

  - The single parameter version passes the COMMANDLINE to the system shell, so usual argument expansion can take place. Be careful to properly quote arguments with the `qs` procedure to avoid shell injection vulnerabilities.
  - The multiple parameter version directly invokes the COMMAND with the ARGUMENT-LIST, and is vastly preferred over the single-parameter version because of its better safety.

#### process-signal

process-signal PID #!optional SIGNALprocedure

  Sends SIGNAL to the process with the id PID using the UNIX system call `kill()`. SIGNAL defaults to the value of the variable `signal/term`.

  NOTE: On native Windows builds (all except cygwin), this procedure is unimplemented and will raise an error.

#### process-spawn

process-spawn MODE COMMAND #!optional ARGUMENT-LIST ENVIRONMENT-LIST EXACT-FLAGprocedure

  Creates and runs a new process with the given COMMAND filename and the optional ARGUMENT-LIST and ENVIRONMENT-LIST. MODE specifies how exactly the process should be executed and must be one or more of the `spawn/...` flags listed below.

  The EXACT-FLAG, default `#f`, controls quote-wrapping of argument strings. When `#t` quote-wrapping is not performed.

  Returns:

  - the exit status when synchronous
  - the PID when asynchronous
  - -1 when failure

  NOTE: On all Unix-like builds (all except native MingW-based Windows platforms), this procedure is unimplemented and will raise an error.

spawn/overlayconstant
spawn/waitconstant
spawn/nowaitconstant
spawn/nowaitoconstant
spawn/detachconstant

  These variables contains special flags that specify the exact semantics of `process-spawn`:

  - `spawn/overlay` replaces the current process with the new one.
  - `spawn/wait` suspends execution of the current process until the spawned process returns.
  - `spawn/nowait` does the opposite (`spawn/nowaito` is identical, according to the Microsoft documentation) and runs the process asynchronously.
  - `spawn/detach` runs the new process in the background, without being attached to a console.

#### process-wait

process-wait #!optional PID NOHANGprocedure

  Suspends the current process until the child process with the id PID has terminated using the UNIX system call `waitpid()`. If PID is not given, then this procedure waits for any child process. If NOHANG is given and not `#f` then the current process is not suspended. This procedure returns three values:

  - PID or 0, if NOHANG is true and the child process has not terminated yet.
  - `#t` if the process exited normally or `#f` otherwise.
  - either the exit status, if the process terminated normally or the signal number that terminated/stopped the process.

  Note that suspending the current process implies that all threads are suspended as well.

  On Windows, `process-wait` always returns `#t` for a terminated process and only the exit status is available. (Windows does not provide signals as an interprocess communication method.)

#### process-sleep

process-sleep SECONDSprocedure

  Puts the process to sleep for SECONDS. Returns either 0 if the time has completely elapsed, or the number of remaining seconds, if a signal occurred.

#### process

process COMMANDLINEprocedure
process COMMAND ARGUMENT-LIST #!optional ENVIRONMENT-ALISTprocedure

  Creates a subprocess and returns three values: an input port from which data written by the sub-process can be read, an output port from which any data written to will be received as input in the sub-process and the process-id of the started sub-process. Blocking reads and writes to or from the ports returned by `process` only block the current thread, not other threads executing concurrently.

  Standard error for the subprocess is linked up to the current process's standard error (see `process*` if you want to reify its standard error into a separate port).

  - The single parameter version passes the string COMMANDLINE to the host-system's shell that is invoked as a subprocess.
  - The multiple parameter version directly invokes the COMMAND as a subprocess. The ARGUMENT-LIST is directly passed, as is ENVIRONMENT-ALIST. These arguments have the same form as the ones of `process-execute`.

  Not using the shell may be preferrable for security reasons.

  Once both the input- and output ports are closed, an implicit `waitpid(3)` is done to wait for the subprocess to finish or to reap a subprocess that has terminated. If the subprocess has not finished, waiting for it will necessarily block all executing threads.

#### process*

process* COMMANDLINEprocedure
process* COMMAND ARGUMENT-LIST #!optional ENVIRONMENT-ALISTprocedure

  Like `process` but returns 4 values: an input port from which data written by the sub-process can be read, an output port from which any data written to will be received as input in the sub-process, the process-id of the started sub-process, and an input port from which data written by the sub-process to `stderr` can be read.

### Shell commands

The commands below are all string-based. This means you have to be very careful to properly quote any arguments to subprocesses, to avoid shell injection bugs which can lead to arbitrary code execution.

You can quote arguments with the `qs` procedure, but it is strongly recommended you use `fork` with `process-execute` or the multi-argument versions of the `process`, `process*` or `process-run` procedures.

#### qs

qs STRING #!optional PLATFORMprocedure

  Escapes STRING suitably for passing to a shell command on PLATFORM. PLATFORM defaults to the value of `(build-platform)` and indicates in which style the argument should be quoted. On Windows systems, the string is simply enclosed in double-quote (`"`) characters, on UNIXish systems, characters that would have a special meaning to the shell are escaped using backslash (`\`).

#### system

system STRINGprocedure

  Execute shell command. The functionality offered by this procedure depends on the capabilities of the host shell. If the forking of a subprocess failed, an exception is raised. Otherwise the return status of the subprocess is returned unaltered.

  On a UNIX system, that value is the raw return value of waitpid(2), which contains signal, core dump and exit status. It is 0 on success. To pull out the signal number or exit status portably requires POSIX calls, but in a pinch you can use something like this:

      ;; Returns two values: #t if the process exited normally or #f otherwise;
      ;; and either the exit status, or the signal number if terminated via signal.
      (define (process-status rc)
        (define (wait-signaled? x) (not (= 0 (bitwise-and x 127))))
        (define (wait-signal x) (bitwise-and x 127))
        (define (wait-exit-status x) (arithmetic-shift x -8))
        (if (wait-signaled? rc)
            (values #f (wait-signal rc))
            (values #t (wait-exit-status rc))))

      #;> (process-status (system "exit 42"))
      #t
      42

#### system*

system* STRINGprocedure

  Similar to `(system STRING)`, but signals an error should the invoked program return a nonzero exit status.

### Pipes

#### call-with-input-pipe

#### call-with-output-pipe

call-with-input-pipe CMDLINE PROC #!optional MODEprocedure
call-with-output-pipe CMDLINE PROC #!optional MODEprocedure

  Call PROC with a single argument: a input- or output port for a pipe connected to the subprocess named in CMDLINE. If PROC returns normally, the pipe is closed and any result values are returned.

#### close-input-pipe

#### close-output-pipe

close-input-pipe PORTprocedure
close-output-pipe PORTprocedure

  Closes the pipe given in PORT and waits until the connected subprocess finishes. The exit-status code of the invoked process is returned.

#### create-pipe

create-pipeprocedure

  The fundamental pipe-creation operator. Calls the C function `pipe()` and returns 2 values: the file-descriptors of the input- and output-ends of the pipe.

  On Windows, there is an optional parameter `MODE`, which defaults to `open/binary | open/noinherit`. This can be `open/binary` or `open/text`, optionally or'ed with `open/noinherit`.

#### open-input-pipe

open-input-pipe CMDLINE #!optional MODEprocedure

  Spawns a subprocess with the command-line string CMDLINE and returns a port, from which the output of the process can be read. If MODE is specified, it should be the keyword `#:text` (the default) or `#:binary`.

#### open-output-pipe

open-output-pipe CMDLINE #!optional MODEprocedure

  Spawns a subprocess with the command-line string CMDLINE and returns a port. Anything written to that port is treated as the input for the process. If MODE is specified, it should be the keyword `#:text` (the default) or `#:binary`.

#### pipe/buf

pipe/bufconstant

  This variable contains the maximal number of bytes that can be written atomically into a pipe or FIFO.

#### with-input-from-pipe

#### with-output-to-pipe

with-input-from-pipe CMDLINE THUNK #!optional MODEprocedure
with-output-to-pipe CMDLINE THUNK #!optional MODEprocedure

  Temporarily set the value of `current-input-port/current-output-port` to a port for a pipe connected to the subprocess named in CMDLINE and call the procedure THUNK with no arguments. After THUNK returns normally the pipe is closed and the standard input-/output port is restored to its previous value and any result values are returned.

      (with-output-to-pipe
        "gs -dNOPAUSE -sDEVICE=jpeg -dBATCH -sOutputFile=signballs.jpg -g600x600 -q -"
        (lambda ()
          (print #<<EOF
       %!IOPSC-1993 %%Creator: HAYAKAWA Takashi<xxxxxxxx@xx.xxxxxx.xx.xx>
       /C/neg/d/mul/R/rlineto/E/exp/H{{cvx def}repeat}def/T/dup/g/gt/r/roll/J/ifelse 8
       H/A/copy(z&v4QX&93r9AxYQOZomQalxS2w!!O&vMYa43d6r93rMYvx2dca!D&cjSnjSnjjS3o!v&6A
       X&55SAxM1CD7AjYxTTd62rmxCnTdSST0g&12wECST!&!J0g&D1!&xM0!J0g!l&544dC2Ac96ra!m&3A
       F&&vGoGSnCT0g&wDmlvGoS8wpn6wpS2wTCpS1Sd7ov7Uk7o4Qkdw!&Mvlx1S7oZES3w!J!J!Q&7185d
       Z&lx1CS9d9nE4!k&X&MY7!&1!J!x&jdnjdS3odS!N&mmx1C2wEc!G&150Nx4!n&2o!j&43r!U&0777d
       ]&2AY2A776ddT4oS3oSnMVC00VV0RRR45E42063rNz&v7UX&UOzF!F!J![&44ETCnVn!a&1CDN!Y&0M
       V1c&j2AYdjmMdjjd!o&1r!M){( )T 0 4 3 r put T(/)g{T(9)g{cvn}{cvi}J}{($)g[]J}J
       cvx}forall/moveto/p/floor/w/div/S/add 29 H[{[{]setgray fill}for Y}for showpage
       EOF
       ) ) )

### Windows specific notes

Use of UTF8 encoded strings for pathnames is not supported. Windows uses a 16-bit UNICODE encoding with special system calls for wide-character support. Only single-byte string encoding can be used.

Previous: Module (chicken pretty-print)

Next: Module (chicken process signal)