Function

Team-FLY

3.5 The exec Function

The fork function creates a copy of the calling process, but many applications require the child process to execute code that is different from that of the parent. The exec family of functions provides a facility for overlaying the process image of the calling process with a new image. The traditional way to use the fork “exec combination is for the child to execute (with an exec function) the new program while the parent continues to execute the original code.

  SYNOPSIS  #include <unistd.h>    extern char **environ;    int execl(const char *path, const char *arg0, ... /*, char *(0) */);    int execle (const char *path, const char *arg0, ... /*, char *(0),                char *const envp[] */);    int execlp (const char *file, const char *arg0, ... /*, char *(0) */);    int execv(const char *path, char *const argv[]);    int execve (const char *path, char *const argv[], char *const envp[]);    int execvp (const char *file, char *const argv[]);  POSIX  

All exec functions return “1 and set errno if unsuccessful. In fact, if any of these functions return at all, the call was unsuccessful . The following table lists the mandatory errors for the exec functions.

errno

cause

E2BIG

size of new process's argument list and environment list is greater than system-imposed limit of ARG_MAX bytes

EACCES

search permission on directory in path prefix of new process is denied, new process image file execution permission is denied , or new process image file is not a regular file and cannot be executed

EINVAL

new process image file has appropriate permission and is in a recognizable executable binary format, but system cannot execute files with this format

ELOOP

a loop exists in resolution of path or file argument

ENAMETOOLONG

the length of path or file exceeds PATH_MAX , or a pathname component is longer than NAME_MAX

ENOENT

component of path or file does not name an existing file, or path or file is an empty string

ENOEXEC

image file has appropriate access permission but has an unrecognized format (does not apply to execlp or execvp )

ENOTDIR

a component of the image file path prefix is not a directory

The six variations of the exec function differ in the way command-line arguments and the environment are passed. They also differ in whether a full pathname must be given for the executable. The execl ( execl , execlp and execle ) functions pass the command-line arguments in an explicit list and are useful if you know the number of command-line arguments at compile time. The execv ( execv , execvp and execve ) functions pass the command-line arguments in an argument array such as one produced by the makeargv function of Section 2.6. The arg i parameter represents a pointer to a string, and argv and envp represent NULL - terminated arrays of pointers to strings.

The path parameter to execl is the pathname of a process image file specified either as a fully qualified pathname or relative to the current directory. The individual command-line arguments are then listed, followed by a (char *)0 pointer (a NULL pointer).

Program 3.4 calls the ls shell command with a command-line argument of -l . The program assumes that ls is located in the /bin directory. The execl function uses its character-string parameters to construct an argv array for the command to be executed. Since argv[0] is the program name, it is the second argument of the execl . Notice that the first argument of execl , the pathname of the command, also includes the name of the executable.

Program 3.4 execls.c

A program that creates a child process to run ls -l .

 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int  main(void) {    pid_t childpid;    childpid = fork();    if (childpid == -1)  {        perror("Failed to fork");        return 1;    }    if (childpid == 0) {                            /* child code */        execl("/bin/ls", "ls", "-l", NULL);        perror("Child failed to exec ls");        return 1;    }    if (childpid != wait(NULL)) {                  /* parent code */        perror("Parent failed to wait due to signal or error");        return 1;    }    return 0; } 

An alternative form is execlp . If the first parameter ( file ) contains a slash, then execlp treats file as a pathname and behaves like execl . On the other hand, if file does not have a slash, execlp uses the PATH environment variable to search for the executable. Similarly, the shell tries to locate the executable file in one of the directories specified by the PATH variable when a user enters a command.

A third form, execle , takes an additional parameter representing the environment of the new process. For the other forms of execl , the new process inherits the environment of the calling process through the environ variable.

The execv functions use a different form of the command-line arguments. Use an execv function with an argument array constructed at run time. The execv function takes exactly two parameters, a pathname for the executable and an argument array. (The makeargv function of Program 2.2 is useful here.) The execve and execvp are variations on execv ; they are similar in structure to execle and execlp , respectively.

Program 3.5 shows a simple program to execute one program from within another program. The program forks a child to execute the command. The child performs an execvp call to overwrite its process image with an image corresponding to the command. The parent, which retains the original process image, waits for the child, using the r_wait function of Program 3.3 from the restart library. The r_wait restarts its wait function if interrupted by a signal.

Example 3.23

The following command line to Program 3.5 causes execcmd to create a new process to execute the ls -l command.

 execcmd ls -l 

