[comp.sys.ibm.pc] MS-DOS puzzle #1

dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (04/22/89)

Here is a puzzle.  First read the question and answer.  Then solve
the puzzle that follows.

     Question:  Why does COMMAND.COM allow redirection of standard
     input and standard output, but not standard error?

     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
     therefore the MS-DOS command interpreter, unlike the
     UNIX shell, can't redirect standard error.

THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
does not, what is the real answer to the question?

I have an answer already, which I will post after a while.
-- 
Rahul Dhesi <dhesi@bsu-cs.bsu.edu>
UUCP:    ...!{iuvax,pur-ee}!bsu-cs!dhesi

mbb@cbnewsh.ATT.COM (martin.b.brilliant) (04/22/89)

From article <6893@bsu-cs.bsu.edu>, by dhesi@bsu-cs.bsu.edu (Rahul Dhesi):
>      Question:  Why does COMMAND.COM allow redirection of standard
>      input and standard output, but not standard error?
> 
>      Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>      therefore the MS-DOS command interpreter, unlike the
>      UNIX shell, can't redirect standard error.
> 
> THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
> does not, what is the real answer to the question?

No, it does not make any sense.  In the first place, there is no such
thing as "UNIX".   UNIX(R) is a trademark of AT&T.  There are UNIX
systems.  MS-DOS is not a UNIX system and never was one.  If MS-DOS can
redirect standard input and standard output without fork(), it could
also redirect standard error if the designers of MS-DOS wanted it to.

The real answer to the question is that the designers of MS-DOS thought
it would be good to allow redirection of standard input and standard
output, but that error messages should always go to the screen.  So
they wrote MS-DOS to direct all error messages to the screen.

M. B. Brilliant					Marty
AT&T-BL HO 3D-520	(201) 949-1858
Holmdel, NJ 07733	att!cbnewsh!mbb or mbb@cbnewsh.ATT.COM

Disclaimer: Opinions stated herein are mine unless and until my employer
	    explicitly claims them; then I lose all rights to them.

lfk@mbio.med.upenn.edu (Lee Kolakowski) (04/22/89)

mbb@cbnewsh.ATT.COM (martin.b.brilliant) writes:
> From article <6893@bsu-cs.bsu.edu>, by dhesi@bsu-cs.bsu.edu (Rahul Dhesi):
> >      Question:  Why does COMMAND.COM allow redirection of standard
> >      input and standard output, but not standard error?
> > 
> >      Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
> >      therefore the MS-DOS command interpreter, unlike the
> >      UNIX shell, can't redirect standard error.
> > 
> > THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
> > does not, what is the real answer to the question?
> No, it does not make any sense.  In the first place, there is no such
> thing as "UNIX".   UNIX(R) is a trademark of AT&T.
>
> The real answer to the question is that the designers of MS-DOS thought
> it would be good to allow redirection of standard input and standard
> output, but that error messages should always go to the screen.  So
> they wrote MS-DOS to direct all error messages to the screen.

First off, what filehandles are redirectable is just a matter of what
mechanisms the shell provides. It has nothing to do with MS-DOS the
underlying operating system, but instead with the most common shell
"command.com".

I know of at least two replacement shells which allow you to redirect
any file handle. MKS does it well with their shell, and Command-Plus
also allows this to happen. Command.com's authors did not create
redirectable filenos other than 0 and 1.

All you have to do is, given a command to redirect a file number
somewhere, dup that fileno to somewhere else.

Seems resonable to me. If you need that capablity, don't argue that it
can't be done, use the product that does it.


--

Frank Kolakowski 

=====================================================================
|lfk@mbio.med.upenn.edu                 ||      Lee F. Kolakowski   |
|kolakowski@mscf.med.upenn.             ||	Univ. of Penna.     |
|c/o jes@eniac.seas.upenn.edu		||	Dept of Chemistry   |
|kolakowski@c.chem.upenn.edu		||	231 South 34th St.  |
|bcooperman.kolakowski@bionet-20.arpa	||	Phila, PA 19104     |
|AT&T:	1-215-898-2927			||--------------------------|
|#include <litigate.h>			||      One-Liner Here!     |
=====================================================================

vg55611@ihuxy.ATT.COM (Gopal) (04/23/89)

In article <6893@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:

>     Question:  Why does COMMAND.COM allow redirection of standard
>     input and standard output, but not standard error?

