Movatterモバイル変換


[0]ホーム

URL:


<<<PreviousHomeNext >>>


NAME

system - issue a command

SYNOPSIS

#include <stdlib.h>

int system(const char *
command);

DESCRIPTION

[CX][Option Start] The functionality described on this reference page is aligned with the ISO C standard. Any conflict between therequirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2017 defers to the ISO Cstandard.[Option End]

Ifcommand is a null pointer, thesystem() function shall determine whether the host environment has a commandprocessor. Ifcommand is not a null pointer, thesystem() function shall pass the string pointed to bycommandto that command processor to be executed in an implementation-defined manner; this might then cause the program callingsystem() to behave in a non-conforming manner or to terminate.

[CX][Option Start] Thesystem() function shall behave as if a child process were created usingfork(),and the child process invoked thesh utility usingexecl() as follows:

execl(<shell path>, "sh", "-c",command, (char *)0);

where <shell path> is an unspecified pathname for thesh utility. It isunspecified whether the handlers registered withpthread_atfork() are calledas part of the creation of the child process.

Thesystem() function shall ignore the SIGINT and SIGQUIT signals, and shall block the SIGCHLD signal, while waiting forthe command to terminate. If this might cause the application to miss a signal that would have killed it, then the applicationshould examine the return value fromsystem() and take whatever action is appropriate to the application if the commandterminated due to receipt of a signal.

Thesystem() function shall not affect the termination status of any child of the calling processes other than theprocess or processes it itself creates.

Thesystem() function shall not return until the child process has terminated.[Option End]

Thesystem() function need not be thread-safe.

RETURN VALUE

Ifcommand is a null pointer,system() shall return non-zero to indicate that a command processor is available, orzero if none is available.[CX][Option Start] Thesystem() function shall always return non-zero whencommand is NULL.[Option End]

[CX][Option Start] Ifcommand is not a null pointer,system() shall return the termination status of the command language interpreter inthe format specified bywaitpid(). The termination status shall be as defined forthesh utility; otherwise, the termination status is unspecified. If some error preventsthe command language interpreter from executing after the child process is created, the return value fromsystem() shall beas if the command language interpreter had terminated usingexit(127) or_exit(127). If a child process cannot becreated, or if the termination status for the command language interpreter cannot be obtained,system() shall return -1 andseterrno to indicate the error.[Option End]

ERRORS

[CX][Option Start] Thesystem() function may seterrno values as described byfork.[Option End]

In addition,system() may fail if:

[ECHILD]
[CX][Option Start]The status of the child process created bysystem() is no longer available.[Option End]

The following sections are informative.

EXAMPLES

None.

APPLICATION USAGE

If the return value ofsystem() 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, whilesystem() must ignore SIGINT and SIGQUIT and block SIGCHLD while waiting for the child to terminate, thehandling of signals in the executed command is as specified byfork() andexec. For example, if SIGINT is being caught or is set to SIG_DFL whensystem() 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 userhas given a command to the application to be executed synchronously (as in the'!' command in many interactiveapplications). In either case, the signal should be delivered only to the child process, not to the application itself. There isone situation where ignoring the signals might have less than the desired effect. This is when the application usessystem()to perform some task invisible to the user. If the user typed the interrupt character ("^C", for example) whilesystem() is being used in this way, one would expect the application to be killed, but only the executed command is killed.Applications that usesystem() in this way should carefully check the return status fromsystem() to see if theexecuted 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 statusfromsystem()'s child process beforesystem() can get the status itself.

The context in which the utility is ultimately executed may differ from that in whichsystem() 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 theexecuted utility changes its environment variables or its current working directory, that change is not reflected in the caller'scontext.

There is no defined way for an application to find the specific path for the shell. However,confstr() can provide a value forPATH that is guaranteed to find thesh utility.

Using thesystem() function in more than one thread in a process or when the SIGCHLD signal is being manipulated by morethan one thread in a process may produce unexpected results.

RATIONALE

Thesystem() function should not be used by programs that have set user (or group) ID privileges. Thefork() andexec family of functions (exceptexeclp() andexecvp()), should be usedinstead. This prevents any unforeseen manipulation of the environment of the user that could cause execution of commands notanticipated by the calling program.

There are three levels of specification for thesystem() function. The ISO C standard gives the most basic. Itrequires that the function exists, and defines a way for an application to query whether a command language interpreter exists. Itsays nothing about the command language or the environment in which the command is interpreted.

POSIX.1-2017 places additional restrictions onsystem(). It requires that if there is a command language interpreter, theenvironment must be as specified byfork() andexec. This ensures, for example, that close-on-execworks, that file locks are not inherited, and that the process ID is different. It also specifies the return value fromsystem() when the command line can be run, thus giving the application some information about the command's completionstatus.

Finally, POSIX.1-2017 requires the command to be interpreted as in the shell command language defined in the Shell and Utilitiesvolume of POSIX.1-2017.

Note that,system(NULL) is required to return non-zero, indicating that there is a command language interpreter. At firstglance, this would seem to conflict with the ISO C standard which allowssystem(NULL) to return zero. There is noconflict, however. A system must have a command language interpreter, and is non-conforming if none is present. It is thereforepermissible for thesystem() function on such a system to implement the behavior specified by the ISO C standard aslong as it is understood that the implementation does not conform to POSIX.1-2017 ifsystem(NULL) returns zero.

It was explicitly decided that whencommand is NULL,system() should not be required to check to make sure thatthe command language interpreter actually exists with the correct mode, that there are enough processes to execute it, and so on.The callsystem(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 isnot under the control of this application and that would cause anysystem() call to fail, that system has been renderednon-conforming.

Early drafts required, or allowed,system() to return witherrno set to [EINTR] if it was interrupted with asignal. This error return was removed, and a requirement thatsystem() not return until the child has terminated was added.This means that if awaitpid() call insystem() exits witherrno setto [EINTR],system() must reissue thewaitpid(). This change was made for tworeasons:

  1. There is no way for an application to clean up ifsystem() returns [EINTR], short of callingwait(), and that could have the undesirable effect of returning the status of children otherthan the one started bysystem().

  2. While it might require a change in some historical implementations, those implementations already have to be changed becausethey usewait() instead ofwaitpid().

Note that if the application is catching SIGCHLD signals, it will receive such a signal before a successfulsystem() callreturns.

To conform to POSIX.1-2017,system() must usewaitpid(), or some similarfunction, instead ofwait().

The following code sample illustrates howsystem() might be implemented on an implementation conforming toPOSIX.1-2017.

#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 ofsystem() (such as the one above) can assume a particular path for theshell, such a path is not necessarily valid on another system. The above example is not portable, and is not intended to be.

Note also that the above example implementation is not thread-safe. Implementations can provide a thread-safesystem()function, but doing so involves complications such as how to restore the signal dispositions for SIGINT and SIGQUIT correctly ifthere are overlapping calls, and how to deal with cancellation. The example above would not restore the signal dispositions andwould leak a process ID if cancelled. This does not matter for a non-thread-safe implementation since canceling a non-thread-safefunction results in undefined behavior (seeCancellation Points).To avoid leaking a process ID, a thread-safe implementation would need to terminate the child process when acting on acancellation.

One reviewer suggested that an implementation ofsystem() might want to use an environment variable such asSHELLto determine which command interpreter to use. The supposed implementation would use the default command interpreter if the onespecified by the environment variable was not available. This would allow a user, when using an application that prompts forcommand lines to be processed usingsystem(), to specify a different command interpreter. Such an implementation isdiscouraged. If the alternate command interpreter did not follow the command line syntax specified in the Shell and Utilitiesvolume of POSIX.1-2017, then changingSHELL would rendersystem() non-conforming. This would affect applications thatexpected the specified behavior fromsystem(), and since the Shell and Utilities volume of POSIX.1-2017 does not mentionthatSHELL affectssystem(), the application would not know that it needed to unsetSHELL.

FUTURE DIRECTIONS

None.

SEE ALSO

Cancellation Points,exec,pipe,pthread_atfork,wait

XBD<limits.h>,<signal.h>,<stdlib.h>,<sys/wait.h>

XCUsh

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 ofat_fork() 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.

End of informative text.

 

return to top of page


<<<PreviousHomeNext >>>


[8]ページ先頭

©2009-2025 Movatter.jp