Getting shell script output in Linux C-c program (such as getting system command output)

Keywords: shell Programming Unix Linux

Catalog

1. Use of temporary documents

1.1 Reorientation using shell

1.2 freopen standard output to file

2. Use anonymous pipes

3. Use popen

4. Summary

1. Use of temporary documents

1.1 Reorientation using shell

The first idea is to redirect the command output to a temporary file, read the temporary file in our application program, and get the results of the execution of external commands. The code 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);
    }

1.2 freopen standard output to file

#define _GNU_SOURCE
#include <stdio.h>

#include <stdlib.h>
 
int main()
{
    if(freopen("file.txt","w",stdout)==NULL)
        fprintf(stderr,"error\n");
    system("ls -ahl");
    printf("This is in the file\n");      //This sentence will be displayed in file.txt.
    fclose(stdout);               
    return 0;
}

freopen can also redirect standard input.

//First, create an in.txt text document and write a number of numbers in the same path
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    freopen("in.txt","r",stdin);     //Read data from in.txt
    freopen("out.txt","w",stdout);  // Write the final data into out.txt
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF)     //Data is entered from in.txt
        printf("%d\n",a+b);             //Write to out.txt
    fclose(stdin);
    fclose(stdout);
    return 0;
}

This use of temporary files as a bridge between the application and external commands, in the application program need to read the file, and then delete the temporary file, more cumbersome, the advantage is simple to achieve, easy to understand. Is there a way to do this without resorting to temporary documents?

2. Use anonymous pipes

In the book Advanced Programming for UNIX Environment, we give an example of output of program results to paging programs through anonymous pipelines, so we can also connect the results of external commands to applications through pipelines. The method is to fork a child process and create an anonymous pipeline, execute shell command in the child process, and dup its standard output to the input of anonymous pipeline. The parent process reads from the pipeline, and then obtains the output of shell command. The code is as follows:

/**
   * Enhanced system function that returns the output of the system call
   *
   * @param[in] cmdstring A command string that calls an external program or script
   * @param[out] buf Buffer that returns the result of an external command
   * @param[in] len Buffer Buffer Length
   *
   * @return 0: Success; - 1: Failure
   */
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_FILENO)
              {
                  return -1;
              }
              close(fd[1]);
          } 
          if (execl("/bin/sh", "sh", "-c", cmdstring, (char*)0) == -1)
              return -1;
      } 
      return 0;
}

3. Use popen

In the process of learning unix programming, it is found that the system also provides a popen function, which can process and call the shell very simply. Its function prototype is as follows:

#include <stdio.h>

FILE *popen(const char *command, const char *type);

int pclose(FILE *stream);

The purpose of this function is to create a pipeline, fork a process, and then execute the shell. The output of the shell can be obtained by reading the file. This method avoids the creation of temporary files and is not limited by the number of characters output. It is recommended to use this method.

popen determines the direction of input / output of command by type r or w, which is relative to the pipeline of command. r denotes that command reads from the pipeline, w denotes that command outputs to its stdout through the pipeline, and popen returns the file flow pointer of the FIFO pipeline. pclose is used to close the pointer after use.

Let's look at an example:

/*******************************************************************************************
** Name:popen.c
**      This program is used to show the usage of popen() .
** Author:zieckey,(zieckey@yahoo.com.cn)
** Date:2007/9/30 11:47
** All rights reserved!
*******************************************************************************************/
#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 scrambling to files later
    stream = popen( "ls -l", "r" ); //The output of the "ls-l" command is read through the pipeline (the "r" parameter) to FILE* stream
    wstream = fopen( "test_popen.txt", "w+"); //Create a new writable file

    fread( buf, sizeof(char), sizeof(buf), stream); //Read the data stream just from FILE* stream into buf
    fwrite( buf, 1, sizeof(buf), wstream );//Writing data in buf to the stream corresponding to FILE * wstream is also written to a file
    
    pclose( stream );  
    fclose( wstream );
    
    return 0;
}   

Read data directly from the data stream returned by popen using the getline function:

#define _GNU_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int
main (void)
{
  FILE *stream;

  char *line = NULL;
  size_t len = 0;
  ssize_t read;


  stream = popen ("ls -l", "r");
  while ((read = getline (&line, &len, stream)) != -1)
    {
      printf ("Retrieved line of length %zu :\n", read);
      printf ("%s", line);
    }

  pclose (stream);

  return 0;
}

 

4. Summary

Statistical data show that the defect rate of code is certain, independent of the language used. Linux Provide a lot of utilities and scripts, call tools and scripts in the program, can undoubtedly simplify the program, thereby reducing the number of code defects. linux shell script is also a powerful tool. We can write scripts as needed and then call custom scripts in programs.

For example: indent getline.c can sort out style issues such as code indentation.

sed-i's/xc2xa0/x 20/g'test.c replaces Chinese in test.c with spaces

Sed-i's/xc2xa0//g'getline.c Deletes Chinese from test.c

 

Posted by cairesdesigns on Thu, 08 Aug 2019 00:38:19 -0700