1/* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 * 12 * @(#)README 3.10 (Berkeley) 03/19/88 13 */ 14 15Compilation notes: 16 17 There is only one compiler option: 18 19 vax use Vax byte order (found in ww.h) 20 Actually MIPSEL is also little-endian. 21 Anyway, they should already be defined in the 22 preprocessor. 23 If neither is defined, big-endian is assumed. 24 25 Ok, there's another one, STR_DEBUG. It turns on consistency checks 26 in the string allocator. It's been left on since performace doesn't 27 seem to suffer. There's an abort() somewhere when an inconsistency 28 is found. It hasn't happened in years. 29 30 The file local.h contains locally tunable constants. 31 32 The makefile used to be updated with mkmf; it has been changed 33at various times to use cpp -M and, currently, mkdep. The only library 34it needs is termcap. 35 36 Window, as is, only runs on 4.3 machines. 37 38 On 4.2 machines, at least these modifications must be done: 39 40 delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ, 41 struct winsize 42 add to ww.h 43 typedef int fd_set; 44 #define FD_ZERO(s) (*(s) = 0) 45 #define FD_SET(b, s) (*(s) |= 1 << (b)) 46 #define FD_ISSET(b, s) (*(s) & 1 << (b)) 47 add to ww.h 48 #define sigmask(s) (1 << (s) - 1) 49 50 51A few notes about the internals: 52 53 The window package. Windows are opened by calling wwopen(). 54Wwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), 55and wwprintf() are also supported. Some of the outputs to windows are 56delayed. Wwupdate() updates the terminal to match the internal screen 57buffer. Wwspawn() spawns a child process on the other end of a window, 58with its environment tailored to the window. Visible windows are 59doubly linked in the order of their overlap. Wwadd() inserts a window 60into the list at a given place. Wwdelete() deletes it. Windows not in 61the list are not visible, though wwwrite() still works. Window was 62written before the days of X and Sunview, so some of the terminology 63is not standard. 64 65 Most functions return -1 on error. Wwopen() returns the null 66pointer. An error number is saved in wwerrno. Wwerror() returns an 67error string based on wwerrno suitable for printing. 68 69 The terminal drivers perform all output to the physical terminal, 70including special functions like character and line insertion and 71deletion. The window package keeps a list of known terminals. At 72initialization time, the terminal type is matched against the list to 73find the right terminal driver to use. The last driver, the generic 74driver, matches all terminals and uses the termcap database. The 75interface between the window package the terminal driver is the `tt' 76structure. It contains pointers to functions to perform special 77functions and terminal output, as well as flags about the 78characteristics of the terminal. Most of these ideas are borrowed 79from the Maryland window package, which in turn is based on Goslin's 80Emacs. 81 82 The IO system is semi-synchronous. Terminal input is signal 83driven, and everything else is done synchronously with a single 84select(). It is roughly event-driven, though not in a clean way. 85 86 Normally, in both conversation mode and command mode, window 87sleeps in a select() in wwiomux() waiting for data from the 88pseudo-terminals. At the same time, terminal input causes SIGIO which 89is caught by wwrint(). The select() returns when at least one of the 90pseudo-terminals becomes ready for reading. 91 92 Wwrint() is the interrupt handler for tty input. It reads input 93into a linear buffer accessed through four pointers: 94 95 +-------+--------------+----------------+ 96 | empty | data | empty | 97 +-------+--------------+----------------+ 98 ^ ^ ^ ^ 99 | | | | 100 wwib wwibp wwibq wwibe 101 102Wwrint() appends characters at the end and increments wwibq (*wwibq++ 103= c), and characters are taken off the buffer at wwibp using the 104wwgetc() and wwpeekc() macros. As is the convention in C, wwibq 105and wwibe point to one position beyond the end. In addition, 106wwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is 107used by wwiomux() to interrupt the select() which would otherwise 108resume after the interrupt. (Actually, I hear this is not true, 109but the longjmp feature is used to avoid a race condition as well. 110Anyway, it means I didn't have to depend on a feature in a 111daily-changing kernel, but that's another story.) The macro 112wwinterrupt() returns true if the input buffer is non-empty. 113Wwupdate(), wwwrite(), and wwiomux() check this condition and will 114return at the first convenient opportunity when it becomes true. 115In the case of wwwrite(), the flag ww_nointr in the window structure 116overrides this. This feature allows the user to interrupt lengthy 117outputs safely. The structure of the input buffer is designed to 118avoid race conditions without blocking interrupts. 119 120 Actually, wwsetjmp and wwinterrupt() are part of a software 121interrupt scheme used by the two interrupt catchers wwrint() and 122wwchild(). Asserting the interrupt lets the synchronous parts of 123the program know that there's an interesting asynchronous condition 124(i.e., got a keyboard character, or a child process died) that they 125might want to process before anything else. The synchronous routines 126can check for this condition with wwinterrupt() or by arranging 127that a longjmp() be done. 128 129 Wwiomux() copies pseudo-terminal output into their corresponding 130windows. Without anything to do, it blocks in a select(), waiting for 131read ready on pseudo-terminals. Reads are done into per-window buffers 132in the window structures. When there is at least one buffer non-empty, 133wwiomux() finds the top most of these windows and writes it using 134wwwrite(). Then the process is repeated. A non-blocking select() is 135done after a wwwrite() to pick up any output that may have come in 136during the write, which may take a long time. Specifically, we use 137this to stop output or flush buffer when a pseudo-terminal tells us to 138(we use pty packet mode). The select() blocks only when all of the 139windows' buffers are empty. A wwupdate() is done prior to this, which 140is the only time the screen is guaranteed to be completely up to date. 141Wwiomux() loops until wwinterrupt() becomes true. 142 143 The top level routine for all this is mloop(). In conversation 144mode, it simply calls wwiomux(), which only returns when input is 145available. The input buffer is then written to the pseudo-terminal of 146the current window. If the escape character is found in the input, 147command mode is entered. Otherwise, the process is repeated. In 148command mode, control is transferred to docmd() which returns only when 149conversation mode is reentered. Docmd() and other command processing 150routines typically wait for input in a loop: 151 152 while (wwpeekc() < 0) 153 wwiomux(); 154 155When the loop terminates, wwgetc() is used to read the input buffer. 156 157 Output to the physical terminal is handled by the lowest level 158routines of the window package, in the files ttoutput.c and tt.h. The 159standard IO package is not used, to get better control over buffering 160and to use non-blocking reads in wwrint(). The buffer size is set to 161approximately one second of output time, based on the baudrate. 162 163 The result of all this complexity is faster response time, 164especially in output stopping and flushing. Wwwrite() checks 165wwinterrupt() after every line. It also calls wwupdate() for each line 166it writes. The output buffer is limited to one second of output time. 167Thus, there is usually only a delay of one to two lines plus one second 168after a ^C or ^S. Also, commands that produce lengthy output can be 169aborted without actually showing all of it on the terminal. (Try the 170'?' command followed by escape immediately.) 171