I think the question really should be - why does MS-DOS allow stdin/stdout
redirection but not stderr ?  Command.com simply goes through DOS to do
the redirection (by playing with the filehandles etc.)

>     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>     therefore the MS-DOS command interpreter, unlike the
>     UNIX shell, can't redirect standard error.

I don't think MS-DOS has stderr defined.  I think at one point, a very early
point (DOS 1.00 ?), it didn't even have stdin and stdout defined, you only
had keyboard / display services.  Later, stdin and stdout were defined, and
the keyboard/display services were mapped to these.  At that time, they
could have added stderr services, but they didn't.

If application programs and compilers seem to have stderr, I am quite sure
that it is because they bypass DOS and use BIOS to write to the display
directly.

>THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
>does not, what is the real answer to the question?

Venu P. Gopal
UUCP:	att!ihuxy!vg55611
Internet: vg55611@ihuxy.att.com
BITNET: com%"vg55611@ihuxy.att.com"   or   com%"vg55611%ihuxy@research.att.com"
Silence those silent letters and save the world 500 million keystrokes a day.

rose@shorty.CS.WISC.EDU (Scott Rose) (04/23/89)

The lack of redirectability of standard error is indeed an unfortunate
feature of command.com.  For those times when it is desirable to perform
this redirection, Microsoft provides the "errout" command.  It comes with
MSC 5.x.  

It is fairly trival to write your own version of this command, by
the by, by making use of the spawn() and dup2() library functions or the
underlying MSDOS services.  Simply use dup2() to connect standard error
to standard output before spawning argv[1], with argv[2]...argv[argc-1]
as the argument vector.  This gives your executed program a little bit
less memory than it would have if you ran it right from the primary command
processor, but that's the only significant downside.  Keep the name of the 
new command short and you won't sacrifice much command line length.

vg55611@ihuxy.ATT.COM (Gopal) (04/23/89)

In article <2936@ihuxy.ATT.COM> I (rather hastily) wrote:

>>     Question:  Why does COMMAND.COM allow redirection of standard
>>     input and standard output, but not standard error?

>I think the question really should be - why does MS-DOS allow stdin/stdout
>redirection but not stderr ?  Command.com simply goes through DOS to do
>the redirection (by playing with the filehandles etc.)

I have to eat my own words, for Norton's book says that stderr is defined
in DOS (filehandle of 2) and he's usually right.  Perhaps redirection
of stderr was simply not implemented in command.com.  I wonder, though,
if applications really write to DOS stderr and not to BIOS.  I would still
guess that if stdin, stdout, stdprn etc. can be re-directed, stderr should
also be possible.

Venu P. Gopal
UUCP:	att!ihuxy!vg55611
Internet: vg55611@ihuxy.att.com
BITNET: com%"vg55611@ihuxy.att.com"   or   com%"vg55611%ihuxy@research.att.com"
Silence those silent letters and save the world 500 million keystrokes a day.

emb978@leah.Albany.Edu (Eric M. Boehm) (04/23/89)

It doesn't make any sense to me. It just happens that some unix shells
provide a consruction like ">&2" to redirect stderr. (Note that this is
a problem in csh). Command.com just doesn't happen to provide such a
construction. I can't see any reason why a substitute shell (a previous
response to this question mentioned 2 such shells) or a program couldn't
redirect stderr by using appropriate file descriptors (handles).

Eric M. Boehm
EMB978@ALBNY1VX.BITNET
EMB978@LEAH.ALBANY.EDU

cs3b3aj@maccs.McMaster.CA (Stephen M. Dunn) (04/23/89)

In article <6893@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:
>     Question:  Why does COMMAND.COM allow redirection of standard
>     input and standard output, but not standard error?

   As I understand it, when you say "<", MS-DOS closes file handle 0 (STDIN)
and then opens the file you specified.  Since it uses the lowest available
handle, it ends up redirecting STDIN.  Ditto for STDOUT redirection.  (This
explanation condensed from _Advanced MS-DOS_, Ray Duncan, Microsoft Press).

   Why can't you redirect STDERR (or, for that matter, STDAUX or STDPRN)?
Because they didn't write in a facility as in *NIX so that you could
specify the handle number to be redirected.  Why?  Probably because they
(read the powers that be at Microsoft, not the guys who coded it) figured
there wasn't enough demand for this feature to justify writing it.

   I can't see that it would take that much extra code to implement *NIX-
