Mail Archives: djgpp-workers/1999/04/06/05:26:11
Let me first note that I run MS-DOS 7.10 (Win98 without GUI). And that
this is quite a long message.
I noticed a problem with setting stdin (or stdout) to binary, if stdin
is connected to the terminal. It happened for instance with `zip':
C> zip > temp
A minimal C program having this problem is:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
int main(void)
{
setmode(0, O_BINARY); /* From (libc)setmode */
return getchar();
}
I know some programs first check isatty(stdin), but someone might want
to be able to type binary data (C-z, C-c, C-m and such) on the
terminal.
The computer freezes when getchar (or any other DOS input function) is
called, C-BREAK does not work, only C-M-DEL. Using 1 (stdout) or 2
(stderr) instead of 0 (stdin) shows exactly the same behaviour, as DOS
just changes the mode of the same `console' if no redirection is used.
I dug all the inner details out of libc, but at first it turned out to
be a problem in DOS itself. After translating things into assembly, I
was convinced it was DOS' fault. It just showed a blinking cursor
waiting for input, but reacted on nothing but C-M-DEL.
A bit more digging (also under the Win98 GUI, which has the same
problem), showed that it might be correct behaviour. The computer did
not `hang', but just waited for 512 key presses (the default buffer
size `_fillsize' in DJGPP).
Those keypresses were not echoed, and C-BREAK was not handled in a
special way (except that it emptied the input buffer, it seems).
Although libc.inf says "`Ctrl-Break' will still cause `SIGINT'", this
is not very useful as it is not delivered until DOS returns...
All problems disappeared when I set stdin to _IONBF (not buffered)
instead of _IOLBF (line buffered). At least, just one key press is
enough to let the C-BREAK through. Nothing is echoed, but should it?
So, to make a long story short, I would like to suggest the following
patch (please correct me if I am wrong!):
--- src/libc/dos/io/setmode.old Sun Apr 4 20:22:40 1999
+++ src/libc/dos/io/setmode.c Sun Apr 4 20:33:16 1999
@@ -6,6 +6,7 @@
#include <errno.h>
#include <fcntl.h>
#include <io.h>
+#include <stdio.h>
#include <libc/dosio.h>
#include <libc/ttyprvt.h>
@@ -47,6 +48,13 @@
{
errno = __doserr_to_errno(regs.x.ax);
return -1;
+ }
+ if ((newmode & 0x83) == 0x83 && isatty(0)) { /* Indicates console
*/
+ stdin->_flag &= ~(_IOFBF|_IOLBF|_IONBF);
+ if (newmode & 0x20)
+ stdin->_flag |= _IONBF;
+ else
+ stdin->_flag |= _IOLBF;
}
if (handle == 0)
__djgpp_set_ctrl_c(!(mode & O_BINARY));
This way, a user can type real binary data on the terminal and still
interrupt with C-BREAK, followed by another key. One thing that I do
not understand is why typing C-@ still prints "^C\r\n" in this mode,
most of the time to stdout. I think it is DOS as I can not find
anything in libc...
Hope this helps.
--
*Groeten, Michel* _http://www.cs.vu.nl/~mdruiter_
____________
\ /====\ / "You know, Beavis, you need things that suck,
\/ \/ to have things that are cool", Butt-Head.
- Raw text -