Program 3.5 avoids constructing the argv parameter to execvp by using a simple trick. The original argv array produced in Example 3.23 contains pointers to three tokens: myexec , ls and -l . The argument array for the execvp starts at &argv[1] and contains pointers to the two tokens ls and -l .

Exercise 3.24

How big is the argument array passed as the second argument to execvp when you execute execcmd of Program 3.5 with the following command line?

 execcmd ls -l *.c 

Answer:

The answer depends on the number of .c files in the current directory because the shell expands *.c before passing the command line to execcmd .

Program 3.6 creates an argument array from the first command-line argument and then calls execvp . Notice that execcmdargv calls the makeargv function only in the child process. Program 2.2 on page 37 shows an implementation of the makeargv function.

Program 3.5 execcmd.c

A program that creates a child process to execute a command. The command to be executed is passed on the command line.

 #include <errno.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include "restart.h" int main(int argc, char *argv[]) {    pid_t childpid;    if (argc < 2){      /* check for valid number of command-line arguments */       fprintf (stderr, "Usage: %s command arg1 arg2 ...\n", argv[0]);       return 1;    }    childpid = fork();    if (childpid == -1) {       perror("Failed to fork");       return 1;    }    if (childpid == 0) {                                      /* child code */       execvp(argv[1], &argv[1]);       perror("Child failed to execvp the command");       return 1;    }    if (childpid != r_wait(NULL)) {                          /* parent code */       perror("Parent failed to wait");       return 1;    }    return 0; } 
Exercise 3.25

How would you pass a string containing multiple tokens to execcmdargv of Program 3.6?

Answer:

Place the command string in double quotes so that the command line interpreter treats the string as a single token. For example, to execute ls -l , call execcmdargv with the following command line.

 execcmdargv "ls -l" 
Exercise 3.26

Program 3.6 only calls the makeargv function in the child process after the fork. What happens if you move the makeargv call before the fork?

Answer:

A parent call to makeargv before the fork allocates the argument array on the heap in the parent process. The fork function creates a copy of the parent's process image for the child. After fork executes, both parent and child have copies of the argument array. A single call to makeargv does not present a problem. However, when the parent represents a shell process, the allocation step might be repeated hundreds of times. Unless the parent explicitly frees the argument array, the program will have a memory leak.

Program 3.6 execcmdargv.c

A program that creates a child process to execute a command string passed as the first command-line argument.

 #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include "restart.h" int makeargv(const char *s, const char *delimiters, char ***argvp); int main(int argc, char *argv[]) {    pid_t childpid;    char delim[] = " \t";    char **myargv;    if (argc != 2) {       fprintf(stderr, "Usage: %s string\n", argv[0]);       return 1;    }    childpid = fork();    if (childpid == -1) {       perror("Failed to fork");       return 1;    }    if (childpid == 0) {                              /* child code */      if (makeargv(argv[1], delim, &myargv) == -1) {         perror("Child failed to construct argument array");      } else {         execvp(myargv[0], &myargv[0]);         perror("Child failed to exec command");      }      return 1;    }    if (childpid != r_wait(NULL)) {                  /* parent code */       perror("Parent failed to wait");       return 1;    }    return 0; } 

The exec function copies a new executable into the process image. The program text, variables, stack and heap are overwritten. The new process inherits the environment (meaning the list of environment variables and their associated values) unless the original process called execle or execve . Files that are open at the time of the exec call are usually still open afterward.

Table 3.3 summarizes the attributes that are inherited by processes after exec . The second column of the table gives library functions related to the items. The IDs associated with the process are intact after exec runs. If a process sets an alarm before calling exec , the alarm still generates a signal when it expires . Pending signals are also carried over on exec in contrast to fork . The process creates files with the same permissions as before exec ran, and accounting of CPU time continues without being reinitialized.

Table 3.3. Attributes that are preserved after calls to exec . The second column lists some library functions relevant to these attributes. A * indicates an attribute inherited in the POSIX:XSI Extension.

attribute

relevant library function

process ID

getpid

parent process ID

getppid

process group ID

getpgid

session ID

getsid

real user ID

getuid

real group ID

getgid

supplementary group IDs

getgroups

time left on an alarm signal

alarm

current working directory

getcwd

root directory

 

file mode creation mask

umask

file size limit *

ulimit

process signal mask

sigprocmask

pending signals

sigpending

time used so far

times

resource limits *

getrlimit , setrlimit

controlling terminal *

open , tcgetpgrp

interval timers *

ualarm

nice value *

nice

semadj values *

semop

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net