[net.micro.pc] I/O Redirection in DOS 2.x

dag@tellab2.UUCP (Donald Graft) (06/19/84)

*

The response from markz@microsoft is very exciting.  It suggests that
DOS 2.x's I/O redirection mechanism may actually be usable for filter
applications.  However, there are a few problems and unanswered questions
in the response.

> I believe that all I/O system calls do support redirection without
> "haphazardness".

> Tabs are *only* expanded for the CPM-compatible system calls.  Handle-based
> calls output tabs.

> Old CPM-style calls ... were made to read up to eof and hang....If ISV's
> will make use of the new handle-based system calls, they will find that I/O
> is handled in a uniform manner.

It seems to me that the second and third quotes above refute the first.  What
markz@microsoft is saying is "Sorry folks, there is a class of calls that do
not properly (or fully) support redirection.  You should not use these calls."
You will look in vain for such a statement in the DOS manual.  The closest I
can find is "we recommend using the new calls."  In fact the manual implies
the opposite.  "You can easily add your own filter to the filters that have
been supplied; just write a program that reads its input from the standard
input device, and writes its output to the  standard output device."
Also, "Note: If an application does not use DOS function calls to perform
standard input and/or output (for example you put text directly into the
video buffer), then filters will not work for that application."  There is
nothing here that suggests that a subset of calls won't work properly with
redirection.  Had I been aware of the distinction between "CPM-style" and
"new" calls, I would have saved a lot of wheel spinning.  markz@microsoft
does not define "CPM-style calls" but I'll assume he means calls other than
2F through 57 (the "new calls").

Given this new information, I will try again to implement an acceptable
filter using DOS 2.x's redirection.  Perhaps markz@microsoft would be
willing to help in this endeavor.

