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;
}
  • 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. – ThibautRenaux May 7 '15 at 22:13
  • I think its due to: unix.stackexchange.com/questions/25372/… – Raymond Bannan May 7 '15 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) – user3629249 May 8 '15 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. – G-Man May 8 '15 at 3:52
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
  • Thank you and everyone else for answering. I was suspecting it wasn't related to anything that I knew, but had to ask somehow. – Mmc Dispenser May 9 '15 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
    Why? Can you explain the logic of your answer? – HalosGhost May 8 '15 at 0:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.