4.2bsd kernel tty pager (contains working source)

Geoff Collyer geoff at utcsstat.UUCP
Tue Aug 14 19:05:27 AEST 1984


This article is a follow-on to my article in January which contained a
kernel tty pager for v7.  This is the long-awaited 4.2 version.

The utcs (4.2bsd) kernel has a *simple* paginator in the kernel tty
driver, originally written by Ron Gomes (sftig!rrg).

This paginator is selectable by ioctl and the screen length is
settable.  It consists of a very small set of kernel changes 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 be
extended slightly to make fewer decisions by making more of its
behavior selectable.

To forestall flames, I will mail a /vmunix to any one who mails me a
flame.  I am not willing to debate this topic; the pager works, works
well and I will never go back to using more(1).

To those who are working on a terminal driver standard, I strongly
recommend that a paginator similar to this one be included in any
proposed standard.

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 4.2bsd
terminal driver.  This code contains no Bell nor AT&T code and is
hereby declared public domain.

---only code and documentation follow this line---
Here are the diffs to tty.4:
-----
124c124
< Output processing is done.
---
> Output processing is done, except for paging.
619c619
< all processing is done except the input editing:
---
> all processing is done except the input editing and paging:

This is a new section:
743a744,781
> .Ul "Paging"
> .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 \fIioctl\fR 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.
> .LP
830a869,870
> .SH HISTORY
> The paging feature was implemented at BNR by Ron Gomes.

This goes in the BUGS section:
832a873,876
> .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.
-----
Here are the /sys/h/tty.h diffs:
---
Add these struct members to the end of struct tty:
80a81,84
> 	struct tpage tpg;	/* Paging parameters */
> /*	unsigned short t_xstate;	/* Extra state bits */
> #define t_xstate t_state		/* save space */
> 	unsigned short t_plc;	/* Line count for paging */
122a127,128
> /* extra internal state bits (encoded in t_xstate) */
> #define TS_PAGEFULL	0x80000000	/* screen full, wait 'til something is typed */
---
Here are the /sys/h/ttychars.h diffs:
---
25a26,30
> struct tpage {
> 	unsigned short t_pagsiz;	/* Page size for automatic paging */
> 	char t_pgparm[4];	/* Reserved for future bells and whistles */
> };
> 
---
Here are the diffs for /sys/h/ioctl.h:
---
127a128,129
> #define TIOCSPAG _IOW(t, 64, struct tpage)
> #define TIOCGPAG _IOR(t, 65, struct tpage)
---
Here are the /sys/sys/tty.c diffs:
---
Add these cases to the giant ioctl switch in ttioctl():
475a476,484
> 	case TIOCGPAG:
> 		bcopy((caddr_t)&tp->tpg, data, sizeof (struct tpage));
> 		break;
> 
> 	case TIOCSPAG:
> 		bcopy(data, (caddr_t)&tp->tpg, sizeof (struct tpage));
> 		break;
> 
> 
Add this at the end of ttyclose():
571a581,583
> 	tp->t_xstate = 0;
> 	tp->tpg.t_pagsiz = 0;
> 	tp->t_plc = 0;
Add this to ttyoutput(), after
	if (c == tp->t_startc)
		goto restartoutput;
701a714,721
> 	tp->t_plc = 0;
> 	if (tp->t_xstate&TS_PAGEFULL) {
> 		tp->t_xstate &= ~TS_PAGEFULL;
> 		wakeup((caddr_t)&tp->t_plc);
> 		if (c == '\n' || (c == '\r' && t_flags&CRMOD))
> 			return;
> 	}
> 
Add this after ``If we're mapping lower case or kludging tildes,'':
1228a1249
> 		 * or paging output,
1232c1253,1254
< 		if (tp->t_flags & (LCASE|TILDE)) {
---
> 		if (tp->tpg.t_pagsiz > 0 && (tp->t_flags&(RAW|CBREAK)) == 0 ||
> 		    tp->t_flags & (LCASE|TILDE)) {
1236c1258,1260
< 				while ((c = ttyoutput(c, tp)) >= 0) {
---
> 				for (ttstoppg(tp, c);
> 				    (c = ttyoutput(c, tp)) >= 0;
> 				    ttstoppg(tp, c)) {
This is an unrelated bug fix; add it after ``if (tp->t_state&TS_NBIO) {'':
1324a1349
> 		splx(s);
1332a1358,1384
> }
> 
> /*
>  * If screen is full, sleep until something is typed.
>  * If paging is on and c is the last newline on a screen,
>  * write a return, mark the terminal as screen-full,
>  * sleep until something is typed.
>  */
> static
> ttstoppg(tp, c)
> register struct tty *tp;
> register int c;
> {
> 	register int s;
> 
> 	while (tp->t_xstate & TS_PAGEFULL)
> 		sleep((caddr_t)&tp->t_plc, TTOPRI);
> 	s = spl5();
> 	if (tp->tpg.t_pagsiz > 0 && (tp->t_flags&(RAW|CBREAK)) == 0 &&
> 	    c == '\n' && ++(tp->t_plc) >= tp->tpg.t_pagsiz) {
> 		ttyoutput('\r', tp);	/* distinctive pause */
> 		ttstart(tp);
> 		tp->t_xstate |= TS_PAGEFULL;
> 		while (tp->t_xstate & TS_PAGEFULL)
> 			sleep((caddr_t)&tp->t_plc, TTOPRI);
> 	}
> 	splx(s);
---
Here are the changes to stty.1:
-----
These paragraphs should be added after the description of brk:
---
.br
.ns
.TP
.BI page \ n
turn on paging mode and set the page size to
.I n
(a number).
(In paging mode output at the terminal is frozen when
.I n
lines have been printed without anything having been typed at the keyboard;
output is started again when a new-line is typed.)
If
.I n
is omitted a page size of 22 is assumed;
setting the page size to 0 turns paging mode off.
.br
.ns
.TP
.B -page
same as `page 0'.
.br
---

Add this section:
---
.SH HISTORY
Modified by Ron Gomes
to turn paging mode (a local addition) on and off.
-----
Here are the diffs for stty.c:
---
8a6
> #include <ctype.h>
129a128
> struct tpage tpg;

Add this after the first TIOCGETP ioctl:
168a168
> 	ioctl(1, TIOCGPAG, &tpg);

Add this after if (eq("gspeed")):
258a259,268
> 		if (eq("page"))
> 			if (argv[1] && isascii(argv[1][0]) &&
> 			    isdigit(argv[1][0])) {
> 				tpg.t_pagsiz = atoi(*++argv);
> 				argc--;
> 			}
> 			else
> 				tpg.t_pagsiz = 22;
> 		if (eq("-page"))
> 			tpg.t_pagsiz = 0;

Add this after the TIOCSETN ioctl:
291a302
> 	ioctl(1, TIOCSPAG, &tpg);

Add this after the fprintf containing ``all==2'':
330a342,343
> 	if(tpg.t_pagsiz)
> 		fprintf(stderr, "page = %d; ", tpg.t_pagsiz);
---

Geoff Collyer, U. of Toronto



More information about the Comp.unix.wizards mailing list