[comp.bugs.4bsd] control-T for 4.3BSD

chris@mimsy.UUCP (05/28/87)

Index:	/sys/h/ioctl.h, /sys/h/tty.h, /sys/h/ttychars.h,
	/sys/sys/tty.c, /bin/stty, /bin/login, /etc/pstat 4.3BSD hack

Description:
	An `enhancement' for 4.3BSD.  Typing ^T (or another
	character of your choice) produces an informational
	line such as:

	load 0.35 0.35 0.31, pid 9306, %cpu 0.00, 52k of 149k, kbd wait

Repeat-By:
	Type ^T.  If it does nothing, and you want it to....

Fix:
	Apply the patches below, then recompile and reinstall (1)
	the kernel, (2) stty, (3) login, and (4) pstat.  I believe
	that covers everything except the `tty' adb script in
	/usr/lib/adb, for which I do not now have changes.

[/sys/h]
RCS file: RCS/ioctl.h,v
retrieving revision 1.1
diff -c2 -r1.1 ioctl.h
*** /tmp/,RCSt1000305	Sun May 24 20:51:42 1987
--- ioctl.h	Thu May 21 22:28:37 1987
***************
*** 36,39 ****
--- 36,43 ----
  	char	t_lnextc;	/* literal next character */
  };
+ struct auxchars {
+ 	short	t_usemap;	/* usestat info bitmap */
+ 	char	t_usest;	/* usestat character */
+ };
  
  /*
***************
*** 224,227 ****
--- 228,245 ----
  #define	TIOCUCNTL	_IOW(t, 102, int)	/* pty: set/clr usr cntl mode */
  #define		UIOCCMD(n)	_IO(u, n)		/* usr cntl op "n" */
+ 
+ #define	TIOCSAUXC	_IOW(t, 59, struct auxchars)	/* set usestat */
+ #define	TIOCGAUXC	_IOR(t, 58, struct auxchars)	/* get usestat */
+ #define		UST_LOAD1	0x0001	/* one-minute load average */
+ #define		UST_LOAD5	0x0002	/* five-minute load average */
+ #define		UST_LOAD15	0x0004	/* fifteen-minute load average */
+ #define		UST_UPTIME	0x0008	/* time since last boot */
+ #define		UST_PGRP	0x0010	/* pgroup leader */
+ #define		UST_CHILDS	0x0020	/* and N children */
+ #define		UST_PCPU	0x0040	/* %cpu they're getting */
+ #define		UST_INCORE	0x0080	/* size and rss of them */
+ #define		UST_FLAGS	0x0100	/* OR of all their flags */
+ #define		UST_STATE	0x0200	/* rough state (in i/o wait, etc) */
+ #define		UST_RAWCPU	0x0400	/* raw or cooked cpu %'age */
  
  #define	OTTYDISC	0		/* old, v7 std tty driver */
===================================================================
RCS file: RCS/tty.h,v
retrieving revision 1.1
diff -c2 -r1.1 tty.h
*** /tmp/,RCSt1000305	Sun May 24 20:51:50 1987
--- tty.h	Fri May 22 17:46:21 1987
***************
*** 68,71 ****
--- 68,72 ----
  	char	t_ispeed, t_ospeed;	/* device */
  	char	t_rocount, t_rocol;	/* tty */
+ 	short	t_mflags;		/* tty */
  	struct	ttychars t_chars;	/* tty */
  	struct	winsize t_winsize;	/* window size */
***************
*** 85,88 ****
--- 86,91 ----
  #define	t_werasc	t_chars.tc_werasc
  #define	t_lnextc	t_chars.tc_lnextc
+ #define	t_usest		t_chars.tc_usest
+ #define	t_usemap	t_chars.tc_usemap
  };
  
***************
*** 136,137 ****
--- 139,142 ----
  #define	VTAB		5
  #define	RETURN		6
