# Process package

The Process package provides support for handling Unix style processes.
For each external process that you want to handle, you need to create a
`ProcessMonitor` and a corresponding `ProcessNotify` object. Each
ProcessMonitor runs as it own actor and upon receiving data will call its
corresponding `ProcessNotify`'s method.

## Example program

The following program will spawn an external program and write to it's
STDIN. Output received on STDOUT of the child process is forwarded to the
ProcessNotify client and printed.

```pony
use "process"
use "files"

actor Main
  new create(env: Env) =>
    // create a notifier
    let client = ProcessClient(env)
    let notifier: ProcessNotify iso = consume client
    // define the binary to run
    try
      let path = FilePath(env.root as AmbientAuth, "/bin/cat")?
      // define the arguments; first arg is always the binary name
      let args: Array[String] val = ["cat"]
      // define the environment variable for the execution
      let vars: Array[String] val = ["HOME=/"; "PATH=/bin"]
      // create a ProcessMonitor and spawn the child process
      let auth = env.root as AmbientAuth
      let pm: ProcessMonitor = ProcessMonitor(auth, auth, consume notifier,
      path, args, vars)
      // write to STDIN of the child process
      pm.write("one, two, three")
      pm.done_writing() // closing stdin allows cat to terminate
    else
      env.out.print("Could not create FilePath!")
    end

// define a client that implements the ProcessNotify interface
class ProcessClient is ProcessNotify
  let _env: Env

  new iso create(env: Env) =>
    _env = env

  fun ref stdout(process: ProcessMonitor ref, data: Array[U8] iso) =>
    let out = String.from_array(consume data)
    _env.out.print("STDOUT: " + out)

  fun ref stderr(process: ProcessMonitor ref, data: Array[U8] iso) =>
    let err = String.from_array(consume data)
    _env.out.print("STDERR: " + err)

  fun ref failed(process: ProcessMonitor ref, err: ProcessError) =>
    match err
    | ExecveError => _env.out.print("ProcessError: ExecveError")
    | PipeError => _env.out.print("ProcessError: PipeError")
    | ForkError => _env.out.print("ProcessError: ForkError")
    | WaitpidError => _env.out.print("ProcessError: WaitpidError")
    | WriteError => _env.out.print("ProcessError: WriteError")
    | KillError => _env.out.print("ProcessError: KillError")
    | CapError => _env.out.print("ProcessError: CapError")
    | Unsupported => _env.out.print("ProcessError: Unsupported")
    else _env.out.print("Unknown ProcessError!")
    end

  fun ref dispose(process: ProcessMonitor ref, child_exit_code: I32) =>
    let code: I32 = consume child_exit_code
    _env.out.print("Child exit code: " + code.string())
```

## Process portability

The ProcessMonitor supports spawning processes on Linux, FreeBSD and OSX.
Processes are not supported on Windows and attempting to use them will cause
a runtime error.

## Shutting down ProcessMonitor and external process

Document waitpid behaviour (stops world)



## Public Types

* [interface ProcessNotify](process-ProcessNotify.md)
* [primitive ExecveError](process-ExecveError.md)
* [primitive PipeError](process-PipeError.md)
* [primitive ForkError](process-ForkError.md)
* [primitive WaitpidError](process-WaitpidError.md)
* [primitive WriteError](process-WriteError.md)
* [primitive KillError](process-KillError.md)
* [primitive Unsupported](process-Unsupported.md)
* [primitive CapError](process-CapError.md)
* [type ProcessError](process-ProcessError.md)
* [type ProcessMonitorAuth](process-ProcessMonitorAuth.md)
* [actor ProcessMonitor](process-ProcessMonitor.md)
* [primitive StartProcessAuth](process-StartProcessAuth.md)
* [primitive CatPath](process-CatPath.md)
* [primitive CatArgs](process-CatArgs.md)
* [primitive EchoPath](process-EchoPath.md)


## Private Types

* [class _ProcessClient](process-_ProcessClient.md)
* [primitive _STDINFILENO](process-_STDINFILENO.md)
* [primitive _STDOUTFILENO](process-_STDOUTFILENO.md)
* [primitive _STDERRFILENO](process-_STDERRFILENO.md)
* [primitive _EPERM](process-_EPERM.md)
* [primitive _ESRCH](process-_ESRCH.md)
* [primitive _EINTR](process-_EINTR.md)
* [primitive _EAGAIN](process-_EAGAIN.md)
* [primitive _EINVAL](process-_EINVAL.md)
* [interface _Process](process-_Process.md)
* [class _ProcessNone](process-_ProcessNone.md)
* [class _ProcessPosix](process-_ProcessPosix.md)
* [class _ProcessWindows](process-_ProcessWindows.md)
* [primitive _FSETFL](process-_FSETFL.md)
* [primitive _FGETFL](process-_FGETFL.md)
* [primitive _FSETFD](process-_FSETFD.md)
* [primitive _FGETFD](process-_FGETFD.md)
* [primitive _FDCLOEXEC](process-_FDCLOEXEC.md)
* [primitive _ONONBLOCK](process-_ONONBLOCK.md)
* [primitive _ERRORBROKENPIPE](process-_ERRORBROKENPIPE.md)
* [primitive _ERRORNODATA](process-_ERRORNODATA.md)
* [class _Pipe](process-_Pipe.md)