style redirection of any handle, but to be honest, I've never needed to
redirect anything other than STDIN or STDOUT (I'm not saying there's no
need to do so, just that I've never needed to do so).

-- 
======================================================================
! Stephen M. Dunn, cs3b3aj@maccs.McMaster.CA ! DISCLAIMER:           !
! Goddamn exams!  I hate them!  I hate them! ! I'm only an undergrad !
======================================================================

nelson@sun.soe.clarkson.edu (Russ Nelson) (04/23/89)

In article <2936@ihuxy.ATT.COM> vg55611@ihuxy.ATT.COM (Gopal) writes:

   In article <6893@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:

   >     Question:  Why does COMMAND.COM allow redirection of standard
   >     input and standard output, but not standard error?

   I think the question really should be - why does MS-DOS allow stdin/stdout
   redirection but not stderr ?  Command.com simply goes through DOS to do
   the redirection (by playing with the filehandles etc.)

In some sense you are right.  However, when command.com gets control via a
critical error interrupt, it fiddles with the undocumented Process Handle
Table at offset $18 in the Program Header.  So I would say that, because
command.com also does critial error handling, it does *not* go through
DOS.
--
--russ (nelson@clutx [.bitnet | .clarkson.edu])
America -- Socialism for the rich people, Capitalism for the rest of us.
	-- Michael Harrington, Co-Chair, Democratic Socialists of America

Ralf.Brown@B.GP.CS.CMU.EDU (04/23/89)

In article <2936@ihuxy.ATT.COM>, vg55611@ihuxy.ATT.COM (Gopal) writes:
}I don't think MS-DOS has stderr defined.  I think at one point, a very early
}point (DOS 1.00 ?), it didn't even have stdin and stdout defined, you only
}had keyboard / display services.  Later, stdin and stdout were defined, and
}the keyboard/display services were mapped to these.  At that time, they
}could have added stderr services, but they didn't.

There is indeed a stderr.  MSDOS opens five standard handles for a process:
      0 is stdin  (default CON)
      1 is stdout (default CON)
      2 is stderr (default CON)
      3 is stdaux (default AUX or COM1)
      4 is stdprn (default PRN or LPT1)

Whoever was responsible for COMMAND.COM simply decided not to implement
stderr, stdaux, or stdprn redirection.  stdaux is useless, though, since
it uses the unusable ROM BIOS serial port "services".

}If application programs and compilers seem to have stderr, I am quite sure
}that it is because they bypass DOS and use BIOS to write to the display
}directly.

No, they can use file handle 2, just like under Un*x.  I use stderr all the
time for error messages.
--
UUCP: {ucbvax,harvard}!cs.cmu.edu!ralf -=-=-=- Voice: (412) 268-3053 (school)
ARPA: ralf@cs.cmu.edu  BIT: ralf%cs.cmu.edu@CMUCCVMA  FIDO: Ralf Brown 1:129/31
			Disclaimer? I claimed something?
	You cannot achieve the impossible without attempting the absurd.

cs3b3aj@maccs.McMaster.CA (Three More Exams) (04/24/89)

In article <2936@ihuxy.ATT.COM> vg55611@ihuxy.UUCP (55421-Gopal,V.P.) writes:
>I don't think MS-DOS has stderr defined.  I think at one point, a very early
>point (DOS 1.00 ?), it didn't even have stdin and stdout defined, you only
>had keyboard / display services.  Later, stdin and stdout were defined, and
>the keyboard/display services were mapped to these.  At that time, they
>could have added stderr services, but they didn't.
>If application programs and compilers seem to have stderr, I am quite sure
>that it is because they bypass DOS and use BIOS to write to the display
>directly.

   Some correct points, some incorrect ones.  Dos 1.* did not support any
form of redirection (it didn't have the "handle" concept at that point ...
all file I/O was done with file control blocks, and I/O to the console,
AUX, etc. was done with specific DOS calls cloned from CP/M).

   DOS 2.* and up added file handle support, and define five handles which
your program automatically receives:
   0:  Standard input, CON by default
   1:  Standard output, CON by default
   2:  Standard error, always connected to CON
   3:  Auxiliary, usually connected to COM1
   4:  List device (PRN), usually connected to LPT1

   So DOS _does_ have stderr, and if you write a C program which outputs
to stderr it will work without the compiler having to translate your output
statements into BIOS calls.
--
======================================================================
! Stephen M. Dunn, cs3b3aj@maccs.McMaster.CA ! DISCLAIMER:           !
! I always wanted to be a lumberjack! - M.P. ! I'm only an undergrad !
======================================================================

