alleged Disgusting kernel hack (contains free kernel paginator)

Geoffrey Collyer geoff at utcsstat.UUCP
Mon Jan 16 16:34:44 AEST 1984


The utcsstat (v7) kernel has a *simple* paginator in the kernel tty
driver, originally written by Ron Gomes of HCR (utzoo!hcr!rrg).
If the 4.2BSD terminal driver is sufficiently similar to v7's,
the same paginator will soon be inserted into the 4.2BSD systems
here; I cannot abide more.

This paginator is selectable by ioctl and the screen length is
settable.  It consists of fourty-four (44) lines of source
(including comments but excluding blank lines) and adds two new
ioctl codes (one to get and one to set the paging parameters).
This paginator makes *very* few decisions of its own and will
soon be extended slightly to make fewer decisions by making more
of its behavior selectable.  The paginator certainly does belong in the
terminal or the terminal driver and this fits in quite nicely with the
UNIX philosophy, thank you.  On utcsstat, only one program paginates
terminal output: the kernel.  It does it quickly and uniformly.

More is not ``a bit slow''; it is a huge, lumbering slug of a program.
(Since we switched from more to kernel pagination in readnews, news
reading, for example, is *much* faster.) It is abysmally written and
unmaintainable.  It is the poorest example of a filter that I can think
of, offhand.  More has countless bugs and does umpteen different
things unrelated to the job of pagination or each other.

As for putting the shell in the kernel, Berkeley does seem to be headed
that way, though they have a blind spot for the primary job done by
more: pagination.

Pipes and filters are still wonderful ideas; signals were a large
improvement at the time since they turned all sorts of phenomena into a
single mechanism.

With the kind permission of Ron Gomes and as a public service I offer
here the changes needed to add a simple kernel paginator to the v7
terminal driver;  4.2BSD changes may follow.  This code contains
no Bell nor AT&T code and is hereby declared public domain.

---only code and documentation follow this line---
In tty.h, add the following definitions:
before the definition of `struct tty',
struct tpage {
	unsigned short	t_pagsiz;	/* Page size for automatic paging */
	char	t_pgparm[4];	/* Reserved for future bells and whistles */
};

at the end of the definition of `struct tty',
	struct	tpage tpg;	/* Paging parameters */
	unsigned short	t_xstate;	/* Extra state bits */
	unsigned short	t_plc;	/* Line count for paging */

after the other definitions of bits in t_state,
/* Extra internal state bits (encoded in t_xstate) */
#define PAGEFULL 01		/* Screen full, wait till something is typed */

after the other ioctl codes (19 and 20 can be any unused terminal ioctl codes),
#define TIOCSPAG	(('t'<<8)|19)
#define TIOCGPAG	(('t'<<8)|20)
---
In tty.c,
at the end of ttyclose,
	tp->t_xstate = 0;
	tp->tpg.t_pagsiz = 0;
	tp->t_plc = 0;

in ttioccomm's switch, before the default: label,
	/*
	 * set and fetch paging parameters
	 */
	case TIOCSPAG:
		if (copyin(addr, (caddr_t)&tp->tpg, sizeof(struct tpage)))
			u.u_error = EFAULT;
		break;

	case TIOCGPAG:
		if (copyout((caddr_t)&tp->tpg, addr, sizeof(struct tpage)))
			u.u_error = EFAULT;
		break;

in ttyinput, before the test for c equal to tun.t_quitc or tun.t_intrc,
		tp->t_plc = 0;
		if (tp->t_xstate&PAGEFULL) {
			tp->t_xstate &= ~PAGEFULL;
			wakeup((caddr_t)&tp->t_plc);
			if (c=='\n' || (c=='\r' && t_flags&CRMOD))
				return;
		}

in ttwrite, before the call to ttyoutput,
		while (tp->t_xstate & PAGEFULL)
			sleep((caddr_t)&tp->t_plc, TTOPRI);
		spl5();
		if ((tp->t_flags&(RAW|CBREAK)) == 0 && tp->tpg.t_pagsiz > 0 &&
		    c == '\n' && ++(tp->t_plc) >= tp->tpg.t_pagsiz) {
			ttyoutput('\r', tp);	/* distinctive pause */
			ttstart(tp);
			tp->t_xstate |= PAGEFULL;
			while (tp->t_xstate & PAGEFULL)
				sleep((caddr_t)&tp->t_plc, TTOPRI);
		}
		spl0();
---
Here are the changes to tty(4):
.PP
In raw mode, every character is passed immediately
to the program without waiting until a full line has been typed.
No erase or kill processing is done;
the end-of-file indicator (EOT), the interrupt character
(ETX) and the quit character (FS) are not treated specially.
There are no delays, no stop/start handshaking, no paging,
and no replacement of
one character for another;
characters are a full 8 bits for both input and output
(parity is up to the program).
...
.PP
CBREAK is a sort of half-cooked (rare?) mode.
Programs can read each character as soon as typed, instead
of waiting for a full line,
but quit, interrupt, stop, and start work, and output delays, case-translation,
CRMOD, XTABS, ECHO, and parity work normally.
On the other hand there is no erase or kill,
no paging,
and no special treatment of \e or EOT.
...
.PP
The terminal interface can be put into a ``paging mode''
in which output will halt when a full ``page''
has been displayed;
output resumes when any character,
other than the start and stop characters,
is typed.
Usually this will be a newline, which is absorbed;
any other character will also restart output but in addition
it will be transmitted to the program reading from the terminal.
The structure referenced in the
.I ioctl
call is defined in
.I <sgtty.h>
as follows:
.PP
.nf
.ft 3
struct tpage {
	unsigned short	t_pagsiz;	/* Page size for automatic paging */
	char	t_pgparm[4];	/* Reserved for future bells and whistles */
};
.fi
.ft R
.PP
The
.I t_pagsiz
value is the number of lines which will be printed before output
stops to wait for a character to be typed;
if this is zero the paging feature is turned off.
The calls are:
.TP
TIOCSPAG
Set the paging parameters for the terminal according to the
pointed-to structure.
.TP
TIOCGPAG
Fetch the paging parameters and store them in the pointed-to structure.
...
.SH HISTORY
.PP
The paging feature was implemented at BNR by Ron Gomes.
...
.PP
The Bell documentation did not say whether
stop and start worked in CBREAK mode,
and claimed that RAW mode did not echo.
...
.SH BUGS
.PP
The paging feature should really take account of a terminal's
line length, to allow for extra newlines caused by wraparound
on over-long lines.
.PP
Raw mode does not do stop/start protocol, which some terminals
absolutely must have at all times.
---

Geoff Collyer, U. of Toronto



More information about the Comp.unix.wizards mailing list