Search code examples
cpipedup2feof

Read an entire pipe - c


I've got some difficulties with this code. I need to get all the information from the pipe at its end. But, I get a segfault error.

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

int main(void){

    int tube[2];

    if(pipe(tube) == -1){
        perror("Erreur");
        exit(1);
    }

    dup2(tube[1],1);

    printf("Few lines \n");
    printf("of an undefined size. \n");

    while (!feof(tube[0])) {
        char temp = fgetc(tube[0]);
        printf("chaine : %c\n", temp);
    }

    return 0;
}

If you have an idea of how I can handle this problem, please explain.


Solution

  • The pipe function returns is pair of int file descriptors, not FILE ones. That means that you can use read, write, or close on them but neither fgetc, nor feof.

    In addition, while(!feof(file)) is (almost) always wrong, because the flag is set after an unsuccessfull read has reached the end of the file.

    And that is not all. You only get an EOF on the read end of a pipe when all descriptors on the write end are closed. So you must close or flush stdout to ensure that all characters have been written to the pipe, close the file descriptor 1 if you have not closed stdout, and close tube[1] which is still a file descriptor for the write end of the tube.

    So you can replace your while loop with:

    close(tube[1]);
    fclose(stdout);
    
    while (1) {
        char temp;
        if (read(tube[0], &temp, 1) < 1) break;
        fprintf(stderr, "chaine : %c\n", temp);
    }
    

    It fixes the SEGFAULT caused by using feof and fgetc on something that is not a FILE, and ensure a proper close of the write end of the file before reading its content to obtain a nice end of file condition.