[comp.sys.ibm.pc] i/o redirection in msdos

fredex@cg-atla.UUCP (Fred Smith) (12/12/89)

I have recently run into an issue where I need to DISABLE temporarily any
i/O redirection that may be in effect.

I have a program that allows the user to escape to a subhsell. If there is
currently any i/o redirection it is, of course, inherited by the child
shell. In this case, the only redirection that exists is that stdin may be
redirected to a file.

I have tried the following:

int old;
FILE * new;

...

old = dup(fileno(stdin));
new = freopen ("CON", "r", stdin);
/* stuff here to do the subhell */
stream = fdopen (old, "r");

At first sight, this all seems to work ok. I can go to a subshell and
all seems fine there, and I can return to my main program and all
still seems fine. However the SECOND time I try to do this to go
back to another subshell, the redirection is not un-done correctly,
in some way I have not been able to diagnose--the keyboard is
non-functional and I find I have to hit the hardware reset
button to get out of it.  After the first time this is done the
fdopen() call returns the same value that stdin had before doing
any of this stuff, which seems to make sense.

Obviously, I am doing something wrong here, but I don't see what it
is. Can any of the wizards out there shed some light on this ?? This
is on PC-DOS 3.3 and MSC 5.1. I would like a method which is not
dependent on any features which were unavailable before 3.0, i.e.,
one which will also work on DOS >= 2.0.

Thanks!

Fred Smith
uunet!samsung!cg-atla!fredex

richard@calvin.spp.cornell.edu (Richard Brittain) (12/13/89)

In article <8157@cg-atla.UUCP> fredex@cg-atla.UUCP (Fred Smith) writes:
>I have recently run into an issue where I need to DISABLE temporarily any
>i/O redirection that may be in effect.
...
>old = dup(fileno(stdin));
>new = freopen ("CON", "r", stdin);
>/* stuff here to do the subhell */
>stream = fdopen (old, "r");
...
>At first sight, this all seems to work ok. I can go to a subshell and
>all seems fine there, and I can return to my main program and all
>still seems fine. However the SECOND time I try to do this to go
>back to another subshell, the redirection is not un-done correctly,
>in some way I have not been able to diagnose--the keyboard is

I had some difficulty doing this in Turbo C 2.0 and finally suspected the
dup() or dup2() library functions.  I wrote my own (they are direct interfaces
to the dos services so they are very simple) and got the following to work.

	int inp, inp2;

	inp = dup(0);
	inp2 = open("CON", O_TEXT|O_RDONLY);
	dup2(0,inp2);

   system("your program here");

	close(inp2);
	dup2(0,inp);
	close(inp);

There was no way I ever got it to work using stream i/o functions only, but
you can always fdopen(0,"r").   I had another routine where I needed to save/
close/restore both stdin and stdout, and I found that the TC library routines
worked on one and failed on the other ( I can't remember which ). Now I use
my own but it is still something of a mystery.

Richard Brittain,                   School of Elect. Eng.,  Upson Hall   
                                    Cornell University, Ithaca, NY 14853
ARPA: richard@calvin.spp.cornell.edu	
UUCP: {uunet,uw-beaver,rochester,cmcl2}!cornell!calvin!richard

pipkins@qmsseq.imagen.com (Jeff Pipkins) (12/14/89)

It sounds like the problem may actually be with the way you are spawning
the child process.  There is a small bug in some versions of MS-DOS in
the EXEC function call that causes ALL the registers to be destroyed on
return, even the stack registers SS & SP.

    < Set up all other registers for EXEC call >
    < Save all registers here >
    Mov  CS:SaveSS, SS    ; Save SS in code segment.
    Mov  CS:SaveSP, SP    ; Save SP in code segment.
    Int  21h              ; Do the EXEC call
    CLI                   ; Compensate for bug in some early 8088s.
    Mov  SS, CS:SaveSS    ; Restore SS
    Mov  SP, CS:SaveSP    ; Restore SP
    < Stack is okay now.  Restore other registers.>

Some ancient MS-DOS manuscripts recommend calling DOS via a long
indirect call to your PSP at offset 50h.  It is best to NEVER DO THIS.
Always use the Int 21h method.

If you are using the MSC library functions to spawn it, I doubt you will
have to worry about this bug at all.  But since you didn't say, I
thought it would be worthwhile to post this for other unsuspecting
assembly-language programmers.

-Jeff
pipkins@imagen.com