|
|
Overlays, performed by the family of exec system calls, can change the executing program, but can not create new processes. Processes are created (or spawned) by the system call fork, which is discussed later.
exec is the name of a family of functions that includes execl, execv, execle, execve, execlp, and execvp. They all have the function of transforming the calling process into a new process. The reason for the variety is to provide different ways of pulling together and presenting the arguments of the function. An example of one version (execl) might be:
execl("/usr/bin/prog2", "prog", progarg1, progarg2, (char *)0);For execl the argument list is
Check the exec(2) manual page for the rest of the details. The key point of the exec family is that there is no return from a successful execution: the new process overlays the process that makes the exec system call. The new process also takes over the process ID and other attributes of the old process. If the call to exec is unsuccessful, control is returned to your program with a return value of -1. You can check errno to learn why it failed.
The system call execl executes another program, without returning; thus, to print the date as the last action of a running program, use:
execl("/bin/date", "date", NULL);
The first argument to execl is the filename of the command; you have to know where it is found in the file system. The second argument is conventionally the program name (that is, the last component of the filename), but this is seldom used except as a placeholder. If the command takes arguments, they are strung out after this; the end of the list is marked by a NULL argument.
The execl call overlays the existing program with the new one, runs that, then exits, without returning to the original program.
The one exception to the rule that the original program never gets control back occurs when there is an error, for example if the file cannot be found or is not executable. If you do not know where date is located, say:
execl("/bin/date", "date", NULL); execl("/usr/bin/date", "date", NULL); printf(stderr, "Someone stole 'date'\n");A variant of execl called execv is useful when you do not know in advance how many arguments there are going to be. The call is:
execv(filename, argp);Where argp is an array of pointers to the arguments; the last pointer in the array must be NULL so execv can tell where the list ends. As with execl, filename is the file in which the program is found, and argp[0] is the name of the program. (This arrangement is identical to the argv array for C program arguments.)
Neither of these functions provides the niceties of normal command execution. There is no automatic search of multiple directories - you have to know precisely where the command is located. Nor do you get the expansion of metacharacters like ``<'', ``>'', ``*'', ``?'' and ``[]'' in the argument list. If you want these, use execl to invoke the shell sh, which then does all the work. Construct a string cmdline that contains the complete command as it would have been typed at the terminal, then say:
execl("/bin/sh", "sh", "-c", cmdline, NULL);The shell is assumed to be at a fixed place, /bin/sh. Its argument -c says to treat the next argument as a whole command line, so it does just what you want. The only problem is in constructing the right information in cmdline.
To get automatic search of multiple directories, you have to use the execvp or execlp variants.
To summarize: