views:

153

answers:

3

For a programming assignment, we have the following requirements:

  1. It needs to be a command-line program written in C.
  2. It needs to read text from a text document. However, we are to do this by using the Unix redirection operator < when running the program rather than having the program load the file itself. (So the program reads the text by pretending it's reading from stdin.)
  3. After reading the data from the file, the program is to poll the user for some extra information before doing its job.

After much research, I can't find a way to retrieve the "old" stdin in order to accomplish part (3). Does anybody know how or if this is even possible?

Technically part (3) is part of a bonus section, which the instructor probably didn't implement himself (it's very lengthy), so it's possible that this is not possible and it's an oversight on his part. However, I certainly don't want to jump to this conclusion.

+3  A: 

Which OS? On Linux the usual trick to accomplish this is to check if stderr is still connected to a tty:

if (isatty(2))

and if so, open a new reading file descriptor to that terminal:

new_stdin = open("/proc/self/fd/2", O_RDONLY);

then duplicate the new file descriptor to stdin (which closes the old stdin):

dup2(new_stdin, 0);

(If stderr has also been redirected, then isatty(2) will return false and you'll have to give up.)

caf
My understanding is that the final program only has to run on Linux, so this is probably a viable option, although I'd like to avoid OS-dependent tricks if I can. I'm awaiting an email response from the instructor for clarification on how we are supposed to do part (3) in conjunction with part (2).Nevertheless, this is a clever approach. Thanks for sharing!
Zach Conn
This isn't Linux-specific, see http://stackoverflow.com/questions/1441251/1441368#1441368 However, sambowry's suggestion is better.
ephemient
You can try stdout too - very often, stdin, stdout and stderr are all both readable and writable at the file descriptor level. Also, you could close the 'old stdin' before opening the new; the new open would use the lowest available file descriptor, which (funnily enough) is file descriptor 0 since you just closed the file that was open on it.
Jonathan Leffler
+5  A: 

On linux, i would open the controlling terminal /dev/tty.

sambowry
This is not Linux-only; this works on any POSIX system as long as the process has not been completely detached from the terminal.
ephemient
+1  A: 

If you run the program like this:

myprog 3<&0 < filename

then you get file descriptor 3 set up for you as a duplicate of stdin. I don't know if this meets the requirements of your assignment, but it might be worth an experiment.

Tim