123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- I fear that the TERMIOS standard now being considered would impede
- unnecessarily real advances in the architecture of Posix systems.
- This is because it specifies at too low a level, and includes many
- many things that do not need to be standardized because one does not
- need to know them in order to write portable application programs.
- The result is to require systems not only to provide the Unix
- functionality, but actually to be implemented like Unix. It is
- hard to use advanced concepts such as remote procedure call and
- indirect capabilities to implement this proposal, even though they
- could easily be used to implement something that behaves "enough" like
- Unix for practical purposes to be a good Posix.
- The standard should avoid trying to describe all the features that
- Unix has. Instead, it should focus on telling application programmers
- standard ways to accomplish the tasks that application programs must do.
- We must think carefully which aspects of the behavior of a standard
- interface must be standard, and which are better left up to the
- system implementor.
- A useful heuristic is that it should not be possible to write a
- portable `stty' program using standard constructs. If the standard
- goes far enough to make this possible, it says too much, and makes it
- impossible for many other systems to provide Posix emulation modes.
- In terminal control, there are a few general areas that need not be
- standardized to enable application programs to be portable:
- * Terminal characteristics data which tell the system how to produce
- standard behavior for the standard system calls.
- For example, there need not be a standard way to control how much
- filling is needed for various characters. As long as the system knows
- how to fill properly, application programs need not care how this
- happens. However, applications do need to be able to prevent
- filling from taking place (with OPOST) so that they can do verbatim
- output.
- Application programs control whether erase-and-kill processing is
- done, so the way to control this must be standard. But the programs
- do not see the screen, so how the system displays the results (perhaps
- by echoing deleted characters on hardcopy terminals, backspacing on
- character display terminals, or doing raster ops on bit map terminals)
- does not need to be discussed.
- * How jobs are connected to their controlling terminals.
- Application programs need to know that there is a controlling
- terminal, or that there may be one; but they do not need to know how
- the system decides whether they have a controlling terminal.
- (One exception: it may be useful to have a standard way to fork
- a child with no controlling terminal).
- Consider an extreme example, CSTOPB. No application program can
- reasonably use this bit. An application program that knows this bit
- exists will run into trouble on terminals that are not connected
- through uarts--hardwired terminals, network ports, or those controlled
- by Emacs. On these kinds of terminals, either there is no CSTOPB or
- else changing CSTOPB will fail to have whatever effect the application
- program intended (probably because it does nothing).
- * Where job control is concerned, it is important to avoid precluding the
- control of ability to use the terminal by means of giving different
- capabilities to different processes and allowing some processes to have
- the power to enable and disable the capabilities used by other processes.
- Next, some specific suggestions.
- * C.7.2.2
- It is better not to talk about how a process can acquire a controllig
- terminal or relinquish one.
- Every system needs some mechanism to connect users' jobs to their
- terminal, but this is an internal part of the system. Many systems
- do this in ways totally unlike Unix. In a capability-based system
- this mechanism may be totally general and may not be restricted
- to terminals, or to a single device per process. Removing such
- restrictions is part of the goal of designing cleaner and more general
- systems.
- The only thing we need to say is how to use setpgrp() to disconnect
- a process from its controlling terminal. For the sake of capability
- based systems, it is best if this is done using a new system call
- that demands a descriptor for the controlling terminal as an argument.
- Use of any other argument would be nonstandard.
- Related control flags such as HUPCL are also better left unmentioned.
- * C.7.2.4
- All we need to standardize about job process groups is enough to make
- it possible to write a portable shell using standard constructs.
- We need ways to do these things:
- **1* make a process the leader of a new job process group.
- **2* grant permission to use the terminal to a child's
- job process group, or revoke permission.
- **3* grab the ability to use the terminal directly, after having
- given a child permission. This is not necessarily the same thing
- as the previous one. Special care is required to define a common
- interface for both *2* and *3*; see below.
- **4* control what should happen to the process when it tries
- to read or write while it lacks permission; and, find out when
- this has occurred.
- A standard should *not* say:
- ** whether more than one child process group can be given permission
- simultaneously by one parent.
- ** whether the parent still has permission to use the terminal
- after giving permission to a child's process group.
- ** what happens to the relation between the parent and the child
- vis-a-vis use of the terminal if the grandparent takes permission away
- from the parent. On Unix systems, this is unpredictable. On
- capability-based systems, permission propagates from the top of the
- tree of processes, and each process can allow or disallow permission
- to propagate to each child.
- ** whether it is an error to grant or revoke a child's permission
- while the parent does not have permission.
- ** any standard way for a child take permission when not given
- permission by its parent. It is easy to implement doing this on Unix,
- but on capability-based systems the child may not get a new capability
- whose access the parent will enable and disable. Then the child will be
- completely unable to do this.
- ** any standard way to use the terminal without permission.
- This too is probably impossible to implement on capability-based systems.
- In fact, the parent might be able to change where the child's capability
- points in addition to turning it on or off. Imagine being able to
- redirect the stdout of a program already running.
- ** that one can do anything that affects the behavior of the
- controlling terminal without using a descriptor for it.
- This includes setpgrp!
- Here are my specific proposals:
- **1* make a process the leader of a new job process group.
- Use a new function new_pgrp (TERMDESC, GETACCESS);
- TERMDESC must be a descriptor for the controlling terminal; that is
- the only standard value, and what happens if it is not that is
- undefined by the standard. On some systems, each open file (even a
- disk file!) will be able to have its own independent set of process
- groups.
- GETACCESS, if nonzero, says to set the pgrp of the terminal to the
- newly created one. If zero is used here, only the parent has the
- ability subsequently to use change_term_pgrp (below) to let grant the
- use of the terminal. GETACCESS makes sense because new_pgrp will be
- used between the fork and the exec, so the choice of GETACCESS value
- will be under control of the parent program even though not the parent
- process.
- It is nonstandard to do new_pgrp in a process that has already
- done an exec. It is recommended for systems not to permit
- new_pgrp with nonzero GETACCESS (at least) after an exec.
- Unix 4.2 will, however, permit it, if this call is implemented for
- it in the straightforward way using standard 4.2 facilities.
- **2* grant permission for terminal use to a child's job process group,
- or revoke permission.
- **3* grab the ability to use the terminal directly, after having
- given a child permission. This is not necessarily the same thing
- as the previous one.
- I propose one new system call to do both of these things.
- The current method, which involves specifying handling for SIGTTOU (or
- is it SIGTTIN) and then changing the process group of the terminal, is
- very unclean and constrains other parts of the system such as how
- signals are implemented.
- We use a new function change_term_pgrp (T, G1, G2);
- which means, "if terminal T's job process group is now G1, change it
- to G2". Zero as G1 or G2 stands for the job process group of this
- process.
- Each of G1 and G2 must be zero or the pid of a child which is a job
- process group leader; otherwise the results are undefined, but it is
- recommended to return an error and do nothing.
- The normal case for this function is that the terminal's current
- process group is that specified by G1, or belongs to a descendant
- process of the process specified by G1. In the normal case, the
- function always succeeds and performs as specified, assuming the
- argument G2 is valid.
- In the abnormal case, it is not specified what happens. It is
- possible for the function to have its normal effect, but only later,
- once some grandparent gives the parent permission once again. It is
- possible for it to signal SIGTTOU or SIGTTIN (choose one) in which
- case the results can depend on whether the signal is handled. If
- SIGTTIN or SIGTTOU (whichever) is ignored, it is possible for it to be
- a no-op, or it is possible for it to set the terminal's pgrp to G2
- anyway.
- It is not necessary to speak about matching uids, because in standard
- usage the real uids are always the same. We need not speak about
- whether root is permitted to do anything special.
- change_term_pgrp can be implemented on Unix as a library routine
- that uses the old ugly recipe involving signal (SIGTTOU).
- On some other systems, where each child job process group can be
- controlled independently and the parent can always use the terminal
- regardless of them, this call would turn off permission for group G1
- (if that is not zero) and then turn on permission for group G2 (if G2
- is not zero). G1 is not needed on Unix, but it is essential on
- systems where multiple children can have permission independently. It
- is never very hard for a shell to remember who it last gave permission
- to.
- Thus the least common denominator of functionality--that which is
- possible on Unix--can be had in a standard way that can be implemented
- on many other kinds of system architectures.
- **4* is handled well by the proposal, except that it should not
- be specified that any actual input or output can take place if
- the signal SIGTTIN or SIGTTOU is ignored. It should be permitted
- for the read or write to hang or be ignored; or the system could
- provide nonstandard ways to control which of these happens.
- * C.7.2.5
- "A call to close () on a terminal device ... all pending input
- is discarded."
- This is a disaster! I fork a subprocess, and it does freopen on
- stdin, and that throws away terminal input???
- Perhaps there was an omission in the text of this part of the
- standard. Perhaps it only means to apply to closing the last open
- descriptor on the terminal. This falls into the domain of how
- controlling terminals are connected with users' jobs, which should not
- be addressed; so if this is what is meant, it would be better not to
- mention it.
- * C.7.2.6.1
- It should not be required that the escape character for verbatim
- entry is \. It is enough to suggest that there be such a
- character. In fact, this is a poor choice, because it is cleanest
- if all printing characters are free of any meaning for input editing.
- * C.7.2.8
- It should not be specified that you cannot escape
- the other special characters such as INTR, QUIT, SUSP...
- It is ok to permit this to be possible and also permit it
- to be impossible. A system might want to allow this if the
- escape character is nonprinting (such as ^V) but not allow this
- if the escape character is printing (such as \); or it could
- have another nonstandard flag that controls this decision.
- * C.7.2.12
- The only flag that an application program needs to know about is OPOST, so
- it would be a good idea to omit discussion of the other fields.
- If they are not omitted, then at least the initial values of variables
- that control how filling should be done should not be specified, since
- many systems will want to initialize these automatically according to
- what is known about the terminal.
- * C.7.2.13
- The only information in c_cflag that is needed by an application
- program is the baud rate, and possibly PARENB (I am not sure;
- depending on the meaning of some of the bits in other words,
- perhaps it is not necessary to deal with PARENB in order to
- send 8-bit data. That would be a good idea in any case.)
- It would be better not to mention the others in the standard.
- Encoding the baud rate in this way is very fragile; we can be
- sure that baud rates will exist that cannot be described.
- It would be better to represent the baud rates simply as binary
- numbers stored in 32-bit fields. It is even possible to define
- ways of doing this that do not require a change in the
- `struct termios', though that interface would only approximately
- work if the baud rate were not one it can describe.
- Simply define a new ioctl for getting "real" access to the
- baud rates.
- * C.7.2.14
- It would be better to omit mention of ECHOE, ECHOPRT and ECHOKE
- because these really pertain to a style of use of the terminal.
- This information really depends on the kind of terminal you have,
- not on which application program is running.
- We should standardize interfaces by which application programs say
- what they want done, at a level that is meaningful for the application
- program. Thus, whether echoing should be done, and whether erase and
- kill should be done, are things that application programs need to control.
- But *how* the echoing looks, or how erase and kill processing looks,
- should be considered part of the internals of the system. Suppose
- the system is window-oriented. Should it still be required to provide
- the functionality of ECHOPRT, which is intended for printing terminals?
- If not, what use is there in mentioning ECHOPRT if it may not do anything?
- It is nice for a system to show erased characters on a printing terminal
- by reechoing them, but even if it fails to do this, that is not a concern
- for the Posix standard. Standard Posix application programs will "work"
- according to this systems idea of what "working" means, which does not
- include reechoing the erased characters.
- PAGEOUT should be part of the standard, but the details of how and
- when the system pauses, or how the user can cause resumption, should
- not be specified. It is enough if the system interprets PAGEOUT by
- pausing often enough to facilitate reading the output and gives the
- user a convenient way to say when to resume.
- The Incompatible Timesharing System offers the program the opportunity
- to get a signal when it attempts to write a character that will cause
- a pause to happen. When this feature is in use, the system does not
- pause; it expects the signal handler to print "--more--" or whatever
- it likes, and then to wait for input. The standard should not
- preclude offering this as an optional way to "pause". Saying nothing
- about how "pausing" works is the easiest way.
- * WRAP
- I wonder how the system knows what column the cursor is in. It cannot
- always know. If all programs that want to do cursor control are
- expected to turn off all output postprocessing, then WRAP need not be
- part of the standard (assuming that OPOST overrides WRAP, as I hope it
- does) because application programs that want postprocessing don't need
- to know whether the wrapping takes place in the terminal or in the
- system.
- It would be clearer to put WRAP in c_oflag.
- * C.7.2.15
- There needs to be a standard for how to disable any one of
- the special characters such as INTR, QUIT, etc.
- This cannot be done by storing a value that "isn't a real character
- code" because there are none! For example 0377, which is often used
- to disable one of these features. is the character Meta-Delete, which
- is a commonly used Emacs command.
- Some Unix systems treat 0377 specially: it really does mean "disable
- this function". Others currently use this to mean that Meta-Delete
- should have the function.
- I think that defining 0377 to mean "disable" would be an adequate
- solution. A slightly better solution would allow any character code
- whatever to be specified, and have "disable" as another alternative.
- For example, the "characters" could actually be shorts, and then a
- value out of range as a character could mean "disable". There could
- be a standard name for one such value that is recommended for this
- use.
- Some systems with special terminals may have special keyboard keys for
- such functions as suspending and editing. I think we should say that
- it is ok for such systems to ignore the characters specified by the
- application program. Their users won't mind; they know which special
- keys to use and won't be confused if those same keys work even when
- they run a program that normally (on ASCII keyboards) wants to select
- special keys.
- * C.7.2.16
- Since TCSBRK is a complicated combination of other calls defined
- here, perhaps it should be deleted from the standard.
- TCEXCL may not make any sense on some systems, so it should not be
- required to have any effect. It may be useful to specify the name and
- its calling sequence as a standard, and say that if it makes sense to
- have exclusive reservation of a terminal then this is the way to do
- it; otherwise this call should do nothing.
- TIOCSPGRP should be replaced by change_term_pgrp, as described above,
- and TIOCGPGRP should be eliminated, because there is no way to define
- the one-and-only pgrp of the terminal on systems where permission
- can be granted independently to various children.
- * Several sections say that "the initial value is all bits clear."
- Surely this does not mean that an application program should expect
- such fields as OPOST and ICANON to be zero when it is started. What,
- then, does it mean?
- If the initial value means "when the system is started" or "when
- the getty starts running", that is something the standard should not
- talk about. There may not be such a thing as a getty.
- The only kind of initial value that would be useful to the users of
- the standard, the writers of portable application programs, is the
- value when an application program is started. But nothing can be said
- about most of the bits at that time, because they depend on the kind
- of terminal on and the user's preferences, and system architecture.
- You might think it is possible to say, for example, that ICANON will
- be 1 when an application program is started. This does not depend on
- the kind of terminal, and few users are likely to prefer no input
- editing. But this is not true when the program is running under Emacs
- with Emacs sending it input from an editor buffer, even though the
- user does have an input editing capability.
- It is best to say nothing about any sort of "initial state" for the
- contents of the termios structure. When programs that care about the
- state, it is enough that the standard says how to set up that state.
- For other programs (most programs) it is sufficient to assume that the
- bits are set the way the user or shell considered reasonable. That is
- all that is needed for writing portable programs.
|