+ 
+ #define	UST_TIMING	1	/* timing out, ignore ^T */
===================================================================
RCS file: RCS/ttychars.h,v
retrieving revision 1.1
diff -c2 -r1.1 ttychars.h
*** /tmp/,RCSt1000305	Sun May 24 20:51:54 1987
--- ttychars.h	Fri May 22 17:46:25 1987
***************
*** 28,31 ****
--- 28,33 ----
  	char	tc_werasc;	/* word erase */
  	char	tc_lnextc;	/* literal next character */
+ 	short	tc_usemap;	/* usestat info bitmap */
+ 	char	tc_usest;	/* usestat character */
  };
  
***************
*** 48,50 ****
--- 50,54 ----
  #define	CWERASE	CTRL(w)
  #define	CLNEXT	CTRL(v)
+ #define	CUSEST	CTRL(t)
+ #define	CUSEMAP (~(UST_UPTIME | UST_FLAGS | UST_CHILDS))
  #endif
[/sys/sys]

RCS file: RCS/tty.c,v
retrieving revision 1.1
diff -c2 -r1.1 tty.c
*** /tmp/,RCSt1000319	Sun May 24 20:52:11 1987
--- tty.c	Sun May 24 20:08:17 1987
***************
*** 106,110 ****
  struct	ttychars ttydefaults = {
  	CERASE,	CKILL,	CINTR,	CQUIT,	CSTART,	CSTOP,	CEOF,
! 	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
  };
  
--- 106,111 ----
  struct	ttychars ttydefaults = {
  	CERASE,	CKILL,	CINTR,	CQUIT,	CSTART,	CSTOP,	CEOF,
! 	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT,
! 	CUSEMAP,CUSEST,
  };
  
***************
*** 263,266 ****
--- 264,268 ----
  	case TIOCSTI:
  	case TIOCSWINSZ:
+ 	case TIOCSAUXC:
  		while (tp->t_line == NTTYDISC &&
  		   u.u_procp->p_pgrp != tp->t_pgrp && tp == u.u_ttyp &&
***************
*** 450,453 ****
--- 452,466 ----
  
  	/*
+ 	 * Set/get local aux chars
+ 	 */
+ 	case TIOCGAUXC:
+ 		bcopy((caddr_t)&tp->t_usemap, data, sizeof (struct auxchars));
+ 		break;
+ 
+ 	case TIOCSAUXC:
+ 		bcopy(data, (caddr_t)&tp->t_usemap, sizeof (struct auxchars));
+ 		break;
+ 
+ 	/*
  	 * Modify local mode word.
  	 */
***************
*** 869,872 ****
--- 882,889 ----
  		goto endcase;
  	}
