Add Book to My BookshelfPurchase This Book Online

Chapter 11 - Processes

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

Simple Program Execution
The simplest way to execute a program from within your program is to use the system function:
    #include <stdlib.h>
    int system(const char *string);
The system function uses the Bourne shell (/bin/sh) with its -c option to execute the shell command contained in string, waits for the command to complete, and then returns the termination status (which includes the exit status) of the command. Example 11-1 demonstrates the use of system.
Example 11-1:  system
#include <stdlib.h>
#include <stdio.h>
struct {
    char    *abbrev;
    char    *fullname;
} days[] = {
    "Sun",  "Sunday",
    "Mon",  "Monday",
    "Tue",  "Tuesday",
    "Wed",  "Wednesday",
    "Thu",  "Thursday",
    "Fri",  "Friday",
    "Sat",  "Saturday",
    0,      0
};
int
main(void)
{
    int i;
    int status;
    char command[BUFSIZ];
    /*
     * For each day, construct a command.
     */
    for (i=0; days[i].abbrev != NULL; i++) {
        /*
         * Run the date command, and use grep to search for
         * the day's abbreviated name.  Redirect the output
         * to /dev/null; we'll use the exit status to find
         * what we want.
         */
        sprintf(command, "date | grep %s > /dev/null", days[i].abbrev);
        /*
         * Run the command.  The termination status is returned
         * in status.
         */
        status = system(command);
        /*
         * The exit status is in the second byte of the
         * termination status.
         *
         * Grep returns 0 if a match was found, 1 if no
         * match was found, and 2 if an error occurred.
         */
        switch ((status >> 8) & 0xff) {
        case 0:
            printf("Today is %s.\n", days[i].fullname);
            break;
        case 1:
            printf("Today is not %s.\n", days[i].fullname);
            break;
        case 2:
            printf("Error in pattern specification.\n");
            exit(1);
        }
    }
    /*
     * Exit with a status of 0, indicating that
     * everything went fine.
     */
    exit(0);
}
    % system
    Today is not Sunday.
    Today is not Monday.
    Today is not Tuesday.
    Today is Wednesday.
    Today is not Thursday.
    Today is not Friday.
    Today is not Saturday.
For each day of the week, the program constructs a command to execute date, sending the output from that to grep, to search for the abbreviated day name. Each time, we save the termination status of grep (in a pipeline, the termination status of the entire pipeline is defined by the termination status of the last command in the pipeline) in the variable status. Next, we extract the exit status from the termination status, figure out what grep was telling us, and print an appropriate message.
The example extracts the exit status from the termination status in a non-portable fashion. As it turns out, this example will work on all versions of UNIX; the exit status is always in the second byte of the termination status. A more portable way to examine the termination status and extract information from it is shown in the next section.
Finally, notice that the commands we build redirect their output to /dev/null (the “bit bucket”). We can do this because we are interested only in whether or not grep found anything, not what it found, and grep tells us this with its exit status. If we did not redirect the output to /dev/null, then when we found a match, the output from date (as printed by grep) would appear in the middle of the output from our program. Try removing the redirection from the command to see the difference.
There are three final points to make about system:
 1.Although convenient, system is also terribly inefficient. Each time it is called, it starts not only the command you want to execute, but also a copy of the shell. If your program executes many commands, you should execute them yourself directly, rather than via system. The means to do this are described in the next section.
 2.System calls and library routines are always more efficient than using system to do the same thing. For example, instead of calling
    system("rm -f file");
    system("mkdir foo");
    system("mv oldfile newfile");
you could include in your program functions we have discussed in previous chapters:
    unlink("file");
    mkdir("foo");
    rename("oldfile", "newfile");
 3.The system function should never, under any circumstances, be used in programs that will be run with superuser permissions, or with the set-user-id bit set. Because system uses the shell to execute commands, there may be ways in which an unethical person can fool your program into executing a command other than the one you intended. This may enable the person to circumvent the security of your computer system.

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback