Xref: utzoo comp.sys.ibm.pc.programmer:2288 alt.msdos.programmer:1834 Path: utzoo!attcan!uunet!mailrus!usenet.ins.cwru.edu!cwlim!trier From: trier@cwlim.CWRU.EDU (Stephen C. Trier) Newsgroups: comp.sys.ibm.pc.programmer,alt.msdos.programmer Subject: Re: Redirecting to/from spawnxx()ed program? Summary: Step-by-step instructions Keywords: redirect stdin/stdout Message-ID: <1990Jul7.040141.23830@usenet.ins.cwru.edu> Date: 7 Jul 90 04:01:41 GMT References: <49978@iuvax.cs.indiana.edu> <1990Jul7.035730.23379@usenet.ins.cwru.edu> Sender: news@usenet.ins.cwru.edu Reply-To: sct%seldon@scl.cwru.edu Followup-To: alt.msdos.programmer Organization: Case Western Reserve Univ. Cleveland, Ohio, (USA) Lines: 77 To understand what the sample program someone has already posted does, examine the MS-DOS dup(), dup2(), and spawn() calls. The key to making redirection work is that the spawn() call passes the currently open stdin, stdout, and stderr handles to its child. Therefore, all that a redirection must do is to change those three handles to point to the proper alternate devices, do the spawn, and change the handles back. The first step in doing this is to save the current values of the standard handles somewhere safe. This is where dup() comes in. For example, #define STDIN 0 old_stdin = dup(STDIN); This code creates a new handle with exactly the same attributes as the current stdin and stores its number in the variable old_stdin. Note that since we're dealing with low-level I/O instead of with C's high-level functions, all of these calls deal with numerical handles instead of FILE *'s. new_stdin = open(filename, O_RDONLY); This line is straightforward enoguh; note that I'm using open, not C's freopen, since freopen changes the C stdin file pointer. It is _not_ guaranteed to change the underlying MS-DOS stdin handle. dup2(new_stdin, STDIN); This is the critical line, the one that actually does the redirection. It forces handle number STDIN to point to the same file as new_stdin. spawnlp("program", ...); Use whatever version of spawn is needed; they all treat redirection in the same manner. dup2(old_stdin, STDIN); This dup2 line "undoes" the redirection, returning the MS-DOS stdin handle to whatever it originally was. close(new_stdin); Don't forget to close the redirected file; otherwise you'll quickly face the MS-DOS 20-file limit! :-) And that's all it takes to do input redirection. If you want to add output or error redirection, just add a line with "stdout" or "stderr" for every line of "stdin" above. The description seems long, but it's only 7 lines of C. There's also a library function to do some I/O redirection, borrowed from Unix. It's called popen(), for "pipe open". popen() allows you to use the C I/O library (fgets, fputs, and so on) to read or write to a pipe to a child program. I found two implementations of popen() in the comp.sources.misc archives. I also wrote a simplified version for smail/PC. I'd be happy to mail copies of the functions; just ask. #include main() { FILE *fp; fp = popen("smail sct", "w"); fprintf(fp, "Hello, world!\n"); pclose(fp); } And presto! The first program in K&R moves into the e-mail era. -- Stephen Trier Case Western Reserve University Home: sct%seldon@scl.cwru.edu Information Network Services Work: trier@cwlim.ins.cwru.edu I do _not_ speak for the University.