+ 	if (c == tp->t_usest) {
+ 		ttystatout(tp);
+ 		goto endcase;
+ 	}
  
  	/*
***************
*** 1661,1663 ****
--- 1678,1862 ----
  		gsignal(tp->t_pgrp, SIGIO); 
  	wakeup((caddr_t)&tp->t_rawq);
+ }
+ 
+ /*
+  * Print out primitive system stats.
+  *	Rehmi Post & Chris Torek
+  */
+ 
+ /* process states */
+ char *ust_states[] = {
+ 	"losing", "waiting", "swapped", "running",
+ 	"idling", "zombied", "stopped", "kbd wait"
+ };
+ 
+ /* which states are most important to know (least best) */
+ char ust_pri[] = {
+ 	7, 3, 4, 1,
+ 	2, 6, 5, 0
+ };
+ 
+ ttystatout(tp)
+ 	register struct tty *tp;
+ {
+ 	register struct proc *p;
+ 	register int x, f = 0, cf = 0;
+ 	int size = 0, rss = 0, ptime = 0, state = 0, pflg = 0;
+ 	float pcpu = 0.0;
+ 	static double magic = 4294967296.0;
+ 	int ttystatgo();
+ #define	comma(s, l)	(s + (cf++ ? 0 : l))
+ #define newp()		if (tp->t_col <= 64); else ttyoutput('\n', tp), cf = 0
+ 
+ 	/* only once per second, and only if there is room */
+ 	if (tp->t_state & TS_ASLEEP || tp->t_mflags & UST_TIMING)
+ 		return;
+ 	tp->t_mflags |= UST_TIMING;
+ 	timeout(ttystatgo, (caddr_t) tp, hz);
+ 
+ 	/* uptime */
+ 	if (tp->t_usemap & UST_UPTIME) {
+ 		long l = time.tv_sec - boottime.tv_sec;
+ 
+ 		if (l < 0)
+ 			l = 0;
+ 		ttyout("up ", tp);
+ 		x = l % 86400L;
+ 		l /= 86400L;
+ 		if (l > 0) {		/* days */
+ 			ttyoutint((int) l, 10, 1, tp);
+ 			ttyout("d ", tp);
+ 		}
+ 		if (x / 3600 > 0) {	/* hours */
+ 			ttyoutint(x / 3600, 10, 1, tp);
+ 			ttyout("h ", tp);
+ 			x %= 3600;
+ 		}
+ 		ttyoutint(x / 60, 10, 2, tp);	/* minutes */
+ 		ttyout("m", tp);
+ 		cf++;
+ 	}
+ 	newp();
+ 
+ 	/* load average */
+ 	if (tp->t_usemap & (UST_LOAD1 | UST_LOAD5 | UST_LOAD15)) {
+ 		ttyout(comma(", load", 2), tp);
+ 		if (tp->t_usemap & UST_LOAD1)
+ 			ttyoutload(tp, 0);
+ 		if (tp->t_usemap & UST_LOAD5)
+ 			ttyoutload(tp, 1);
+ 		if (tp->t_usemap & UST_LOAD15)
+ 			ttyoutload(tp, 2);
+ 		newp();
+ 	}
+ 
+ 	/* sum up all connected processes */
+ 	for (p = allproc; p != NULL; p = p->p_nxt) {
+ 		if (p->p_pgrp == tp->t_pgrp) {
+ 			if (ust_pri[p->p_stat] < ust_pri[state])
+ 				state = p->p_stat;
+ 			if (p->p_stat == SSLEEP &&
+ 			    p->p_wchan == (caddr_t) &tp->t_rawq)
+ 				state = 7;
+ 			if (p->p_stat != SZOMB) {
+ 				pcpu += (float) p->p_pctcpu;
+ 				size += p->p_tsize + p->p_ssize + p->p_dsize;
+ 				rss += p->p_rssize;
+ 				pflg |= p->p_flag;
+ 				ptime += p->p_time;
+ 			}
+ 			f++;
+ 		}
+ 	}
+ 
+ 	if (f) {
+ 		/* pid, %cpu, size, rss */
+ 		if (tp->t_usemap & UST_PGRP) {
+ 			ttyout(comma(", pid ", 2), tp);
+ 			ttyoutint(tp->t_pgrp, 10, 1, tp);
+ 		}
+ 		newp();
+ 		if (tp->t_usemap & UST_CHILDS) {
+ 			ttyout(comma(" children ", 1), tp);
+ 			ttyoutint(f, 10, 1, tp);
+ 		}
+ 		newp();
+ 		if (tp->t_usemap & UST_PCPU) {
+ 			ttyout(comma(", %cpu ", 2), tp);
+ 			if (tp->t_usemap & UST_RAWCPU)
+ 				x = pcpu * 10000.0 + 0.5;
+ 			else
+ 				x = 10000.0 * pcpu /	/* ! */
+ 					(1.0 - ((1 << (ptime >> 2)) / magic));
+ 			ttyoutint(x / 100, 10, 1, tp);
+ 			(void) ttyoutput('.', tp);
+ 			ttyoutint(x % 100, 10, 2, tp);
+ 		}
+ 		newp();
+ 		if (tp->t_usemap & UST_INCORE) {
+ 			ttyout(comma(", ", 2), tp);
+ 			ttyoutint(rss >> 1, 10, 1, tp);
+ 			ttyout("k of ", tp);
+ 			ttyoutint(size >> 1, 10, 1, tp);
+ 			(void) ttyoutput('k', tp);
+ 		}
+ 		newp();
+ 		if (tp->t_usemap & UST_FLAGS) {
+ 			ttyout(comma(", flags ", 2), tp);
+ 			ttyoutint(pflg, 16, 1, tp);
+ 		}
+ 		newp();
+ 		if (tp->t_usemap & UST_STATE) {
+ 			ttyout(comma(", ", 2), tp);
+ 			ttyout(ust_states[state], tp);
+ 			cf++;
+ 		}
+ 		if (cf)
+ 			(void) ttyoutput('\n', tp);
+ 	} else
+ 		ttyout(comma("; no process\n", 2), tp);
+ 
+ 	/*
+ 	 * Reset "t_rocount" so pending input will
+ 	 * be retyped if backspacing follows.
+ 	 */
+ 	tp->t_rocount = 0;
+ }
+ 
+ ttystatgo(tp)
+ 	register struct tty *tp;
+ {
+ 
+ 	tp->t_mflags &= ~UST_TIMING;
+ }
+ 
+ ttyoutload(tp, n)
+ 	register struct tty *tp;
+ 	int n;
+ {
+ 	register int x;
+ 	extern double avenrun[];
+ 
+ 	(void) ttyoutput(' ', tp);
+ 	x = avenrun[n] * 100.0 + 0.5;
+ 	if (x < 0)
+ 		x = 0;
+ 	ttyoutint(x / 100, 10, 1, tp);
+ 	(void) ttyoutput('.', tp);
+ 	ttyoutint(x % 100, 10, 2, tp);
+ }
+ 
+ ttyoutint(n, base, mindigits, tp)
+ 	register int n, base, mindigits;
+ 	register struct tty *tp;
+ {
+ 	char info[16];
+ 	register char *p = info;
+ 
+ 	while (--mindigits >= 0 || n) {
+ 		*p++ = "0123456789abcdef"[n % base];
+ 		n /= base;
+ 	}
+ 	while (p > info)
+ 		(void) ttyoutput(*--p, tp);
  }

