Date: Sun, 15 Mar 1998 16:42:23 +0200 (IST) From: Eli Zaretskii To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: ^Z in text-mode output to the screen Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk There's a problem in the current libc which I'd like to solve in v2.02. One of its consequences is the following lossage: C:\DJGPP\BIN> grep foobar * grep: writing output: No space left on device (ENOSPC) This happens if one of the files has the ^Z character embedded in it. This is caused by the assumption in the low-level libc functions which write data, that if you instruct DOS to write a buffer and DOS writes only part thereof, the reason is that the disk is full, and so they set errno to ENOSPC. This assumption breaks if the data is written to the console which hasn't been switched to raw mode (i.e., the I/O is done in text mode). DOS stops writing and returns prematurely when asked to write data with embedded ^Z characters to a character device in cooked mode. Here's the problem: DOS doesn't give any indication that would allow to distinguish between the disk full case and the ^Z case. The only thing we can do is to assume that if the handle points to a character device that's in cooked mode, we have the ^Z case. We can certainly do so in the case of the console device (it obviously cannot become ``full''). I'm not certain about other devices, though. For example, what if somebody writes to COM1, and the other side breaks the connection? Assuming we can distinguish between these two cases, the next question is what to do about that. It seems that the best alternative is to filter ^Z out of the data, as if it were not there. Any other alternative would mean trouble in some cases. For example, if the buffer begins with ^Z, if we don't write it and return 0, many programs will take that as an error and print an error message. (Btw, an attempt to have that error message make some sense was the original motivation for assigning ENOSPC to errno in these cases.) Filtering ^Z is easily done in functions which examine each character in the buffer (e.g., `write'). In other cases, I suggest only to handle the case where ^Z is the first character in the buffer. If ^Z is somewhere in the middle, the caller will get a smaller return value than the size of buffer it wanted to write, and will typically try to write the rest of the buffer beginning with the next unwritten character, which is ^Z. Here's a list of libc functions which are relevant to this issue: `fwrite', `write', `_write', `_flsbuf' Questions: 1) Is it okay to assume that premature end of output to the console device in cooked mode means ^Z? How about other character devices? 2) Does anybody see any problems with filtering ^Z out of data when writing to the console device in cooked mode? How about other character devices? 3) Is the filtering method outlined above good enough? Does anybody see a better way?