How to read until EOF from STDOUT in C?

Viewed 415

#1: I do not know the size of output produced by stdout, given a command.

#2: I don't want to use char array like

char buffer[1024];

as it will result in memory shortage or wastage.

#3: If I use character pointer like

char *buffer;

I will have to allocate allocate memory for it like

buffer = (char *)malloc(1024 * sizeof(char));

#4: If I use getc() within while loop like

char *buf, c;
int i=0, j=1;
int pipefd[2];
int  stdout_bk;
code[message_read] = '\0';
stdout_bk = dup(fileno(stdout));
pipe(pipefd);
dup2(pipefd[1], STDOUT_FILENO);

system(code);
close(pipefd[1]);

dup2(stdout_bk, STDOUT_FILENO);
buf = (char*)malloc(sizeof(char));

while(c!=End_Of_File) // What should I replace End_Of_File with?
{
    c = getc(pipefd[0]);
    buf = (char*)realloc(buf, j * sizeof(char));
    buf[i] = c;
    i++;
    j++;
}

I do not know what is the End_Of_file for the stdout data.

P.S.: the program runs a command, e.g., system("setarch x86_64 -R dd if=/proc/self/maps | grep bin/dd") or system("ls -al") and I need to get the STDOUT. For that I have used dup2 and need to pipe the output to a buffer.

NOTE: the output can be of variable length.

1 Answers

There are many issues with your code:

  • c must be defined with type int
  • getc() cannot take a system handle as an argument, you must wrap that in a FILE* with fdopen().
  • End_Of_File for data returned by getc() is simply EOF and c must have type int for end of file testing to be reliable.
  • reallocating the array one byte at a time is inefficient and might be more wasteful than reallocating by chunks
  • more importantly you might want to allocate one extra byte for a null terminator if you intend to use this buffer as a C string.
  • the output of the system() command will be limited to the size of the system pipe buffers, usually around 5KB, so your program will get stuck for any larger output.
  • it is much simpler to use popen() for your purpose.

Here is a simplified version:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char code[] = "ls -lR";
    char *buf = NULL;
    int c;
    int i = 0;
    FILE *fp;

    fp = popen(code, "r");
    if (fp == NULL) {
        fprintf(stderr, "popen error\n");
        return 1;
    }
    while ((c = getc(fp)) != EOF) {
        buf = (char *)realloc(buf, i + 2);
        if (buf == NULL) {
            fprintf(stderr, "out of memory\n");
            pclose(fp);
            return 1;
        }
        buf[i++] = (char)c;
    }
    pclose(fp);
    printf("output: %d bytes\n", i);
    if (buf != NULL) {
        buf[i] = '\0';
        fputs(buf, stdout);
    }
    free(buf);        
    return 0;
}
Related