When you do cat file_name | ./a.out
the standard input of your program is tied to a pipe linking it to the output of cat
. Your program will never get to see the user input - the very stream from where it would arrive has been replaced by the aforementioned pipe.
Mind you, I suspect that with some horrible POSIX-specific trickery you may be able to reopen it going straight for the tty device, but it's just bad design. If you need to both read from a file and accept interactive user input just accept the file as a command line argument and use stdin to interact with the user.
Edit
This is an example of the Unix-specific kludges that one can attempt, assuming that the process still has a controlling terminal. After reading all the original stdin, I'm opening /dev/tty
(which is the controlling terminal of the process) and re-linking stdin
to it.
Disclaimer: this is for entertainment purposes only, don't do this for real.
#include <stdio.h>
#include <stdlib.h>
void die(const char *msg) {
fprintf(stderr, "%s\n", msg);
fputs(msg, stderr);
exit(1);
}
int main() {
/* Read all of stdin and count the bytes read (just to do something with it) */
int ch;
unsigned long count = 0;
while((ch = getchar())!=EOF) {
count++;
}
printf("Read %lu bytes from stdin\n", count);
/* Open the controlling terminal and re-link it to the relevant C library FILE *
* Notice that the UNIX fd for stdin is still the old one (it's
* surprisingly complex to "reset" stdio stdin to a new UNIX fd) */
if(freopen("/dev/tty", "r", stdin) == NULL) {
die("Failed freopen");
}
/* Do something with this newly gained console */
puts("How old are you?");
fflush(stdout);
int age = -1;
if(scanf("%d", &age)!=1) {
die("Bad input");
}
printf("You are %d years old\n", age);
return 0;
}
(previously I had a solution that checked if stderr
or stdout
were still consoles, which was even more of a kludge; thanks @rici for reminding me of the fact that POSIX has the concept of "controlling terminal", which is accessible through /dev/tty
)