[comp.unix.wizards] Reading from stderr

m5@lynx.uucp (Mike McNally) (04/13/89)

Am I in good company in believing that a program that reads from
standard error is a naughty program?  It seems to be done (usually) as
an alternative to the horrible drudgery of opening /dev/tty.  I ask
because I'm facing the problem of fixing our OS to cope with this
(actually it'll just be a minor, even trivial, change to init, and
maybe some stuff in the stdio library).  Maybe I'm old fashioned, but
if I want to read a response from the terminal I figure it's best to go
ahead and open the tty.  I mean, somebody invented /dev/tty for that
very reason; hell, even RSTS has KB:!

Uncompress does it, by the way; that's the only thing about the compress
stuff I can find to complain about.

-- 
Mike McNally                                    Lynx Real-Time Systems
uucp: {voder,athsys}!lynx!m5                    phone: 408 370 2233

            Where equal mind and contest equal, go.

andrew@frip.wv.tek.com (Andrew Klossner) (04/15/89)

[]

	"Am I in good company in believing that a program that reads
	from standard error is a naughty program?  It seems to be done
	(usually) as an alternative to the horrible drudgery of opening
	/dev/tty."

What if the program was exec'ed with channels 0, 1, and 2 open but with
no controlling terminal?  The open of /dev/tty will fail.  (Of course,
in this case stderr is probably open for output only.)

There are window systems that work this way, running processes without
controlling terminals (no ptys), but I haven't seen much of them
lately.

  -=- Andrew Klossner   (uunet!tektronix!orca!frip!andrew)      [UUCP]
                        (andrew%frip.wv.tek.com@relay.cs.net)   [ARPA]

jiii@visdc.UUCP (John E Van Deusen III) (04/15/89)

In article <5437@lynx.UUCP> m5@lynx.UUCP (Mike McNally) writes:
> Am I in good company in believing that a program that reads from
> standard error is a naughty program?  It seems to be done (usually) as
> an alternative to the horrible drudgery of opening /dev/tty. ...

In one application that I have there is a program running in the middle
of a pipe line that sometimes forks an interactive shell.  Once I used

exec </dev/tty >/dev/tty

in order for the shell to access the terminal.  The problem was that if
the su command were subsequently invoked, the proper entry in
/etc/ttytype would not be found, and because of the way /etc/profile was
set up, TERM would be zapped.  So I changed my line to

exec 0<&2 1>&2

Of course I knew that the standard error file wasn't redirected.  It is
also possible to remember the name of your terminal in an environment
variable.  My point is that opening /dev/tty is NOT the same as
restoring your standard input and output to their condition prior to
redirection.

To do the same thing within a C program, you would close(2) fildes 0 and
use the dup(2) system call to return a fildes 0 with the save open file
as fildes 2.  The same process would apply to fildes 1.  Since file
descriptors 0, 1, and 2 are all opened with oflag set to O_RDWR, and
stderr is unbuffered, there shouldn't be any reason why you couldn't
read from fildes 2.  I agree with Mr. McNally that it is something I
would prefer not to do.
--
John E Van Deusen III, PO Box 9283, Boise, ID  83707, (208) 343-1865

uunet!visdc!jiii

friedl@vsi.COM (Stephen J. Friedl) (04/16/89)

In article <508@visdc.UUCP>, jiii@visdc.UUCP (John E Van Deusen III) writes:
> Since file
> descriptors 0, 1, and 2 are all opened with oflag set to O_RDWR, and
> stderr is unbuffered, there shouldn't be any reason why you couldn't
> read from fildes 2.

An expansion here: stdin, stdout, and stderr are not opened independantly.
the terminal device is opened and the resulting fildes is dup-ed twice
to yield stdout and stderr.

     Steve

-- 
Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 
3B2-kind-of-guy   / friedl@vsi.com  / {attmail, uunet, etc}!vsi!friedl

"I'm making a fashion statement: I'm saying I don't know how to dress." - me

m5@lynx.uucp (Mike McNally) (04/17/89)

In article <508@visdc.UUCP> jiii@visdc.UUCP (John E Van Deusen III) writes:
>In article <5437@lynx.UUCP> m5@lynx.UUCP (Mike McNally) writes:
>> [ asking about reading from stderr vs. opening /dev/tty ]
>
>In one application that I have there is a program running in the middle
>of a pipe line that sometimes forks an interactive shell.  Once I used
>
>exec </dev/tty >/dev/tty
>
>in order for the shell to access the terminal.  The problem was that if
>the su command were subsequently invoked, the proper entry in
>/etc/ttytype would not be found. . .

Gosh all hemlock!  I guess I just found an incompatibility between our
OS and UNIX.  When I open "/dev/tty" on my (non-UNIX) machine, the
"driver" for "/dev/tty" does some magic happy stuff and gets the
current control device info, and returns a dup'ed file descriptor for
that.  Thus, when I look at the device number via fstat(), I get the
real tty beef.

Oh well, I guess I should change the question a little:  what's the
advantage of having "/dev/tty" behave the way it does in this respect?
That is, would a massive catastrophe occur if a file descriptor
returned from an open request on "/dev/tty" was a real honest-to-gosh
dup of the control tty file descriptor?  (Not that I'm suggesting that
UNIX be changed; I just need to know if I really ought to bother to
break a feature that turns out to be a compatibility issue.)

-- 
Mike McNally                                    Lynx Real-Time Systems
uucp: {voder,athsys}!lynx!m5                    phone: 408 370 2233

            Where equal mind and contest equal, go.

john@hcr.UUCP (John R. MacMillan) (04/19/89)

