Message-ID: From: Michel de Ruiter To: "'DJGPP workers'" Subject: setmode problem Date: Tue, 6 Apr 1999 11:27:45 +0200 X-Mailer: Internet Mail Service (5.5.2448.0) Reply-To: djgpp-workers AT delorie DOT com 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 #include #include 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 #include #include +#include #include #include @@ -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.