tjr@cbnewsc.ATT.COM (thomas.j.roberts) (04/24/89)

From article <238@cbnewsh.ATT.COM>, by mbb@cbnewsh.ATT.COM (martin.b.brilliant):
> From article <6893@bsu-cs.bsu.edu>, by dhesi@bsu-cs.bsu.edu (Rahul Dhesi):
>>      Question:  Why does COMMAND.COM allow redirection of standard
>>      input and standard output, but not standard error?
>> 
>>      Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>>      therefore the MS-DOS command interpreter, unlike the
>>      UNIX shell, can't redirect standard error.
> 
> The real answer to the question is that the designers of MS-DOS thought
> it would be good to allow redirection of standard input and standard
> output, but that error messages should always go to the screen.  So
> they wrote MS-DOS to direct all error messages to the screen.

It's even worse than that (!) - you CAN redirect file-descriptor 2 in
a program that then EXECs another program. Unfortunately, some programs
put error messages onto file-descriptor 2, and some put them directly
onto the screen. The "designers" (:-^) of MS-DOS decided NOT to standardize
how error messages are presented.

	[IMHO that was a very arrogant attitude on their part, and is merely 
	 one instance of why MS-DOS is so difficult to do serious applications
	 in (e.g. look at the TSR mess)].

Tom Roberts
att!ihnet!tjr

davidr@hplsla.HP.COM (David M. Reed) (04/25/89)

I do not know why MicroSoft did not implement filehandle re-direction so
that the user could re-direct I/O other than stdin and stdout.  To me it
is another example of MS-DOS being brain-dead, and one of the reasons I
prefer to use the MKS Korn-shell.

Recently we had need (again) for this capability of directing stderr to a
file.  The program a user was running here would encounter an error, write
the message to stdout, and then the program would end with a clear screen
action!  Insufficient time to read the message.  (One really had to be 
watching the screen to even see that what looked like an error message
had been flashed to the screen.  And since this program was typically
auto-running for about 45 minutes of number crunching before it go to the
error, the user was not typically watching the screen.)  So I started up
the program for him under the MKS shell with stderr being sent to a file,
and, wonder of wonders, the next time the program aborted we had the error
message neatly captured in a file!

psfales@ihlpb.ATT.COM (Fales) (04/25/89)

In article <2535@maccs.McMaster.CA>, cs3b3aj@maccs.McMaster.CA (Three More Exams) writes:
> 
>    DOS 2.* and up added file handle support, and define five handles which
> your program automatically receives:
>    0:  Standard input, CON by default
>    1:  Standard output, CON by default
>    2:  Standard error, always connected to CON
>    3:  Auxiliary, usually connected to COM1
>    4:  List device (PRN), usually connected to LPT1
> 
>    So DOS _does_ have stderr, and if you write a C program which outputs
> to stderr it will work without the compiler having to translate your output
> statements into BIOS calls.


Score one more for the MKS toolkit.  I never realized that it could do this,
until someone pointed it out recently, but I just tried it and it works:  
you can redirect stderr, stdprn (and presumably stdaux) from the MKS shell, 
using exactly the the same syntax you would on a *NIX system.
i
n
e
w
s

f
i
l
l
-- 
Peter Fales			AT&T, Room 5B-414
				2000 N. Naperville Rd.
UUCP:	...att!ihlpb!psfales	Naperville, IL 60566
Domain: psfales@ihlpb.att.com	work:	(312) 979-8031

feg@clyde.ATT.COM (Forrest Gehrke) (04/25/89)

In article <552@cbnewsc.ATT.COM>, tjr@cbnewsc.ATT.COM (thomas.j.roberts) writes:
> 
> 	[IMHO that was a very arrogant attitude on their part, and is merely 
> 	 one instance of why MS-DOS is so difficult to do serious applications
> 	 in (e.g. look at the TSR mess)].

To what extent Microsoft is responsible for the "TSR mess", I can
not say.  They have a very good and full explanation of how to
program TSR's in their Encylopedia.  However, most of the what
you call the TSR mess is due to poor programming.

Forrest Gehrke
 

alex@mks.UUCP (Alex White) (04/26/89)

