5

Given the following code, why does cat only print the contents of the pipe after I've typed \n or CTRL+D? What are the conditions for cat to actually print what it read?

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

int main(void){
    int pid,p[2];
    char ch;
    pipe(p);
    if((pid=fork()) == -1){
        fprintf(stderr,"Error:can't create a child!\n");
        exit(2);
    }
    if(pid){
        close(p[0]);
        while((ch=getchar())!=EOF){
            write(p[1],&ch,1);
        }
        close(p[1]);
        wait(0);
    }else{
        close(p[1]);
        close(0);
        dup(p[0]);
        close(p[0]);
        execlp("cat","cat",NULL);
    }
    return 0;
}
4
  • If you try running cat on its own on the command line, you'll see it doesn't print anything until you press Return or Ctrl+D. That's the expected behavior. Commented May 7, 2015 at 22:13
  • I think its due to: unix.stackexchange.com/questions/25372/… Commented May 7, 2015 at 22:21
  • 1
    the returned value (which will only exist if execlp() fails ) needs to be passed to perror() and then call exit(-1) Commented May 8, 2015 at 0:05
  • 1
    For that matter, while ((ch=getchar()) != EOF) { write(1,&ch,1); } doesn't print anything until you press Return or Ctrl+D, either. Commented May 8, 2015 at 3:52

2 Answers 2

5

That has nothing to do with cat, pipes or buffering. Your "problem" is upstreams, at the terminal device.

If every character you enter at the keyboard in the terminal was available for reading by your application immediately and cat, then would you enter aBackspacebReturn, your application would read a then ^? then b then ^M, which is not what you want and is not what you get.

What you want and get is for it to read a^J instead.

You get that because in the default canonical mode, the terminal device driver (the tty line discipline) implements a line editor that lets you enter text and edit it (with limited capabilities), and the text you enter is only available for reading when you press Return.

To avoid that, you can tell the terminal device to leave that canonical mode. For instance, by doing stty raw, and you'll see your application and cat get the characters immediately, but probably the behaviour is not what you expect.

You'll also notice that for other types of input, like a pipe, characters are output as soon as they arrive as in :

(printf x; sleep 1; echo y) | that-command
1
  • Thank you and everyone else for answering. I was suspecting it wasn't related to anything that I knew, but had to ask somehow. Commented May 9, 2015 at 7:48
-2

follow this loop:

while((ch=getchar())!=EOF)
{
        write(p[1],&ch,1);
}

with:

char carriageReturn = 0x0D;
write( p[1], &carriageReturn, 1 );
1
  • 1
    Why? Can you explain the logic of your answer?
    – HalosGhost
    Commented May 8, 2015 at 0:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .