1*16284Sedward@(#)README 3.2 84/04/05 215556Sedward 3*16284SedwardCompilation notes: 415556Sedward 5*16284Sedward The flags: 6*16284Sedward 715556Sedward O_SUN use 68000 byte ordering 815556Sedward O_4_1C 4.1c 915556Sedward O_4_1A 4.1a 1015556Sedward 11*16284Sedward 4.2bsd on a vax needs no flags. Some systems will need the jobs library. 12*16284Sedward4.1a does not support the 't' command. 1315556Sedward 14*16284Sedward The makefile should be updated with mkmf. The only library it needs 15*16284Sedwardis termcap (and jobs for 4.1). 1615556Sedward 17*16284Sedward Do not profile on 4.1. A bug in the system causes profiling 18*16284Sedwardto stay on after an exec. 1915556Sedward 2015556Sedward 21*16284SedwardA few notes about the internals: 22*16284Sedward 23*16284Sedward The window package. Windows are opened by calling wwopen(). 24*16284SedwardWwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), 25*16284Sedwardand wwprintf() are also supported. Some of the outputs to windows are 26*16284Sedwarddelayed. Wwupdate() updates the terminal to match the internal screen 27*16284Sedwardbuffer. Wwspawn() spawns a child process on the other end of a window, 28*16284Sedwardwith it's environment tailored to the window. Visible windows are 29*16284Sedwarddoubly linked in the order of their overlap. Wwadd() inserts a window 30*16284Sedwardinto the list. Wwdelete() deletes it. Windows not in the list are not 31*16284Sedwardvisible, though wwwrite() still works. 32*16284Sedward 33*16284Sedward Most functions return -1 on error. Wwopen() returns the null 34*16284Sedwardpointer. An error number is saved in wwerrno. Wwerror() returns 35*16284Sedwardan error message based on wwerrno suitable for printing. 36*16284Sedward 37*16284Sedward The terminal drivers perform all output to the physical terminal, 38*16284Sedwardincluding special functions like character and line insertion and 39*16284Sedwarddeletion. The window package keeps a list of known terminals. At 40*16284Sedwardinitialization time, the terminal type is matched against the list to 41*16284Sedwardfind the right terminal driver to use. The last driver, the generic 42*16284Sedwarddriver, matches all terminals and uses the termcap database. The 43*16284Sedwardinterface between the window package the terminal driver is the `tt' 44*16284Sedwardstructure. It contains pointers to functions to perform special 45*16284Sedwardfunctions and terminal output, as well as flags about the 46*16284Sedwardcharacteristics of the terminal. 47*16284Sedward 48*16284Sedward The IO system is semi-synchronous. Terminal input is signal driven, 49*16284Sedwardand everything else is done synchronously with a single select(). 50*16284Sedward 51*16284Sedward Normally, in both conversation mode and command mode, window sleeps in 52*16284Sedwarda select() in wwiomux() waiting for data from the pseudo-terminals. At the 53*16284Sedwardsame time, terminal input causes SIGIO which is caught by wwrint(). The 54*16284Sedwardselect() returns when at least one of the pseudo-terminals becomes ready 55*16284Sedwardfor reading. 56*16284Sedward 57*16284Sedward Wwrint() is the interrupt handler for tty input. It reads input into 58*16284Sedwarda linear buffer accessed through four pointers: 59*16284Sedward 60*16284Sedward +-------+--------------+----------------+ 61*16284Sedward | empty | data | empty | 62*16284Sedward +-------+--------------+----------------+ 63*16284Sedward ^ ^ ^ ^ 64*16284Sedward | | | | 65*16284Sedward wwib wwibp wwibq wwibe 66*16284Sedward 67*16284SedwardWwrint() appends characters at the end and increments wwibq (*wwibq++ = c), 68*16284Sedwardand characters are taken from the buffer at wwibp using the wwgetc() and 69*16284Sedwardwwpeekc() macros. As is the convention in C, wwibq and wwibe point to 70*16284Sedwardone position beyond the end. In addition, wwrint() will do a 71*16284Sedwardlongjmp(wwjmpbuf) if wwsetjmp is true. This is used by wwiomux() to 72*16284Sedwardinterrupt the select() which would otherwise resume after the 73*16284Sedwardinterrupt. The macro wwinterrupt() returns true if the input buffer is 74*16284Sedwardnon-empty. Wwupdate(), wwwrite(), and wwiomux() check this condition 75*16284Sedwardand will return at the first convenient opportunity when it becomes 76*16284Sedwardtrue. In the case of wwwrite(), the flag ww_nointr in the window 77*16284Sedwardstructure overrides this. This feature allows the user to interrupt 78*16284Sedwardlengthy outputs safely. The structure of the input is carefully 79*16284Sedwarddesigned to avoid race conditions without blocking interrupts. 80*16284Sedward 81*16284Sedward Wwiomux() copies pseudo-terminal outputs into their corresponding 82*16284Sedwardwindows. Without anything to do, it blocks in a select(), waiting for 83*16284Sedwardread ready on pseudo-terminals. Reads are done into per-window buffers 84*16284Sedwardin the window structures. When there is at least one buffer non-empty, 85*16284Sedwardwwiomux() finds the top most of these windows and writes it using 86*16284Sedwardwwwrite(). Then the process is repeated. The select() blocks only when 87*16284Sedwardall of the windows' buffers are empty. The non-blocking select() is 88*16284Sedwarddone only to pick up any output that may have come in during the wwwrite(), 89*16284Sedwardwhich may take a long time. A wwupdate() is done prior to calling 90*16284Sedwarda blocking select(). This is the only time the screen is guaranteed to 91*16284Sedwardbe completely up to date. The pseudo-terminals run in packet mode to 92*16284Sedwardcontrol output flushing and stopping. Wwiomux() loops until 93*16284Sedwardwwinterrupt() becomes true. 94*16284Sedward 95*16284Sedward The top level routine for all this is mloop(). In conversation mode, 96*16284Sedwardit simply calls wwiomux(), which only returns when input is available. 97*16284SedwardThe input buffer is then written to the pseudo-terminal of the current 98*16284Sedwardwindow. If the escape character is found in the input, command mode 99*16284Sedwardis entered. Otherwise, the process is repeated. In command mode, 100*16284Sedwardcontrol is transferred to docmd() which returns only when conversation 101*16284Sedwardmode is reentered. Docmd() and other command processing routines 102*16284Sedwardtypically wait for input in a loop: 103*16284Sedward 104*16284Sedward while (peekc() < 0) 105*16284Sedward wwiomux(); 106*16284Sedward 107*16284SedwardWhen the loop terminates, getc() is used to read the input buffer. 108*16284Sedward 109*16284Sedward Output to the physical terminal is handled by the lowest level 110*16284Sedwardroutines of the window package, in the files ttoutput.c and tt.h. The 111*16284Sedwardstandard IO package is not used, for better control over buffering and 112*16284Sedwardto use non-blocking reads in wwrint(). The buffer size is set to 113*16284Sedwardapproximately one second of output time, based on the baudrate. 114*16284Sedward 115*16284Sedward The result of all this complexity is faster response time, 116*16284Sedwardespecially in output stopping and flushing. Wwwrite() checks 117*16284Sedwardwwinterrupt() after every line. It also calls wwupdate() for each line 118*16284Sedwardit writes. The output buffer is limited to one second of output time. 119*16284SedwardThus, there is usually only a delay of one to two lines plus one second 120*16284Sedwardafter a ^C or ^S. Also, commands that produce lengthy output can be 121*16284Sedwardaborted without actually showing all of it on the terminal. (Try the 122*16284Sedward'h' command followed by escape immediately.) 123