system.3p (14909B)
- '\" et
- .TH SYSTEM "3P" 2017 "IEEE/The Open Group" "POSIX Programmer's Manual"
- .\"
- .SH 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.
- .\"
- .SH NAME
- system
- \(em issue a command
- .SH SYNOPSIS
- .LP
- .nf
- #include <stdlib.h>
- .P
- int system(const char *\fIcommand\fP);
- .fi
- .SH 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\(hy2017 defers to the ISO\ C standard.
- .P
- If
- .IR command
- is a null pointer, the
- \fIsystem\fR()
- function shall determine whether the host environment has a command
- processor. If
- .IR command
- is not a null pointer, the
- \fIsystem\fR()
- function shall pass the string pointed to by
- .IR command
- to that command processor to be executed in an implementation-defined
- manner; this might then cause the program calling
- \fIsystem\fR()
- to behave in a non-conforming manner or to terminate.
- .P
- The
- \fIsystem\fR()
- function shall behave as if a child process were created using
- \fIfork\fR(),
- and the child process invoked the
- .IR sh
- utility using
- \fIexecl\fR()
- as follows:
- .sp
- .RS 4
- .nf
- execl(<\fIshell path\fP>, "sh", "-c", \fIcommand\fP, (char *)0);
- .fi
- .P
- .RE
- .P
- where <\fIshell path\fP> is an unspecified pathname for the
- .IR sh
- utility. It is unspecified whether the handlers registered with
- \fIpthread_atfork\fR()
- are called as part of the creation of the child process.
- .P
- The
- \fIsystem\fR()
- 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
- \fIsystem\fR()
- and take whatever action is appropriate to the application if the
- command terminated due to receipt of a signal.
- .P
- The
- \fIsystem\fR()
- function shall not affect the termination status of any child of the
- calling processes other than the process or processes it itself
- creates.
- .P
- The
- \fIsystem\fR()
- function shall not return until the child process has terminated.
- .P
- The
- \fIsystem\fR()
- function need not be thread-safe.
- .SH "RETURN VALUE"
- If
- .IR command
- is a null pointer,
- \fIsystem\fR()
- shall return non-zero to indicate that a command processor is
- available, or zero if none is available.
- The
- \fIsystem\fR()
- function shall always return non-zero when
- .IR command
- is NULL.
- .P
- If
- .IR command
- is not a null pointer,
- \fIsystem\fR()
- shall return the termination status of the command language interpreter
- in the format specified by
- \fIwaitpid\fR().
- The termination status shall be as defined for the
- .IR sh
- 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
- \fIsystem\fR()
- shall be as if the command language interpreter had terminated using
- .IR exit (127)
- or
- .IR _exit (127).
- If a child process cannot be created, or if the termination status for
- the command language interpreter cannot be obtained,
- \fIsystem\fR()
- shall return \-1 and set
- .IR errno
- to indicate the error.
- .SH ERRORS
- The
- \fIsystem\fR()
- function may set
- .IR errno
- values as described by
- .IR "\fIfork\fR\^(\|)".
- .br
- .P
- In addition,
- \fIsystem\fR()
- may fail if:
- .TP
- .BR ECHILD
- The status of the child process created by
- \fIsystem\fR()
- is no longer available.
- .LP
- .IR "The following sections are informative."
- .SH EXAMPLES
- None.
- .SH "APPLICATION USAGE"
- If the return value of
- \fIsystem\fR()
- is not \-1, its value can be decoded through the use of the macros
- described in
- .IR <sys/wait.h> .
- For convenience, these macros are also provided in
- .IR <stdlib.h> .
- .P
- Note that, while
- \fIsystem\fR()
- 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
- \fIfork\fR()
- and
- .IR exec .
- For example, if SIGINT is being caught or is set to SIG_DFL when
- \fIsystem\fR()
- is called, then the child is started with SIGINT handling set to
- SIG_DFL.
- .P
- 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
- .BR '!'
- 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
- \fIsystem\fR()
- to perform some task invisible to the user. If the user typed the
- interrupt character (\c
- .BR \(dq\(haC\(dq ,
- for example) while
- \fIsystem\fR()
- is being used in this way, one would expect the application to be
- killed, but only the executed command is killed. Applications that use
- \fIsystem\fR()
- in this way should carefully check the return status from
- \fIsystem\fR()
- to see if the executed command was successful, and should take
- appropriate action when the command fails.
- .P
- Blocking SIGCHLD while waiting for the child to terminate prevents the
- application from catching the signal and obtaining status from
- \fIsystem\fR()'s
- child process before
- \fIsystem\fR()
- can get the status itself.
- .P
- The context in which the utility is ultimately executed may differ from
- that in which
- \fIsystem\fR()
- 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.
- .P
- There is no defined way for an application to find the specific path
- for the shell. However,
- \fIconfstr\fR()
- can provide a value for
- .IR PATH
- that is guaranteed to find the
- .IR sh
- utility.
- .P
- Using the
- \fIsystem\fR()
- 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.
- .SH RATIONALE
- The
- \fIsystem\fR()
- function should not be used by programs that have set user (or group)
- ID privileges. The
- \fIfork\fR()
- and
- .IR exec
- family of functions (except
- \fIexeclp\fR()
- and
- \fIexecvp\fR()),
- 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.
- .P
- There are three levels of specification for the
- \fIsystem\fR()
- 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.
- .P
- POSIX.1\(hy2008 places additional restrictions on
- \fIsystem\fR().
- It requires that if there is a command language interpreter, the
- environment must be as specified by
- \fIfork\fR()
- and
- .IR exec .
- This ensures, for example, that close-on-\c
- .IR exec
- works, that file locks are not inherited, and that the process ID is
- different. It also specifies the return value from
- \fIsystem\fR()
- when the command line can be run, thus giving the application some
- information about the command's completion status.
- .P
- Finally, POSIX.1\(hy2008 requires the command to be interpreted as in the shell
- command language defined in the Shell and Utilities volume of POSIX.1\(hy2017.
- .P
- Note that,
- .IR 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
- .IR 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
- \fIsystem\fR()
- 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\(hy2008 if
- .IR system (NULL)
- returns zero.
- .P
- It was explicitly decided that when
- .IR command
- is NULL,
- \fIsystem\fR()
- 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
- .IR 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
- \fIsystem\fR()
- call to fail, that system has been rendered non-conforming.
- .P
- Early drafts required, or allowed,
- \fIsystem\fR()
- to return with
- .IR errno
- set to
- .BR [EINTR]
- if it was interrupted with a signal. This error return was removed, and
- a requirement that
- \fIsystem\fR()
- not return until the child has terminated was added. This means that if
- a
- \fIwaitpid\fR()
- call in
- \fIsystem\fR()
- exits with
- .IR errno
- set to
- .BR [EINTR] ,
- \fIsystem\fR()
- must reissue the
- \fIwaitpid\fR().
- This change was made for two reasons:
- .IP " 1." 4
- There is no way for an application to clean up if
- \fIsystem\fR()
- returns
- .BR [EINTR] ,
- short of calling
- \fIwait\fR(),
- and that could have the undesirable effect of returning the status of
- children other than the one started by
- \fIsystem\fR().
- .IP " 2." 4
- While it might require a change in some historical implementations,
- those implementations already have to be changed because they use
- \fIwait\fR()
- instead of
- \fIwaitpid\fR().
- .P
- Note that if the application is catching SIGCHLD signals, it will
- receive such a signal before a successful
- \fIsystem\fR()
- call returns.
- .P
- To conform to POSIX.1\(hy2008,
- \fIsystem\fR()
- must use
- \fIwaitpid\fR(),
- or some similar function, instead of
- \fIwait\fR().
- .P
- The following code sample illustrates how
- \fIsystem\fR()
- might be implemented on an implementation conforming to POSIX.1\(hy2008.
- .sp
- .RS 4
- .nf
- #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);
- }
- .fi
- .P
- .RE
- .P
- Note that, while a particular implementation of
- \fIsystem\fR()
- (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.
- .P
- Note also that the above example implementation is not thread-safe.
- Implementations can provide a thread-safe
- \fIsystem\fR()
- function, but doing so involves complications such as how to restore the
- signal dispositions for SIGINT and SIGQUIT correctly if there are
- overlapping calls, and how to deal with cancellation. The example
- above would not restore the signal dispositions and would leak
- a process ID if cancelled. This does not matter for a
- non-thread-safe implementation since canceling a non-thread-safe
- function results in undefined behavior (see
- .IR "Section 2.9.5.2" ", " "Cancellation Points").
- To avoid leaking a process ID, a thread-safe implementation would need
- to terminate the child process when acting on a cancellation.
- .P
- One reviewer suggested that an implementation of
- \fIsystem\fR()
- might want to use an environment variable such as
- .IR 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
- \fIsystem\fR(),
- 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\(hy2017, then changing
- .IR SHELL
- would render
- \fIsystem\fR()
- non-conforming. This would affect applications that expected the
- specified behavior from
- \fIsystem\fR(),
- and since the Shell and Utilities volume of POSIX.1\(hy2017 does not mention that
- .IR SHELL
- affects
- \fIsystem\fR(),
- the application would not know that it needed to unset
- .IR SHELL .
- .SH "FUTURE DIRECTIONS"
- None.
- .SH "SEE ALSO"
- .IR "Section 2.9.5.2" ", " "Cancellation Points",
- .IR "\fIexec\fR\^",
- .IR "\fIpipe\fR\^(\|)",
- .IR "\fIpthread_atfork\fR\^(\|)",
- .IR "\fIwait\fR\^(\|)"
- .P
- The Base Definitions volume of POSIX.1\(hy2017,
- .IR "\fB<limits.h>\fP",
- .IR "\fB<signal.h>\fP",
- .IR "\fB<stdlib.h>\fP",
- .IR "\fB<sys_wait.h>\fP"
- .P
- The Shell and Utilities volume of POSIX.1\(hy2017,
- .IR "\fIsh\fR\^"
- .\"
- .SH COPYRIGHT
- Portions of this text are reprinted and reproduced in electronic form
- from IEEE Std 1003.1-2017, Standard for Information Technology
- -- Portable Operating System Interface (POSIX), The Open Group Base
- Specifications Issue 7, 2018 Edition,
- Copyright (C) 2018 by the Institute of
- Electrical and Electronics Engineers, Inc and The Open Group.
- 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.opengroup.org/unix/online.html .
- .PP
- 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.kernel.org/doc/man-pages/reporting_bugs.html .