I've condensed my problem into the following code:
#include <stdio.h>
int main(){
char buffer[256];
printf("Enter input: ");
scanf("%s", buffer);
system("/bin/sh");
return 0;
}
If I run this program with user input, I get:
user@ubuntu:~/testing/temp$ ./main
Enter input: Test
$
With the last line being the shell that the program started.
But if I run the program with input coming from the pipeline:
user@ubuntu:~/testing/temp$ echo 'test' | ./main
Enter input: user@ubuntu:~/testing/temp$
The program doesn't seem to open the shell.
After some tinkering, I realized that if I did this:
user@ubuntu:~/testing/temp$ (python -c "print 'test'" ; echo 'ls') | ./main
a.out main main.c
Enter input: user@ubuntu:~/testing/temp
I was able to run the ls
command in the opened shell.
So, two questions:
- Why doesn't the shell open like it did in the first case?
- How can I deal with this? It's very inconvenient to have to decide what commands to run before running the program: I'd much rather have a shell where I can dynamically choose what commands to run.
Best Answer
In the first case,
stdin
is a terminal and the shell is interactive. It waits for your commands etc.In the second case
stdin
is a pipe, and the shell is non-interactive. Your program consumes the first line onstdin
(namely the stringtest\n
), then the shell tries to readstdin
and seesEOF
. It exits, because that's what programs that getEOF
on input are supposed to do.In the third case the shell again is non-interactive, for the same reason. Your
scanf()
consumes the first line onstdin
(i.e.test\n
), then the shell readsls
. The shell runsls
, tries to read more commands, seesEOF
, and exits.If by "dealing with it" you mean running an interactive shell when
stdin
is connected to a pipe, the solution is to use apty(7)
.