Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read from pipe line by line in C

Tags:

c

stdout

stdin

pipe

How can I separate the lines which are coming from a pipe. In the pipe there is this text:

HALLO:500\n
TEST:300\N
ADAD
ADAWFFA
AFAGAGAEG

I want to separate the lines from the pipe because i want to save the values in variables.

Here is my c code:

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

#define BUFFERSIZE    1

int main(int argc, char **argv){
    unsigned char     buffer[BUFFERSIZE];
    FILE                         *instream;
    int                            bytes_read=0;
    int                            buffer_size=0;


    buffer_size=sizeof(unsigned char)*BUFFERSIZE;
    /* open stdin for reading */
    instream=fopen("/dev/stdin","r");

    /* did it open? */
    if(instream!=NULL){
        /* read from stdin until it's end */
        while((bytes_read=fread(&buffer, buffer_size, 1, instream))==buffer_size){
            fprintf(stdout, "%c", buffer[0]);
        }
    }
    /* if any error occured, exit with an error message */
    else{
        fprintf(stderr, "ERROR opening stdin. aborting.\n");
        exit(1);
    }

    return(0);
}

Is this the right way to read from pipe for the best line by line?

like image 322
bladepit Avatar asked Apr 23 '13 07:04

bladepit


People also ask

What does pipe () do in C?

The pipe function creates a pipe and puts the file descriptors for the reading and writing ends of the pipe (respectively) into filedes [0] and filedes [1] . An easy way to remember that the input end comes first is that file descriptor 0 is standard input, and file descriptor 1 is standard output.

What does read () do in C?

The read() function reads data previously written to a file. If any portion of a regular file prior to the end-of-file has not been written, read() shall return bytes with value 0. For example, lseek() allows the file offset to be set beyond the end of existing data in the file.

What does pipe () return?

pipe() creates a pipe, a unidirectional data channel that can be used for interprocess communication. The array pipefd is used to return two file descriptors referring to the ends of the pipe. pipefd[0] refers to the read end of the pipe. pipefd[1] refers to the write end of the pipe.


1 Answers

This is usually just called reading from stdin. The program shouldn't care whether the input is a pipe, a redirected file, or a keyboard.

fread will just read until the buffer is full. Use fgets to read a line.

Also the buffer size should be big enough to hold the line. For little one-off programs, you can just pick a number. Or there's a standard name BUFSIZ which gives you a pretty-big buffer. How big? Big enough. Really? Probably.

fgets will copy the newline character in the string unless the string fills up first. So you can test the last character to tell if the line was truncated or not. With reasonable inputs, that's not going to happen. But a more robust approach would allocate a larger buffer, copy the partial line, and call fgets again tp keep trying to get a complete line.

#include <stdio.h>

int main() {
    char buf[BUFSIZ];
    fgets(buf, sizeof buf, stdin);
    if (buf[strlen(buf)-1] == '\n') {
        // read full line
    } else {
        // line was truncated
    }
    return 0;
}

This gets you halfway to being protected from the dreaded buffer overflow problem. fgets will not write more than the size passed to it. The other half, as mentioned above, is doing something sensible with the possible partial lines that may result from unexpectedly long input lines.

like image 122
luser droog Avatar answered Nov 16 '22 00:11

luser droog