186d7f5d3SJohn Marino/*- 286d7f5d3SJohn Marino * Copyright (c) 1990, 1993 386d7f5d3SJohn Marino * The Regents of the University of California. All rights reserved. 486d7f5d3SJohn Marino * 586d7f5d3SJohn Marino * This code is derived from software contributed to Berkeley by 686d7f5d3SJohn Marino * Edward Wang at The University of California, Berkeley. 786d7f5d3SJohn Marino * 886d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without 986d7f5d3SJohn Marino * modification, are permitted provided that the following conditions 1086d7f5d3SJohn Marino * are met: 1186d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright 1286d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer. 1386d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 1486d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the 1586d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution. 1686d7f5d3SJohn Marino * 3. Neither the name of the University nor the names of its contributors 1786d7f5d3SJohn Marino * may be used to endorse or promote products derived from this software 1886d7f5d3SJohn Marino * without specific prior written permission. 1986d7f5d3SJohn Marino * 2086d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2186d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2286d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2386d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2486d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2586d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2686d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2786d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2886d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2986d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3086d7f5d3SJohn Marino * SUCH DAMAGE. 3186d7f5d3SJohn Marino * 3286d7f5d3SJohn Marino * @(#)README 8.1 (Berkeley) 6/6/93 3386d7f5d3SJohn Marino */ 3486d7f5d3SJohn Marino 3586d7f5d3SJohn MarinoCompilation notes: 3686d7f5d3SJohn Marino 3786d7f5d3SJohn Marino Compiler options: 3886d7f5d3SJohn Marino 3986d7f5d3SJohn Marino BYTE_ORDER (used only in ww.h) 4086d7f5d3SJohn Marino It should already be defined in machine/endian.h. 4186d7f5d3SJohn Marino The code knows about BIG_ENDIAN, LITTLE_ENDIAN, and PDP_ENDIAN. 4286d7f5d3SJohn Marino It only cares about byte order in words, so PDP_ENDIAN 4386d7f5d3SJohn Marino is the same as LITTLE_ENDIAN. 4486d7f5d3SJohn Marino OLD_TTY 4586d7f5d3SJohn Marino If you don't have Posix termios, then define this. 4686d7f5d3SJohn Marino VMIN_BUG 4786d7f5d3SJohn Marino Even if you have Posix termios, define this if the MIN and TIME 4886d7f5d3SJohn Marino feature in noncanonical mode doesn't work correctly. 4986d7f5d3SJohn Marino 5086d7f5d3SJohn Marino Ok, there's another one, STR_DEBUG. It turns on consistency checks 5186d7f5d3SJohn Marino in the string allocator. It's been left on since performace doesn't 5286d7f5d3SJohn Marino seem to suffer. There's an abort() somewhere when an inconsistency 5386d7f5d3SJohn Marino is found. It hasn't happened in years. 5486d7f5d3SJohn Marino 5586d7f5d3SJohn Marino The file local.h contains locally tunable constants. 5686d7f5d3SJohn Marino 5786d7f5d3SJohn Marino The makefile used to be updated with mkmf; it has been changed 5886d7f5d3SJohn Marinoat various times to use cpp -M and, currently, mkdep. The only library 5986d7f5d3SJohn Marinoit needs is termcap. 6086d7f5d3SJohn Marino 6186d7f5d3SJohn Marino Window, as is, only runs on 4.3 (or later) machines. 6286d7f5d3SJohn Marino 6386d7f5d3SJohn Marino On 4.2 machines, at least these modifications must be done: 6486d7f5d3SJohn Marino 6586d7f5d3SJohn Marino delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ, 6686d7f5d3SJohn Marino struct winsize 6786d7f5d3SJohn Marino add to ww.h 6886d7f5d3SJohn Marino typedef int fd_set; 6986d7f5d3SJohn Marino #define FD_ZERO(s) (*(s) = 0) 7086d7f5d3SJohn Marino #define FD_SET(b, s) (*(s) |= 1 << (b)) 7186d7f5d3SJohn Marino #define FD_ISSET(b, s) (*(s) & 1 << (b)) 7286d7f5d3SJohn Marino add to ww.h 7386d7f5d3SJohn Marino #define sigmask(s) (1 << (s) - 1) 7486d7f5d3SJohn Marino 7586d7f5d3SJohn Marino 7686d7f5d3SJohn MarinoA few notes about the internals: 7786d7f5d3SJohn Marino 7886d7f5d3SJohn Marino The window package. Windows are opened by calling wwopen(). 7986d7f5d3SJohn MarinoWwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), 8086d7f5d3SJohn Marinoand wwprintf() are also supported. Some of the outputs to windows are 8186d7f5d3SJohn Marinodelayed. Wwupdate() updates the terminal to match the internal screen 8286d7f5d3SJohn Marinobuffer. Wwspawn() spawns a child process on the other end of a window, 8386d7f5d3SJohn Marinowith its environment tailored to the window. Visible windows are 8486d7f5d3SJohn Marinodoubly linked in the order of their overlap. Wwadd() inserts a window 8586d7f5d3SJohn Marinointo the list at a given place. Wwdelete() deletes it. Windows not in 8686d7f5d3SJohn Marinothe list are not visible, though wwwrite() still works. Window was 8786d7f5d3SJohn Marinowritten before the days of X and Sunview, so some of the terminology 8886d7f5d3SJohn Marinois not standard. 8986d7f5d3SJohn Marino 9086d7f5d3SJohn Marino Most functions return -1 on error. Wwopen() returns the null 9186d7f5d3SJohn Marinopointer. An error number is saved in wwerrno. Wwerror() returns an 9286d7f5d3SJohn Marinoerror string based on wwerrno suitable for printing. 9386d7f5d3SJohn Marino 9486d7f5d3SJohn Marino The terminal drivers perform all output to the physical terminal, 9586d7f5d3SJohn Marinoincluding special functions like character and line insertion and 9686d7f5d3SJohn Marinodeletion. The window package keeps a list of known terminals. At 9786d7f5d3SJohn Marinoinitialization time, the terminal type is matched against the list to 9886d7f5d3SJohn Marinofind the right terminal driver to use. The last driver, the generic 9986d7f5d3SJohn Marinodriver, matches all terminals and uses the termcap database. The 10086d7f5d3SJohn Marinointerface between the window package the terminal driver is the `tt' 10186d7f5d3SJohn Marinostructure. It contains pointers to functions to perform special 10286d7f5d3SJohn Marinofunctions and terminal output, as well as flags about the 10386d7f5d3SJohn Marinocharacteristics of the terminal. Most of these ideas are borrowed 10486d7f5d3SJohn Marinofrom the Maryland window package, which in turn is based on Goslin's 10586d7f5d3SJohn MarinoEmacs. 10686d7f5d3SJohn Marino 10786d7f5d3SJohn Marino The IO system is semi-synchronous. Terminal input is signal 10886d7f5d3SJohn Marinodriven, and everything else is done synchronously with a single 10986d7f5d3SJohn Marinopoll(). It is roughly event-driven, though not in a clean way. 11086d7f5d3SJohn Marino 11186d7f5d3SJohn Marino Normally, in both conversation mode and command mode, window 11286d7f5d3SJohn Marinosleeps in a poll() in wwiomux() waiting for data from the 11386d7f5d3SJohn Marinopseudo-terminals. At the same time, terminal input causes SIGIO which 11486d7f5d3SJohn Marinois caught by wwrint(). The poll() returns when at least one of the 11586d7f5d3SJohn Marinopseudo-terminals becomes ready for reading. 11686d7f5d3SJohn Marino 11786d7f5d3SJohn Marino Wwrint() is the interrupt handler for tty input. It reads input 11886d7f5d3SJohn Marinointo a linear buffer accessed through four pointers: 11986d7f5d3SJohn Marino 12086d7f5d3SJohn Marino +-------+--------------+----------------+ 12186d7f5d3SJohn Marino | empty | data | empty | 12286d7f5d3SJohn Marino +-------+--------------+----------------+ 12386d7f5d3SJohn Marino ^ ^ ^ ^ 12486d7f5d3SJohn Marino | | | | 12586d7f5d3SJohn Marino wwib wwibp wwibq wwibe 12686d7f5d3SJohn Marino 12786d7f5d3SJohn MarinoWwrint() appends characters at the end and increments wwibq (*wwibq++ 12886d7f5d3SJohn Marino= c), and characters are taken off the buffer at wwibp using the 12986d7f5d3SJohn Marinowwgetc() and wwpeekc() macros. As is the convention in C, wwibq 13086d7f5d3SJohn Marinoand wwibe point to one position beyond the end. In addition, 13186d7f5d3SJohn Marinowwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is 13286d7f5d3SJohn Marinoused by wwiomux() to interrupt the poll() which would otherwise 13386d7f5d3SJohn Marinoresume after the interrupt. (Actually, I hear this is not true, 13486d7f5d3SJohn Marinobut the longjmp feature is used to avoid a race condition as well. 13586d7f5d3SJohn MarinoAnyway, it means I didn't have to depend on a feature in a 13686d7f5d3SJohn Marinodaily-changing kernel, but that's another story.) The macro 13786d7f5d3SJohn Marinowwinterrupt() returns true if the input buffer is non-empty. 13886d7f5d3SJohn MarinoWwupdate(), wwwrite(), and wwiomux() check this condition and will 13986d7f5d3SJohn Marinoreturn at the first convenient opportunity when it becomes true. 14086d7f5d3SJohn MarinoIn the case of wwwrite(), the flag ww_nointr in the window structure 14186d7f5d3SJohn Marinooverrides this. This feature allows the user to interrupt lengthy 14286d7f5d3SJohn Marinooutputs safely. The structure of the input buffer is designed to 14386d7f5d3SJohn Marinoavoid race conditions without blocking interrupts. 14486d7f5d3SJohn Marino 14586d7f5d3SJohn Marino Actually, wwsetjmp and wwinterrupt() are part of a software 14686d7f5d3SJohn Marinointerrupt scheme used by the two interrupt catchers wwrint() and 14786d7f5d3SJohn Marinowwchild(). Asserting the interrupt lets the synchronous parts of 14886d7f5d3SJohn Marinothe program know that there's an interesting asynchronous condition 14986d7f5d3SJohn Marino(i.e., got a keyboard character, or a child process died) that they 15086d7f5d3SJohn Marinomight want to process before anything else. The synchronous routines 15186d7f5d3SJohn Marinocan check for this condition with wwinterrupt() or by arranging 15286d7f5d3SJohn Marinothat a longjmp() be done. 15386d7f5d3SJohn Marino 15486d7f5d3SJohn Marino Wwiomux() copies pseudo-terminal output into their corresponding 15586d7f5d3SJohn Marinowindows. Without anything to do, it blocks in a poll(), waiting for 15686d7f5d3SJohn Marinoread ready on pseudo-terminals. Reads are done into per-window buffers 15786d7f5d3SJohn Marinoin the window structures. When there is at least one buffer non-empty, 15886d7f5d3SJohn Marinowwiomux() finds the top most of these windows and writes it using 15986d7f5d3SJohn Marinowwwrite(). Then the process is repeated. A non-blocking poll() is 16086d7f5d3SJohn Marinodone after a wwwrite() to pick up any output that may have come in 16186d7f5d3SJohn Marinoduring the write, which may take a long time. Specifically, we use 16286d7f5d3SJohn Marinothis to stop output or flush buffer when a pseudo-terminal tells us to 16386d7f5d3SJohn Marino(we use pty packet mode). The poll() blocks only when all of the 16486d7f5d3SJohn Marinowindows' buffers are empty. A wwupdate() is done prior to this, which 16586d7f5d3SJohn Marinois the only time the screen is guaranteed to be completely up to date. 16686d7f5d3SJohn MarinoWwiomux() loops until wwinterrupt() becomes true. 16786d7f5d3SJohn Marino 16886d7f5d3SJohn Marino The top level routine for all this is mloop(). In conversation 16986d7f5d3SJohn Marinomode, it simply calls wwiomux(), which only returns when input is 17086d7f5d3SJohn Marinoavailable. The input buffer is then written to the pseudo-terminal of 17186d7f5d3SJohn Marinothe current window. If the escape character is found in the input, 17286d7f5d3SJohn Marinocommand mode is entered. Otherwise, the process is repeated. In 17386d7f5d3SJohn Marinocommand mode, control is transferred to docmd() which returns only when 17486d7f5d3SJohn Marinoconversation mode is reentered. Docmd() and other command processing 17586d7f5d3SJohn Marinoroutines typically wait for input in a loop: 17686d7f5d3SJohn Marino 17786d7f5d3SJohn Marino while (wwpeekc() < 0) 17886d7f5d3SJohn Marino wwiomux(); 17986d7f5d3SJohn Marino 18086d7f5d3SJohn MarinoWhen the loop terminates, wwgetc() is used to read the input buffer. 18186d7f5d3SJohn Marino 18286d7f5d3SJohn Marino Output to the physical terminal is handled by the lowest level 18386d7f5d3SJohn Marinoroutines of the window package, in the files ttoutput.c and tt.h. The 18486d7f5d3SJohn Marinostandard IO package is not used, to get better control over buffering 18586d7f5d3SJohn Marinoand to use non-blocking reads in wwrint(). The buffer size is set to 18686d7f5d3SJohn Marinoapproximately one second of output time, based on the baudrate. 18786d7f5d3SJohn Marino 18886d7f5d3SJohn Marino The result of all this complexity is faster response time, 18986d7f5d3SJohn Marinoespecially in output stopping and flushing. Wwwrite() checks 19086d7f5d3SJohn Marinowwinterrupt() after every line. It also calls wwupdate() for each line 19186d7f5d3SJohn Marinoit writes. The output buffer is limited to one second of output time. 19286d7f5d3SJohn MarinoThus, there is usually only a delay of one to two lines plus one second 19386d7f5d3SJohn Marinoafter a ^C or ^S. Also, commands that produce lengthy output can be 19486d7f5d3SJohn Marinoaborted without actually showing all of it on the terminal. (Try the 19586d7f5d3SJohn Marino'?' command followed by escape immediately.) 196