Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site fortune.UUCP Path: utzoo!watmath!clyde!floyd!harpo!ihnp4!fortune!rpw3 From: rpw3@fortune.UUCP Newsgroups: net.unix Subject: Re: pty.c in 4.1BSD ? - (nf) Message-ID: <2813@fortune.UUCP> Date: Thu, 22-Mar-84 07:05:38 EST Article-I.D.: fortune.2813 Posted: Thu Mar 22 07:05:38 1984 Date-Received: Fri, 23-Mar-84 08:19:25 EST Sender: notes@fortune.UUCP Organization: Fortune Systems, Redwood City, CA Lines: 167 #R:vaxwalle:-14000:fortune:26900033:000:9520 fortune!rpw3 Mar 22 02:38:00 1984 "What is a pty?" [163 lines, but please, no flames, guys, it's history/tutorial time...] The pseudo-teletype ("pty") is not a Berkeley-ism, nor even a UNIX-ism. It's pretty widely industry standard on timesharing operating systems. (My first exposure to them was back in 1970, on DEC PDP-10's, but they were old even then. They pronounced the acronym "pity", to rhyme with "tty".) ((My apologies if I leave out earlier systems, maybe MULTICS, of which I have no direct experience.)) A pseudo-teletype is a specialized form of a "virtual device", that is, a "device" which is really manifested by a program ("Pay no attention to the [process] behind the curtain!"). As said in the excerpt you quoted, a pty normally has two ends, a "master" end and a "slave" end. Under UNIX, the "master" end is normally named "/dev/ptyNN" while the slave end is named "/dev/ttyNN". (On some systems the slaves are "/dev/ttypN".) The point is that since (if the implementation of "pty.c" is correct, and it should be) there is no way that a process can (easily) tell that the "slave" end is not a real, live, physical piece of hardware, and a process controlling the "master" end can EXACTLY emulate a physical human sitting at a terminal typing and reading. In fact, this emulation is generally so exact that the slave ends are simply listed in /etc/ttys with all the other terminals, and get a "getty/login/shell" from "init" just like the rest, with a line in /etc/ttys like "1mtty03" or "1mttyp3" (login port, 9600 baud, /dev/tty03 or /dev/ttyp3). [Here on, assume slaves named ttyNN.] So (messy details of flag handling and synchronization omitted), some process "X" opens the master side of a pty, say /dev/pty43. Since the beginning of time, some copy of the program "getty" was trying to open /dev/tty43 (since "init" forks a copy of "getty" for each line in /etc/ttys), and that open now completes, since "somebody" (process X) just "dialed in". "Getty" writes a banner on tty43, which X reads by reading pty43. X then "types" its login name by writing on pty43 which "getty" reads on tty43, and so on through the login process, running the shell, and then the user programs, etc. "Terminal input" is "typed" by X by writing on pty43, "display output" is "read" by X by reading pty43, and all the user programs are dumb and happy thinking there's a human on the other end of tty43. So why would one want to do this? Basically, in historical order of evolution, four reasons: 1. Batch (Background) Processing of Commands. On systems (not UNIX) which are NOT process oriented, and which therefore did NOT have the concept of a "fork", there was no easy way to have background (or "batch") jobs. The pty was a clever, elegant solution that left the basic "timesharing" nature of the system unchanged, while providing essentially what we now call shell scripts. Example: On a PDP-10, you said ".submit foo.ctl" and "foo.ctl" was fed to an operator program named BATCON (run from one of the operator's consoles) that opened a pty and "typed" your monitor commands in (including logging you in and out), and saved up the output in a file called "foo.log" for your later amusement and amazement (since Murphy's Law was true even back then ;-}). Even with all that convenience (;-}), systems administrators got tired of having a terminal in the machine room for EACH copy of EACH operator service program (no "fork", remember, so one tty for each line printer spooler and for each batch stream and for each card reader...), so... 2. Job Control - Multiple jobs active from one terminal. A new operator service program (named OPSER on PDP-10's, OPRCON on TOPS-20) was invented which incestuously used ptys to control all of the other operator service jobs! You could type a line into a given job by prefixing the line with the subjob number or mnemonic (set up by the operator), such as, to change forms on printer 3 you said "L3-forms payroll2" (or something). Since it was perfectly general, the operator could also do small utility tasks (like accounting, etc.) through the same terminal (except for the hassle of those other jobs sometimes yammering at you -- but there were commands to handle that). For convenience, if you typed a line that didn't start with "XX-" it assumed you meant the last one you explicitly talked to, so an extended conversation was fairly confortable. Eventually, ordinary users started using OPSER when they needed to multiplex several activities, or whenever they needed its script and logging features. (Like the "script" program.) In modern terminology, what you had there was a line-oriented "window" manager, similar to the "Maryland Windows" package, but for Teletype Model 33's. Or, somewhat like Berkeley 4.1bsd job-control under the C-shell ("csh"), but with processes NOT suspended just because you weren't typing at them (they could still type out progress reports, if you didn't disable them). [Personal aside to any wizards who have made it this far: having used both OPSER and 4.1 csh with job-control, I'll take pty-based "job control" hands down, PROVIDED it's always there and is the default. I understand the problem in S5 is you have to decide ahead of time whether you're going to need it (?).] Home stretch... 3. Network Virtual Terminals. With the advent of networks of many strange and wonderful kinds, seldom being integrated into the operating system completely on first release, the ancient pty was again drawn into service [is this getting a little thick? ;-}] as a quick, simple, effective way of implementing a basic network service -- remote logins. The operating systems (including UNIX) rarely treated network connections as full citizens, and besides, there were many versions -- which one(s) to support? The answer (even today, often) is to have a program running on the target system (the one you're trying to login on) called a "network virtual terminal protocol server" (typically named "vtpsrv") which sits around waiting for people out in the network to connect to it (via whatever net hardware and software one might have). When someone does so, the "vtpsrv" handles all the network stuff, eventually passing characters typed by a user (or a program) out in the network to the master side of a pty as if the user were local to the target machine, and "displaying" output (read from the pty) by sending it back out into the network. Because of the local (target) "vtpsrv", the target operating system doesn't have to worry about "network terminals" -- it doesn't have any! (That's the "virtual" part.) Smarter versions of "vtpsrv" (or of the corresponding program that the real user runs out there in the network, usually called "vtp") can sometimes also handle some transformations from one terminal type to another (a different meaning of "virtual terminal"). Naturally, there should be some standards around for how the various pieces talk to each other. There are, but of course they are network dependent. Within the ARPAnet (or other nets using IP/TCP protocols), the protocol between a "vtp" and a "vtpsrv" is called "Telnet" (NOT to be confused with the company Telenet!). Within the CCITT world (the "X.nn" and "V.nn" international standards), the protocol between the user and "vtp" (yes, users have to obey protocols, too!) is called X.28, the protocol between "vtp" and "vtpsrv" is called X.29, and the overall scheme is called X.3 (and sits on top of X.25 -- aren't you glad you asked?). Telenet (the company) uses protocols VERY close to the CCITT standards. Of course, as efficiency becomes an issue, it is tempting to put all of "vtpsrv" in the kernel of the operating system, and this is often cited as a mark of a "integrated" network offering. Nevertheless, the flexibility of the pty approach often wins over raw efficiency. (Various players do it various ways.) Finally (and this IS short), 4. Virtual Devices. Although the pty is a specialized virtual device, having (usually) just the set of "ioctl" calls needed to emulate a tty, sometimes people will use them to emulate hardware that hasn't been built yet (or for which the driver hasn't been written yet), in order to decouple the writing/building of the "system" side (driver/hardware) from the "user" side (applications programs). With a little tinkering (mostly just more general handling of ioctl's), ptys can be made to emulate any UNIX "character device". This hack has even been used occasionaly to execute programs that would only run on specific hardware or kernels, when equivalent (but unfortunately, different) systems were available. SUMMARY These days, #3 (networks) is the most common use of ptys, but the increasing emphasis on "windows" is reviving #2 (multiplexing). [May this lengthy, chatty, uneven reminiscence be of use to someone.] Rob Warnock UUCP: {sri-unix,amd70,hpda,harpo,ihnp4,allegra}!fortune!rpw3 DDD: (415)595-8444 USPS: Fortune Systems Corp, 101 Twin Dolphin Drive, Redwood City, CA 94065 p.s. I have completely ignored the issue of the so-called "mpx" device, found (partially) in UNIX Edition 7 (v.7) (and other UNIXs, as well as several non-UNIX systems), which could be used like a pty with one master side and many slave sides. Requicat In Pacem. Who knows, it may become "popular" again some day, eh?