system() — Execute a command

Standards

Standards / Extensions C or C++ Dependencies

ISO C
POSIX.1
XPG4
XPG4.2
IEEE Std 1003.1, 2004 Edition

both  

Format

#include <stdlib.h>

int system(const char *string);

General description

The system() function has two different behaviors. These behaviors are designated as ANSI system() and POSIX system(). The ANSI system() behavior is based on the ISO C standard definition of the function, whereas the POSIX system() behavior is based on the POSIX standard definition. The ANSI system() behavior is used when a) running POSIX(OFF) or b) when running POSIX(ON) and environment variable __POSIX_SYSTEM is set to NO. Otherwise the POSIX system() behavior is used.

Restrictions:
  1. The ANSI system() behavior is not supported for AMODE 64 applications. If the ANSI system() behavior is requested using either mechanism described above, system() returns -1 and errno is set to ENOSYS.
  2. The system() function is not supported under CICS®. If the string argument is NULL, system() returns 0 since there is no command processor under CICS, otherwise it returns -1.
ANSI system() function:
Note: In this topic, MVS™ specifically refers to MVS batch (excluding batch TSO/E), whereas TSO/E includes both batch TSO/E (IKJEFT01 as the program specified on the JCL EXEC statement) and interactive TSO/E (which is TSO/E at a terminal).

Using the ANSI system() function, you can call commands, EXECs, CLISTs, or executable modules under MVS and TSO/E. You cannot use the ANSI system() function to invoke z/OS® UNIX services shell programs.

The string argument can take one of the two formats:

command-line
A string with TSO/E command line syntax:
command_name parm1 parm2 … 
Example:
system("user_pgm1 1234 abcd xyz");

If the string argument is in the command-line format, the system() function passes the given string to the command processor, if available, for execution.

named-program
A string, of the following form, with no embedded blanks except in the PARM area.
"PGM=program_name[,PARM='....']"
Example:
system("PGM=user_pgm1, PARM='1234 abcd xyz'");

If the string argument is a named-program format, the system() function calls program_name with the parameters following “PARM=”, if any.

The two formats are supported under both MVS and TSO/E, but not all targets can be called from all environments. For example, TSO/E commands cannot be called in an MVS environment. As a result, the two formats are equivalent under MVS, but are different under TSO/E. The details of each are provided below. For maximum portability when invoking executable modules under the different environments, use the named-program format.

If the specified executable module is a z/OS XL C or z/OS XL C++ module, full initialization and termination will be performed: including, but not limited to, automatic closing of files and releasing of fetched modules. In addition, if the ANSI system() call uses the named-program format under either MVS or TSO/E, or the command-line format under MVS, information can be passed across the program boundary using memory files. Memory files are not removed until either the highest level (root) program in the call chain terminates or the clrmemf() function is used. Standard streams are also shared in this environment.

ANSI MVS considerations: Under MVS, the ANSI system() function accepts either command-line or named-program format strings. However, the command-line string is restricted to specifying only executable modules (that is, TSO/E commands, EXECs, and CLISTs cannot be specified). Because of this restriction, both formats provide the same functionality.

In the case of either a command-line or named-program string, the ANSI system() function will search the usual MVS sources (STEPLIB/JOBLIB concatenation, Link Pack Area (LPA), Extended Link Pack Area (ELPA), and the link libraries) for the specified program name. The LINK SVC is used to give control to the program.

Under MVS, using ATTACH instead of ANSI system() will prevent you from sharing memory files or standard streams between the programs.

ANSI TSO/E considerations: Under TSO/E, the ANSI system() function accepts either command-line or named-program format strings.

Command-line format strings are presented to the TSO/E command processor and can be used to execute user modules, TSO/E commands, EXECs or CLISTs. If there is any ambiguity as to what is to be run when a command-line format string is supplied, the hierarchy is:
  1. TSO/E command or user module
  2. CLIST or EXEC

Therefore, if a command-line format string is used and a CLIST or EXEC exists with the same name as a TSO/E command or user module, the TSO/E EXEC command must be used to specifically invoke the CLIST or EXEC.

If the command-line format string is used to call a user module, it effectively uses ATTACH to execute the program. As with MVS, when using ATTACH, memory files and standard streams are not shared between the programs. This is the reason that named-program format strings should be used for maximum portability. The named-program format provides the same memory file and standard stream sharing in both the MVS and TSO/E environments.

Notes:
  1. If an executable module is placed in the STEPLIB or ISPLLIB (under ISPF), TSO/E will allow the module to be activated as a command. Recall from the discussion above, that, if a CLIST or EXEC has the same name, the module would be activated first, due to the hierarchy rules. Activating a module as a command involves a different input interface. If required, you can use the CALL command to activate a module that is not prepared to take the TSO/E command input format. z/OS XL C and z/OS XL C++ modules can be called as TSO/E commands.
  2. A module that exists in the Link Pack Area (LPA) or Extended Link Pack Area (ELPA) and not in the STEPLIB concatenation (ISPLLIB on ISPF) will not be activated as a TSO/E command, and is treated as an executable module.

Named-program format strings are not presented to the TSO/E command processor and can only be used to execute user modules.

POSIX system() function: Using the POSIX system() function, you can call z/OS UNIX services shell programs. You cannot use the POSIX system() function to call commands, EXECs, CLISTs, or executable modules under MVS and TSO/E.

The POSIX system() function passes string to the sh shell command for execution. The environment is established by the runtime library through a spawn() of the shell.

The POSIX system() function ignores the SIGINT and SIGQUIT signals, and blocks the SIGCHILD signal while it waits for the command specified by string argument to end.

Special considerations for POSIX C: The system() function has these additional considerations:
  • A program running with POSIX(ON) can call another program that will also use POSIX(ON) only if the calling program uses the POSIX system() function to invoke the called program out of the shell. Using the ANSI system() function to call a program that will also use POSIX(ON) will result in message CEE3648S being issued, followed by ABENDU4093-AC.
  • A program running with POSIX(ON) can receive signals other than SIGINT, SIGQUIT, or SIGCHLD while the POSIX system() function is waiting for the shell command to complete. If there is a signal catcher registered for the signal, it will be invoked immediately. If the signal catcher calls siglongjmp() or setcontext() to pass control back to the application, the SIGINT and SIGQUIT signals will remain ignored, and the SIGCHLD signal will remain blocked.
  • If the calling program is the child of a forked process, it cannot use the ANSI system() function to run TSO/E commands since the TSO/E address space is not available.
  • If the calling program was invoked using one of the exec or spawn functions, it cannot use the ANSI system() function to run TSO/E commands since the TSO/E address space is not available.
  • The system() function is not thread-safe. It cannot be called simultaneously from more than one thread. A multithreaded application must ensure that no more than one system() call is ever outstanding from the various threads. Results are undefined if this restriction is violated..
  • When using a signal handler and setting the default handler for SIGCHLD to be SIG_IGN, an errno value of ECHILD will be returned. This is due to the speed at which the process executes and finishes before system() can call waitpid() to wait for the child process to end. In this case, the ECHILD can be ignored because the process has already completed successfully and returned.
Note: If an application invokes a z/OS UNIX service shell command or utility that performs terminal I/O, the command may fail due to the z/OS UNIX services shell file descriptors not being initialized. z/OS UNIX files for terminal I/O must be defined. An example of how these can be defined in a C application are as follows:
stdin = fopen("/tmp/sys.stdin","r");
stdout = fopen("/tmp/sys.stdout","w");
stderr = fopen("/tmp/sys.stderr","w");
See z/OS XL C/C++ applications with z/OS UNIX System Services C functions in topic 1.9 for more information about using POSIX support.

Mixed environments across an ANSI system() call: The mixing of z/OS Language Environment®, C/370™ Library Version 1 or Version 2, and System Programming C (SPC) environments across a system() call is not supported. Whichever of these environments is active when the first system() call is made is the only one that is tolerated in the system() call chain. Results are undefined if this restriction is violated.

Returned value

If the string argument is a NULL pointer, the system() function returns nonzero if a command processor exists, or 0 if one does not exist.

ANSI MVS considerations: The returned value from ANSI system() will be that from the user module, if successfully called. If system() cannot call the specified module, the returned value is -1 and errno is set appropriately.

ANSI TSO/E considerations: The returned value from ANSI system() will be nonzero if the command processor cannot execute the command or user module. The macros __abendcode and __rsncode will contain the abend code and reason code from a failing TSO/E command, EXEC, or CLIST.

POSIX considerations: If the string argument is a NULL pointer, the POSIX system() function returns nonzero. If the string argument is not NULL, the POSIX system() function returns the termination status of the command language interpreter in the format specified by waitpid(). If a child process cannot be created, or if the termination status for the command language interpreter cannot be obtained, system() returns -1.

Note: When using a signal handler and setting the default handler for SIGCHLD to be SIG_IGN, an errno value of ECHILD will be returned. This is due to the speed at which the process executes and finishes before system() can call waitpid() to wait for the child process to end. In this case, the ECHILD can be ignored because the process has already completed successfully and returned.

If system() returns -1, errno may be set to one of the following:

Error Code
Description
EAGAIN
There are insufficient resources to create another process, or the maximum number of processes you can run has been reached.
ECHILD
The new process finished before system() could call waitpid() to wait for the child process to end. This error can be ignored because the child process has already completed successfully and returned.
ENOMEM
The process requires more space than is available.
ENOSYS
The ANSI system() function was requested from an AMODE 64 application.

Example

/* This example illustrates how to use system() to execute a command which
   returns the time.  The example works only under TSO.
 */
#include <stdlib.h>

int main(void)
{
    int rc;
    rc = system("time");
    exit(0);
}
/* This example may only be used in a POSIX program.  */
#include <stdlib.h>

int main(void)
{
    int result;

    result = system("date | tee result.log");
}

Related information