142954Sbostic/*- 262450Sbostic * Copyright (c) 1990, 1993 362450Sbostic * The Regents of the University of California. All rights reserved. 433514Sbostic * 542954Sbostic * This code is derived from software contributed to Berkeley by 642954Sbostic * Edward Wang at The University of California, Berkeley. 733514Sbostic * 842954Sbostic * %sccs.include.redist.c% 942954Sbostic * 10*62451Sbostic * @(#)README 8.1 (Berkeley) 06/06/93 1118742Sedward */ 1218742Sedward 1316284SedwardCompilation notes: 1415556Sedward 1556709Sedward Compiler options: 1616284Sedward 1736258Sedward BYTE_ORDER (used only in ww.h) 1836258Sedward It should already be defined in machine/endian.h. 1936258Sedward The code knows about BIG_ENDIAN, LITTLE_ENDIAN, and PDP_ENDIAN. 2036258Sedward It only cares about byte order in words, so PDP_ENDIAN 2136258Sedward is the same as LITTLE_ENDIAN. 2256709Sedward OLD_TTY 2356709Sedward If you don't have Posix termios, then define this. 2456709Sedward VMIN_BUG 2556709Sedward Even if you have Posix termios, define this if the MIN and TIME 2656709Sedward feature in noncanonical mode doesn't work correctly. 2715556Sedward 2832343Sedward Ok, there's another one, STR_DEBUG. It turns on consistency checks 2932343Sedward in the string allocator. It's been left on since performace doesn't 3032343Sedward seem to suffer. There's an abort() somewhere when an inconsistency 3132343Sedward is found. It hasn't happened in years. 3232343Sedward 3316398Sedward The file local.h contains locally tunable constants. 3415556Sedward 3532343Sedward The makefile used to be updated with mkmf; it has been changed 3632343Sedwardat various times to use cpp -M and, currently, mkdep. The only library 3732343Sedwardit needs is termcap. 3815556Sedward 3956709Sedward Window, as is, only runs on 4.3 (or later) machines. 4015556Sedward 4129718Sedward On 4.2 machines, at least these modifications must be done: 4215556Sedward 4329718Sedward delete uses of window size ioctls: TIOCGWINSZ, TIOCSWINSZ, 4429718Sedward struct winsize 4529718Sedward add to ww.h 4629718Sedward typedef int fd_set; 4729718Sedward #define FD_ZERO(s) (*(s) = 0) 4829718Sedward #define FD_SET(b, s) (*(s) |= 1 << (b)) 4929718Sedward #define FD_ISSET(b, s) (*(s) & 1 << (b)) 5029718Sedward add to ww.h 5129718Sedward #define sigmask(s) (1 << (s) - 1) 5229718Sedward 5329718Sedward 5416284SedwardA few notes about the internals: 5516284Sedward 5616284Sedward The window package. Windows are opened by calling wwopen(). 5716284SedwardWwwrite() is the primitive for writing to windows. Wwputc(), wwputs(), 5816284Sedwardand wwprintf() are also supported. Some of the outputs to windows are 5916284Sedwarddelayed. Wwupdate() updates the terminal to match the internal screen 6016284Sedwardbuffer. Wwspawn() spawns a child process on the other end of a window, 6132343Sedwardwith its environment tailored to the window. Visible windows are 6216284Sedwarddoubly linked in the order of their overlap. Wwadd() inserts a window 6316535Sedwardinto the list at a given place. Wwdelete() deletes it. Windows not in 6432343Sedwardthe list are not visible, though wwwrite() still works. Window was 6532343Sedwardwritten before the days of X and Sunview, so some of the terminology 6632343Sedwardis not standard. 6716284Sedward 6816284Sedward Most functions return -1 on error. Wwopen() returns the null 6916535Sedwardpointer. An error number is saved in wwerrno. Wwerror() returns an 7016535Sedwarderror string based on wwerrno suitable for printing. 7116284Sedward 7216284Sedward The terminal drivers perform all output to the physical terminal, 7316284Sedwardincluding special functions like character and line insertion and 7416284Sedwarddeletion. The window package keeps a list of known terminals. At 7516284Sedwardinitialization time, the terminal type is matched against the list to 7616284Sedwardfind the right terminal driver to use. The last driver, the generic 7716284Sedwarddriver, matches all terminals and uses the termcap database. The 7816284Sedwardinterface between the window package the terminal driver is the `tt' 7916284Sedwardstructure. It contains pointers to functions to perform special 8016284Sedwardfunctions and terminal output, as well as flags about the 8132343Sedwardcharacteristics of the terminal. Most of these ideas are borrowed 8232343Sedwardfrom the Maryland window package, which in turn is based on Goslin's 8332343SedwardEmacs. 8416284Sedward 8516535Sedward The IO system is semi-synchronous. Terminal input is signal 8616535Sedwarddriven, and everything else is done synchronously with a single 8732343Sedwardselect(). It is roughly event-driven, though not in a clean way. 8816284Sedward 8916535Sedward Normally, in both conversation mode and command mode, window 9016535Sedwardsleeps in a select() in wwiomux() waiting for data from the 9116535Sedwardpseudo-terminals. At the same time, terminal input causes SIGIO which 9216535Sedwardis caught by wwrint(). The select() returns when at least one of the 9316535Sedwardpseudo-terminals becomes ready for reading. 9416284Sedward 9516535Sedward Wwrint() is the interrupt handler for tty input. It reads input 9616535Sedwardinto a linear buffer accessed through four pointers: 9716284Sedward 9816284Sedward +-------+--------------+----------------+ 9916284Sedward | empty | data | empty | 10016284Sedward +-------+--------------+----------------+ 10116284Sedward ^ ^ ^ ^ 10216284Sedward | | | | 10316284Sedward wwib wwibp wwibq wwibe 10416284Sedward 10532343SedwardWwrint() appends characters at the end and increments wwibq (*wwibq++ 10632343Sedward= c), and characters are taken off the buffer at wwibp using the 10732343Sedwardwwgetc() and wwpeekc() macros. As is the convention in C, wwibq 10832343Sedwardand wwibe point to one position beyond the end. In addition, 10932343Sedwardwwrint() will do a longjmp(wwjmpbuf) if wwsetjmp is true. This is 11032343Sedwardused by wwiomux() to interrupt the select() which would otherwise 11132343Sedwardresume after the interrupt. (Actually, I hear this is not true, 11232343Sedwardbut the longjmp feature is used to avoid a race condition as well. 11332343SedwardAnyway, it means I didn't have to depend on a feature in a 11432343Sedwarddaily-changing kernel, but that's another story.) The macro 11532343Sedwardwwinterrupt() returns true if the input buffer is non-empty. 11632343SedwardWwupdate(), wwwrite(), and wwiomux() check this condition and will 11732343Sedwardreturn at the first convenient opportunity when it becomes true. 11832343SedwardIn the case of wwwrite(), the flag ww_nointr in the window structure 11932343Sedwardoverrides this. This feature allows the user to interrupt lengthy 12032343Sedwardoutputs safely. The structure of the input buffer is designed to 12132343Sedwardavoid race conditions without blocking interrupts. 12216284Sedward 12332343Sedward Actually, wwsetjmp and wwinterrupt() are part of a software 12432343Sedwardinterrupt scheme used by the two interrupt catchers wwrint() and 12532343Sedwardwwchild(). Asserting the interrupt lets the synchronous parts of 12632343Sedwardthe program know that there's an interesting asynchronous condition 12732343Sedward(i.e., got a keyboard character, or a child process died) that they 12832343Sedwardmight want to process before anything else. The synchronous routines 12932343Sedwardcan check for this condition with wwinterrupt() or by arranging 13032343Sedwardthat a longjmp() be done. 13132343Sedward 13232343Sedward Wwiomux() copies pseudo-terminal output into their corresponding 13316284Sedwardwindows. Without anything to do, it blocks in a select(), waiting for 13416284Sedwardread ready on pseudo-terminals. Reads are done into per-window buffers 13516284Sedwardin the window structures. When there is at least one buffer non-empty, 13616284Sedwardwwiomux() finds the top most of these windows and writes it using 13716535Sedwardwwwrite(). Then the process is repeated. A non-blocking select() is 13816535Sedwarddone after a wwwrite() to pick up any output that may have come in 13916535Sedwardduring the write, which may take a long time. Specifically, we use 14016535Sedwardthis to stop output or flush buffer when a pseudo-terminal tells us to 14116535Sedward(we use pty packet mode). The select() blocks only when all of the 14216535Sedwardwindows' buffers are empty. A wwupdate() is done prior to this, which 14316535Sedwardis the only time the screen is guaranteed to be completely up to date. 14416535SedwardWwiomux() loops until wwinterrupt() becomes true. 14516284Sedward 14616535Sedward The top level routine for all this is mloop(). In conversation 14716535Sedwardmode, it simply calls wwiomux(), which only returns when input is 14816535Sedwardavailable. The input buffer is then written to the pseudo-terminal of 14916535Sedwardthe current window. If the escape character is found in the input, 15016535Sedwardcommand mode is entered. Otherwise, the process is repeated. In 15116535Sedwardcommand mode, control is transferred to docmd() which returns only when 15216535Sedwardconversation mode is reentered. Docmd() and other command processing 15316535Sedwardroutines typically wait for input in a loop: 15416284Sedward 15516535Sedward while (wwpeekc() < 0) 15616284Sedward wwiomux(); 15716284Sedward 15816535SedwardWhen the loop terminates, wwgetc() is used to read the input buffer. 15916284Sedward 16016284Sedward Output to the physical terminal is handled by the lowest level 16116284Sedwardroutines of the window package, in the files ttoutput.c and tt.h. The 16216535Sedwardstandard IO package is not used, to get better control over buffering 16316535Sedwardand to use non-blocking reads in wwrint(). The buffer size is set to 16416284Sedwardapproximately one second of output time, based on the baudrate. 16516284Sedward 16616284Sedward The result of all this complexity is faster response time, 16716284Sedwardespecially in output stopping and flushing. Wwwrite() checks 16816284Sedwardwwinterrupt() after every line. It also calls wwupdate() for each line 16916284Sedwardit writes. The output buffer is limited to one second of output time. 17016284SedwardThus, there is usually only a delay of one to two lines plus one second 17116284Sedwardafter a ^C or ^S. Also, commands that produce lengthy output can be 17216284Sedwardaborted without actually showing all of it on the terminal. (Try the 17316535Sedward'?' command followed by escape immediately.) 174