#

/*
 *	ps - process status
 *	examine and print certain things about processes
 */

#include </param.h>
#include </proc.h>
#include </tty.h>
#include </user.h>
#define EGOOD		0
#define EBAD		1
#define NONEWLINE	0
#define NEWLINE		1
#define OUTPUT		1

struct	{
	char	lobyte;
	char	hibyte;
};
struct {
	char	name[8];
	int  type;
	char  *value;
} nl[4]{
	"_proc", 0, 0,
	"_swapdev", 0, 0,
	"_syspara", 0, 0,
	"\0\0\0\0\0\0\0\0", 0, 0
};

struct	proc mproc[1];

int	ua[256];
int	chkpid;
int	lflg;
int	nflg;
int	cflg;
int	xflg;
int	tflg;
int	aflg;
int	mem;
int	swmem;
int	swap;
char	swapnam[20];
int	nproc	NPROC;

int	ndev;
int	devc[65];
int	devl[65];
char	*coref;
char	*unix	"/unix";
int	swapdev;
struct ibuf {
	char	idevmin, idevmaj;
	int	inum;
	int	iflags;
	char	inl;
	char	iuid;
	char	igid;
	char	isize0;
	int	isize;
	int	iaddr[8];
	char	*ictime[2];
	char	*imtime[2];
	int	fill;
};
char	partab[1];


main(argc, argv)
char **argv;
{
	struct proc *p;
	int n, b;
	int i, c;
	char *ap,*aq;
	int uid, puid;
	extern fout;

	argc--;
	argv++;
	if (argc>0 && *argv[0] == '-') {
		ap = argv[0];
		while (*ap) 
			switch (*ap++) {
		case 'a':
			aflg = 1;
			break;

		case 't':	/* Processes of a given teletype */
			aq = argv[1];
			argv++;
			argc--;
			if(*aq)
				tflg.lobyte = *aq++;
			if(*aq)
				tflg.hibyte = *aq++;
			aflg++;
			if(tflg == '?')
				xflg++;
			break;

		case 'x':	/* All processes */
			xflg++;
			if(aflg == 0)
				aflg  = 20;
			break;

		case '-':
			break;

		case 'l':	/* Long listing */
			lflg++;
			break;

		case 's':	/* Namelist other that /unix */
			nflg++;
			break;

		default:
			chkpid=atoi(--ap);
			*ap = '\0';
			break;
		}
		argc--;
		argv++;
	}

	if(nflg){
		unix = argv[argc-1];
	}
	if(nlist(unix, nl) <0){
		printf("No namelist\n");
		done(EBAD);
	}
	coref = "/dev/mem";
	if(((argc>=1)&&(nflg == 0))||((argc>=2)&&nflg)){
		coref = argv[0];
		cflg++;
	}
	if ((mem = open(coref, 0)) < 0) {
		printf("Can't open %s\n",coref);
		done(EBAD);
	}
	swmem = open(coref, 0);
	if(chdir("/dev") < 0) {
		write(2,"cannot change to /dev\n",22);
		done(EBAD);
	}
	/*
	 * read mem to find swap dev.
	 */
	if((seek(mem, nl[1].value, 0)<0)||
	(read(mem, &swapdev, 2) != 2)){
		printf("No swapdev\n");
	}
	/*
	 * read number of processes
	 */
	if(nl[2].type > 0){
		seek(mem,nl[2].value,0);
		read(mem,nproc,2);
	}
	/*
	 * Locate proc table
	 */
	if(seek(mem, nl[0].value, 0)<0){
		printf("Can't seek to proc table \n");
		done(EBAD);
	}
	getdev();
	uid = getuid() & 0377;
	fout = dup(OUTPUT);
	if (lflg){
		printf("swap device %s\n",swapnam);
	printf(" F S UID   PID  PPID CPU PRI NICE  ADDR  SZ  WCHAN LNE TIME COMMAND\n"); 
	}else
		if (chkpid==0) printf("   PID LNE TIME COMMAND\n");
	for (i=0; i<nproc; i++) {
		if(read(mem, mproc, sizeof mproc)!= sizeof mproc){
			printf("Read error proc table\n");
		}
		if (mproc[0].p_stat==0)
			continue;
		if (((mproc[0].p_pgrp==0) && (xflg==0))||
			((xflg&&(aflg==20))&&(mproc[0].p_pgrp != 0)))
			continue;
		puid = mproc[0].p_uid & 0377;
		if ((uid != puid && aflg==0) ||
		    (chkpid!=0 && chkpid!=mproc[0].p_pid))
			continue;
		if(prcom(puid))
			printf("\n");
		flush();
	}
	done(EGOOD);
}