[/bin]

RCS file: stty.c,v
retrieving revision 1.1
diff -c2 -r1.1 stty.c
*** /tmp/,RCSt1000295	Sun May 24 20:50:07 1987
--- stty.c	Sun May 24 20:45:23 1987
***************
*** 13,16 ****
--- 13,17 ----
  #ifndef lint
  static char sccsid[] = "@(#)stty.c	5.4 (Berkeley) 4/4/86";
+ static char RCSid[] = "$Header: stty.c,v 1.2 87/05/24 20:44:59 chris Exp $";
  #endif not lint
  
***************
*** 22,25 ****
--- 23,29 ----
  #include <sys/ioctl.h>
  
+ #define	pcol(x, y)	pcoln(x, y, 7)
+ #define	pco2(x, y)	pcoln(x, y, 6)
+ 
  struct
  {
***************
*** 44,49 ****
--- 48,57 ----
  	"exta",	EXTA,
  	"19200", EXTA,
+ 	"19.2k", EXTA,
+ 	"19.2", EXTA,
  	"extb",	EXTB,
  	"38400", EXTB,
+ 	"38.4k", EXTB,
+ 	"38.4", EXTB,
  	0,
  };
***************
*** 140,143 ****
--- 148,191 ----
  };
  
+ struct ust_option {
+ 	char	*uo_name;
+ 	short	uo_set, uo_clear;
+ } ust_options[] = {
+ 	"load1",	UST_LOAD1,	0,
+ 	"-load1",	0,		UST_LOAD1,
+ 	"load5",	UST_LOAD5,	0,
+ 	"-load5",	0,		UST_LOAD5,
+ 	"load15",	UST_LOAD15,	0,
+ 	"-load15",	0,		UST_LOAD15,
+ 	"load",		UST_LOAD1|UST_LOAD5|UST_LOAD15, 0,
+ 	"-load",	0,		UST_LOAD1|UST_LOAD5|UST_LOAD15,
+ 	"uptime",	UST_UPTIME,	0,
+ 	"-uptime",	0,		UST_UPTIME,
+ 	"pid",		UST_PGRP,	0,
+ 	"-pid",		0,		UST_PGRP,
+ 	"children",	UST_CHILDS,	0,
+ 	"-children",	0,		UST_CHILDS,
+ 	"cpu",		UST_PCPU,	0,
+ 	"-cpu",		0,		UST_PCPU,
+ 	"size",		UST_INCORE,	0,
+ 	"-size",	0,		UST_INCORE,
+ 	"flags",	UST_FLAGS,	0,
+ 	"-flags",	0,		UST_FLAGS,
+ 	"state",	UST_STATE,	0,
+ 	"-state",	0,		UST_STATE,
+ 	"rawcpu",	UST_RAWCPU,	0,
+ 	"-rawcpu",	0,		UST_RAWCPU,
+ 	"cookedcpu",	0,		UST_RAWCPU,
+ 	"stdusest",	UST_LOAD1|UST_LOAD5|UST_LOAD15|UST_PGRP|
+ 			UST_PCPU|UST_INCORE|UST_STATE|UST_RAWCPU,
+ 					UST_UPTIME|UST_CHILDS|UST_FLAGS,
+ 	"-usest",	0,		0,
+ 	"-stdusest",	UST_LOAD1|UST_LOAD15|UST_UPTIME|
+ 			UST_PCPU|UST_INCORE|UST_STATE,
+ 					UST_CHILDS|UST_PGRP|UST_FLAGS|
+ 					UST_RAWCPU|UST_LOAD5,
+ 	0,		0,		0
+ };
+ 
  struct tchars tc;
  struct ltchars ltc;
