[alt.sources] w6ps - XENIX 386 "realtime" ps on Wyse 60

wht@tridom.uucp (Warren Tucker) (10/28/89)

This ditty displays XENIX V/386 process status in "real time" on a Wyse
60 in native mode.  Login shells (**argv == '-') are omitted.  It works
with SCO XENIX V/386 2.3.1 and beyond and compiles ok with development
system 2.3.1. Just unshar and make.  The README talks about necessary
permissions.

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  README
#	  Makefile
#	  w6.c
#	  w6.h
#	  w6ps.c
#
if test -f README; then echo "File README exists"; else
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
Xw6ps - XENIX V/386 Wyse 60 process status display in 43-line, 132-col mode
X
XThis ditty displays XENIX V/386 process status in "real time" on a Wyse
X60 in native mode.  Login shells (**argv == '-') are omitted.  It works
Xwith SCO XENIX V/386 2.3.1 and beyond and compiles ok with development
Xsystem 2.3.1.
X
XIt is offered to the public domain with no warranty as-is: a reasonable
X"ps" that doesn't blow up with seek errors (so far :-)) and a decent
Xtoolkit for Wyse 60 manipulation and kmem/mem munging.
X
XNOTES:
X1.  w6ps must be able to access /dev/{*mem,swap}.  This means:
X    a. chmod +r /dev/{*mem,swap}   BAD IDEA
X    b. chown sysinfo w6ps;chmod u+s w6ps
X
X2.  I use a Wyse 60 as a non-enabled terminal on "/dev/tty2h" and the
Xprogram has that name hard-coded; you'll probably need to change
X'w6tty_default' in w6.c.
X
X3.  The program misbehaves if there are more than about 40 "non-login"
Xprocesses.
X
X4.  The terminal is expected to be set for 9600 baud.
X
X5.  w6test tests the w6.c driver.
SHAR_EOF
chmod 0644 README || echo "restore of README fails"
fi
if test -f Makefile; then echo "File Makefile exists"; else
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X#  CHK=0xD8E4
X#
X# 	Makefile for w6test and w6ps
X#
X# NOTE: w6ps needs chown sysinfo,chmod u+s for access to /dev/{*mem,swap}
X# 
X#+:EDITS:
X#:01-07-1989-12:21-wht-creation
X
XC_EXTRA = -i -M3
XCFLAGS  = -LARGE -DLINT_ARGS -Ox -K $(C_EXTRA)
XLDFLAGS = $(C_EXTRA) -lx
X
X.c.o:;	cc -c $(CFLAGS) $*.c 
X
XW6PS_OFILES = \
X	w6ps.o\
X	w6.o
X
Xall: w6ps w6test
X
Xw6test: w6test.o
X	cc $(LDFLAGS) w6test.o -o w6test
X
Xw6ps: $(W6PS_OFILES)
X	cc $(LDFLAGS) $(W6PS_OFILES) -o w6ps
X
Xw6test.o: w6.c
X	cc -DTEST -Fow6test.o -c $(CFLAGS) w6.c 
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
fi
if test -f w6.c; then echo "File w6.c exists"; else
echo "x - extracting w6.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > w6.c &&
X/* CHK=0xF46E */
X
Xchar *w6tty_default = "/dev/tty2h";
X
X/*+-------------------------------------------------------------------------
X	w6.c - Wyse 60 (native mode) display driver
X	...!gatech!emory!tridom!wht - Public Domain
X
X  Defined functions:
X	_w6_delta_attr(bit,state)
X	_w6_lgetc(char_rtnd)
X	main()
X	w6_132cols()
X	w6_24lines()
X	w6_25lines()
X	w6_42lines()
X	w6_43lines()
X	w6_80cols()
X	w6attr(attr)
X	w6blink(on)
X	w6close()
X	w6clr()
X	w6clrline()
X	w6clrtobot()
X	w6clrtoeol()
X	w6ctrl(ctrl_cmd)
X	w6dim(on)
X	w6eolwrap(on)
X	w6home()
X	w6ins_line()
X	w6mon_mode(on)
X	w6move(y,x)
X	w6norm()
X	w6oneseg()
X	w6open(line)
X	w6prog_fkey_label(keynum,str)
X	w6prog_fkey_str(keynum,str)
X	w6putc(ch)
X	w6reverse(on)
X	w6scroll(onflag)
X	w6set_time()
X	w6topline(msg)
X	w6underline(on)
X	w6xonxoff(on)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:01-04-1989-18:03-wht-creation */
X
X#include <stdio.h>
X#include <signal.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/errno.h>
X
X#if defined(M_XENIX)
X#include <sys/stat.h>
X#include <sys/ioctl.h>
X#include <string.h>
X#include <fcntl.h>
X#include <termio.h>
X#endif
X
X#if defined(pyr)
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <sys/termio.h>
X#include <strings.h>
X#endif
X
X#include <time.h>
X#include <sys/timeb.h>
X
X#include "w6.h"
Xextern int		errno;
X
Xint		w6fd = -1;			/* file descriptor for line */
Xchar	w6_ttyname[64];		/* /dev/ttyname for line */
Xstruct termio w6_termio;	/* attributes for the line to remote */
X
X
Xvoid w6putc(ch)
Xchar ch;
X{ write(w6fd,&ch,1); }
X
Xvoid w6putcs(str,count) char *str; int count;
X{ write(w6fd,str,count);}
X
Xvoid w6puts(str) char *str;
X{ write(w6fd,str,strlen(str));}
X
Xvoid w6xonxoff(on)
X{ w6putcs("\033c2",3); w6putc(on ? '1' : '0'); }
X
Xvoid w6clr()					/* clear screen */
X{ w6putc(26);}
X
Xchar w6_home[]={ ESC,'{'};
Xvoid w6home()					/* home screen */
X{ w6putcs(w6_home,2); }
X
Xvoid w6scroll(onflag)			/* scroll on/off */
X{ w6putc(ESC); w6putc((onflag) ? 'O' : 'N'); }
X
Xvoid w6oneseg()					/* whole screen one segment */
X{
Xstatic char w6_oneseg[]={ ESC,'x','0',};
X	w6putcs(w6_oneseg,3);
X}
X
Xvoid w6topline(msg)
Xchar *msg;
X{
Xstatic char w6_topline[]={ESC,'F'};
X	w6putcs(w6_topline,2);
X	w6putcs(msg,strlen(msg));
X	w6putc(0x0D);
X}
X
Xvoid w6ctrl(ctrl_cmd)			/* display control */
Xint	ctrl_cmd;
X{
Xstatic char w6_ctrl[]={ ESC,'`' };
X	w6putcs(w6_ctrl,2); 
X	w6putc(ctrl_cmd);
X}
Xstatic int _w6_cols = -1;
X
Xvoid w6_132cols()
X{ w6ctrl(W6_132);_w6_cols = 132;}
Xvoid w6_80cols()
X{ w6ctrl(W6_80); _w6_cols = 80;}
X
Xvoid _w6lines(spec) char spec;
X{ static char cmd[] = {ESC,'e'};
X	w6putcs(cmd,2); w6putc(spec);
X}
Xvoid w6_24lines()
X{ _w6lines('('); }
Xvoid w6_25lines()
X{ _w6lines(')'); }
Xvoid w6_42lines()
X{ _w6lines('*'); }
Xvoid w6_43lines()
X{ _w6lines('+'); }
X
Xvoid w6ins_line()
X{ w6putc(ESC);w6putc('E');}
X
Xvoid w6move(y,x)
Xunsigned char y,x;
X{
Xchar buf[16];
X	if(_w6_cols == 80)
X		sprintf(buf,"\033=%c%c",y+20,x+20);
X	else
X		sprintf(buf,"\033a%dR%dC",y + 1,x + 1);
X	w6puts(buf);
X}
X
Xvoid w6clrtoeol()
X{ static char cmd[]={ESC,'c','O'};
X	w6putcs(cmd,3);
X}
X
Xvoid w6clrtobot()
X{ static char cmd[]={ESC,'Y'};
X	w6putcs(cmd,2);
X}
X
Xvoid w6clrline()
X{ static char cmd[]={0x0D,ESC,'c','O'};
X	w6putcs(cmd,4);
X}
X
Xvoid w6set_time()
X{
Xchar buf[10];
Xlong time();
Xlong now = time((long *)0);
Xstruct tm *localtime();
Xstruct tm *lt = localtime(&now);
X	sprintf(buf,"\033c8%02d%02d",lt->tm_hour,lt->tm_min);
X	w6puts(buf);
X}
X
X
Xstatic char w6_attrcmd[]={ ESC,'G'};
Xstatic char w6_attr = '0';
X
Xvoid w6norm()							/* normal attribute */
X{
X	w6_attr = '0';
X	w6putcs(w6_attrcmd,2);
X	w6putc(w6_attr);
X}
X
Xvoid w6attr(attr)						/* absolute */
X{
X	w6_attr = '0' | attr;
X	w6putcs(w6_attrcmd,2);
X	w6putc(w6_attr);
X}
X
Xvoid _w6_delta_attr(bit,state)			/* delta */
Xunsigned char bit,state;
X{
X	if(state)
X		w6_attr |= bit;
X	else
X		w6_attr &= ~bit;
X	w6putcs(w6_attrcmd,2);
X	w6putc(w6_attr);
X}
X
Xvoid w6blink(on)						/* blink */
X{ _w6_delta_attr(W6BLINK,on); }
X
Xvoid w6reverse(on)						/* reverse */
X{ _w6_delta_attr(W6REVERSE,on); }
X
Xvoid w6underline(on)					/* reverse */
X{ _w6_delta_attr(W6UNDERLINE,on); }
X
Xvoid w6dim(on)							/* dim */
X{ _w6_delta_attr(W6DIM,on); }
X
X
Xvoid w6eolwrap(on)
X{ w6putcs("\033d",2); w6putc(on ? '/' : '.'); }
X
Xvoid w6mon_mode(on)
X{	w6eolwrap(on); w6putc(ESC); w6putc(on ? 'U' : 'u'); }
X
Xvoid w6prog_fkey_str(keynum,str)
Xint		keynum;
Xchar *str;
X{
Xchar wstr[128];
X	sprintf(wstr,"\033z%c%s\177",keynum - 1 + '@',str);
X	w6puts(wstr);
X
X}	/* end of w6prog_fkey_str */
X
Xvoid w6prog_fkey_label(keynum,str)
Xint		keynum;
Xchar *str;
X{
Xchar wstr[128];
X
X	sprintf(wstr,"\033z%c%s\177",keynum - 1 + '0',str);
X	write(w6fd,wstr,strlen(wstr));
X
X}	/* end of w6prog_fkey_label */
X
X/*+-------------------------------------------------------------------------
X	_w6_lgetc(char_rtnd) -- get char from line
X--------------------------------------------------------------------------*/
Xvoid
X_w6_lgetc(char_rtnd)
Xchar	*char_rtnd;
X{
Xextern int errno;
X
XREAD_AGAIN:
X	errno = 0;
X	if(read(w6fd,char_rtnd,1) < 1)
X	{
X		if(errno == EINTR)			/* if signal interrupted, ... */
X			goto READ_AGAIN;
X		exit(250);
X	}
X}	/* end of _w6_lgetc */
X
X/*+----------------------------------------------------------------------
X	w6open(line)
Xreturns negative W6_OPEN_ codes if failure else positive pid using line
Xelse 0 if successful open
X------------------------------------------------------------------------*/
Xint
Xw6open(line)
Xchar *line;
X{
Xregister int itmp;
X
X	strcpy(w6_ttyname,line);
X	if(!strcmp(w6_ttyname,"/dev/tty"))
X		return(W6_OPEN_INVALID);
X	if(w6fd >= 0)
X		return(W6_OPEN_ALREADY);
X
X	w6fd = open(w6_ttyname,O_RDWR | O_NDELAY,0777);
X	if(w6fd < 0)
X	{
X		perror(w6_ttyname);
X		return(W6_OPEN_OPNFAIL);
X	}
X	else
X	{
X		fcntl(w6fd,F_SETFL,O_RDWR);
X		ioctl(w6fd,(int)TCGETA,(char *) &w6_termio);
X		w6_termio.c_iflag = IGNPAR | IGNBRK | IXON;
X		w6_termio.c_oflag = OPOST | ONLCR | ONOCR;
X		w6_termio.c_cflag = CREAD | CLOCAL | CS8 | CSTOPB | B9600;
X#if defined(USE_XCLUDE)
X		w6_termio.c_lflag = XCLUDE;
X#else
X		w6_termio.c_lflag = 0;
X#endif
X		w6_termio.c_cc[VMIN]   = 1;
X		w6_termio.c_cc[VTIME]  = 1;
X		ioctl(w6fd,(int)TCSETA,(char *) &w6_termio);
X	}
X
X	w6mon_mode(0);
X	w6xonxoff(1);
X	w6set_time();
X	return(0);
X
X}	/* end of w6open */
X
X/*+-----------------------------------------------------------------------
X	w6close()
X------------------------------------------------------------------------*/
Xvoid w6close()
X{
X	if(w6fd < 0)
X		return;
X	close(w6fd);
X	w6fd = -1;
X
X}	/* end of w6close */
X
X#if defined(TEST)
Xmain()
X{
Xregister int offset;
Xregister int itmp;
X
X	if(itmp = w6open(w6tty_default))
X	{
X		printf("w6open error %d\n",itmp);
X		exit(1);
X	}
X
X	w6set_time();
X	w6ctrl(W6SCROFF);
X	w6clr();
X	w6topline("");
X	w6ctrl(W6SCRON);
X	w6ctrl(W6CUROFF);
X	w6eolwrap(1);
X	w6topline("Wyse 60 test");
X	w6_132cols();
X	w6_43lines();
X
X	for(offset = 0; offset < 100; offset += 10)
X	{
X		for(itmp = 1; itmp < 10; itmp++)
X		{
X			w6move(itmp,itmp + offset);
X			w6putc('\\');
X		}
X
X		for(itmp = 9; itmp > 0; itmp--)
X		{
X			w6move(itmp,offset + 20 - itmp);
X			w6putc('/');
X		}
X	}
X
X	w6move(16,0);
X
X	w6norm();
X	w6puts("normal");
X	w6putc('\n');
X
X	w6reverse(1);
X	w6puts("reverse");
X	w6putc('\n');
X
X	w6dim(1);
X	w6puts("dim reverse");
X	w6norm();
X	w6putc('\n');
X
X	w6blink(1);
X	w6puts("blinking\n");
X
X	w6attr(W6DIM);
X	w6puts("dim\n");
X
X	w6blink(1);
X	w6puts("dim blinking");
X	w6norm();
X	w6putc('\n');
X
X	w6move(23,0,stdout);
X	w6ctrl(W6SCRON);
X
X	w6ctrl(W6CURLIN);
X	w6ctrl(W6CURON);
X	w6move(0,0);
X	w6puts("*");
X	w6move(42,0);
X	w6puts("*");
X	w6close();
X	exit(1);
X}
X
X#endif
X
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 w6.c || echo "restore of w6.c fails"
fi
if test -f w6.h; then echo "File w6.h exists"; else
echo "x - extracting w6.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > w6.h &&
X/* CHK=0xE557 */
X/*+-------------------------------------------------------------------------
X	w6.h
X	...!gatech!emory!tridom!wht - Public Domain
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:01-05-1989-18:35-wht-creation */
X
X#ifdef ESC
X#undef ESC
X#endif
X#define ESC	0x1B
X
X/* w6open() and related routines error codes */
X#define W6_OPEN_INVALID	-1		/* for invalid tty name */
X#define W6_OPEN_UNKPID	-2		/* unknown pid using line */
X#define W6_OPEN_LCKERR	-3		/* lock file open error */
X#define W6_OPEN_NODEV	-4		/* device does not exist */
X#define W6_OPEN_OPNFAIL	-5		/* could not open line */
X#define W6_OPEN_ALREADY	-6		/* line already open */
X
X/* w6ctrl() parameters */
X#define W6CUROFF		'0'	/* cursor off */
X#define W6CURON			'1'	/* cursor on */
X#define W6CURBLK		'2'	/* cursor steady block */
X#define W6CURLINBLINK	'3'	/* cursor blinking block */
X#define W6CURLIN		'4'	/* cursor steady line */
X#define W6CURBLKBLINK	'5'	/* cursor blinking block */
X#define W6SCROFF		'8'	/* turn off screen */
X#define W6SCRON			'9'	/* turn on screen */
X#define W6_132			';'	/* 132 column */
X#define W6_80			':'	/* 80 column */
X#define W6SCRLJUMP		'@'	/* jump scroll */
X#define W6SCRLSMOOTH1	'<'	/* smooth scroll 1 line per second */
X#define W6SCRLSMOOTH2	'='	/* smooth scroll 2 line per second */
X#define W6SCRLSMOOTH4	'>'	/* smooth scroll 4 line per second */
X#define W6SCRLSMOOTH8	'?'	/* smooth scroll 8 line per second */
X
X/* w6attr() parameters */
X#define W6BLINK		0x02
X#define W6REVERSE	0x04
X#define W6UNDERLINE	0x08
X#define W6DIM		0x40
X
SHAR_EOF
chmod 0644 w6.h || echo "restore of w6.h fails"
fi
if test -f w6ps.c; then echo "File w6ps.c exists"; else
echo "x - extracting w6ps.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > w6ps.c &&
X/* CHK=0xC5D1 */
X/*+-------------------------------------------------------------------------
X	w6ps.c - XENIX V/386 Wyse 60 process status display
X	...!gatech!emory!tridom!wht - Public Domain
X
X  Defined functions:
X	display_line0()
X	display_proc(iproc,initial)
X	display_procs(initial)
X	error_term(text)
X	find_utmp_for_pgrp(pgrp)
X	get_cpu_time_str(timeval)
X	get_procs()
X	get_user(proc,slot,user)
X	getpwent_and_enter(uid)
X	init_uid_name_hash()
X	main(argc,argv,envp)
X	perror_term(text,code)
X	pgrp_to_ttyname(pgrp)
X	proc_pid_compare(p1,p2)
X	read_utmp()
X	uid_name_enter(uid,name)
X	uid_to_name(uid)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:01-05-1989-13:27-wht-creation */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <pwd.h>
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/types.h>
X#include <sys/page.h>
X#include <sys/seg.h>
X#include <sys/proc.h>
X#include <sys/signal.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#include <sys/var.h>
X#include <sys/utsname.h>
X#include <utmp.h>
X#include "w6.h"
X
Xchar *malloc(int);
Xchar *calloc(int,int);
X
Xextern int errno;
X
Xint memfd;
Xint kmemfd;
Xint swapfd;
X
Xint w6ps_pid;
Xint noldprocs;
Xint nprocs;
Xint mpid;
Xint hz;
Xunsigned short avenrun[3];
Xstruct var v;
Xstruct file *files;
Xstruct inode *inodes;
Xstruct text *texts;
Xstruct proc *procs;
Xstruct proc *oldprocs;
Xstruct mount *mounts;
Xstruct buf *bufs;
Xstruct buf *bufstart;
Xstruct user user;
Xdaddr_t	swplo;
Xstruct utsname utsname;
Xtime_t	ktime;
Xtime_t	klbolt;
X#define MAX_UTMP 32
Xint nutmps = 0;
Xstruct utmp utmps[MAX_UTMP];
X
X#define	XL_V		0
X#define	XL_FILE		1
X#define	XL_INODE	2
X#define	XL_PROC		3
X#define	XL_TEXT		4
X#define	XL_MOUNT	5
X#define	XL_BUFFER	6
X#define	XL_SWPLO	7
X#define	XL_TIME		8
X#define	XL_LBOLT	9
X#define	XL_UTSNAME	10
X#define	XL_USER		11
X#define	XL_AVENRUN	12
X#define	XL_MPID		13
X#define	XL_HZ		14
X
Xstruct xlist namelist[] = 
X{
X	{ 0,0,0,"_v" },
X	{ 0,0,0,"_file" },
X	{ 0,0,0,"_inode" },
X	{ 0,0,0,"_proc" },
X	{ 0,0,0,"_text" },
X	{ 0,0,0,"_mount" },
X	{ 0,0,0,"_bufstrt" },
X	{ 0,0,0,"_swplo" },
X	{ 0,0,0,"_time" },
X	{ 0,0,0,"_lbolt" },
X	{ 0,0,0,"_utsname" },
X	{ 0,0,0,"_u" },
X	{ 0,0,0,"_avenrun" },
X	{ 0,0,0,"_mpid" },
X	{ 0,0,0,"_hz" },
X	{ 0,0,0,(char *) 0 }
X};
X
Xperror_term(text,code)
Xchar *text;
Xint code;
X{
X	fputs(text,stdout);
X	printf(" code=%d ",code);
X	perror("");
X	exit(1);
X}
X
Xerror_term(text)
Xchar *text;
X{
X	fputs(text,stdout);
X	exit(1);
X}
X
X/*+-------------------------------------------------------------------------
X	read_utmp()
X--------------------------------------------------------------------------*/
Xvoid
Xread_utmp()
X{
Xint utmpfd;
Xstruct utmp *tutmp = utmps;
X
X	nutmps = 0;
X	if((utmpfd = open("/etc/utmp",O_RDONLY,755)) < 0)
X	{
X		perror_term("/etc/utmp",errno);
X		exit(1);
X	}
X
X	while(read(utmpfd,(char *)(tutmp++),sizeof(struct utmp)) > 0)
X	{
X		if(++nutmps == MAX_UTMP)
X			error_term("too many utmp entries for me to handle");
X	}
X	close(utmpfd);
X}	/* end of read_utmp */
X
X/*+-------------------------------------------------------------------------
X	find_utmp_for_pgrp(pgrp)
X--------------------------------------------------------------------------*/
Xstruct utmp *
Xfind_utmp_for_pgrp(pgrp)
Xint pgrp;
X{
Xstruct utmp *tutmp = utmps;
Xregister int count = nutmps;
X
X	while(count--)
X	{
X		if(tutmp->ut_pid == pgrp)
X			return(tutmp);
X		tutmp++;
X	}
X	return((struct utmp *)0);
X}	/* end of find_utmp_for_pgrp */
X
X/*+-------------------------------------------------------------------------
X	pgrp_to_ttyname(pgrp)
X--------------------------------------------------------------------------*/
Xchar *
Xpgrp_to_ttyname(pgrp)
Xint pgrp;
X{
Xstruct utmp *tutmp;
X
X	if(!(tutmp = find_utmp_for_pgrp(pgrp)))
X	{
X		read_utmp();
X		tutmp = find_utmp_for_pgrp(pgrp);
X	}
X	if(!tutmp)
X		return("??");
X	else
X		return(tutmp->ut_id);
X}	/* end of pgrp_to_ttyname */
X
X/*+-------------------------------------------------------------------------
X	get_user(proc,slot,user)
X--------------------------------------------------------------------------*/
Xget_user(proc,slot,user)
Xstruct proc *proc;
Xint slot;	/* not used */
Xstruct user *user;
X{
X	struct proc *first_proc = (struct proc *) namelist[XL_PROC].xl_value;
X	long swapaddr;
X	int i;
X
X	if((proc->p_flag & (SSWAP|SPARTOUT)) || ! (proc->p_flag & SLOAD))
X	{
X		swapaddr = proc->p_addr[0].te_frameno * NBPC;
X		lseek(swapfd,swapaddr,0);
X		read(swapfd,user,sizeof *user);
X	} else 
X	{
X		lseek(memfd,proc->p_addr[0].te_frameno * NBPC,0);
X		read(memfd,user,sizeof *user);
X	}
X	if((user->u_procp - first_proc) == proc->p_dummy0)
X		return(1);
X	else
X		return(0);
X
X}	/* end of get_user */
X
X/*+-------------------------------------------------------------------------
Xuid to username conversion; thanks for the idea to William LeFebvre
X--------------------------------------------------------------------------*/
X#define UID_NAME_HASH_SIZE	127	/* prime */
X#define HASH_EMPTY			-1
X#define HASHIT(i)			((i) % UID_NAME_HASH_SIZE)
X
Xstruct uid_name_hash_entry {
X	int  uid;
X	char name[10];
X};
X
Xstruct uid_name_hash_entry uid_name_table[UID_NAME_HASH_SIZE];
Xint uid_count = 0;
X
X/*+-------------------------------------------------------------------------
X	init_uid_name_hash()
X--------------------------------------------------------------------------*/
Xvoid
Xinit_uid_name_hash()
X{
Xregister int ihash = 0;
Xregister struct uid_name_hash_entry *hashent = uid_name_table;
X
X	while(ihash++ < UID_NAME_HASH_SIZE)
X	{
X		hashent->uid = HASH_EMPTY;
X		hashent++;
X	}
X}	/* end of init_uid_name_hash */
X
X/*+-------------------------------------------------------------------------
X	uid_name_enter(uid,name)
X--------------------------------------------------------------------------*/
Xint
Xuid_name_enter(uid,name)
Xregister int uid;
Xregister char *name;
X{
Xregister int table_uid;
Xregister int hashval;
X
X	if(++uid_count >= UID_NAME_HASH_SIZE)
X		error_term("too many user names");
X
X	hashval = HASHIT(uid);
X	while((table_uid = uid_name_table[hashval].uid) != HASH_EMPTY)
X	{
X		if(table_uid == uid)
X			return(hashval);
X		hashval = (hashval + 1) % UID_NAME_HASH_SIZE;
X	}
X
X	uid_name_table[hashval].uid = uid;
X	strncpy(uid_name_table[hashval].name,name,
X		sizeof(uid_name_table[0].name));
X
X	return(hashval);
X
X}	/* end of uid_name_enter */
X
X/*+-------------------------------------------------------------------------
X	getpwent_and_enter(uid)
X--------------------------------------------------------------------------*/
Xgetpwent_and_enter(uid)
Xregister int uid;
X{
Xregister int hashval;
Xregister struct passwd *pwd;
Xchar errant[10];
Xstruct passwd *getpwuid();
X
X	pwd = getpwuid(uid);
X	endpwent();
X	if(pwd)
X	{
X		hashval = uid_name_enter(pwd->pw_uid,pwd->pw_name);
X		return(hashval);
X	}
X	sprintf(errant,"%d",uid);
X	return(uid_name_enter(uid,errant));
X}	/* end of getpwent_and_enter */
X
X/*+-------------------------------------------------------------------------
X	uid_to_name(uid)
X--------------------------------------------------------------------------*/
Xchar *
Xuid_to_name(uid)
Xregister int uid;
X{
Xregister int uid_hash;
Xregister int table_uid;
Xregister char *name;
X
X	uid_hash = HASHIT(uid);
X	while((table_uid = uid_name_table[uid_hash].uid) != uid)
X	{
X		if(table_uid == HASH_EMPTY)
X		{
X			/* not in hash table */
X			uid_hash = getpwent_and_enter(uid);
X			break;		/* out of while */
X		}
X		uid_hash = (uid_hash + 1) % UID_NAME_HASH_SIZE;
X	}
X	return(uid_name_table[uid_hash].name);
X}	/* end of char *uid_to_name */
X
X/*+-----------------------------------------------------------------------
X	char *get_cpu_time_str(timeval)
X  6-char static string address is returned
X------------------------------------------------------------------------*/
Xchar *get_cpu_time_str(timeval)
Xlong timeval;
X{
Xstatic char timestr[10];
Xlong mm,ss;
X
X/*	timeval /= hz; */
X	timeval /= 50;
X	mm = timeval / 60L;
X	timeval -= mm * 60L;
X	ss = timeval;
X
X	if(mm > 999)
X		sprintf(timestr,"%5ldu",mm);
X	else
X		sprintf(timestr,"%3lu:%02lu",mm,ss);
X	return(timestr);
X}	/* end of get_cpu_time_str */
X
X#define AVENRUN_Y	0
X#define AVENRUN_X	0
X/*+-------------------------------------------------------------------------
X	display_line0()
X--------------------------------------------------------------------------*/
Xvoid
Xdisplay_line0()
X{
Xregister int count;
Xregister int itmp;
Xchar s64[64];
X
X	w6move(AVENRUN_Y,AVENRUN_X);
X
X	lseek(kmemfd,namelist[XL_AVENRUN].xl_value,0);
X	read(kmemfd,avenrun,sizeof(avenrun));
X
X	lseek(kmemfd,namelist[XL_MPID].xl_value,0);
X	read(kmemfd,&mpid,sizeof(mpid));
X
X	sprintf(s64,"last pid: %5d  load averages:",
X		mpid,avenrun[0],avenrun[1],0);
X	w6puts(s64);
X
X	for(count = 0; count < 3; count++)
X	{
X		itmp = avenrun[count];
X		sprintf(s64,"  %d.%02d",itmp / 100, itmp % 100);
X		w6puts(s64);
X	}
X
X}	/* end of display_line0 */
X
X#define PROC_Y		2
X#define PROC_X		0
X#define UID_X		2
X#define PID_X		12
X#define PPID_X		18
X#define PGRP_X		24
X#define CPU_X		30
X#define TIM_X		34
X#define PRI_X		38
X#define NICE_X		42
X#define WSIZE_X		45
X#define TSIZE_X		50
X#define SSIZE_X		55
X#define UTIME_X		60
X#define STIME_X		67
X#define TTY_X		74
X#define CMD_X		78
X
X/*+-------------------------------------------------------------------------
X	display_proc(iproc,initial)
X00000000001111111111222222222233333333334444444444555555555566666666667777777777
X01234567890123456789012345678901234567890123456789012345678901234567890123456789
XS     USER   PID  PPID  PGRP  CPU TIM PRI NI WSIZ TSIZ SSIZ UCPU   SCPU   TTY CM
X# ########X ##### ##### ##### ### ### ### ## #### #### #### ###### ###### ### ##
X--------------------------------------------------------------------------*/
Xvoid
Xdisplay_proc(iproc,initial)
Xregister int iproc;
Xregister int initial;
X{
Xregister int positioned = 0;
Xregister int itmp;
Xregister int got_user;
Xstruct proc *tproc = procs + iproc;
Xstruct proc *oproc = oldprocs + iproc;
Xstatic char *p_stat_str = " S?RIZTXXX";
Xchar buf[20];
X
X	if((itmp = (tproc->p_stat == SRUN)) ||
X		((tproc->p_stat != SRUN) && (oproc->p_stat == SRUN)))
X	{
X		initial = 1;
X		if(itmp && (tproc->p_pid != w6ps_pid))
X		{
X			w6reverse(1);
X			w6dim(1);
X		}
X	}
X
X	if(initial || (tproc->p_stat != oproc->p_stat))
X	{
X		w6move(PROC_Y + 2 + iproc,PROC_X);
X		w6putc(p_stat_str[tproc->p_stat]);
X		w6putc(' ');
X		positioned = 1;
X	}
X
X	if(initial || (tproc->p_uid != oproc->p_uid))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + UID_X);
X		sprintf(buf,"%8s",uid_to_name(tproc->p_uid));
X		w6puts(buf);
X		w6putc((tproc->p_uid != tproc->p_suid) ? '#' : ' ');
X		w6putc(' ');
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_pid != oproc->p_pid))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + PID_X);
X		sprintf(buf,"%5d ",tproc->p_pid);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_ppid != oproc->p_ppid))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + PPID_X);
X		sprintf(buf,"%5d ",tproc->p_ppid);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_pgrp != oproc->p_pgrp))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + PGRP_X);
X		sprintf(buf,"%5d ",tproc->p_pgrp);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_cpu != oproc->p_cpu))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + CPU_X);
X		sprintf(buf,"%3u ",tproc->p_cpu);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_time != oproc->p_time))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + TIM_X);
X		sprintf(buf,"%3u ",tproc->p_time);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_pri != oproc->p_pri))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + PRI_X);
X		sprintf(buf,"%3u ",tproc->p_pri);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_nice != oproc->p_nice))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + NICE_X);
X		sprintf(buf,"%2d ",tproc->p_nice);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_wsize != oproc->p_wsize))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + WSIZE_X);
X		sprintf(buf,"%4d ",tproc->p_wsize);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_tsize != oproc->p_tsize))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + TSIZE_X);
X		sprintf(buf,"%4d ",tproc->p_tsize);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X	if(initial || (tproc->p_ssize != oproc->p_ssize))
X	{
X		if(!positioned)
X			w6move(PROC_Y + 2 + iproc,PROC_X + SSIZE_X);
X		sprintf(buf,"%4d ",tproc->p_ssize);
X		w6puts(buf);
X		positioned = 1;
X	}
X	else
X		positioned = 0;
X
X/* since not saving user area, always update fields from it */
X	if(!positioned)
X		w6move(PROC_Y + 2 + iproc,PROC_X + UTIME_X);
X	if(got_user = get_user(tproc,iproc,&user))
X	{
X		w6puts(get_cpu_time_str(user.u_utime));
X		w6putc(' ');
X		w6puts(get_cpu_time_str(user.u_stime));
X		w6putc(' ');
X	}
X	else
X		w6puts("------ ------ ");
X	positioned = 1;
X
X	if(!positioned)
X		w6move(PROC_Y + 2 + iproc,PROC_X + TTY_X);
X	sprintf(buf,"%3.3s ",pgrp_to_ttyname(tproc->p_pgrp));
X	w6puts(buf);
X	positioned = 1;
X
X	if(!positioned)
X		w6move(PROC_Y + 2 + iproc,PROC_X + CMD_X);
X	if(got_user)
X	{
X	register char *cptr = user.u_psargs;
X		while(*cptr)
X		{
X			*cptr &= 0x7F;
X			if(*cptr < 0x20)
X				*cptr = 0x20;
X			cptr++;
X		}
X		w6puts(user.u_psargs);
X	}
X	else
X	{
X		switch(tproc->p_stat)
X		{
X			case SIDL:
X				w6puts("------ in creation ------");
X				break;
X			case SZOMB:
X				w6puts("----- in termination -----");
X				break;
X			case SXBRK:
X			case SXSTK:
X			case SXTXT:
X				w6puts("-------- swapping --------");
X			default:
X				w6puts("???");
X		}
X	}
X
X	w6clrtoeol();
X	w6norm();
X
X}	/* end of display_proc */
X
X/*+-------------------------------------------------------------------------
X	display_procs(initial)
X--------------------------------------------------------------------------*/
Xvoid
Xdisplay_procs(initial)
Xint initial;
X{
Xregister int iproc;
X	for(iproc = 0; iproc < nprocs; iproc++)
X		display_proc(iproc,(iproc >= noldprocs) ? 1 : initial);
X	w6clrtobot();
X}	/* end of display_procs */
X
X/*+-------------------------------------------------------------------------
X	proc_pid_compare(p1,p2)
X--------------------------------------------------------------------------*/
Xproc_pid_compare(p1,p2)
Xstruct proc *p1;
Xstruct proc *p2;
X{
X	return(p1->p_pid - p2->p_pid);
X}	/* end of proc_pid_compare */
X
X/*+-------------------------------------------------------------------------
X	get_procs()
X--------------------------------------------------------------------------*/
Xvoid
Xget_procs()
X{
Xregister int iproc;
Xregister int proc_size = v.v_proc * sizeof(struct proc);
Xstruct proc *tproc;
X
X/* save old proc structure */
X	memcpy((char *)oldprocs,(char *)procs,proc_size);
X	noldprocs = nprocs;
X
X/* read current procs - steal iproc register int temporarily */
X	lseek(kmemfd,namelist[XL_PROC].xl_value,0);
X	if((iproc = read(kmemfd,procs,proc_size)) != proc_size)
X		perror_term("get_procs: cannot read kmem",iproc);
X
X/* if slot not in use, force to end when sorting */
X	nprocs = 0;
X	for(iproc = 0;iproc < v.v_proc;iproc++)
X	{
X		tproc = procs + iproc;
X		tproc->p_dummy0 = iproc;		/* save slot number */
X		if((tproc->p_stat == 0) || (tproc->p_pgrp == tproc->p_pid) ||
X			(tproc->p_pgrp == 0))
X			tproc->p_pid = 32767;
X		else
X			nprocs++;
X	}
X
X/* sort new procs array */
X	qsort((char *)procs,v.v_proc,sizeof(struct proc),proc_pid_compare);
X
X}	/* end of get_procs */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X--------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xregister int itmp;
Xchar s80[80];
Xextern char *w6tty_default;
X
X	setbuf(stdout,NULL);
X	setbuf(stderr,NULL);
X
X	w6ps_pid = getpid();
X
X	if(itmp = w6open(w6tty_default))
X	{
X		printf("w6open error %d\n",itmp);
X		exit(1);
X	}
X
X	w6ctrl(W6SCROFF);
X	w6clr();
X	w6topline("");
X	w6ctrl(W6SCRON);
X	w6ctrl(W6CUROFF);
X	w6eolwrap(1);
X	w6_132cols();
X	w6_43lines();
X
X	if(access("/xenix",4))
X	{
X		fprintf(stderr,"must have read access to /xenix\n");
X		exit(1);
X	}
X	if(xlist("/xenix",namelist) != 0)
X	{
X		perror("w6ps: namelist");
X		exit(1);
X	}
X
X	if(access("/dev/mem",4) || access("/dev/kmem",4) ||
X		access("/dev/swap",4))
X	{
X		fprintf(stderr,"w6ps: must be owned by root or sysinfo + setuid\n");
X		exit(1);
X	}
X
X	if((memfd = open("/dev/mem",O_RDONLY)) < 0)
X	{
X		perror("w6ps: /dev/mem");
X		exit(1);
X	}
X	if((kmemfd = open("/dev/kmem",O_RDONLY)) < 0)
X	{
X		perror("w6ps: /dev/kmem");
X		exit(1);
X	}
X	if((swapfd = open("/dev/swap",O_RDONLY)) < 0)
X	{
X		perror("w6ps: /dev/swap");
X		exit(1);
X	}
X
X	lseek(kmemfd,namelist[XL_V].xl_value,0);
X	read(kmemfd,&v,sizeof v);
X
X	lseek(kmemfd,namelist[XL_SWPLO].xl_value,0);
X	read(kmemfd,&swplo,sizeof swplo);
X
X	lseek(kmemfd,namelist[XL_UTSNAME].xl_value,0);
X	read(kmemfd,&utsname,sizeof utsname);
X
X	lseek(kmemfd,namelist[XL_HZ].xl_value,0);
X	read(kmemfd,&hz,sizeof hz);
X
X	sprintf(s80,"%s - %s %s %s",utsname.nodename,
X		utsname.sysname,utsname.version,utsname.release);
X	w6topline(s80);
X
X	if(!(procs = (struct proc *)calloc(1,v.v_proc * sizeof(struct proc))))
X	{
X		fprintf(stderr,"no memory\n");
X		exit(1);
X	}
X
X	if(!(oldprocs = (struct proc *)malloc(v.v_proc * sizeof(struct proc))))
X	{
X		fprintf(stderr,"no memory\n");
X		exit(1);
X	}
X	noldprocs = nprocs = 0;
X
X	init_uid_name_hash();
X
X	w6move(PROC_Y,PROC_X);
X	w6puts("S     USER   PID  PPID  PGRP  CPU TIM PRI NI WSIZ TSIZ SSIZ UCPU   SCPU   TTY CMD");
X	w6move(PROC_Y + 1,PROC_X);
X	w6puts("- --------- ----- ----- ----- --- --- --- -- ---- ---- ---- ------ ------ --- --");
X	get_procs();
X	display_line0();
X	display_procs(1);
X
X	while(1)
X	{
X		sleep(2);
X		get_procs();
X		display_line0();
X		display_procs(0);
X	}
X
X	exit(0);
X}	/* end of main */
X
X
SHAR_EOF
chmod 0644 w6ps.c || echo "restore of w6ps.c fails"
fi
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Ker-au'-lo-phon.  An 8-foot partial flue-stop, having metal pipes
surmounted by adjustable rings, and with a hole bored near the top
of each pipe, producing a soft and "reedy" tone.