getdev()
{
	register struct { int dir_ino; char dir_n[14]; } *p;
	register i, c;
	int f;
	char dbuf[512];
	int sbuf[20];

	f = open("/dev", 0);
	if(f < 0) {
		write(2,"cannot open /dev\n",16);
		done(EBAD);
	}
	swap = -1;
	c = 0;

loop:
	i = read(f, dbuf, 512);
	if(i <= 0) {
		close(f);
		if(swap < 0) {
			write(2,"no swap device\n",15);
		}
		ndev = c;
		return;
	}
	while(i < 512)
		dbuf[i++] = 0;
	for(p = dbuf; p < dbuf+512; p++) {
		if(p->dir_ino == 0)
			continue;
		if(p->dir_n[0] == 'l' &&
		   p->dir_n[1] == 'n' &&
		   p->dir_n[2] != 0   &&
		   p->dir_n[4] == 0) {
			if(stat(p->dir_n, sbuf) < 0)
				continue;
			devc[c].lobyte = p->dir_n[2];
			devc[c].hibyte = p->dir_n[3];
			devl[c] = sbuf->iaddr[0];
			c++;
			continue;
		}
		if(swap >= 0)
			continue;
		if(stat(p->dir_n, sbuf) < 0)
			continue;
		if((sbuf->iflags & 060000) != 060000)
			continue;
		if(sbuf->iaddr[0] == swapdev){
			swapdev = -1;
			if(cflg){
				if((swap = open("/dev/null",0))<0){
					printf("No null device\n");
				}
			}else{
				if((swap = open(p->dir_n, 0))<0){
					printf("Can't open %s\n",p->dir_n);
				}
			}
			copy(swapnam,"/dev/",5);
			copy(&swapnam[5],p->dir_n,14);
		}
	}
	goto loop;
}


prcom(puid)
{
	int  mf;
	register int *ip;
	register char *cp, *cp1;
	long tm;
	int c, nbad;
	long	o,oc;

	o = mproc[0].p_addr;
	if (mproc[0].p_flag&SLOAD) {
		mf = swmem;
		o =<< 6;
	} else {
		mf = swap;
		o =<< 9;
		if(swap<0)
			return(NONEWLINE);
	}
	lseek(mf, o, 0);
	if (read(mf, &ua[0], 512) != 512)
		return(NONEWLINE);
	c = gettty();
	if(tflg && c != tflg)
		return(NONEWLINE);
	if (lflg) {
		if(mproc[0].p_wchan&&(mproc[0].p_pri > 0))
		printf("%2o %c%4d", mproc[0].p_flag,
			'W' ,puid);
		else
			printf("%2o %c%4d", mproc[0].p_flag,
				"0SWRIZT"[mproc[0].p_stat], puid);
	}
	printf("%6u", mproc[0].p_pid);
	if (lflg) {
		printf("%6u%4d%4d%5d %5o%4d", mproc[0].p_ppid, mproc[0].p_cpu&0377,
			mproc[0].p_pri,
			mproc[0].p_nice,
			mproc[0].p_addr, (mproc[0].p_size+7)>>3);
		if (mproc[0].p_wchan)
			printf("%7o", mproc[0].p_wchan); else
			printf("       ");
	}
	printf("  %c%c", c.lobyte,c.hibyte);
	if (mproc[0].p_stat==5) {
		printf("  <defunct>");
		return(NEWLINE);
	}
	if(cflg&&((mproc[0].p_flag&SLOAD) == 0))
		return(NEWLINE);
	tm = (ua[0].u_utime + ua[0].u_stime + 30)/60;
	printf(" %2ld:", tm/60);
	tm =% 60;
	printf(tm<10?"0%ld":"%ld", tm);
	if(mproc[0].p_pid == 0){
		printf(" Scheduler\n");
		return(NONEWLINE);
	}
	c = mproc[0].p_size - 8;
	oc = c;
	oc =<< 6;
	o =+ oc;
	lseek(mf, o, 0);
	if (read(mf, ua, 512) != 512)
		return(NEWLINE);
	for (ip = &ua[256]; ip > &ua[0];) {
		if (*--ip == -1) {
			cp = ip+1;
			if (*cp==0)
				cp++;
			nbad = 0;
			for (cp1 = cp; cp1 < &ua[256]; cp1++) {
				c = *cp1;
				if (c==0)
					*cp1 = ' ';
				else if (c < ' ' || c > 0176) {
					if (++nbad >= 5) {
						*cp1++ = ' ';
						break;
					}
					*cp1 = '?';
				}
			}
			while (*--cp1==' ')
				*cp1 = 0;
			printf(lflg?" %.30s":" %.60s", cp);
			return(NEWLINE);
		}
	}
	return(NEWLINE);
}

gettty()
{
	register i;
	int q;

	q.lobyte = '?';
	q.hibyte = ' ';
	if (ua[0].u_ttyp==0){
		return(q);
	}
	for (i=0; i<ndev; i++)
		if (devl[i] == ua[0].u_ttyd)
			return(devc[i]);
	return(q);
}

done(code)
{
	flush();
	exit(code);
}
copy(a,b,c)
char	*a,*b;
int	c;
{
	register i;
	register char *p,*q;

	p = a;
	q = b;
	for(i=0;i<c;i++){
		if(*q == '\0')
			break;
		*p++ = *q++;
	}
	return(i);
}
