SYSTEM(3) Linux Programmer's Manual SYSTEM(3)
NAME
system - execute a shell command
SYNOPSIS
#include <stdlib.h>
int system(const char *command);
DESCRIPTION
The system() library function uses fork(2) to create a child process
that executes the shell command specified in command using execl(3) as
follows:
execl("/bin/sh", "sh", "-c", command, (char *) 0);
system() returns after the command has been completed.
During execution of the command, SIGCHLD will be blocked, and SIGINT
and SIGQUIT will be ignored, in the process that calls system() (these
signals will be handled according to their defaults inside the child
process that executes command).
If command is NULL, then system() returns a status indicating whether a
shell is available on the system.
RETURN VALUE
The return value of system() is one of the following:
* If command is NULL, then a nonzero value if a shell is available, or
0 if no shell is available.
* If a child process could not be created, or its status could not be
retrieved, the return value is -1.
* If a shell could not be executed in the child process, then the
return value is as though the child shell terminated by calling
_exit(2) with the status 127.
* If all system calls succeed, then the return value is the termina-
tion status of the child shell used to execute command. (The termi-
nation status of a shell is the termination status of the last com-
mand it executes.)
In the last two cases, the return value is a "wait status" that can be
examined using the macros described in waitpid(2). (i.e., WIFEXITED(),
WEXITSTATUS(), and so on).
system() does not affect the wait status of any other children.
ATTRIBUTES
For an explanation of the terms used in this section, see
attributes(7).
+----------+---------------+---------+
|Interface | Attribute | Value |
+----------+---------------+---------+
|system() | Thread safety | MT-Safe |
+----------+---------------+---------+
CONFORMING TO
POSIX.1-2001, POSIX.1-2008, C89, C99.
NOTES
system() provides simplicity and convenience: it handles all of the
details of calling fork(2), execl(3), and waitpid(2), as well as the
necessary manipulations of signals; in addition, the shell performs the
usual substitutions and I/O redirections for command. The main cost of
system() is inefficiency: additional system calls are required to cre-
ate the process that runs the shell and to execute the shell.
If the _XOPEN_SOURCE feature test macro is defined (before including
any header files), then the macros described in waitpid(2) (WEXITSTA-
TUS(), etc.) are made available when including <stdlib.h>.
As mentioned, system() ignores SIGINT and SIGQUIT. This may make pro-
grams that call it from a loop uninterruptible, unless they take care
themselves to check the exit status of the child. For example:
while (something) {
int ret = system("foo");
if (WIFSIGNALED(ret) &&
(WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
break;
}
According to POSIX.1, it is unspecified whether handlers registered
using pthread_atfork(3) are called during the execution of system().
In the glibc implementation, such handlers are not called.
In versions of glibc before 2.1.3, the check for the availability of
/bin/sh was not actually performed if command was NULL; instead it was
always assumed to be available, and system() always returned 1 in this
case. Since glibc 2.1.3, this check is performed because, even though
POSIX.1-2001 requires a conforming implementation to provide a shell,
that shell may not be available or executable if the calling program
has previously called chroot(2) (which is not specified by
POSIX.1-2001).
It is possible for the shell command to terminate with a status of 127,
which yields a system() return value that is indistinguishable from the
case where a shell could not be executed in the child process.
Caveats
Do not use system() from a privileged program (a set-user-ID or set-
group-ID program, or a program with capabilities) because strange val-
ues for some environment variables might be used to subvert system
integrity. For example, PATH could be manipulated so that an arbitrary
program is executed with privilege. Use the exec(3) family of func-
tions instead, but not execlp(3) or execvp(3) (which also use the PATH
environment variable to search for an executable).
system() will not, in fact, work properly from programs with set-user-
ID or set-group-ID privileges on systems on which /bin/sh is bash ver-
sion 2: as a security measure, bash 2 drops privileges on startup.
(Debian uses a different shell, dash(1), which does not do this when
invoked as sh.)
Any user input that is employed as part of command should be carefully
sanitized, to ensure that unexpected shell commands or command options
are not executed. Such risks are especially grave when using system()
from a privileged program.
SEE ALSO
sh(1), execve(2), fork(2), sigaction(2), sigprocmask(2), wait(2),
exec(3), signal(7)
COLOPHON
This page is part of release 4.15 of the Linux man-pages project. A
description of the project, information about reporting bugs, and the
latest version of this page, can be found at
https://www.kernel.org/doc/man-pages/.
2017-09-15 SYSTEM(3)
SYSTEM(3P) POSIX Programmer's Manual SYSTEM(3P)
PROLOG
This manual page is part of the POSIX Programmer's Manual. The Linux
implementation of this interface may differ (consult the corresponding
Linux manual page for details of Linux behavior), or the interface may
not be implemented on Linux.
NAME
system -- issue a command
SYNOPSIS
#include <stdlib.h>
int system(const char *command);
DESCRIPTION
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-2008
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 implementa-
tion-defined manner; this might then cause the program calling system()
to behave in a non-conforming manner or to terminate.
The system() function shall behave as if a child process were created
using fork(), and the child process invoked the sh utility using
execl() as follows:
execl(<shell path>, "sh", "-c", command, (char *)0);
where <shell path> is an unspecified pathname for the sh utility. It is
unspecified whether the handlers registered with pthread_atfork() 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 termi-
nate. 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 applica-
tion 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 ter-
minated.
The system() function need not be thread-safe.
RETURN VALUE
If command is a null pointer, system() shall return non-zero to indi-
cate that a command processor is available, or zero if none is avail-
able. The system() function shall always return non-zero when command
is NULL.
If command is not a null pointer, system() shall return the termination
status of the command language interpreter in the format specified by
waitpid(). The termination status shall be as defined for the sh util-
ity; 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 termina-
tion status for the command language interpreter cannot be obtained,
system() shall return -1 and set errno to indicate the error.
ERRORS
The system() function may set errno values as described by fork().
In addition, system() may fail if:
ECHILD The status of the child process created by system() is no longer
available.
The following sections are informative.
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 conve-
nience, 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 sig-
nals in the executed command is as specified by fork() 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 per-
form 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 sys-
tem()'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 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() can provide a value for PATH that is
guaranteed to find the sh utility.
Using the system() function in more than one thread in a process or
when the SIGCHLD signal is being manipulated by more than one thread in
a process may produce unexpected results.
RATIONALE
The system() function should not be used by programs that have set user
(or group) ID privileges. The fork() and exec family of functions
(except execlp() and execvp()), 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-2008 places additional restrictions on system(). It requires
that if there is a command language interpreter, the environment must
be as specified by fork() and exec. This ensures, for example, that
close-on-exec works, that file locks are not inherited, and that the
process ID is different. It also specifies the return value from sys-
tem() when the command line can be run, thus giving the application
some information about the command's completion status.
Finally, POSIX.1-2008 requires the command to be interpreted as in the
shell command language defined in the Shell and Utilities volume of
POSIX.1-2008.
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 com-
mand 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-2008
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 inter-
preter actually exists with the correct mode, that there are enough
processes to execute it, and so on. The call system(NULL) could, theo-
retically, check for such problems as too many existing child pro-
cesses, 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-con-
forming.
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() call in system()
exits with errno set to [EINTR], system() must reissue the waitpid().
This change was made for two reasons:
1. There is no way for an application to clean up if system() returns
[EINTR], short of calling wait(), and that could have the undesir-
able effect of returning the status of children other than the one
started by system().
2. While it might require a change in some historical implementations,
those implementations already have to be changed because they use
wait() instead of waitpid().
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-2008, system() must use waitpid(), or some simi-
lar function, instead of wait().
The following code sample illustrates how system() might be implemented
on an implementation conforming to POSIX.1-2008.
#include <signal.h>
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);
sigprocmask(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 por-
table, and is not intended to be.
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 spec-
ify a different command interpreter. Such an implementation is discour-
aged. If the alternate command interpreter did not follow the command
line syntax specified in the Shell and Utilities volume of
POSIX.1-2008, 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-2008
does not mention that SHELL affects system(), the application would not
know that it needed to unset SHELL.
FUTURE DIRECTIONS
None.
SEE ALSO
exec, pipe(), pthread_atfork(), wait()
The Base Definitions volume of POSIX.1-2008, <limits.h>, <signal.h>,
<stdlib.h>, <sys_wait.h>
The Shell and Utilities volume of POSIX.1-2008, sh
COPYRIGHT
Portions of this text are reprinted and reproduced in electronic form
from IEEE Std 1003.1, 2013 Edition, Standard for Information Technology
-- Portable Operating System Interface (POSIX), The Open Group Base
Specifications Issue 7, Copyright (C) 2013 by the Institute of Electri-
cal and Electronics Engineers, Inc and The Open Group. (This is
POSIX.1-2008 with the 2013 Technical Corrigendum 1 applied.) In the
event of any discrepancy between this version and the original IEEE and
The Open Group Standard, the original IEEE and The Open Group Standard
is the referee document. The original Standard can be obtained online
at http://www.unix.org/online.html .
Any typographical or formatting errors that appear in this page are
most likely to have been introduced during the conversion of the source
files to man page format. To report such errors, see https://www.ker-
nel.org/doc/man-pages/reporting_bugs.html .
IEEE/The Open Group 2013 SYSTEM(3P)