When programming in C under Linux to execute Shell commands or scripts, the system function is generally used. However, it only returns whether the execution was successful or failed, without returning the corresponding return value of the executed Shell command or script. The following method can be used to achieve this requirement:Temporary FileSince the return value of the system function does not provide the execution return value of the Shell command or script, we can utilize Shell’s redirection operation to redirect the execution return content to a temporary file. After execution, we can read and parse the temporary file, and then delete it. The corresponding code example is as follows:
#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);
}
The code example demonstrates redirecting the Shell command executed by system to a temporary file. After that, we need to open and read the temporary file for processing before deleting it. This operation requires the use of a temporary file, so let’s explore a method that does not use a temporary file.Anonymous PipeThe following example creates a child process using fork and establishes an anonymous pipe. In the child process, the Shell command is executed, and its standard output is duped to the input end of the anonymous pipe. The parent process then reads from this anonymous pipe to obtain the output content of the Shell command execution. The code is as follows:
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) {
close(fd[1]);
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 {
close(fd[0]);
if (fd[1] != STDOUT_FILENO) {
if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
return -1;
}
close(fd[1]);
}
if (execl("/bin/sh", "sh", "-c", cmdstring, (char*)0) == -1)
return -1;
}
return 0;
}
The popen function in Linux programming can also be used to achieve this requirement. Its prototype is as follows:
FILE *popen(const char *command, const char *type);
This function creates a pipe, forks a process, and then executes the Shell command. The output of the Shell is obtained by reading from the file, which avoids creating a temporary file and is not limited by the number of output characters.The popen function uses a FIFO pipe to execute external programs, and the relevant usage instructions are as follows:
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
The popen function determines the input/output direction after executing the command based on whether type is ‘r’ or ‘w’. ‘r’ indicates that the command reads from the pipe, while ‘w’ indicates that the command writes to its stdout through the pipe. popen returns a file stream pointer for the FIFO pipe. pclose is used to close this pointer.The following is the corresponding demo source code:
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void){
FILE *stream;
FILE *wstream;
char buf[1024];
memset(buf, '\0', sizeof(buf)); // Initialize buf to avoid writing garbage to the file later
stream = popen("ls -l", "r"); // Read the output of the "ls -l" command through the pipe ("r" parameter) into FILE* stream
wstream = fopen("test_popen.txt", "w+"); // Create a writable file
fread(buf, sizeof(char), sizeof(buf), stream); // Read the data stream from FILE* stream into buf
fwrite(buf, 1, sizeof(buf), wstream); // Write the data from buf to the stream corresponding to FILE* wstream, which is also written to the file
pclose(stream); fclose(wstream);
return 0;
}
In summary, several common methods for obtaining the Shell execution return content in C have been compiled. Users can choose according to their needs.