conan@vax1.acs.udel.EDU (Robert B Carroll) (04/22/89)
Once stdin is closed, how do you open it up again so that all the stdio functions(scanf, gets etc. etc. etc.) will work via a terminal keyboard? to explain it in more detail, my C program: 1) reads user info typed in from keyboard 2) does a freopen and acts like a file is now standard input 3) then i need to 'make' standard input be the keyboard so that i can get info typed in from the keyboard again. I'm an 'end-user', so i can't do any super user calls. any help would be most appreciated. i haven't solved step 3 yet. please send responses via email: -- conan@vax1.acs.udel.edu CONAN THE BARBARIAN
ugkamins@sunybcs.uucp (John Kaminski) (04/22/89)
The original post wanted to know how to reconnect the stdin to the terminal after it had been attached to a file, assumedly through redirection. What I just tried on a BSD system, and works: fclose(stdin); *stdin = *fopen("/dev/tty", "r"); The "*" before stdin is necessary because of the way stdin is defined in <stdio.h>. Another method that SHOULD work is akin to the way I've seen some shell code do it: close(0); dup2(0, open("/dev/tty", O_RDONLY, 0x700)); Of course, this doesn't check for a failed open() call. Also, I guess: close(0); dup(open("/dev/tty", O_RDONLY, 0x700)); SHOULD work. Note that any of read, write, or read/write should be OK, as well as many different file modes (last arg to open()).
chris@mimsy.UUCP (Chris Torek) (04/23/89)
In article <5414@cs.Buffalo.EDU> ugkamins@sunybcs.uucp (John Kaminski) writes: >The original post wanted to know how to reconnect the stdin to the terminal >after it had been attached to a file, assumedly through redirection. What I >just tried on a BSD system, and works: > > fclose(stdin); > *stdin = *fopen("/dev/tty", "r"); This is a horrible thing to do. (It does not work in some SysVs and SunOSes.) The original question indicated that the program was to read from stdin switch to an alternate file switch back to stdin and that this was all done from within a single C program being written by the questioner. The simplest approach is: main() { FILE *fp; read_commands(stdin); if ((fp = fopen(other_file, "r")) == NULL) ... error ... read_commands(fp); (void) fclose(fp); read_commands(stdin); } If the `switch to a file' is due to a particular command, read_commands() can maintain its own stack of files (possibly by being recursive). It is not a good idea to assign to or through any of the `standard' streams. Instead, declare your own pointer and make it point to one of the standard streams. There is nothing wrong with register FILE *fp = stdin; ... work with fp ... but there is with fileno(stdin) = expression; and the like. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
guy@auspex.auspex.com (Guy Harris) (04/23/89)
>The original post wanted to know how to reconnect the stdin to the terminal >after it had been attached to a file, assumedly through redirection. What I >just tried on a BSD system, and works: > > fclose(stdin); > *stdin = *fopen("/dev/tty", "r"); > >The "*" before stdin is necessary because of the way stdin is defined in ><stdio.h>. *Urk* while this may work, I don't think it's *guaranteed* to work. In most UNIX standard I/O implementations, a standard I/O stream is represented by a pointer to an object of type FILE (or of type "struct _iobuf", which FILE is a #define for). Said structure can be copied by assignment; you have to dereference said pointer to do so, which is why the "*" is needed. *However*, I don't know whether every standard I/O implementation in the world would work correctly if you copy one FILE object atop another one. There's a better way of doing this, namely to declare: FILE *input; and do your reading from "input" rather than "stdin". This means you have to use "getc(input)" rather than "getchar()", and the like. You first do input = stdin; and all reads from "input" come from the standard input. You then do input = fopen(file, "r"); and - assuming "fopen" doesn't return NULL, due to it being unable to open "file"; DON'T forget to check for this! - all reads from "input" will come from the file in question. Finally, you do fclose(file); input = stdin; which will close the file and make all reads from "input" come from the standard input again. One advantage of this is that, unlike schemes involving "/dev/tty", it will work even if you redirect your standad input away from your terminal; input will come from the file you redirected to, and then from the file opened by the program, and then go back to the file to which input was originally redirected.
carroll@s.cs.uiuc.edu (04/24/89)
Having already made myself look like an idiot on a related subject, I'll try again :-) I think you are looking at the problem backwards. You want to be able to read from several files, one of which happens to be stdin. I strongly suggest that you use generic file manipulations (e.g., fprintf, fgetc, etc.) on a global (FILE *). Then the solution is simple - init the global to stdin, later set it to the other file you want to read from, and then when you are done, set it back to stdin (which is still there). In fact, you could even write a set of stack routines that would allow you to "push" (FILE *)'s and retrieve them on EOF without little difficulty. We did this for a low level programming class - I can send you example code if you want. Alan M. Carroll "And then you say, carroll@s.cs.uiuc.edu We have the Moon, so now the Stars..." - YES CS Grad / U of Ill @ Urbana ...{ucbvax,pur-ee,convex}!s.cs.uiuc.edu!carroll
les@chinet.chi.il.us (Leslie Mikesell) (04/24/89)
In article <3398@udccvax1.acs.udel.EDU> conan@vax1.acs.udel.EDU (Robert B Carroll) writes: >Once stdin is closed, how do you open it up again so that >all the stdio functions(scanf, gets etc. etc. etc.) will work >via a terminal keyboard? to explain it in more detail, my C >program: >1) reads user info typed in from keyboard >2) does a freopen and acts like a file is now standard input >3) then i need to 'make' standard input be the keyboard so that > i can get info typed in from the keyboard again. One way is to dup(2) the original file descriptor to hold a copy before the freopen. To get it back, close(0); dup(copy);. There might be some problems with buffered input if you had not read to EOF on the alternate stream. Les Mikesell
gwyn@smoke.BRL.MIL (Doug Gwyn) (04/25/89)
In article <1495@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: >*However*, I don't know whether every standard I/O implementation in the >world would work correctly if you copy one FILE object atop another one. I can think of several ways in which it could fail, but in any case it's a bad idea because it "orphans" any resources that were previously associated with the stream.