NAME
system — issue a
command
SYNOPSIS
#include
<stdlib.h>
int system(const char *command);
DESCRIPTION
[CX] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2024 defers to the ISO C standard.
If command is a null pointer, the
system () function shall determine whether the host
environment has a command processor. If command is not a
null pointer, the system () function shall pass the
string pointed to by command to that command processor to
be executed in an implementation-defined manner; this might then cause the
program calling system () to behave in a
non-conforming manner or to terminate.
[CX] The system ()
function shall behave as if a child process were created using
fork(3), and the child process invoked the
sh(1) utility using execl(3) as
follows:
execl(<shell path>, "sh", "-c", "--", command, (char *)0);
where < shell path > is an unspecified pathname for the sh(1) utility. It is implementation-defined whether the handlers registered with pthread_atfork(3) are called as part of the creation of the child process.
The system () function shall ignore the
SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while
waiting for the command to terminate. If this might cause the application to
miss a signal that would have killed it, then the application should examine
the return value from system () and take whatever
action is appropriate to the application if the command terminated due to
receipt of a signal.
The system () function shall not affect
the termination status of any child of the calling processes other than the
process or processes it itself creates.
The system () function shall not return
until the child process has terminated.
If concurrent calls to system () are made
from multiple threads, it is unspecified whether:
- each call saves and restores the dispositions of the SIGINT and SIGQUIT signals independently, or
- in a set of concurrent calls the dispositions in effect after the last call returns are those that were in effect on entry to the first call.
If a thread is cancelled while it is in a call to
system (), it is unspecified whether the child
process is terminated and waited for, or is left running.
RETURN VALUE
If command is a null pointer,
system () shall return non-zero to indicate that a
command processor is available, or zero if none is available.
[CX] The system () function shall
always return non-zero when command is NULL.
[CX] If command is
not a null pointer, system () shall return the
termination status of the command language interpreter in the format
specified by waitpid(3). The termination status shall be
as defined for the sh(1) utility; otherwise, the
termination status is unspecified. If some error prevents the command
language interpreter from executing after the child process is created, the
return value from system () shall be as if the
command language interpreter had terminated using
exit (127) or
_exit
(127). If a child process cannot be created, or if the termination status
for the command language interpreter cannot be obtained,
system () shall return -1 and set
errno to indicate the error.
ERRORS
[CX] The system ()
function may set errno values as described by
fork(3).
In addition, system () may fail if:
- [ECHILD]
- [CX] The status of the child process created by
system() is no longer available.
EXAMPLES
None.
APPLICATION USAGE
If the return value of system () is not
-1, its value can be decoded through the use of the macros described in
<sys/wait.h>. For convenience, these macros
are also provided in <stdlib.h>.
Note that, while system () must ignore
SIGINT and SIGQUIT and block SIGCHLD while waiting for the child to
terminate, the handling of signals in the executed command is as specified
by fork(3) and exec. For example, if
SIGINT is being caught or is set to SIG_DFL when
system () is called, then the child is started with
SIGINT handling set to SIG_DFL.
Ignoring SIGINT and SIGQUIT in the parent process prevents
coordination problems (two processes reading from the same terminal, for
example) when the executed command ignores or catches one of the signals. It
is also usually the correct action when the user has given a command to the
application to be executed synchronously (as in the
‘’! command in many interactive
applications). In either case, the signal should be delivered only to the
child process, not to the application itself. There is one situation where
ignoring the signals might have less than the desired effect. This is when
the application uses system () to perform some task
invisible to the user. If the user typed the interrupt character (
"^C", for example) while
system () is being used in this way, one would
expect the application to be killed, but only the executed command is
killed. Applications that use system () in this way
should carefully check the return status from system
() to see if the executed command was successful, and should take
appropriate action when the command fails.
Blocking SIGCHLD while waiting for the child to terminate prevents
the application from catching the signal and obtaining status from
system ()'s child process before
system () can get the status itself.
The context in which the utility is ultimately executed may differ
from that in which system () was called. For
example, file descriptors that have the FD_CLOEXEC or FD_CLOFORK flag set
are closed, and the process ID and parent process ID are different. Also, if
the executed utility changes its environment variables or its current
working directory, that change is not reflected in the caller's context.
There is no defined way for an application to find the specific path for the shell. However, confstr(3) can provide a value for PATH that is guaranteed to find the sh(1) utility.
Although system () is required to be
thread-safe, it is recommended that concurrent calls from multiple threads
are avoided, since system () is not required to
coordinate the saving and restoring of the dispositions of the SIGINT and
SIGQUIT signals across a set of overlapping calls, and therefore the signals
might end up being set to ignored after the last call returns. Applications
should also avoid cancelling a thread while it is in a call to
system () as the child process may be left running
in that event. In addition, if another thread alters the disposition of the
SIGCHLD signal, a call to signal(3) may produce unexpected
results.
RATIONALE
The system () function should not be used
by programs that have set user (or group) ID privileges. The
fork(3) and exec family of functions
(except execlp(3) and execvp(3)), should
be used instead. This prevents any unforeseen manipulation of the
environment of the user that could cause execution of commands not
anticipated by the calling program.
There are three levels of specification for the
system () function. The ISO C standard gives the
most basic. It requires that the function exists, and defines a way for an
application to query whether a command language interpreter exists. It says
nothing about the command language or the environment in which the command
is interpreted.
POSIX.1-2024 places additional restrictions on
system (). It requires that if there is a command
language interpreter, the environment must be as specified by
fork(3) and exec. This ensures, for
example, that close-on- exec works, that process-owned
file locks are not inherited, and that the process ID is different. It also
specifies the return value from system () when the
command line can be run, thus giving the application some information about
the command's completion status.
Finally, POSIX.1-2024 requires the command to be interpreted as in the shell command language defined in the Shell and Utilities volume of POSIX.1-2024.
Note that, system (NULL) is required to
return non-zero, indicating that there is a command language interpreter. At
first glance, this would seem to conflict with the ISO C standard which
allows system (NULL) to return zero. There is no
conflict, however. A system must have a command language interpreter, and is
non-conforming if none is present. It is therefore permissible for the
system () function on such a system to implement the
behavior specified by the ISO C standard as long as it is understood that
the implementation does not conform to POSIX.1-2024 if
system (NULL) returns zero.
It was explicitly decided that when command is
NULL, system () should not be required to check to
make sure that the command language interpreter actually exists with the
correct mode, that there are enough processes to execute it, and so on. The
call system (NULL) could, theoretically, check for
such problems as too many existing child processes, and return zero.
However, it would be inappropriate to return zero due to such a (presumably)
transient condition. If some condition exists that is not under the control
of this application and that would cause any system
() call to fail, that system has been rendered non-conforming.
Early drafts required, or allowed, system
() to return with errno set to [EINTR] if it was
interrupted with a signal. This error return was removed, and a requirement
that system () not return until the child has
terminated was added. This means that if a waitpid(3) call
in system () exits with errno set
to [EINTR], system () must reissue the
waitpid(3). This change was made for two reasons:
- There is no way for an application to clean up if
system() returns [EINTR], short of calling wait(3), and that could have the undesirable effect of returning the status of children other than the one started bysystem(). - While it might require a change in some historical implementations, those implementations already have to be changed because they use wait(3) instead of waitpid(3).
Note that if the application is catching SIGCHLD signals, it will
receive such a signal before a successful system ()
call returns.
To conform to POSIX.1-2024, system () must
use waitpid(3), or some similar function, instead of
wait(3).
The following code sample illustrates how
system () might be implemented on an implementation
conforming to POSIX.1-2024.
int system(const char *cmd)
{
int stat;
pid_t pid;
struct sigaction sa, savintr, savequit;
sigset_t saveblock;
if (cmd == NULL)
return(1);
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigemptyset(&savintr.sa_mask);
sigemptyset(&savequit.sa_mask);
sigaction(SIGINT, &sa, &savintr);
sigaction(SIGQUIT, &sa, &savequit);
sigaddset(&sa.sa_mask, SIGCHLD);
pthread_sigmask(SIG_BLOCK, &sa.sa_mask, &saveblock);
if ((pid = fork()) == 0) {
sigaction(SIGINT, &savintr, (struct sigaction *)0);
sigaction(SIGQUIT, &savequit, (struct sigaction *)0);
sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *)0);
execl("/bin/sh", "sh", "-c", "--", cmd, (char *)0);
_exit(127);
}
if (pid == -1) {
stat = -1; /* errno comes from fork() */
} else {
while (waitpid(pid, &stat, 0) == -1) {
if (errno != EINTR){
stat = -1;
break;
}
}
}
sigaction(SIGINT, &savintr, (struct sigaction *)0);
sigaction(SIGQUIT, &savequit, (struct sigaction *)0);
sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *)0);
return(stat);
}
Note that, while a particular implementation of
system () (such as the one above) can assume a
particular path for the shell, such a path is not necessarily valid on
another system. The above example is not portable, and is not intended to
be.
Earlier versions of this standard did not require
system () to be thread-safe because it alters the
process-wide disposition of the SIGINT and SIGQUIT signals. It is now
required to be thread-safe to align with the ISO C standard, which (since
the introduction of threads in 2011) requires that it avoids data races.
However, the function is not required to coordinate the saving and restoring
of the dispositions of the SIGINT and SIGQUIT signals across a set of
overlapping calls, and the above example does not do so. The example also
does not terminate and wait for the child process if the calling thread is
cancelled, and so would leak a process ID in that event.
One reviewer suggested that an implementation of
system () might want to use an environment variable
such as SHELL to determine which command interpreter to
use. The supposed implementation would use the default command interpreter
if the one specified by the environment variable was not available. This
would allow a user, when using an application that prompts for command lines
to be processed using system (), to specify a
different command interpreter. Such an implementation is discouraged. If the
alternate command interpreter did not follow the command line syntax
specified in the Shell and Utilities volume of POSIX.1-2024, then changing
SHELL would render system ()
non-conforming. This would affect applications that expected the specified
behavior from system (), and since the Shell and
Utilities volume of POSIX.1-2024 does not mention that
SHELL affects system (), the
application would not know that it needed to unset SHELL
.
Earlier versions of this standard required the
command string to be passed as the next argument after
"-c" (omitting
"--"). This meant that portable
applications needed to take care not to pass a command string beginning with
<hyphen-minus> ( ‘-’) or
<plus-sign> ( ‘+’), as it would
then be interpreted as containing options. Now that implementations are
required to pass the "--", applications no
longer need to do this.
FUTURE DIRECTIONS
None.
SEE ALSO
V2_chap02(3), exec(3), pipe(3), pthread_atfork(3), wait(3)
XBD <limits.h>, <signal.h>, <stdlib.h>, <sys/wait.h>
XCU sh(1)
CHANGE HISTORY
First released in Issue 1. Derived from Issue 1 of the SVID.
Issue 6
Extensions beyond the ISO C standard are marked.
Issue 7
Austin Group Interpretation 1003.1-2001 #055 is applied, clarifying the thread-safety of this function and treatment of pthread_atfork(3) handlers.
Austin Group Interpretation 1003.1-2001 #156 is applied.
SD5-XSH-ERN-30 is applied.
POSIX.1-2008, Technical Corrigendum 2, XSH/TC2-2008/0365 [627] is applied.
Issue 8
Austin Group Defect 768 is applied, adding OFD-owned file locks.
Austin Group Defect 1302 is applied, aligning this function with the ISO/IEC 9899:2018 standard.
Austin Group Defect 1317 is applied, making it implementation-defined whether the handlers registered with pthread_atfork(3) are called.
Austin Group Defect 1318 is applied, adding FD_CLOFORK.
Austin Group Defect 1440 is applied, adding a
"--" argument to the specified
execl(3) call.