As far as the MORE filter is concerned, I have located my disassembly and
I still have questions.  I will give the disassembly and then my questions.
(I've used a "pseudo" assembly language in which all numbers are hex.)

MORE.ASM
--------

START	MOV	AH,30			;get DOS version
	INT	21
	XCHG	AL,AH
	CMP	AX,0200			;test for DOS 2.0
	JNB	L1
	MOV	DX,ERRMSG		;print error message
	MOV	AH,09
	INT	21
	INT	20			;exit
L1	MOV	BYTE PTR [LINES],19	;number of lines per screen
	MOV	AH,0F			;get video parameters
	INT	10
	MOV	[COLS],AH		;number of columns
	MOV	DX,ERRMSG+1B		;print CR-LF
	MOV	AH,09
	INT	21
	XOR	BX,BX			;duplicate stdin handle
	MOV	AH,45
	INT	21
	MOV	BP,AX			;BP is new stdin handle
	MOV	AH,3E			;close original stdin
	INT	21
	MOV	BX,0002			;duplicate stderr
	MOV	AH,45
	INT	21
L11	CLD				;set increment for strings
	MOV	DX,BUFFER		;point to read buffer
	MOV	CX,1000			;read 4K bytes from stdin
	MOV	BX,BP
	MOV	AH,3F
	INT	21
	OR	AX,AX			;if EOF, quit
	JNZ	L2
L3	INT	20
L2	MOV	CX,AX			;save number of bytes read
	MOV	SI,DX			;point to read buffer
L10	LODSB
	CMP	AL,1A			;if *ptr = ^Z, quit
	JZ	L3
	CMP	AL,0D			;if *ptr = \r
	JNZ	L4
	MOV	BYTE PTR [COL_CNT],01	;	reset column count to 1
	JMP	PRINT			;	print \r
L4	CMP	AL,0A			;if *ptr = \n
	JNZ	L5
	INC	BYTE PTR [LINE_NO]	;	increment line count
	JMP	PRINT			;	print \n
L5	CMP	AL,08			;if *ptr = ^H
	JNZ	L6
	CMP	BYTE PTR [COL_CNT],01	;	if column 1, print ^H
	JZ	PRINT
	DEC	BYTE PTR [COL_CNT]	;	not column 1, decrement
					;	column count and print ^H
	JMP	PRINT
L6	CMP	AL,09			;if *ptr = ^I
	JNZ	L7
	MOV	AH,[COL_CNT]		;get column count
	ADD	AH,07			;	add 7
	AND	AH,F8			;	mod 8
	INC	AH
	MOV	[COL_CNT],AH		;	adjust column count
	JMP	PRINT			;	print ^I
L7	CMP	AL,07			;if *ptr = ^G
	JZ	PRINT			;	print ^G
	INC	BYTE PTR [COL_CNT]	;*ptr = none of above, bump column
					;	count
	MOV	AH,[COL_CNT]		;at max. column?
	CMP	AH,[COLS]
	JBE	PRINT			;	if no, print the character
	INC	BYTE PTR [LINE_NO]	;	else increment line number and
					;		reset column count to 1
	MOV	BYTE PTR [COL_CNT],01
PRINT	MOV	DL,AL			;print *ptr to stdout
	MOV	AH,02
	INT	21
	MOV	AH,[LINE_NO]		;had 24 lines?
	CMP	AH,[LINES]
	JB	L8
	MOV	DX,MORE			;	yes, print "more" message,
	MOV	AH,09			;	clear stdin buffer, and wait
	INT	21			;	for char. to be typed, then
	MOV	AH,0C			;	print CR-LF
	MOV	AL,01
	INT	21
	MOV	DX,ERRMSG+1B
	MOV	AH,09
	INT	21
	MOV	BYTE PTR [LINE_NO],01	;	reset line number
	MOV	BYTE PTR [COL_CNT],01	;	reset column count
	DEC	SI
	INC	CX
L8	DEC	CX			;	no, decrement number read
	JZ	L9
	JMP	L10			;get next character from buffer
L9	JMP	L11			;refill buffer from stdin
LINES	DB	19			;lines/screen
COLS	DB	50			;number of columns
LINE_NO DB	1
COL_CNT DB	1
MORE	DB	0D,'-- MORE --','$'
ERRMSG  DB	'MORE: Incorrect DOS version',0D,0A,'$'
BUFFER	DB	0			;read buffer

END MORE.ASM
------------

And now for my questions:

1)  Why is it necessary to duplicate the original stdin and then close it?
    Why can't the original stdin file handle be used?  (I am an applications
    programmer and not a systems "boffin".  markz@microsoft implies that
    this is well-known and obvious.  Somebody please educate me.)

2)  The stderr handle is also duplicated but the original is not closed.
    Again, why is it necessary to duplicate the handle, and why is the
    original not closed as for stdin?  The new stderr handle is not saved
    and is not used.  What is going on here???

3)  MORE uses a "CPM-style" call for output (function 2).  Was this used
    to support control-S, control-Q, and control-BREAK?  Do the "new calls"
    support them?  Or was it used just to get tab expansion?

4)  > Magic? That sounds just like MORE on *NIX to me.

    I have looked at the source for more.c and can find no duplication 
    and closing of stdin.  What does markz@microsoft mean?

markz@microsoft also suggests that my C compiler is not using "new calls"
and that could be the source of my problems.  But the Desmet compiler
checks to see which version is running and then uses (or at least the
manual so claims) the 2.0-type calls.  This seems to be correct as path
names are correctly handled.

As I said, I will try again to implement an acceptable filter using the
Desmet compiler and the new information provided by markz@microsoft.
I will post an article giving the results as I think this is a topic of
general interest.  In the meantime, it would be helpful if markz@microsoft
could respond to the points raised here.

Filled with new hope,

...ihnp4!tellab1!tellab2!dag             Donald Graft

dag@tellab2.UUCP (Donald Graft) (06/26/84)

*
Our site was off the net for several days.  Could someone let
me know if there has been any further discussion or response from
markz@microsoft since my posting that contained the disassembly of
MORE.  Thanks.

...ihnp4!tellab1!tellab2!dag                 Donald Graft