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