Subject: Consistent mode of file-opens
From: [email-masked] (Kimon Kontovassilis)

9 Oct 1997 02:41:12 -0700
Message-ID: <[email-masked]>
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
To: [email-masked]
Cc: [email-masked] (Kimon Kontovassilis)

Hello, fellows!

Although it's several months I 've joined the list, this is my first
stand-up-and-talk time; so, I guess, before anything else, I should send
a couple of sincere THANK-YOU words both to the CYGNUS people 
and to the many persons on this list that keep on improving gnu-win32.

The purpose of this message is the expression of my worries on the 
consistency of binary/text modes of opened files. Extensive (maybe too
extensive) discussions have taken place on this subject and I definitely
wouldn't want this message to regurgitate things already said.
Thus, I consider all past discussions on default binary vs text translations
an already known background and I 'm going to build on the (apparently now
permanently adopted) proposition that the default file-open mode is determined
by the mount-table flags in the registry.

Consider now a system setup where all mount points have been flagged as
binary. (As previous discussions on this list have fully explained, such a
setting is virtually necessary, if binary-file-oriented applications are to
behave properly without being individually modified.)
The problem is that stdin, stdout and stderr are still opened in text mode.
This breaks redirection and pipe operations dealing with binary data.
Things like

	gunzip -c file.tar.gz | tar xvf -
or
	tr < binfile -d some-funny-char | split
or
	cat pieces of a big bin file > wholefile

do no work properly, as is well known to most participants in this list.
I find this a major flaw: redirections and pipes should be transparent to
the operation of programs (and this includes programs operating on binary
files).

Why don't std{in,out,err} obey the default translation mode? Well, I haven't
heard of an explicit reason for this, but I suppose a good reason is that
these streams are by default connected to the console, and the console is
inherently text-oriented. The default keyboard drivers forward lines ended
by <cr>/<lf> and ^Z is valuable for signifying EOF from the keyboard.
Furthermore, the default console driver requires <cr>/<lf> pairs to
properly display lines on the screen.

So, in effect, opening in text mode is the right thing to do, as long as
the standard streams are connected to the console. However, if these
streams are redirected, the streams should be opened in binary mode, if the
rest of file opens have been setup so.

There is some time that it has occurred to me that the right mode is not
hard to find out, given the function isatty(). Try it out for yourselves;
save this little program:

	#include <stdio.h>
	#include <string.h>
	#include <unistd.h>
	
	void check_fd(int fd, FILE *ofp)
	{
		if (isatty(fd))
			fprintf(ofp, "fd %d IS a tty:\t%s\n", fd, ttyname(fd));
		else
			fprintf(ofp, "fd %d is NOT a tty\n", fd);
	}
	
	int main(int argc, char *argv[])
	{
	 	/* where to report */
		FILE *ofp =
			(argc > 1 && strcmp(argv[1], "-1") == 0)
			? stdout : stderr;
	
		check_fd(0, ofp);
		check_fd(1, ofp);
		check_fd(2, ofp);
	}

compile it to produce, say, test4tty, then try:

	test4tty
	test4tty > file
	test4tty < file
	echo | test4tty
	test4tty | cat

with same results in all of COMMAND.COM, 4DOS and bash. In bash you may
further wish to try things like

	test4tty < /dev/null
	test4tty -1 2>file
	test4tty < /dev/null 2>&1 | cat
	echo `test4tty`

and you will see that isatty() does a pretty good job. Similarly, things
work consistently with popen()/pclose().

So, this brings up the following question: couldn't the start-up code
(maybe just before handing over to main, or at any other appropriate point)
do things like:

	if (!isatty(0))
		_setmode(0, O_BINARY);

(and similarly for descriptors 1 and 2) if the default mode for (say) the root
drive is binary? Or, if you don't like the "root" drive convention, add
provision for a new registry key, governing the standard streams when they are
!isatty(), this registry key being settable by some extended notation in the
mount command.

It seems so obvious to me that I 'm quite surprised that no-one else saw it
before me. The feasibility of my solution, however, is purely speculative,
as I haven't access to the source code.
Maybe I 'm foolishly ignorant of some other major issue that prevents this
solution :-) If so, I would definitely want to hear about it.

Best regards,
Kimon
-----------------
Dr. Kimon Kontovasilis,
Institute for Informatics & Telecommunications,
National Center for Scientific Research Demokritos,
GR-15310 AG. PARASKEVI ATTIKIS, PoB 60228, Greece
-
For help on using this list (especially unsubscribing), send a message to
"[email-masked]" with one line of text: "help".