Shell – cat into stdin then pipe into program keeps forked shell open, why

command lineinputpipeshell

I'm not sure what's going on but I've been trying to understand what is happening with the input and output. So here is my program.

#include <stdio.h>
#include <stdlib.h>
int main(){
    char pass[8];
    fgets(pass, 8, stdin);
    if (pass[1] == 'h'){
        printf("enter shell\n");
        system("/bin/bash");
        printf("leave shell\n");
    }
    return 0;
}

And here are some terminal commands. When I run it regularly, and input 'hh', the shell stays opened.

idkanything ~ $ ./a.out
hh
enter shell
bash-3.2$

Now I try to echo then pipe, but the shell closes immediately.

idkanything ~ $ echo "hh" | ./a.out
enter shell
leave shell

So now here is when it works:

idkanything ~ $ cat <(python -c 'print "hh"') - | ./a.out
enter shell
this work
/bin/bash: line 1: this: command not found
leave shell

But when I leave out the '-' for stdin, it does not work as in the shell closes immediately.

idkanything ~ $ cat <(python -c 'print "hh"') | ./a.out
enter shell
leave shell

When I have cat at the end here, it also works.

idkanything ~ $ (python -c 'print "hh"'; cat) | ./a.out
enter shell
this works
/bin/bash: line 1: this: command not found
leave shell

Can someone please explain what's going on? What specifically about the commands that work makes the shell stay open? Why does the shell only stay open for these commands and not for the other commands like echoing "hh" and then piping that in.

I believe it may have something to do with stdout.

Best Answer

For the cases where it "works", you are leaving a process running cat which is reading its standard input, which has not been closed. Since that is not (yet) closed, cat continues to run, leaving its standard output open, which is used by the shell (also not closed).

Related Question