[comp.unix.wizards] SURVEY RESULTS: Should fd 3 be /dev/tty?

bernsten@phoenix.Princeton.EDU (Dan Bernstein) (05/04/89)

>  Should file descriptor 3 be, by new convention, /dev/tty?

The survey results are in, and they send clear messages to AT&T and
to Berkeley:

AT&T: Why does v8/v9 have fd 3 as another name for /dev/tty? There is
very little interest in or use for it. Those few applications that want
/dev/tty can open it themselves. You might make some people happy by
having a ``standard command input'' instead.

BERKELEY: Programmers *expect* that /dev/tty can be opened at any time.
But some BSD changes make this untrue. Make sure that it is true in
future releases. (Start by letting /dev/tty be opened while EXCL is set.)

I received responses from 26 people. Apologies for any errors in this list.

  pdb@SEI.CMU.EDU (Patrick Barron)
  flee@shire.cs.psu.edu (Felix Lee)
  haahr@bogey.princeton.edu (Paul Haahr)
  mark%jhereg@src.honeywell.com (Mark Colburn)
  bes%holin%mtune@att.att.com (Bradley Smith)
  ficc!peter@uunet.UU.NET (Peter da Silva)
  vlb@apple.com (Vicki Brown)
  taux01!amos@nsc.nsc.com (Amos Shapir)
  att!pegasus!hansen (Tony)
  n3dmc!johnl@uunet.UU.NET (John Limpert)
  att!cbosgd!alice!andrew
  sneaky!gordon@texbell.swbt.com (Gordon Burditt)
  ki4pv!cdis-1!tanner@ucf-cs.ucf.edu (T. Andrews)
  tbl@apollo.com
  @RELAY.CS.NET:andrew%frip.wv.tek.com@tektronix.tek.com (Andrew Klossner)
  jfc@ATHENA.MIT.EDU (John Carr)
  hznx@vax5.CCS.CORNELL.EDU (Dan Dulitz)
  auspex!auspex.com!guy@uunet.UU.NET (Guy Harris)
  gwyn@BRL.MIL (Doug Gwyn)
  arnold@mathcs.emory.edu (Arnold Robbins)
  talos!kjones@uunet.UU.NET (Kyle Jones)
  sco!seanf@ucscc.UCSC.EDU (Sean Fagan)
  jbuck@epimass.epi.com (Joe Buck)
  bzs@bu-cs.BU.EDU (Barry Shein)
  @pucc:brossard%litsun2.epfl.ch@CLSEPF51.bitnet (Alain Brossard)
  nazgul@apollo.com (Kee Hinckley)

The responses can be broken down as follows:

  3 It's already in AT&T's v8/v9
  2 Yes, a standard command-input stream would be useful
  1 Why not?
  4 Why?
  3 No, but a standard command-input stream would be useful
 11 No

The basic problem here is that ``control terminal'' is a fundamental
part of a process state, deemed important enough to have an entry in
the u area but not important enough to have easy user-level access.
Rather than having ioctls doing the dirty work, there should be
explicit system calls to detach from, attach to, and gain a file
descriptor for control terminals. In general u area information is
accessible through system calls, and only non-process state information
is relegated to device drivers and ioctls; I don't see why ttys are
handled differently.

Soapbox aside, below is a discussion of each point brought up.
Parenthesized numbers indicate the frequency of each argument.

(5) What do you do with processes having no control terminal:   The easy
answer is to have fd 3 be closed. When you reattach, you reopen fd 3.

(8) You can open /dev/tty in any case, and the extra effort necessary
is negligible:   If it were always possible to open /dev/tty, this would
be a valid argument, but in current BSD releases many special features
(TIOCEXCL being the one where this most annoys me) eliminate the ability
to open /dev/tty. If this is fixed, then I'll agree that there's no
point of making fd 3 be /dev/tty.

(5) Many programs, and the SVID, assume that a program starts with
exactly fds 0, 1, and 2 open:   This is a valid argument against
writing bad code and against the SVID. Seriously, any change that
breaks old programs (and standards) should be considered carefully.
Listen, AT&T!

(6) Having an extra file descriptor for ``command input'' would be
useful if it is redirectable:   I agree completely and would love
the subsequent simplification in more, awk, make, etc. Under the
current one-input two-output model, it is simply impossible to
write a ``standard'' program to interleave two inputs. Changing
the standard model to two-input two-output is a potentially very
useful generalization.

