# Process Utilities

`processutils.h`/`processutils.cpp` locate and run external programs - Python postprocessing scripts, the OpenVAF compiler - as child processes, built on Boost.Process (v2) and Boost.Asio.

## `findProgram()`

Resolves a program name to a full path, trying in order: the path directly, if it's already absolute; the directory containing the simulator's own executable (`executableFile()`, via `boost::dll::program_location()`), for a bundled copy of a tool like `openvaf-r` shipped alongside the simulator binary without needing to be on `PATH`; and finally the system `PATH` (see [Platform Abstraction](libplatform.md)'s `findFileInSystemPath()`). Successful lookups are cached in a static map keyed by the requested name, so repeated calls for the same program - e.g. once per OSDI-compiled device, all needing the same `openvaf-r` - skip the filesystem search after the first.

## `runProcess()`

Spawns `prog` with `args` in one of two modes: `collect=true` captures stdout/stderr into strings, using Boost.Asio readable pipes and `async_read` with `transfer_all()`, then blocks on `ios.run()` followed by `c.wait()`; `collect=false` just waits for the child to exit without capturing output, for callers that only care about the exit code or want the child to inherit the simulator's own streams.

The child's environment is copied from the current process's (`boost::process::v2::environment::current()`), substituting a single space for an empty value to work around a library-level "empty env string" bug rather than passing it through unmodified. It is then optionally extended: `pythonPath`, if given, is appended to `PYTHONPATH` (so an embedded Python postprocessing script can `import` simulator-supplied helper modules); `parentFilePath`, if given, is exposed to the child as `SIM_PARENT_FILE_DIR` (so a script can resolve its own relative paths against the netlist file that invoked it). A nonzero exit code is reported through the [`Status`](status.md) parameter (`Status::Process`) rather than being treated as a C++-level error - running a process to completion and it returning failure is an expected outcome to handle, not an exceptional one.

## `executableFile()`

The simulator's own executable path, via `boost::dll::program_location()`, cached in a function-local static - what `findProgram()` uses to look for bundled tools next to itself.
