---
name: "__pmProcessAddArg"
section: "3"
platform: "linux"
package: "pcp"
version: "7.2.2-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/__pmProcessAddArg"
---

# \_\_pmProcessAddArg(3)

process execution support

## NAME

**\_\_pmProcessAddArg**, **\_\_pmProcessUnpickArgs**, **\_\_pmProcessExec**, **\_\_pmProcessFree** - process execution support

## C SYNOPSIS

**#include "pmapi.h"**\
 **#include "libpcp.h"**

**int \_\_pmProcessAddArg(\_\_pmExecCtl\_t \*\****handle***, const char \****arg***);**\
 **int \_\_pmProcessUnpickArgs(\_\_pmExecCtl\_t \*\****handle***,** **const char \****command***);**\
 **int \_\_pmProcessExec(\_\_pmExecCtl\_t \*\****handle***,** **int** *toss***,** **int** *wait***);**\
 **void \_\_pmProcessFree(\_\_pmExecCtl\_t \*\****handle***);**

**cc ... -lpcp**

## CAVEAT

This documentation is intended for internal Performance Co-Pilot (PCP) developer use.

These interfaces are not part of the PCP APIs that are guaranteed to remain fixed across releases, and they may not work, or may provide different semantics at some point in the future.

## DESCRIPTION

Within the libraries and applications of the Performance Co-Pilot (PCP) these routines are provide a convenient and safe alternative to [**system**(3)](/system/3.md) for executing commands in a separate process.

Use **\_\_pmProcessAddArg** to register the executable and command arguments in order. *handle* should be set to **NULL** before the first call to **\_\_pmProcessAddArg** for a particular command execution and it will be set to an opaque pointer to data structures that are manipulated in **\_\_pmProcessAddArg**, **\_\_pmProcessExec** and the related [**\_\_pmProcessPipe**(3)](/__pmProcessPipe/3.md) routines.

When called with *handle* set to **NULL** *arg* is treated as the name of the command to be executed and subsequent calls (if any) are for the arguments to that command. The name of the command can be a full pathname, or the name of an executable that can be found on the current **$PATH** as per the rules of **execvp**(2) that is used by **\_\_pmProcessExec**.

**\_\_pmProcessUnpickArgs** is a convenience wrapper to assist conversion of code that assumes the *command* is a shell command that has been prepared for use with [**system**(3)](/system/3.md) or [**popen**(3)](/popen/3.md) in existing code. The arguments in *command* are picked off one-by-one and used to call **\_\_pmProcessAddArg**. The parser is simple, as the routine is designed for simple shell command syntax, where arguments are separated by one or more spaces but embedded spaces within an argument are allowed if the argument is enclosed in single or double quotes.  More advanced shell syntax like escape characters and input-output redirection are not recognized.

Once all the command name and arguments have been registered calling **\_\_pmProcessExec** uses a [**fork**(2)](/fork/2.md) and **execvp**(2) sequence to execute the command.

The argument *toss* may be used to assign some or all of the standard I/O streams for the command to */dev/null* - specifically *toss* is either **PM\_EXEC\_TOSS\_NONE** to keep all I/O streams the same as the parent process, else the bit-wise or of **PM\_EXEC\_TOSS\_STDIN** and/or **PM\_EXEC\_TOSS\_STDOUT** and/or **PM\_EXEC\_TOSS\_STDERR** to reassign **stdin**, **stdout** and **stderr** respectively. **PM\_EXEC\_TOSS\_ALL** is a convenience macro equivalent to **PM\_EXEC\_TOSS\_STDIN \| PM\_EXEC\_TOSS\_STDOUT \| PM\_EXEC\_TOSS\_STDERR**.

The *wait* argument should be **PM\_EXEC\_WAIT** if **\_\_pmProcessExec** should wait for completion of the command and harvest the exit status, else **PM\_EXEC\_NOWAIT** in which case **\_\_pmProcessExec** returns immediately (effectively running the command in the background).

Nested calling of **\_\_pmProcessExec** and/or [**\_\_pmProcessPipe**(3)](/__pmProcessPipe/3.md) is not allowed.  Once **\_\_pmProcessAddArg** is called with *handle* set to **NULL** to start the registration and execution sequence any attempt to start a second registration sequence will be blocked until the first one is completed by calling **\_\_pmProcessExec** or [**\_\_pmProcessPipe**(3)](/__pmProcessPipe/3.md).

## DIAGNOSTICS

If successful **\_\_pmProcessAddArg** returns 0.  Other conditions are rare (e.g. memory allocation failure) and are indicated by a return value that can be decoded using [**pmErrStr**(3)](/pmErrStr/3.md). When an error does occur **\_\_pmProcessAddArg** cleans up any allocations made in the current call and uses *handle* to clean up any allocations made by previous calls so there is no need for the caller to worry about memory leaks, and then (re)sets *handle* to **NULL** before returning.

**\_\_pmProcessUnpickArgs** returns 0 on success.  In the case of an unterminated string, a message is generated and **PM\_ERR\_GENERIC** is returned. Other return values less than 0 indicate a more serious error and the value can be decoded using [**pmErrStr**(3)](/pmErrStr/3.md). When an error does occur the clean up is similar to **\_\_pmProcessAddArg** so there is no need for the caller to worry about memory leaks.

Similarly, on success **\_\_pmProcessExec** will release any storage allocations prior to return, so there is no need for the caller to worry about memory leaks.

The one case where the caller may need to clean up memory allocation is after one or more successful calls to **\_\_pmProcessAddArg** and/or **\_\_pmProcessUnpickArgs**, if the caller wishes to abandon the sequence, then calling **\_\_pmProcessFree** will release any storage allocated by these routines and reset *handle* to **NULL**.

The return status from **\_\_pmProcessExec** is more complicated. If either **PM\_EXEC\_NOWAIT** is specified, or the command completes with an exit status of 0, the return value is 0. Return values less than 0 indicate a more serious error and the value can be decoded using [**pmErrStr**(3)](/pmErrStr/3.md). If the command was executed, but did not exit with status of 0 then the return value is an encoding of the [**waitpid**(2)](/waitpid/2.md) status as follows: 2000 if something unknown went wrong, else if 1000 + signal number of the command was killed or stopped by a signal, else the exit status of the command.

## SEE ALSO

**execvp(2),** [**fork**(2)](/fork/2.md), [**\_\_pmProcessPipe**(3)](/__pmProcessPipe/3.md), [**popen**(3)](/popen/3.md), [**system**(3)](/system/3.md) and **waitpid**(3).