(3) v8/v9 already has fd 3 as /dev/tty:   Why? AT&T, if you want
to make this change, go all the way and accompany stdin, stdout,
and stderr with cmdin. Don't make a non-redirectable file descriptor
for what's already in the name space.

(2) Don't waste a file descriptor:   Very few programs would suffer
from this waste.

(2) Use stderr for /dev/tty like some versions of more do:   stderr
is redirected very often, and it may not be readable.

(1) Use stderr for cmdin, and make it readable:   If stderr is
redirected, it is rarely to the same place as where you want
command input from. It doesn't make sense to force input and
output to be the same place.

(1) Since fd 3 can be redirected, it is insecure for programs like
passwd, su, etc. to trust fd 3 to be /dev/tty:   Since the advent
of pseudo-terminals this argument has been moot.

(1) ``If fd 0 isn't a terminal the program shouldn't ask any more
questions'':   Say goodbye to more.

(2) Standard errors could go anywhere, not just /dev/tty:   The
two people who made this argument thought I was asking ``should fd 2
be /dev/tty?'' Nobody's proposing changing stderr.

In summary, *if* it is always possible to open /dev/tty, people don't
really need it as a file descriptor. It may be useful to change the
basic model of stdin-stdout-stderr to stdin-stdout-stderr-cmdin,
although that wasn't the original question.

---Dan Bernstein, bernsten@phoenix.princeton.edu

snoopy@sopwith.UUCP (Snoopy) (05/05/89)

In article <8123@phoenix.Princeton.EDU> bernsten@phoenix.Princeton.EDU (Dan Bernstein) writes:

|(6) Having an extra file descriptor for ``command input'' would be
|useful if it is redirectable:   I agree completely and would love
|the subsequent simplification in more, awk, make, etc. Under the
|current one-input two-output model, it is simply impossible to
|write a ``standard'' program to interleave two inputs. Changing
|the standard model to two-input two-output is a potentially very
|useful generalization.
|
|(3) v8/v9 already has fd 3 as /dev/tty:   Why? AT&T, if you want
|to make this change, go all the way and accompany stdin, stdout,
|and stderr with cmdin. Don't make a non-redirectable file descriptor
|for what's already in the name space.

Can I insert my pet peeve here?  There is also a need for a standard
auxiliary output.  stderr is often pressed into service for non-error
output.  I claim that this is a bad thing.  It is a pain to scan through
verbose output checking for error messages.  There should be a standard
place to send a 2nd data stream seperate from the error messages.
I run into this problem much more frequently than the case of needing
two input streams.

A second input stream could be useful for other things besides commands,
perhaps call it auxin?

So, how about: stdin, auxin, stdout, stderr, and auxout ?

    _____     
   /_____\    Snoopy	"My dot-matrix does Postscript."
  /_______\   
    |___|     tekecs.gwd.tek.com!sopwith!snoopy		 qiclab!sopwith!snoopy
    |___|     sun!nosun!illian!sopwith!snoopy		parsely!sopwith!snoopy

bzs@bu-cs.BU.EDU (Barry Shein) (05/06/89)

>Can I insert my pet peeve here?  There is also a need for a standard
>auxiliary output.  stderr is often pressed into service for non-error
>output.  I claim that this is a bad thing.  It is a pain to scan through
>verbose output checking for error messages.  There should be a standard
>place to send a 2nd data stream seperate from the error messages.
>I run into this problem much more frequently than the case of needing
>two input streams.

I think we're missing the spirit here and getting too literal minded
(ie. that some messages sent to stderr aren't errors, that isn't
exactly why it was called stderr.)

It would probably be better to just write programs to use some sort of
character tag at the beginning so you could de-mux the different types
of messages at the other end with grep rather than reworking all of
Unix to solve this problem. Granted that doesn't help with previously
written code you can't change. TWENEX used some sort of chars like %
for informatory, # for error or some such thing (but, of course, they
didn't have pipes or grep so it wasn't as handy as it might be in a
unix program.)
-- 

	-Barry Shein, Software Tool & Die

There's nothing more terrifying to hardware vendors than
satisfied customers.

mike@thor.acc.stolaf.edu (Mike Haertel) (05/07/89)

