trusty (3) system.3posix.gz

Provided by: manpages-posix-dev_2.16-1_all bug

NAME

       system - issue a command

SYNOPSIS

       #include <stdlib.h>

       int system(const char *command);

DESCRIPTION

       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 implementation-defined manner; this might
       then cause the program calling system() to behave in a non-conforming manner or to terminate.

       The environment of the executed command shall be 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.

       The  system()  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 system() and take
       whatever action is appropriate to the application 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 terminated.

RETURN VALUE

       If  command  is  a  null  pointer, system() shall return non-zero to indicate that a command processor is
       available, or zero if none is available.   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
       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 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 termination 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 convenience, 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  signals  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  perform  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 system()'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.

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.

       IEEE Std 1003.1-2001 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  system()  when  the  command  line can be run, thus giving the
       application some information about the command's completion status.

       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.

       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 command 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 IEEE Std 1003.1-2001 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 interpreter actually exists with the correct mode, that there are enough
       processes to execute it, and so on.  The call 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 system() call to fail, that system has been rendered non-
       conforming.

       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 undesirable 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  IEEE Std 1003.1-2001,  system() must use waitpid(), or some similar function, instead of
       wait().

       The following code sample illustrates how system() might be implemented on an  implementation  conforming
       to IEEE Std 1003.1-2001.

              #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
       portable, 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
       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  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 IEEE Std 1003.1-2001 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()  ,  waitpid()  ,  the  Base  Definitions  volume  of  IEEE Std 1003.1-2001,  <limits.h>,
       <signal.h>, <stdlib.h>, <sys/wait.h>, the Shell and Utilities volume of IEEE Std 1003.1-2001, sh

       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 .