How To: Execute Shell Commands in C Using system() Or popen()

c shell commands

This article will outline how to call shell commands from your C program using the system() call and the popen() functions. The system() call and the popen() call each have their place and differ enough to give an example and explanation of both.

Execute a Shell Command Using system()

The system() function takes a string as its argument, this string should consist of the shell command you wish to call. Its return value must be run through another function call to retrieve the result of your executed shell command. For example, if you typed ls on the command line, its return value is 0 if it was successful. Let me show you:

int run_sys_call(char *buffer)
{
    int res;
    res = system(buffer);
    if ( WEXITSTATUS(res) != 0 ) {
                syslog(LOG_CRIT," System call failed.\n");
                syslog(LOG_CRIT," %s\n",buffer);
    }
    return res;
}

OR more simply:

int res;
// This will execute the LS command in the current directory, 
//     unfortunately the result is just an exit code.
res = system("ls -l");

This function takes a character array, then passes this string into your “system()” function. The return value is -1 on error, or the exit code of the command WEXITSTATUS(res). This way if you were calling a Bash script it may have various exit codes, this allows you to get that exit code. The downside of the system() function is you couldn’t grab say data in a file, or if you were to “cat” a file you could only get the exit code as the return value and not the contents of that file. This is where popen() comes into play.

Execute a Shell Command Using popen()

The popen() command allows a user to execute the shell command exclusively as a read or a write. The function is a pipe stream that opens a process by creating that pipe, forking, and invoking a shell! All from one command, not too bad, not too bad at all. The return value from popen() is a normal standard I/O stream and must be closed with pclose() rather than fclose(). Writing to such a stream writes to the standard input of the command; the command’s standard output is the same as that of the process that called popen(), unless this is altered by the command itself. Reading from a “popened” stream reads the command’s standard output, and the command’s standard input is the same as that of the process that called popen().

#define COMMAND_LEN 20
#define DATA_SIZE 512
 
void get_popen_data()
    FILE *pf;
    char command[COMMAND_LEN];
    char data[DATA_SIZE];
 
    // Execute a process listing
    sprintf(command, "ps aux wwwf"); 
 
    // Setup our pipe for reading and execute our command.
    pf = popen(command,"r"); 
 
    if(!pf){
      fprintf(stderr, "Could not open pipe for output.\n");
      return;
    }
 
    // Grab data from process execution
    fgets(data, DATA_SIZE , pf);
 
    // Print grabbed data to the screen.
    fprintf(stdout, "-%s-\n",data); 
 
    if (pclose(pf) != 0)
        fprintf(stderr," Error: Failed to close command stream \n");
 
    return;
}

The popen() function takes either “r” for reading or “w” for writing. This example shows grabbing a process listing from the shell and reading it back through the pipe then displaying it to the screen.

Depending on what you need to achieve and what results you need from the shell command, system() and popen() should cover the basic for executing shell commands.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *