Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

Section 8.13 systemFunction 265


#include <stdlib.h>

int system(const char *cmdstring);

Returns: (see below)

Ifcmdstringis a null pointer,systemreturns nonzeroonly if a command processor
is available. This featuredetermines whether thesystemfunction is supported on a
given operating system. Under the UNIX System,systemis always available.
Becausesystemis implemented by callingfork,exec,andwaitpid,thereare
three types of return values.


  1. If either theforkfails orwaitpidreturns an error other thanEINTR,system
    returns−1witherrnoset to indicate the error.

  2. If theexecfails, implying that the shell can’t be executed, the return value is as
    if the shell had executedexit(127).

  3. Otherwise, all three functions —fork,exec,andwaitpid—succeed, and the
    return value fromsystemis the termination status of the shell, in the format
    specified forwaitpid.


Some older implementations ofsystemreturned an error (EINTR)ifwaitpidwas
interrupted by a caught signal. Because there is no strategy that an application can use to
recover from this type of error (the process ID of the child is hidden from the caller),
POSIX later added the requirement thatsystemnot return an error in this case. (We
discuss interrupted system calls in Section 10.5.)

Figure8.22 shows an implementation of thesystemfunction. The one featurethat
it doesn’t handle is signals. We’ll update this function with signal handling in
Section 10.18.
The shell’s-coption tells it to take the next command-line argument—cmdstring,in
this case—asits command input instead of reading from standardinput or from a given
file. The shell parses this null-terminated C string and breaks it up into separate
command-line arguments for the command. The actual command string that is passed
to the shell can contain any valid shell commands. For example, input and output
redirection using<and>can be used.
If we didn’t use the shell to execute the command, but tried to execute the
command ourself, it would be moredifficult. First, we would want to callexeclp,
instead ofexecl, to use thePATHvariable, like the shell.We would also have to break
up the null-terminated C string into separate command-line arguments for the call to
execlp.Finally, we wouldn’t be able to use any of the shell metacharacters.
Note that we call_exitinstead ofexit.We do this to prevent any standardI/O
buffers, which would have been copied from the parent to the child across thefork,
from being flushed in the child.
Free download pdf