diff-p1003.letter.~3~ 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. I fear that the TERMIOS standard now being considered would impede
  2. unnecessarily real advances in the architecture of Posix systems.
  3. This is because it specifies at too low a level, and includes many
  4. many things that do not need to be standardized because one does not
  5. need to know them in order to write portable application programs.
  6. The result is to require systems not only to provide the Unix
  7. functionality, but actually to be implemented like Unix. It is
  8. hard to use advanced concepts such as remote procedure call and
  9. indirect capabilities to implement this proposal, even though they
  10. could easily be used to implement something that behaves "enough" like
  11. Unix for practical purposes to be a good Posix.
  12. The standard should avoid trying to describe all the features that
  13. Unix has. Instead, it should focus on telling application programmers
  14. standard ways to accomplish the tasks that application programs must do.
  15. We must think carefully which aspects of the behavior of a standard
  16. interface must be standard, and which are better left up to the
  17. system implementor.
  18. A useful heuristic is that it should not be possible to write a
  19. portable `stty' program using standard constructs. If the standard
  20. goes far enough to make this possible, it says too much, and makes it
  21. impossible for many other systems to provide Posix emulation modes.
  22. In terminal control, there are a few general areas that need not be
  23. standardized to enable application programs to be portable:
  24. * Terminal characteristics data which tell the system how to produce
  25. standard behavior for the standard system calls.
  26. For example, there need not be a standard way to control how much
  27. filling is needed for various characters. As long as the system knows
  28. how to fill properly, application programs need not care how this
  29. happens. However, applications do need to be able to prevent
  30. filling from taking place (with OPOST) so that they can do verbatim
  31. output.
  32. Application programs control whether erase-and-kill processing is
  33. done, so the way to control this must be standard. But the programs
  34. do not see the screen, so how the system displays the results (perhaps
  35. by echoing deleted characters on hardcopy terminals, backspacing on
  36. character display terminals, or doing raster ops on bit map terminals)
  37. does not need to be discussed.
  38. * How jobs are connected to their controlling terminals.
  39. Application programs need to know that there is a controlling
  40. terminal, or that there may be one; but they do not need to know how
  41. the system decides whether they have a controlling terminal.
  42. (One exception: it may be useful to have a standard way to fork
  43. a child with no controlling terminal).
  44. Consider an extreme example, CSTOPB. No application program can
  45. reasonably use this bit. An application program that knows this bit
  46. exists will run into trouble on terminals that are not connected
  47. through uarts--hardwired terminals, network ports, or those controlled
  48. by Emacs. On these kinds of terminals, either there is no CSTOPB or
  49. else changing CSTOPB will fail to have whatever effect the application
  50. program intended (probably because it does nothing).
  51. * Where job control is concerned, it is important to avoid precluding the
  52. control of ability to use the terminal by means of giving different
  53. capabilities to different processes and allowing some processes to have
  54. the power to enable and disable the capabilities used by other processes.
  55. Next, some specific suggestions.
  56. * C.7.2.2
  57. It is better not to talk about how a process can acquire a controllig
  58. terminal or relinquish one.
  59. Every system needs some mechanism to connect users' jobs to their
  60. terminal, but this is an internal part of the system. Many systems
  61. do this in ways totally unlike Unix. In a capability-based system
  62. this mechanism may be totally general and may not be restricted
  63. to terminals, or to a single device per process. Removing such
  64. restrictions is part of the goal of designing cleaner and more general
  65. systems.
  66. The only thing we need to say is how to use setpgrp() to disconnect
  67. a process from its controlling terminal. For the sake of capability
  68. based systems, it is best if this is done using a new system call
  69. that demands a descriptor for the controlling terminal as an argument.
  70. Use of any other argument would be nonstandard.
  71. Related control flags such as HUPCL are also better left unmentioned.
  72. * C.7.2.4
  73. All we need to standardize about job process groups is enough to make
  74. it possible to write a portable shell using standard constructs.
  75. We need ways to do these things:
  76. **1* make a process the leader of a new job process group.
  77. **2* grant permission to use the terminal to a child's
  78. job process group, or revoke permission.
  79. **3* grab the ability to use the terminal directly, after having
  80. given a child permission. This is not necessarily the same thing
  81. as the previous one. Special care is required to define a common
  82. interface for both *2* and *3*; see below.
  83. **4* control what should happen to the process when it tries
  84. to read or write while it lacks permission; and, find out when
  85. this has occurred.
  86. A standard should *not* say:
  87. ** whether more than one child process group can be given permission
  88. simultaneously by one parent.
  89. ** whether the parent still has permission to use the terminal
  90. after giving permission to a child's process group.
  91. ** what happens to the relation between the parent and the child
  92. vis-a-vis use of the terminal if the grandparent takes permission away
  93. from the parent. On Unix systems, this is unpredictable. On
  94. capability-based systems, permission propagates from the top of the
  95. tree of processes, and each process can allow or disallow permission
  96. to propagate to each child.
  97. ** whether it is an error to grant or revoke a child's permission
  98. while the parent does not have permission.
  99. ** any standard way for a child take permission when not given
  100. permission by its parent. It is easy to implement doing this on Unix,
  101. but on capability-based systems the child may not get a new capability
  102. whose access the parent will enable and disable. Then the child will be
  103. completely unable to do this.
  104. ** any standard way to use the terminal without permission.
  105. This too is probably impossible to implement on capability-based systems.
  106. In fact, the parent might be able to change where the child's capability
  107. points in addition to turning it on or off. Imagine being able to
  108. redirect the stdout of a program already running.
  109. ** that one can do anything that affects the behavior of the
  110. controlling terminal without using a descriptor for it.
  111. This includes setpgrp!
  112. Here are my specific proposals:
  113. **1* make a process the leader of a new job process group.
  114. Use a new function new_pgrp (TERMDESC, GETACCESS);
  115. TERMDESC must be a descriptor for the controlling terminal; that is
  116. the only standard value, and what happens if it is not that is
  117. undefined by the standard. On some systems, each open file (even a
  118. disk file!) will be able to have its own independent set of process
  119. groups.
  120. GETACCESS, if nonzero, says to set the pgrp of the terminal to the
  121. newly created one. If zero is used here, only the parent has the
  122. ability subsequently to use change_term_pgrp (below) to let grant the
  123. use of the terminal. GETACCESS makes sense because new_pgrp will be
  124. used between the fork and the exec, so the choice of GETACCESS value
  125. will be under control of the parent program even though not the parent
  126. process.
  127. It is nonstandard to do new_pgrp in a process that has already
  128. done an exec. It is recommended for systems not to permit
  129. new_pgrp with nonzero GETACCESS (at least) after an exec.
  130. Unix 4.2 will, however, permit it, if this call is implemented for
  131. it in the straightforward way using standard 4.2 facilities.
  132. **2* grant permission for terminal use to a child's job process group,
  133. or revoke permission.
  134. **3* grab the ability to use the terminal directly, after having
  135. given a child permission. This is not necessarily the same thing
  136. as the previous one.
  137. I propose one new system call to do both of these things.
  138. The current method, which involves specifying handling for SIGTTOU (or
  139. is it SIGTTIN) and then changing the process group of the terminal, is
  140. very unclean and constrains other parts of the system such as how
  141. signals are implemented.
  142. We use a new function change_term_pgrp (T, G1, G2);
  143. which means, "if terminal T's job process group is now G1, change it
  144. to G2". Zero as G1 or G2 stands for the job process group of this
  145. process.
  146. Each of G1 and G2 must be zero or the pid of a child which is a job
  147. process group leader; otherwise the results are undefined, but it is
  148. recommended to return an error and do nothing.
  149. The normal case for this function is that the terminal's current
  150. process group is that specified by G1, or belongs to a descendant
  151. process of the process specified by G1. In the normal case, the
  152. function always succeeds and performs as specified, assuming the
  153. argument G2 is valid.
  154. In the abnormal case, it is not specified what happens. It is
  155. possible for the function to have its normal effect, but only later,
  156. once some grandparent gives the parent permission once again. It is
  157. possible for it to signal SIGTTOU or SIGTTIN (choose one) in which
  158. case the results can depend on whether the signal is handled. If
  159. SIGTTIN or SIGTTOU (whichever) is ignored, it is possible for it to be
  160. a no-op, or it is possible for it to set the terminal's pgrp to G2
  161. anyway.
  162. It is not necessary to speak about matching uids, because in standard
  163. usage the real uids are always the same. We need not speak about
  164. whether root is permitted to do anything special.
  165. change_term_pgrp can be implemented on Unix as a library routine
  166. that uses the old ugly recipe involving signal (SIGTTOU).
  167. On some other systems, where each child job process group can be
  168. controlled independently and the parent can always use the terminal
  169. regardless of them, this call would turn off permission for group G1
  170. (if that is not zero) and then turn on permission for group G2 (if G2
  171. is not zero). G1 is not needed on Unix, but it is essential on
  172. systems where multiple children can have permission independently. It
  173. is never very hard for a shell to remember who it last gave permission
  174. to.
  175. Thus the least common denominator of functionality--that which is
  176. possible on Unix--can be had in a standard way that can be implemented
  177. on many other kinds of system architectures.
  178. **4* is handled well by the proposal, except that it should not
  179. be specified that any actual input or output can take place if
  180. the signal SIGTTIN or SIGTTOU is ignored. It should be permitted
  181. for the read or write to hang or be ignored; or the system could
  182. provide nonstandard ways to control which of these happens.
  183. * C.7.2.5
  184. "A call to close () on a terminal device ... all pending input
  185. is discarded."
  186. This is a disaster! I fork a subprocess, and it does freopen on
  187. stdin, and that throws away terminal input???
  188. Perhaps there was an omission in the text of this part of the
  189. standard. Perhaps it only means to apply to closing the last open
  190. descriptor on the terminal. This falls into the domain of how
  191. controlling terminals are connected with users' jobs, which should not
  192. be addressed; so if this is what is meant, it would be better not to
  193. mention it.
  194. * C.7.2.6.1
  195. It should not be required that the escape character for verbatim
  196. entry is \. It is enough to suggest that there be such a
  197. character. In fact, this is a poor choice, because it is cleanest
  198. if all printing characters are free of any meaning for input editing.
  199. * C.7.2.8
  200. It should not be specified that you cannot escape
  201. the other special characters such as INTR, QUIT, SUSP...
  202. It is ok to permit this to be possible and also permit it
  203. to be impossible. A system might want to allow this if the
  204. escape character is nonprinting (such as ^V) but not allow this
  205. if the escape character is printing (such as \); or it could
  206. have another nonstandard flag that controls this decision.
  207. * C.7.2.12
  208. The only flag that an application program needs to know about is OPOST, so
  209. it would be a good idea to omit discussion of the other fields.
  210. If they are not omitted, then at least the initial values of variables
  211. that control how filling should be done should not be specified, since
  212. many systems will want to initialize these automatically according to
  213. what is known about the terminal.
  214. * C.7.2.13
  215. The only information in c_cflag that is needed by an application
  216. program is the baud rate, and possibly PARENB (I am not sure;
  217. depending on the meaning of some of the bits in other words,
  218. perhaps it is not necessary to deal with PARENB in order to
  219. send 8-bit data. That would be a good idea in any case.)
  220. It would be better not to mention the others in the standard.
  221. Encoding the baud rate in this way is very fragile; we can be
  222. sure that baud rates will exist that cannot be described.
  223. It would be better to represent the baud rates simply as binary
  224. numbers stored in 32-bit fields. It is even possible to define
  225. ways of doing this that do not require a change in the
  226. `struct termios', though that interface would only approximately
  227. work if the baud rate were not one it can describe.
  228. Simply define a new ioctl for getting "real" access to the
  229. baud rates.
  230. * C.7.2.14
  231. It would be better to omit mention of ECHOE, ECHOPRT and ECHOKE
  232. because these really pertain to a style of use of the terminal.
  233. This information really depends on the kind of terminal you have,
  234. not on which application program is running.
  235. We should standardize interfaces by which application programs say
  236. what they want done, at a level that is meaningful for the application
  237. program. Thus, whether echoing should be done, and whether erase and
  238. kill should be done, are things that application programs need to control.
  239. But *how* the echoing looks, or how erase and kill processing looks,
  240. should be considered part of the internals of the system. Suppose
  241. the system is window-oriented. Should it still be required to provide
  242. the functionality of ECHOPRT, which is intended for printing terminals?
  243. If not, what use is there in mentioning ECHOPRT if it may not do anything?
  244. It is nice for a system to show erased characters on a printing terminal
  245. by reechoing them, but even if it fails to do this, that is not a concern
  246. for the Posix standard. Standard Posix application programs will "work"
  247. according to this systems idea of what "working" means, which does not
  248. include reechoing the erased characters.
  249. PAGEOUT should be part of the standard, but the details of how and
  250. when the system pauses, or how the user can cause resumption, should
  251. not be specified. It is enough if the system interprets PAGEOUT by
  252. pausing often enough to facilitate reading the output and gives the
  253. user a convenient way to say when to resume.
  254. The Incompatible Timesharing System offers the program the opportunity
  255. to get a signal when it attempts to write a character that will cause
  256. a pause to happen. When this feature is in use, the system does not
  257. pause; it expects the signal handler to print "--more--" or whatever
  258. it likes, and then to wait for input. The standard should not
  259. preclude offering this as an optional way to "pause". Saying nothing
  260. about how "pausing" works is the easiest way.
  261. * WRAP
  262. I wonder how the system knows what column the cursor is in. It cannot
  263. always know. If all programs that want to do cursor control are
  264. expected to turn off all output postprocessing, then WRAP need not be
  265. part of the standard (assuming that OPOST overrides WRAP, as I hope it
  266. does) because application programs that want postprocessing don't need
  267. to know whether the wrapping takes place in the terminal or in the
  268. system.
  269. It would be clearer to put WRAP in c_oflag.
  270. * C.7.2.15
  271. There needs to be a standard for how to disable any one of
  272. the special characters such as INTR, QUIT, etc.
  273. This cannot be done by storing a value that "isn't a real character
  274. code" because there are none! For example 0377, which is often used
  275. to disable one of these features. is the character Meta-Delete, which
  276. is a commonly used Emacs command.
  277. Some Unix systems treat 0377 specially: it really does mean "disable
  278. this function". Others currently use this to mean that Meta-Delete
  279. should have the function.
  280. I think that defining 0377 to mean "disable" would be an adequate
  281. solution. A slightly better solution would allow any character code
  282. whatever to be specified, and have "disable" as another alternative.
  283. For example, the "characters" could actually be shorts, and then a
  284. value out of range as a character could mean "disable". There could
  285. be a standard name for one such value that is recommended for this
  286. use.
  287. Some systems with special terminals may have special keyboard keys for
  288. such functions as suspending and editing. I think we should say that
  289. it is ok for such systems to ignore the characters specified by the
  290. application program. Their users won't mind; they know which special
  291. keys to use and won't be confused if those same keys work even when
  292. they run a program that normally (on ASCII keyboards) wants to select
  293. special keys.
  294. * C.7.2.16
  295. Since TCSBRK is a complicated combination of other calls defined
  296. here, perhaps it should be deleted from the standard.
  297. TCEXCL may not make any sense on some systems, so it should not be
  298. required to have any effect. It may be useful to specify the name and
  299. its calling sequence as a standard, and say that if it makes sense to
  300. have exclusive reservation of a terminal then this is the way to do
  301. it; otherwise this call should do nothing.
  302. TIOCSPGRP should be replaced by change_term_pgrp, as described above,
  303. and TIOCGPGRP should be eliminated, because there is no way to define
  304. the one-and-only pgrp of the terminal on systems where permission
  305. can be granted independently to various children.
  306. * Several sections say that "the initial value is all bits clear."
  307. Surely this does not mean that an application program should expect
  308. such fields as OPOST and ICANON to be zero when it is started. What,
  309. then, does it mean?
  310. If the initial value means "when the system is started" or "when
  311. the getty starts running", that is something the standard should not
  312. talk about. There may not be such a thing as a getty.
  313. The only kind of initial value that would be useful to the users of
  314. the standard, the writers of portable application programs, is the
  315. value when an application program is started. But nothing can be said
  316. about most of the bits at that time, because they depend on the kind
  317. of terminal on and the user's preferences, and system architecture.
  318. You might think it is possible to say, for example, that ICANON will
  319. be 1 when an application program is started. This does not depend on
  320. the kind of terminal, and few users are likely to prefer no input
  321. editing. But this is not true when the program is running under Emacs
  322. with Emacs sending it input from an editor buffer, even though the
  323. user does have an input editing capability.
  324. It is best to say nothing about any sort of "initial state" for the
  325. contents of the termios structure. When programs that care about the
  326. state, it is enough that the standard says how to set up that state.
  327. For other programs (most programs) it is sufficient to assume that the
  328. bits are set the way the user or shell considered reasonable. That is
  329. all that is needed for writing portable programs.