In article <10309@ihlpb.ATT.COM> psfales@ihlpb.ATT.COM (Fales) writes:
>In article <2535@maccs.McMaster.CA>, cs3b3aj@maccs.McMaster.CA (Three More Exams) writes:
>Score one more for the MKS toolkit.  I never realized that it could do this,
>until someone pointed it out recently, but I just tried it and it works:  
>you can redirect stderr, stdprn (and presumably stdaux) from the MKS shell, 
>using exactly the the same syntax you would on a *NIX system.

Actually, you can even better than this.
Since nobody actually ever uses, or cares about stdprn or stdaux, 
my profile.ksh file starts with:
	exec 3<&-
	exec 4<&-
which CLOSES stdprn and stdaux, leaving all programs with an extra
2 file descriptors.
Yes, I agree, its a grotesque non-intuitive command to use.
However, it is useful.
You can also do things like
	exec 2>errors
and then all error messages after that point would go to the file `errors'.

lfk@mbio.med.upenn.edu (Lee Kolakowski) (04/27/89)

Also you can install a device driver for say a tektronics emulation, such as
PC plot. I made this device driver named TEK.
Then you can say 
	exec < CON > TEK

And then from then on you are using the TEK device for your console driver


--

Frank Kolakowski 

=====================================================================
|lfk@mbio.med.upenn.edu                 ||      Lee F. Kolakowski   |
|kolakowski@mscf.med.upenn.             ||	Univ. of Penna.     |
|c/o jes@eniac.seas.upenn.edu		||	Dept of Chemistry   |
|kolakowski@c.chem.upenn.edu		||	231 South 34th St.  |
|bcooperman.kolakowski@bionet-20.arpa	||	Phila, PA 19104     |
|AT&T:	1-215-898-2927			||--------------------------|
|#include <litigate.h>			||      One-Liner Here!     |
=====================================================================

ralf@b.gp.cs.cmu.edu (Ralf Brown) (04/27/89)

In article <45133@clyde.ATT.COM> feg@clyde.ATT.COM (Forrest Gehrke) writes:
}To what extent Microsoft is responsible for the "TSR mess", I can
}not say.  They have a very good and full explanation of how to
}program TSR's in their Encylopedia.  However, most of the what
}you call the TSR mess is due to poor programming.

Except that you are forgetting that people were writing TSRs for about five
years before the MS-DOS Encyclopedia (non-buggy version) was available.  If
MS had started right out with documentation such as the Encyclopedia, and
pushing for a standard (such as TeSseRact, which is used by a number of 
programs such as Borland's THELP.COM), things would be a lot less messy.
-- 
{harvard,uunet,ucbvax}!b.gp.cs.cmu.edu!ralf -=-=- AT&T: (412)268-3053 (school) 
ARPA: RALF@B.GP.CS.CMU.EDU |"Tolerance means excusing the mistakes others make.
FIDO: Ralf Brown at 129/31 | Tact means not noticing them." --Arthur Schnitzler
BITnet: RALF%B.GP.CS.CMU.EDU@CMUCCVMA -=-=- DISCLAIMER? I claimed something?
-- 

dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (07/11/89)

In article <6893@bsu-cs.bsu.edu> a long time ago I wrote:
>Here is a puzzle.  First read the question and answer.  Then solve
>the puzzle that follows.
>
>     Question:  Why does COMMAND.COM allow redirection of standard
>     input and standard output, but not standard error?
>
>     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>     therefore the MS-DOS command interpreter, unlike the
>     UNIX shell, can't redirect standard error.
>
>THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
>does not, what is the real answer to the question?
>
>I have an answer already, which I will post after a while.

Here is my answer, which I am posting "after a while" as promised.

Yes, the answer above does make a little sense.  It may not be the
complete reason why the MS-DOS command interpreter will redirect
standard output but not standard error.

If you have a fork() system call, you can redirect I/O as follows (some
details omitted):

     pid = fork();
     if (pid == 0) {		/* child */
	redirect file descriptors as needed;
	execute new program;
     } else {			/* parent */
	wait for child to exit;
     }

In the above scheme, only the file descriptors of the child process are
ever redirected.  The parent's fds are left completely untouched.

The MS-DOS command interpreter can't use fork().  In order to redirect
a file descriptor for a child process, it must redirect its own file
descriptor before the EXEC, and save the old file descriptor
somewhere.  One way of doing this is to use dup2() to create a
duplicate high-numbered fd.

So for example, it could save the current standard output fd (normally
1) as fd number 15, then close fd 1 and reopen it attached to a file
for output, and it has redirected standard output to go to a file.
Then the command interpreter executes the command as a subprocess using
the EXEC system call.  After the subprocess returns, it can do another
dup2() to get a duplicate of fd 15 into fd 1.  This restores the
original standard output.

But if it does this, then the new process has an extra open file handle
available to it, since EXEC duplicates all open files.  (MS-DOS has no
close-on-exec flag.)  This is risky.  A badly-designed program could
write garbage to fd 15 (which was not really supposed to be open at
all).

Perhaps the COMMAND.COM designer felt that enough was enough.  Even if
he had to supply extra fds to a subprocess that might mess with them
without knowing they were open, he wasn't about to let standard error
(which you absolutely HAVE to have to print error messages) get messed
up by a rogue subprocess.

There is another possibility.  Maybe COMMAND.COM uses some undocumented
feature of the MS-DOS kernel to redirect standard output.  Maybe they
only had enough bits left over in the PSP two handle two redirected fds
but not three.  It could be, for example, that COMMAND.COM first loads
the new program, then changes its PSP to the new PSP using an
"undocumented" system call, does the I/O redirection, and then jumps to
the new program.  For some undocumented reason, redirection of standard
error doesn't work (a bug in the undocumented system call, which is why
instead of documenting it in a later version, Microsoft created a new
one instead?).

The final possibility is that the COMMAND.COM designer didn't want to
take the risk of the standard error stream suddenly freezing.
When you initially open a device for output, it is in a mode in which
it stops accepting any further writes as soon as it sees a control Z.
(The original objective was apparently to prevent trailing garbage in
CP/M files showing up at odd times.)  It wouldn't do to let the
standard error stream freeze up like this, for then where would you
print error messages like "Stream frozen due to control-Z -- System
Halted"??  On earlier MS-DOS versions, the command

     echo ^Z

(that's a real control Z) produces an odd error message (try it).
It wouldn't do to not be able to print this odd message in case
somebody did something like

     echo 2>&1 ^Z

instead.

The above speculation may or may not be based on many facts, but it
*is* based surely on *one* important fact:  If it weren't for the
absence of fork(), we wouldn't even have to wonder why COMMAND.COM
won't redirect standard error.
-- 
Rahul Dhesi <dhesi@bsu-cs.bsu.edu>
UUCP:    ...!{iuvax,pur-ee}!bsu-cs!dhesi

richard@calvin.EE.CORNELL.EDU (Richard Brittain) (07/11/89)

In article <8167@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:
>
>In article <6893@bsu-cs.bsu.edu> a long time ago I wrote:
>>     Question:  Why does COMMAND.COM allow redirection of standard
>>     input and standard output, but not standard error?
>>
>>     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>>     therefore the MS-DOS command interpreter, unlike the
>>     UNIX shell, can't redirect standard error.
>>
>>THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
>>does not, what is the real answer to the question?
 ......
>The MS-DOS command interpreter can't use fork().  In order to redirect
>a file descriptor for a child process, it must redirect its own file
>descriptor before the EXEC, and save the old file descriptor
>somewhere.  One way of doing this is to use dup2() to create a
>duplicate high-numbered fd.
 ......
>But if it does this, then the new process has an extra open file handle
>available to it, since EXEC duplicates all open files.  (MS-DOS has no
>close-on-exec flag.)  This is risky.  A badly-designed program could
>write garbage to fd 15 (which was not really supposed to be open at
>all).
 ...... 
>Rahul Dhesi <dhesi@bsu-cs.bsu.edu>
>UUCP:    ...!{iuvax,pur-ee}!bsu-cs!dhesi

	This sounds like a C programmer thinking only in terms of the standard
way to handle things in C.  Since stderr defaults to the console every time
control returns to COMMAND.COM, why bother preserving the state with a dup'd
file handle - just reopen it to the redirected file, then later close and
reopen to the console.  Even if stderr were pointing at a file when you
wanted to redirect it, you would only need to remember the file name and
offset to retore later on - there is no need to keep a spare file handle
open in the meantime.  
	It seems to me to be purely a design decision not to allow stderr to be
redirected by the "default" shell, although there is no reason why a
replacement shell could not do so (like ksh in the MKS toolkit).  I work
on a non-unix system a lot of the time (Harris VOS) in which there is a
definite design decision to make it very hard (though not quite impossible)
to redirect stderr.
	Also, note that the latest DOS has a child inherit/not inherit attribute
on handles if sharing is used, so actually the dup method could then be
used safely.

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

ho@fergvax.unl.edu (Michael Ho) (07/11/89)

From article <8167@bsu-cs.bsu.edu>, by dhesi@bsu-cs.bsu.edu (Rahul Dhesi):
> 
> In article <6893@bsu-cs.bsu.edu> a long time ago I wrote:
>>
>>     Question:  Why does COMMAND.COM allow redirection of standard
>>     input and standard output, but not standard error?
>>
>>     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
>>     therefore the MS-DOS command interpreter, unlike the
>>     UNIX shell, can't redirect standard error.
>>
>>THE PUZZLE.  Does the above make any sense?  If it does, why?  If it
>>does not, what is the real answer to the question?
>>

Why can't MS-DOS just redirect all three file handles, and after the
command is complete, do this:

	close(2);
	open ("CON", O_WRITE);  { this could be wrong;  I haven't done
	fdup (2, 1);                medium-level I/O in a while     }
	close (0);
	open ("CON", O_READ);

After all, CON is like /dev/tty in Unix, isn't it?  It's always there, and
never goes away.  Any program which wants a piece of the terminal can open
CON, so why not COMMAND?  Or am I just being naive?
---
	... Michael Ho, University of Nebraska    <ho@fergvax.unl.edu>

dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (07/12/89)

In article <1171@calvin.EE.CORNELL.EDU> richard@calvin.spp.cornell.edu
(Richard Brittain) writes:
>Since stderr defaults to the console every time
>control returns to COMMAND.COM, why bother preserving the state with a dup'd
>file handle...

Ah, but the reason why stderr defaults to the console every time
is precisely because currently stderr cannot be redirected.

Consider the following hypothetical command in a new enhanced MS-DOS,
which allows redirection of stderr with the >* notation:

	  command >* errors.out < commands.txt

We are invoking a new copy of COMMAND.COM and making its stderr go to
the file errors.out.  This new COMMAND.COM cannot just reopen the
console for its standard error stream.
-- 
Rahul Dhesi <dhesi@bsu-cs.bsu.edu>
UUCP:    ...!{iuvax,pur-ee}!bsu-cs!dhesi

ralf@b.gp.cs.cmu.edu (Ralf Brown) (07/12/89)

In article <1171@calvin.EE.CORNELL.EDU> richard@calvin.spp.cornell.edu (Richard Brittain) writes:
}In article <8167@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes:
}>
}>In article <6893@bsu-cs.bsu.edu> a long time ago I wrote:
}>>     Question:  Why does COMMAND.COM allow redirection of standard
}>>     input and standard output, but not standard error?
}>>
}>>     Answer:  MS-DOS, unlike UNIX, doesn't have a fork() system call;
}>>     therefore the MS-DOS command interpreter, unlike the
}>>     UNIX shell, can't redirect standard error.
} ......
}>The MS-DOS command interpreter can't use fork().  In order to redirect
}>a file descriptor for a child process, it must redirect its own file
}>descriptor before the EXEC, and save the old file descriptor
}>somewhere.  One way of doing this is to use dup2() to create a
}>duplicate high-numbered fd.
} ......
}>But if it does this, then the new process has an extra open file handle
}>available to it, since EXEC duplicates all open files.  (MS-DOS has no
}>close-on-exec flag.)  This is risky.  A badly-designed program could
}>write garbage to fd 15 (which was not really supposed to be open at
}>all).
} ...... 
}	This sounds like a C programmer thinking only in terms of the standard
}way to handle things in C.  Since stderr defaults to the console every time
}control returns to COMMAND.COM, why bother preserving the state with a dup'd
}file handle - just reopen it to the redirected file, then later close and
}reopen to the console.  Even if stderr were pointing at a file when you
}wanted to redirect it, you would only need to remember the file name and
}offset to retore later on - there is no need to keep a spare file handle
}open in the meantime.  
.
First, stderr does not necesarily refer to the console--I have a program to
redirect standard error, and if I use it to run COMMAND.COM on a batch file,
having COMMAND unilaterally change stderr to the console after executing a
command with redirection would defeat this (same thing goes for stdin and
stdout--you can run a COMMAND with them redirected and re-redirect them in
a batch file).  Secondly, the file name is not necesarily available.  If
another program did the redirection before spawning COMMAND, the name will
be inaccessible.

Note that the CTTY command is functionally equivalent to running another copy
of COMMAND.COM with both input and output redirected to the specified device.
	CTTY COM1   <==>   COMMAND <COM1 >COM2
.
}	Also, note that the latest DOS has a child inherit/not inherit attribute
}on handles if sharing is used, so actually the dup method could then be
}used safely.

But note that setting the attribute is only available on OPEN, not on DUP or
DUP2....  Unless the program redirecting std{in,out,err} opens the
un-redirected handle to begin with, it can't make the file uninheritable.
And if it did make it uninheritable, un-redirected output would require a DUP
anyway, since the original handle couldn't be passed to the child.

What can be done, however, (and this works for DOS 2 and up), is to copy the
appropriate entries in the Process File Table in the PSP, zap them to FFh
(unused), do the EXEC, and then restore the entries.  While the child will
then get the same handle number on opening a file, it will refer to a
different file (the above is what the no-inherit attribute does, anyway--it
zaps the uninheritable handles in the child's PFT to FFh).
-- 
{harvard,uunet,ucbvax}!b.gp.cs.cmu.edu!ralf -=-=- AT&T: (412)268-3053 (school)
ARPA: RALF@CS.CMU.EDU     |"The optimist is the kind of person who believes a
FIDO: Ralf Brown 1:129/46 | housefly is looking for a way out."--Geo.J.Nathan
BITnet: RALF%CS.CMU.EDU@CMUCCVMA -=-=-=-=-=- DISCLAIMER? I claimed something?

toma@tekgvs.LABS.TEK.COM (Tom Almy) (07/13/89)

In article <5486@pt.cs.cmu.edu> ralf@b.gp.cs.cmu.edu (Ralf Brown) writes:
>What can be done, however, (and this works for DOS 2 and up), is to copy the
>appropriate entries in the Process File Table in the PSP, zap them to FFh
>(unused), do the EXEC, and then restore the entries.  While the child will
>then get the same handle number on opening a file, it will refer to a
>different file (the above is what the no-inherit attribute does, anyway--it
>zaps the uninheritable handles in the child's PFT to FFh).

Right on!  I was working on a large programming environment that needed
to EXEC arbitrary programs (or a DOS shell), with the ability to redirect
stdin, stdout, and stderr.  I did a variation of Ralf's scheme:
1. Save entire PFT (it's not that big!)
2. Set entries above the std* ones to FFh (effectively temprarily closes
   my programs files, without DOS overhead, but requiring a larger FILES=
   spec in config.sys).
3. Set to 0FFh and then open each redirected std*, one at a time.  Since
   the open command uses the lowest numbered free descriptor, this works
   well.
4. EXEC the program
5. Do a close on each redirected std*.
6. Restore PFT from saved copy.

Was that easy enough?  Much simpler than the contortions in UNIX with
those DUP2s! There certainly is no reason COMMAND.COM couldn't
do it.  And fork() has nothing to do with it.

Tom Almy
toma@tekgvs.labs.tek.com
Standard Disclaimers Apply

maa@nbires.nbi.com (Mark Armbrust) (07/15/89)

In article <5565@tekgvs.LABS.TEK.COM> toma@tekgvs.LABS.TEK.COM (Tom Almy) writes:
>In article <5486@pt.cs.cmu.edu> ralf@b.gp.cs.cmu.edu (Ralf Brown) writes:
>>What can be done, however, (and this works for DOS 2 and up), is to copy the
>>appropriate entries in the Process File Table in the PSP, zap them to FFh
>
>1. Save entire PFT (it's not that big!)
>2. Set entries above the std* ones to FFh (effectively temprarily closes
>
>Was that easy enough?  Much simpler than the contortions in UNIX with
>those DUP2s! There certainly is no reason COMMAND.COM couldn't
>do it.  And fork() has nothing to do with it.

I prefer to use the dos calls to do the job since there is a dos version
dependancy when mucking directly with the jfn_table in the pdb.  

Starting with some version of dos between 2.11 and 3.2 (I only have these two 
handy to look at), jfn_table_length and jfn_table_pointer have been added to 
the pdb.  

pdb + 32h:	jfn_table_len	dw	?	; length of jfn table
pdb + 34h:	jfn_table_ptr	dd	?	; FAR pointer to jfn table

These are initialized to point to the jfn_table in the pdb, but can be changed
by an application to point to a larger jfn_table.  Starting in dos 3.3, there
is a documented dos call (int 21h, ah=67h) to do this!

-- 

Mark Armbrust
maa@nbires.nbi.com
maa@nbires.UUCP