***************
*** 144,147 ****
--- 192,196 ----
  struct sgttyb mode;
  struct winsize win;
+ struct auxchars auxil;
  int	lmode;
  int	oldisc, ldisc;
***************
*** 166,169 ****
--- 215,219 ----
  	"werase",	&ltc.t_werasc,		CWERASE,
  	"lnext",	&ltc.t_lnextc,		CLNEXT,
+ 	"usest",	&auxil.t_usest,		CUSEST,
  	0
  };
***************
*** 175,179 ****
  char	**iargv;
  {
! 	int i;
  	register struct special *sp;
  	char obuf[BUFSIZ];
--- 225,229 ----
  char	**iargv;
  {
! 	register int i;
  	register struct special *sp;
  	char obuf[BUFSIZ];
***************
*** 189,192 ****
--- 239,243 ----
  	ioctl(1, TIOCGLTC, &ltc);
  	ioctl(1, TIOCGWINSZ, &win);
+ 	ioctl(1, TIOCGAUXC, &auxil);
  	if(argc == 1) {
  		prmodes(0);
***************
*** 314,318 ****
--- 365,376 ----
  				lmode &= ~modes[i].lreset;
  				lmode |= modes[i].lset;
+ 				goto cont;
  			}
+ 		for(i = 0; ust_options[i].uo_name; i++)
+ 			if (eq(ust_options[i].uo_name)) {
+ 				auxil.t_usemap |= ust_options[i].uo_set;
+ 				auxil.t_usemap &= ~ust_options[i].uo_clear;
+ 				goto cont;
+ 			}
  		if(arg)
  			fprintf(stderr,"unknown mode: %s\n", arg);
***************
*** 325,328 ****
--- 383,387 ----
  	ioctl(1, TIOCSLTC, &ltc);
  	ioctl(1, TIOCLSET, &lmode);
+ 	ioctl(1, TIOCSAUXC, &auxil);
  	ioctl(1, TIOCSWINSZ, &win);
  }
***************
*** 329,335 ****
  
  eq(string)
! char *string;
  {
! 	int i;
  
  	if(!arg)
--- 388,394 ----
  
  eq(string)
! register char *string;
  {
! 	register int i;
  
  	if(!arg)
***************
*** 461,477 ****
  		case NTTYDISC:
  			fprintf(stderr,"\
! erase  kill   werase rprnt  flush  lnext  susp   intr   quit   stop   eof\
! \n"); 
! 			pcol(mode.sg_erase, -1);
! 			pcol(mode.sg_kill, -1);
! 			pcol(ltc.t_werasc, -1);
! 			pcol(ltc.t_rprntc, -1);
! 			pcol(ltc.t_flushc, -1);
! 			pcol(ltc.t_lnextc, -1);
! 			pcol(ltc.t_suspc, ltc.t_dsuspc);
! 			pcol(tc.t_intrc, -1);
! 			pcol(tc.t_quitc, -1);
! 			pcol(tc.t_stopc, tc.t_startc);
! 			pcol(tc.t_eofc, tc.t_brkc);
  			fprintf(stderr,"\n");
  			break;
--- 520,536 ----
  		case NTTYDISC:
  			fprintf(stderr,"\
! erase kill  weras rprnt flush lnext susp  intr  quit  stop  eof   usest\n");
! 			pco2(mode.sg_erase, -1);
! 			pco2(mode.sg_kill, -1);
! 			pco2(ltc.t_werasc, -1);
! 			pco2(ltc.t_rprntc, -1);
! 			pco2(ltc.t_flushc, -1);
! 			pco2(ltc.t_lnextc, -1);
! 			pco2(ltc.t_suspc, ltc.t_dsuspc);
! 			pco2(tc.t_intrc, -1);
! 			pco2(tc.t_quitc, -1);
! 			pco2(tc.t_stopc, tc.t_startc);
! 			pco2(tc.t_eofc, tc.t_brkc);
! 			pco2(auxil.t_usest, -1);
  			fprintf(stderr,"\n");
  			break;
***************
*** 492,499 ****
  			fprintf(stderr, "\n");
  	}
  }
  
! pcol(ch1, ch2)
! 	int ch1, ch2;
  {
  	int nout = 0;
--- 551,578 ----
  			fprintf(stderr, "\n");
  	}
+ #define	map(str, bit)	fprintf(stderr, str + ((auxil.t_usemap & bit) != 0))
+ #define	UST_LOAD	(UST_LOAD1 | UST_LOAD5 | UST_LOAD15)
+ 	if (all == 2 && ldisc == NTTYDISC) {
+ 		if ((auxil.t_usemap & UST_LOAD) == UST_LOAD)
+ 			fprintf(stderr, "load (load1 load5 load15) ");
+ 		else {
+ 			map("-load1 ", UST_LOAD1);
+ 			map("-load5 ", UST_LOAD5);
+ 			map("-load15 ", UST_LOAD15);
+ 		}
+ 		map("-uptime ", UST_UPTIME);
+ 		map("-pid ", UST_PGRP);
+ 		map("-children ", UST_CHILDS);
+ 		map("-cpu ", UST_PCPU);
+ 		map("-size ", UST_INCORE);
+ 		map("-flags ", UST_FLAGS);
+ 		map("-state ", UST_STATE);
+ 		map("-rawcpu ", UST_RAWCPU);
+ 		putc('\n', stderr);
+ 	}
  }
  
! pcoln(ch1, ch2, n)
! 	int ch1, ch2, n;
  {
  	int nout = 0;
***************
*** 527,531 ****
  		}
  	}
! 	while (nout < 7) {
  		fprintf(stderr, " ");
  		nout++;
--- 606,610 ----
  		}
  	}
! 	while (nout < n) {
  		fprintf(stderr, " ");
  		nout++;

RCS file: RCS/login.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c2 -r1.1 -r1.2
*** /tmp/,RCSt1009357	Wed May 27 21:29:10 1987
--- /tmp/,RCSt2009357	Wed May 27 21:29:14 1987
***************
*** 13,16 ****
--- 13,17 ----
  #ifndef lint
  static char sccsid[] = "@(#)login.c	5.15 (Berkeley) 4/12/86";
+ static char rcsid[] = "$Header: login.c,v 1.2 87/05/24 21:01:06 chris Exp $";
  #endif not lint
  
***************
*** 87,90 ****
--- 88,93 ----
  struct winsize win = { 0, 0, 0, 0 };
  
+ struct auxchars aux = { CUSEMAP, CUSEST };
+ 
  int	rflag;
  int	usererr = -1;
***************
*** 166,169 ****
--- 169,173 ----
  	ioctl(0, TIOCSETC, &tc);
  	ioctl(0, TIOCSETP, &ttyb);
+ 	ioctl(0, TIOCSAUXC, &aux);
  	for (t = getdtablesize(); t > 2; t--)
  		close(t);
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris