[comp.unix.questions] "temporarily" redirecting stdin

dpaulso@relay.nswc.navy.mil (Dave Paulson) (12/15/89)

i have a program which wants to initialize itself by reading in a
configuration file.  a lex/yacc scanner/parser pair will handle the
reading of the config file.  now, the scanner that lex generates
gathers its tokens from stdin (a behavior i want to retain),
but i'll need to use stdin for my own purposes after the
initialization is complete.   

what i propose to do is summarized in the following pseudocode:

	stdin_save = dup(fileno(stdin));  /* stdin_save is an int */
	freopen("config.file","r",stdin); /* connect stdin to the config file*/
	yyparse();			  /* works ok, input comes from file */
	close(fileno(stdin));		  /* free stdin descriptor */
	dup(stdin_save);		  /* restore old stdin */
	
this doesn't work.  after the second dup(), reading stdin results
in EOF.  what have i overlooked?


-- 
Dave Paulson			Synetics / Naval Surface Warfare Center
dpaulso@relay.nswc.navy.mil	voice:	 (703) 663-2137

chris@mimsy.umd.edu (Chris Torek) (12/15/89)

In article <1989Dec14.185745.7465@relay.nswc.navy.mil>
dpaulso@relay.nswc.navy.mil (Dave Paulson) writes:
>	stdin_save = dup(fileno(stdin));  /* stdin_save is an int */
>	freopen("config.file","r",stdin); /* connect stdin to the config file*/
>	yyparse();			  /* works ok, input comes from file */
>	close(fileno(stdin));		  /* free stdin descriptor */
>	dup(stdin_save);		  /* restore old stdin */
>	
>this doesn't work.  after the second dup(), reading stdin results
>in EOF.  what have i overlooked?

A great deal.

This sort of `playing around behind stdio's back' is a bad idea.  You
can get it to work in one, two, or perhaps even a dozen implementations,
but there will always be a rogue out there that does things differently.

The best thing to do is note that lex reads not from stdin, but from
yyin, which is initialised to stdin as

	FILE *yyin = stdin, *yyout = stdout;

hence to read `config.file', simply say

	extern FILE *yyin;
	yyin = fopen("config.file", "r");
	if (yyin == NULL) {
		complain, etc.
		exit(1); /* or whatever */
	} else {
		(void) yyparse();	/* do we care if it accepts? */
		(void) fclose(yyin);	/* what do we do on error here?? */
	}

This is much safer than fooling with dup/close/dup sequences.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris