Linux C Programs Execute shell commands and get methods to return results __linux

Source: Internet
Author: User
Tags call shell

It is said that statistical data indicate that the defect rate of code is certain, regardless of the language used. Linux provides a lot of utilities and scripts to invoke tools and scripts in a program that can simplify programs and reduce the number of code flaws. Linux shell script is also a powerful tool, we can script as needed, and then call custom script in the program.
One sentence in Unix programming art is that a row of Shell scripts is better than Wan C. So in Linux programming, how does the C program call the shell command and how does it get the return result of the command? Let's take a look at it together. 1. Call Shell command

In general, there are three common ways to invoke shell commands in a Linux system using the C Program: System (), Popen (), EXEC series functions. Using System () does not require a user to create a process because it is already encapsulated, directly to the shell command, and Popen () to execute the shell command with less overhead than system (); Exec requires a user fork/vfork process, and then exec The required shell command. 1.1 system () function Prototypes

int system (const char *command);  
function Description

System () invokes the fork () to produce the child process, which invokes the/BIN/SH-C string to execute the command represented by the parameter string string, which then returns the process of the original call. The SIGCHLD signal is temporarily shelved during the call to System () and the SIGINT and sigquit signals are ignored. return value

If system () fails while calling/bin/sh, 127 is returned, and the other failure reason returns-1. If the argument string is a null pointer (null), a value other than 0 is returned. If the system () call succeeds, the return value after executing the shell command is finally returned, but this return value is also likely to return 127 for system () call/bin/sh failure, so it is best to check errno again to confirm execution success. Additional Instructions

Do not use System () when writing programs with Suid/sgid permissions, because system () inherits environment variables, which can cause problems with systems security through environment variables. Sample

#include <stdlib.h>

int main (int argc, char *argv[])
{
    system ("Ls-al/etc/passwd/etc/shadow");
    return 0;
}
1.2 popen () function Prototypes
FILE *popen (const char *command, const char *type);  

int Pclose (FILE *stream);  
function Description

Popen () invokes fork () to produce the child process, and then calls/bin/sh-c from the child process to execute the command of the parameter command. The parameter type can be read by using "R", and "w" for writing. According to this type value, Popen () establishes a standard output device or standard input device that is attached to a subprocess, and then returns a file pointer. The process can then use this file pointer to read the output device of a child process or to a standard input device that is written to a child process. In addition, all other functions that use the file pointer (files *) operation are available except for the fclose (). return value

If successful, return the file pointer, otherwise NULL is returned, and the reason for the error is stored in the errno. Attention Matters

Try to avoid using popen () when writing programs with Suid/sgid permissions, because Popen () inherits environment variables, which can cause system security problems through environment variables. Sample

#include <stdio.h> 

int main (int argc, char *argv[])
{ 
    FILE *fp; 
    Char buffer[80]; 

    Fp=popen ("cat/etc/passwd", "R"); 
    Fgets (buffer,sizeof (buffer), FP); 
    printf ("%s", buffer); 

    return 0;
}
1.3 exec function cluster function Prototypes
int execl (const char *path, const char *arg, ...);    

int EXECLP (const char *file, const char *arg, ...);    

int execle (const char *path, const char *arg, ..., Char *const envp[]);    

int execv (const char *path, char *const argv[]);    

int EXECVP (const char *file, char *const argv[]);    

int Execve (const char *path, char *const argv[], char *const envp[];  
Sample

Creates a new subprocess using Vfork (), and then calls the EXEC function family.

#include <unistd.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
    char *args[] = { "LS", "-al", "/etc/passwd"};

    if (vfork () = = 0)
    {
        execv ("/bin/ls", args);
    }
    else
    {        
        printf ("This is the parent process\n");
    }
    return 0;
}
2. Get return result

We've shown several ways to invoke the shell command in C programs, where we find a problem--although we can tell if the shell command was executed, but sometimes we can't get the information it returns. Well, then you can consider the following methods. 2.1 Using temporary files

The easiest way to think first is to redirect the shell command output to a temporary file, read the temporary file in our application, and get the results of the external command execution.
The code looks like this:

#define CMD_STR_LEN 1024

int Mysystem (char *cmdstring, char *tmpfile)
{
    char cmd_string[cmd_str_len];

    Tmpnam (tmpfile);
    sprintf (cmd_string, "%s >%s", cmdstring, tmpfile);

    return system (cmd_string);
}

This use of temporary files as a bridge between application and external commands, the need to read files in the application, and then delete the temporary file, more cumbersome, the advantage is simple, easy to understand. 2.2 using anonymous pipes

In the UNIX Environment Advanced Programming (APUE) book gives an example of an anonymous pipeline that outputs program results to a paging program, and it is thought that we can also use pipelines to connect the results of external commands to the application. The method is to fork a subprocess, create an anonymous pipe, execute the shell command in the subprocess, and DUP its standard output to the input of the anonymous pipe, and the parent process reads from the pipe to get the output of the shell command.
The code looks like this:

/** * Enhanced system function that returns the output of the system call * @param [in] cmdstring a command string that invokes an external program or script @param [out] buf a buffer * that returns the result of an external command @para M[in] Len Buffer buf length * * @return 0: successful;
    -1: Failed/int Mysystem (char *cmdstring, char *buf, int len) {int fd[2];
    pid_t pid; 

    int n, Count;
    memset (buf, 0, Len);
    if (pipe (FD) < 0) {return-1;
    } if ((PID = fork ()) < 0) {return-1;     else if (PID > 0)/* Parent Process */{close (fd[1]);

        /* Close Write end */count = 0;
        while ((n = read (fd[0], buf + count, len)) > 0 && count > len) {count = n;
        Close (fd[0]);
        if (Waitpid (PID, NULL, 0) > 0) {return-1;     } else/* child process */{close (fd[0]); /* Close Read end */if (fd[1]!= Stdout_fileno) {if (Dup2 (fd[1), Stdout_fileno)!= Stdout_fi LENO) {return-1;
        Close (fd[1]);
        } if (Execl ("/bin/sh", "sh", "C", Cmdstring, (char*) 0) = = 1) {return-1;
} return 0; }
2.3 using Popen ()

In the example of executing the shell command, we used the Popen () function, which you may have discovered, using Popen () to get the return result of the command.
The function is to create a pipe, fork a process, and then execute the shell, and the shell's output can be obtained by reading the file. This method avoids the creation of temporary files and is not limited by the number of output characters, and is recommended for use.
Popen () uses FIFO pipes to execute external programs. It determines the command's input/output direction by Type R or W, and R and W are relative to the command's pipe. R indicates that the command is read from the pipe, and W represents the file stream pointer that the command outputs to its stdout,popen () from the pipe to the FIFO pipe. Pclose () is used to close this pointer when the end is used.
The sample code looks like this:

 #include <stdio.h> #include <string.h> int main (int argc,char*argv[]) {      
    FILE *fstream = NULL;    
    Char buff[1024];   

    memset (buff, 0, sizeof (buff)); if (NULL = = FStream = Popen ("Ifconfig", "R"))) {fprintf (stderr, "Execute command failed:%s", Strerro      
        R (errno));      
    return-1;    
    while (NULL!= fgets (buff, sizeof (buff), fstream)) {printf ("%s", buff);    

    } pclose (FStream);     
return 0; }   
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.