>In article <8123@phoenix.Princeton.EDU> bernsten@phoenix.Princeton.EDU (Dan Bernstein) writes:
>|(3) v8/v9 already has fd 3 as /dev/tty:   Why? AT&T, if you want
>|to make this change, go all the way and accompany stdin, stdout,
>|and stderr with cmdin. Don't make a non-redirectable file descriptor
>|for what's already in the name space.

v9 has a /dev/tty which is just a link to /dev/fd/3.

When v9 programs need to get at the terminal, I bet they just open
/dev/tty like on any other version of Unix.

One good reason to implement /dev/tty this way is that /dev/tty is
a pretty weird device driver with an incestuous relationship to
other data structures in the kernel.  /dev/fd/ has a similar problem.
By implementing /dev/tty as a link to /dev/fd/3 the v9 people
were able to reduce the count of ugly incestuous drivers to 1.

Another advantage is that one can redirect descriptor 3 to fool
programs that stupidly insist on talking to /dev/tty.  With streams
you can even give them a working tty ioctl interface . . .
-- 
Mike Haertel <mike@stolaf.edu>
main() ??< printf("hello, world??/n"); ??>

andrew@alice.UUCP (Andrew Hume) (05/07/89)

give me a break. can't find the error messages in stderr because of
all the other stuff? oh dear. why not put all the crap on some other
file descriptor and let stderr be what it should be? that's
why we have stdout and stderr; so we don't have to do this horseshit
on stdout. luckily the solution for stdout works for stderr;
don't multiplex.

dmr@alice.UUCP (05/07/89)

The survey for which Bernstein gives the results (8123@phoenix.Princeton.EDU)
has slid off our netnews directory, but the answers seem to suggest
misconceptions about the way /dev/tty works in the Ninth Edition
system.  Since our scheme seems to work conveniently, and differently
from most other contemporary systems, I'll describe it.  However, since
I don't remember the question that was originally asked, this may not
answer it.

In V9, there are special files named /dev/fd/0, /dev/fd/1 etc.
They do not have devices associated with them; instead opening
one of them causes an internal dup(2) of the corresponding already-open
file.  For convenience, /dev/stdin is linked to /dev/fd/0 and so
things like `cmd | cat hdr /dev/stdin trlr' can be used without
having to put special conventions (like a `-' argument) into
commands.

/dev/tty is linked to /dev/fd/3, and the programs that create login
sessions make file descriptor 3 refer to the terminal just like
descriptors 0,1,2.  (The standard such program is /etc/init, but there
are also the network connection acceptors).  Inheritance of file 3
takes place by the usual mechanism.

The advantage of the scheme is that the notion of `controlling
terminal' can be mostly removed from the kernel.  By an explicit
request, a process may ask that it become a process group leader, and
that any signals generated by a particular stream should be sent to
its process group.  However, a process does not need to remember this
stream.  We keep it for convenience (it is printed by ps) but the
information isn't used in the kernel.

The notion of /dev/tty is a peculiar one, because programs are run in
many environments, and programs have their own ideas of what they
want.  The essence is a way of getting to the user's terminal in spite
of I/O redirection; for example, as a matter of policy, programs that
read passwords should strongly encourage people to type them in
directly rather than storing them in files.  However, programs run in
the background (for example with &, or via cron or at) may not have a
terminal in any useful sense.

Our scheme of making the descriptor for the terminal merely one of the
several conventionally-available ones has, on balance, given rise to
fewer surprises and misbehaviors than previous attempts that wired the
notion into the kernel.  Such surprises as do occur can be debugged and
understood by tools and reasoning already familiar to users, and don't
depend on special kernel algorithms that determine the meaning of
/dev/tty.  Many Unix variants exhibit peculiar behaviors when /dev/tty
is tied to a special association of a control terminal and a process
(for example, non-working signals when you reuse an incoming line with
an old process on it, or a daemon process taking over your terminal
line.)

At the same time, we're aware that one can view this scheme as yet
another step in an infinite regress--perhaps in a couple of years
people will learn that file 3 can be redirected too, and we might need
file 4 to really, REALLY refer to the terminal.

The fact that file descriptor 3 was picked was a matter of choosing a
convenient convention.  Indeed, at first we used the largest permitted
file descriptor.  Because this varied, it seemed simpler to switch to
the lowest free descriptor.

	Dennis Ritchie
	att!research!dmr
	dmr@research.att.com