In article <1094@vsi.COM> friedl@vsi.UUCP writes:
|In article <508@visdc.UUCP>, jiii@visdc.UUCP (John E Van Deusen III) writes:
|> Since file
|> descriptors 0, 1, and 2 are all opened with oflag set to O_RDWR, ...
|
|An expansion here: stdin, stdout, and stderr are not opened independantly.
|the terminal device is opened and the resulting fildes is dup-ed twice
|to yield stdout and stderr.

But this isn't required of stdio, is it?  I used systems where stderr
is write-only, and programs which read from it had to be fixed.
-- 
John R. MacMillan		Sometimes you have to go for the two
HCR Corporation			in the bush.
{utzoo,utcsri}!hcr!john		

dg@lakart.UUCP (David Goodenough) (04/19/89)

From article <5451@lynx.UUCP>, by m5@lynx.uucp (Mike McNally):
> Oh well, I guess I should change the question a little:  what's the
> advantage of having "/dev/tty" behave the way it does in this respect?
> That is, would a massive catastrophe occur if a file descriptor
> returned from an open request on "/dev/tty" was a real honest-to-gosh
> dup of the control tty file descriptor?

The only real problem would be for daemons and the like which have no
controlling tty. But I suppose that open / the /dev/tty driver could be
made clever enough to make this work as well (i.e. select action based on
whether the process has a controlling tty or not).

Of course _REAL_ operating systems (like I run on pallio) have
stdkbd defined, so I can _ALWAYS_ get at the terminal input line
when I need it. :-) :-) :-) :-) :-)


		Comments anyone?
-- 
	dg@lakart.UUCP - David Goodenough		+---+
						IHS	| +-+-+
	....... !harvard!xait!lakart!dg			+-+-+ |
AKA:	dg%lakart.uucp@xait.xerox.com		  	  +---+

kremer@cs.odu.edu (Lloyd Kremer) (04/20/89)

In article <330@hcr.UUCP> john@hcr.UUCP (John R. MacMillan) writes:

>In article <1094@vsi.COM> friedl@vsi.UUCP writes:
>|In article <508@visdc.UUCP>, jiii@visdc.UUCP (John E Van Deusen III) writes:
>|> Since file
>|> descriptors 0, 1, and 2 are all opened with oflag set to O_RDWR, ...
>|
>|An expansion here: stdin, stdout, and stderr are not opened independently.
>|the terminal device is opened and the resulting fildes is dup-ed twice
>|to yield stdout and stderr.
>
>But this isn't required of stdio, is it?  I used systems where stderr
>is write-only, and programs which read from it had to be fixed.


I think there is a confusion here between high level I/O (stdin, stdout,
stderr) and low level I/O (file descriptors 0, 1, 2).

In any UNIX variant I have used, I have found that the previous posters
were correct in saying that descriptors 0, 1, and 2 are originally created
by the sequence

	open(..., O_RDWR);  /* returns first available descriptor, 0 */
	dup(0);             /* returns first available descriptor, 1 */
	dup(0);             /* returns first available descriptor, 2 */

hence,

	read(2, ..., ...);

should work.  However, when the stdio FILEs are initialized, stdin is set for
read-only (_IOREAD), stdout is set for write-only (_IOWRT), and stderr is
set for write-only with no buffering (_IOWRT|_IONBF); hence

	getc(stderr);

would not work.  So it depends on the level of I/O you are using.

You can check your own system's stdio setup with this short program:

	#include <stdio.h>

	main()
	{
		int flag[3];

		/* gotta get these before doing any stdio */
		flag[0] = stdio->_flag;
		flag[1] = stdout->_flag;
		flag[2] = stderr->_flag;
		printf("stdin  is \\%03o\n", flag[0]);
		printf("stdout is \\%03o\n", flag[1]);
		printf("stderr is \\%03o\n", flag[2]);
		return(0);
	}

and comparing the results to the flag values #define'd in <stdio.h>.

As for absolute guarantees, "It works for me!".  :-)

-- 
					Lloyd Kremer
					Brooks Financial Systems
					...!uunet!xanth!brooks!lloyd
					Have terminal...will hack!

guy@auspex.auspex.com (Guy Harris) (04/23/89)

 >In any UNIX variant I have used, I have found that the previous posters
 >were correct in saying that descriptors 0, 1, and 2 are originally created
 >by the sequence

...

 >hence,
 >
 >	read(2, ..., ...);
 >
 >should work.

Note: the word "originally" is very important here.  There is *NO*
guarantee that file descriptor 2 is open for reading!  You might have
done:

	command >file 2>&1		# Bourne/Korn shell

or

	command >&file			# C shell

or piped the standard output and error to another program (e.g.,
"more"), or sent the standard output and error to different files,
or....

Programs should be *VERY* careful about reading from the standard error
- whether doing so directly from file descriptor 2 or doing so from the
standard I/O stream "stderr".  They should *ONLY* do so if they know for
certain that the standard error refers to what they think it does; if
they think it's a synonym for "the user's terminal", they should think
again - it's not guaranteed to refer to the user's terminal.

"/dev/tty" is guaranteed to refer to the process's controlling terminal,
which is generally the user's terminal - assuming the program *has* a
controlling terminal, which it generally won't if run from "cron" or
"at"/"batch", for example - so if they want to be certain they talk to
"the user", they should use "/dev/tty" instead (and be prepared not to
be able to open it; if they can't open it, it's probably because the
program is running as a "cron" or "at"/"batch" job, or being run with
"rsh", or otherwise not being run completely interactively).