SysIII/usr/src/cmd/ps.c

Compare this file to the similar file:
Show the results in this format:


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

#include <stdio.h>
#include <a.out.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/var.h>
#include <core.h>

#define NTTYS	20
#define SIZ 	30
#define TSIZE	100
#define ARGSIZ	30

struct nlist nl[] = {
	{ "_proc" },
	{ "_swplo" },
	{ "_v" },
	{ 0 },
};

union {
	struct proc mprc;
	struct xproc zprc;
	} prc;
#define mproc prc.mprc
#define zproc prc.zprc
struct	var  v;
#ifdef pdp11
struct	user u;
#endif
#ifdef vax
union { struct user yy;
	int xx[128] [UPAGES];
	} zz;
#define u zz.yy
int	pagetbl[128];
int	mf;
#endif

int	retcode=1;
int	c;
int	lflg;
int	eflg;
int	uflg;
int	aflg;
int	dflg;
int	pflg;
int	fflg;
int	gflg;
int	tflg;
int	sflg;
int	errflg;
char	*gettty();
char	*ttyname();
int	mem;
int	swmem;
int	swap;
daddr_t	swplo;
char	argbuf[ARGSIZ];
char	*parg;
char	*p1;
char	*coref;
char	*memf;
long lseek();

int	ndev;
struct devl {
	char	dname[DIRSIZ];
	dev_t	dev;
} devl[256];

static	int uid_num[TSIZE];	/* for u option */
static	char *uid_name[TSIZE];
static	int uidn = 0;
int	uid_tbl[SIZ];
int	nuids = 0;
char	*tty[NTTYS];	/* for t option */
int	ntty = 0;
int	pid[SIZ];	/* for p option */
int	npid = 0;
int	grpid[SIZ];	/* for g option */
int	ngrpid = 0;

main(argc, argv)
char **argv;
{
	register char **ttyp = tty;
	char *system, *name;
	char *p;
	int puid, ppid, ppgrp;
	int i, found;
	extern char *optarg;
	extern int optind;
	char	*getstr;
	char *usage="ps [ -edalf ] [ -c corefile ] [ -s swapdev ] [ -n namelist ] [ -t tlist ]";
	char *usage2="	[ -p plist ] [ -u ulist ] [ -g glist ]";
	char *malloc();
	unsigned size;

	getstr = "lfeadn:s:c:t:p:g:u:";
	system = "/unix";
#ifdef vax
		coref = "/dev/kmem";
		memf = "/dev/mem";
#else
		coref = "/dev/mem";
		memf = coref;
#endif

	while ((c = getopt(argc,argv,getstr)) != EOF)
		switch(c) {
		case 'l':		/* long listing */
			lflg++;
			break;

		case 'f':		/* full listing */
			fflg++;
			break;

		case 'e':		/* list for every process */
			eflg++;
			tflg = uflg = pflg = gflg = 0;
			break;

		case 'a':		/* same as e except no proc grp leaders */
			aflg++; 	/* and no non-terminal processes     */
			break;

		case 'd':		/* same as e except no proc grp leaders */
			dflg++;
			break;

		case 'n':		/* alternate namelist */
			system = optarg;
			break;

		case 'c':		/* core file given */
			coref = optarg;	
			memf = coref;
			break;

		case 's':		/* swap device given */
			sflg++;
			if ((swap = open(optarg, 0)) < 0 ) {
				fprintf(stderr, "ps: cannot open %s\n",optarg);
				done(1);
			}
			break;

		case 't':		/* terminals */
			tflg++;
			p1 = optarg;
			do {
				parg = argbuf;
				if (ntty >= NTTYS)
					break;
				getarg();
				if (strncmp(parg,"tty",3) == 0)
					parg += 3;
				size = strlen(parg);
				if ((p = malloc(++size)) == 0) {
					fprintf(stderr,"ps: no memory\n");
					done(1);
				}
				strcpy(p,parg);
				*ttyp++ = p;
				ntty++;
			}
			while (*p1);
			break;

		case 'p':		/* proc ids */
			pflg++;
			p1 = optarg;
			parg = argbuf;
			do {
				if (npid >= SIZ)
					break;
				getarg();
				pid[npid++] = atoi(parg);
			}
			while (*p1);
			break;

		case 'g':		/* proc group */
			gflg++;
			p1 = optarg;
			parg = argbuf;
			do {
				if (ngrpid >= SIZ)
					break;
				getarg();
				grpid[ngrpid++] = atoi(parg);
			}
			while (*p1);
			break;

		case 'u':		/* user name or number */
			uflg++;
			p1 = optarg;
			parg = argbuf;
			do {
				getarg();
				uopt(parg);
			}
			while (*p1);
			break;

		case '?':		/* error */
			errflg++;
			break;
		}
	if ( errflg || (optind < argc)) {
		fprintf(stderr,"usage: %s\n%s\n",usage,usage2);
		done(1);
	}
	if (tflg)
		*ttyp = 0;
	/* if specifying options not used, current terminal is default */
	if ( !(aflg || eflg || dflg || uflg || tflg || pflg || gflg )) {
		name = ttyname(2);
		if (strncmp(name+5,"tty",3)==0)
			*ttyp++ = name+8;
		else
			*ttyp++ = name+5;
		*ttyp = 0;
		ntty++;
		tflg++;
	}
	if (eflg)
		tflg = uflg = pflg = gflg = aflg = dflg = 0;
	if (aflg || dflg)
		tflg = 0;
	nlist(system, nl);
	if(nl[0].n_type==0||nl[1].n_type==0||nl[2].n_type==0) {
		fprintf(stderr, "ps: no namelist\n");
		done(1);
	}
#ifdef	vax
	nl[0].n_value = ((int)nl[0].n_value & 0x3fffffff);
	nl[1].n_value = ((int)nl[1].n_value & 0x3fffffff);
	nl[2].n_value = ((int)nl[2].n_value & 0x3fffffff);
#endif
	if ((mem = open(coref, 0)) < 0) {
		fprintf(stderr, "ps: no mem\n");
		done(1);
	}
	if ((swmem = open(memf,0)) < 0) {
		fprintf(stderr, "ps: no mem\n");
		done(1);
	}
	if (chdir("/dev") < 0) {
		fprintf(stderr, "ps: cannot change to /dev\n");
		done(1);
	}
	/*
	 * Find base of swap
	 */
	l_lseek(mem, (long)nl[1].n_value, 0);
	r_read(mem, (char *)&swplo, sizeof(swplo));
	/*
	 * read to find proc table size
	 */
	l_lseek(mem, (long)nl[2].n_value, 0);
	r_read(mem, (char *)&v, sizeof(v));
	/*
	 * Locate proc table
	 */
	l_lseek(mem, (long)nl[0].n_value, 0);
	getdev();
	if (fflg && lflg )
		printf("  F S    UID   PID  PPID  C PRI NI    ADDR SZ    WCHAN   STIME TTY TIME COMD\n");
	else if (fflg)
		printf("    UID   PID  PPID  C   STIME TTY  TIME COMMAND\n");
	else if (lflg)
		printf("  F S   UID   PID  PPID  C PRI NI    ADDR SZ   WCHAN TTY  TIME COMD\n");
	else
		printf("   PID TTY TIME COMMAND\n");
	/* determine which processes to print info about */
	for (i=0; i<v.v_proc; i++) {
		found = 0;
		r_read(mem, (char *)&mproc, sizeof(mproc));
		if (mproc.p_stat == 0)	
			continue;
		puid = mproc.p_uid;
		ppid = mproc.p_pid;
		ppgrp = mproc.p_pgrp;
		if ((ppid == ppgrp) && (dflg || aflg))
			continue;
		if (eflg || dflg)
			found++;
		else if (pflg && search(pid, npid, ppid))
			found++;
		else if (uflg && ufind(puid))
			found++;
		else if (gflg && search(grpid, ngrpid, ppgrp))
			found++;
		if ( !found && !tflg && !aflg )
			continue;
		if (prcom(puid,found)) {
			printf("\n");
			retcode =0;
		}
	}
	done(retcode);
}

/* getdev reads in the open devices (terminals) and stores */
/* info in the devl structure.  /dev/swap is opened */
getdev()
{
#include <sys/stat.h>
	register FILE *df;
	struct stat sbuf;
	struct direct dbuf;

	if ((df = fopen("/dev", "r")) == NULL) {
		fprintf(stderr, "ps: cannot open /dev\n");
		done(1);
	}
	ndev = 0;
	while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
		if(dbuf.d_ino == 0)
			continue;
		if(stat(dbuf.d_name, &sbuf) < 0)
			continue;
		if ((sbuf.st_mode&S_IFMT) != S_IFCHR)
			continue;
		strcpy(devl[ndev].dname, dbuf.d_name);
		devl[ndev].dev = sbuf.st_rdev;
		ndev++;
	}
	fclose(df);
	if ( !sflg ) {
		if ((swap = open("/dev/swap", 0)) < 0) {
			fprintf(stderr, "ps: cannot open /dev/swap\n");
			done(1);
		}
	}
}

/* getarg finds next argument in list and copies arg into argbuf  */
/* p1 first pts to arg passed back from getopt routine.  p1 is then */
/* bumped to next character that is not a comma or blank - p1 null */
/* indicates end of list    */

getarg()
{
	char *parga;
	parga = argbuf;
	while(*p1 && *p1 != ',' && *p1 != ' ')
		*parga++ = *p1++;
	*parga = '\0';

	while( *p1 && ( *p1 == ',' || *p1 == ' ') )
		p1++;
}

/* gettty returns the user's tty number or ? if none  */
char *gettty()
{
	register i;
	register char *p;

	if (u.u_ttyp==0)
		return("?");
	for (i=0; i<ndev; i++) {
		if (devl[i].dev == u.u_ttyd) {
			p = devl[i].dname;
			if (strncmp(p,"tty",3) == 0)
				p += 3;
			return(p);
		}
	}
	return("?");
}

#ifdef pdp11
long	round(a,b)
	long		a, b;
{
	long		w = ((a+b-1)/b)*b;

	return(w);
}
#endif

typedef unsigned pos;
struct map {
	long	b1, e1; long f1;
	long	b2, e2; long f2;
};
struct map datmap;

int	file;

/* print info about the process */
prcom(puid,found)
int puid,found;
{
	int abuf[BSIZE/sizeof(int)];
	long addr;
	register int *ip;
	register char *cp, *cp1;
	char *cp2;
	char *ctime();
	time_t time();
	time_t *clock, *tloc;
	time_t tim;
	char timbuf[26];
	char *curtim = timbuf;
	char *sttim, *s1;
	long tm;
	int c, nbad, badflg;
	register char *tp;
	long	txtsiz, datsiz, stksiz;
	int	septxt;
	int	match, i;
	int	nbytes;
	int	uzero = 0;
	register char **ttyp, *str;
	int	lw=(lflg?35:80);

	/* if process is zombie, call print routine and return */
	if (mproc.p_stat==SZOMB) {
		if ( tflg && !found)
			return(0);
		else {
			przom(puid);
			return(1);
		}
	}
	/* Determine if process is in memory or swap space */
	/* and read in user block */
#ifdef vax
	if ((mproc.p_flag& (SLOAD | SSPART)) == 0) {
		addr = (mproc.p_swaddr+swplo)<<9;
		mf = swap;
		l_lseek(mf, addr, 0);
		if ((nbytes = read(mf, (char *)&u, sizeof(u))) != sizeof(u)) {
			if (( nbytes == 0) && sflg) {
				uzero++;
				for ( i = 0, tp = (char *) &u; i < sizeof(u); i++)
					*tp++ = '\0';
			}
			else
				return(0);
		}
	} else {
		for(c=0; c<UPAGES; c++) {
			l_lseek(swmem,(long)mproc.p_addr[c]<<9,0);
			if (read(swmem,(char *)(((int *)&u)+128*c),512) != 512)	/* get u page */
				return(0);
		}
	}
#endif
#ifdef pdp11
	if (mproc.p_flag&SLOAD) {
		addr = ctob((long)mproc.p_addr);
		file = swmem;
	} else {
		addr = (mproc.p_addr+swplo)<<9;
		file = swap;
	}
	l_lseek(file, addr, 0);
	if ((nbytes = read(file, (char *)&u, sizeof(u))) != sizeof(u))
		if (( nbytes == 0) && sflg && (file == swap)) {
			uzero++;
			for ( i = 0, tp = (char *) &u; i < sizeof(u); i++)
				*tp++ = '\0';
		} else 
			return(0);
#endif

	/* get current terminal - if none (?) and aflg is set */
	/* then don't print info - if tflg is set, check if term */
	/* is in list of desired terminals and print if so   */
	tp = gettty();
	if ( aflg && (*tp == '?' ))
		return(0);
	if(tflg && !found) {	/* the t option */
		for (ttyp=tty, match=0; (str = *ttyp) !=0 && !match; ttyp++)
			if (strcmp(tp,str) == 0)
				match++;
		if(!match)
			return(0);
	}

	if (lflg)
		printf("%3o %c", mproc.p_flag&0377, "OSWRIZT"[mproc.p_stat]);	/* F S */
	if (fflg) {
		i = getunam(puid);
		if (i >= 0)
			printf("%7s", uid_name[i]);
		else
			printf("%7d", puid);
	}
	else if (lflg)
		printf("%6d", puid);
	printf("%6u",mproc.p_pid);	/* PID */
	if (lflg || fflg)
		printf("%6u%3d", mproc.p_ppid, mproc.p_cpu&0377);	/* PPID  CPU */
	if (lflg) {
		printf("%4d%3d",mproc.p_pri, mproc.p_nice);	/* PRI  NICE */
#ifdef vax
		printf("%8x%3d", mproc.p_addr[0], mproc.p_size);	/* ADDR  SZ */
		if (mproc.p_wchan)
			printf("%9x",mproc.p_wchan);	/* WCHAN */
		else
			printf("         ");
#endif
#ifdef pdp11
		printf("%8o%3d", mproc.p_addr, (mproc.p_size+7)>>3);
		if (mproc.p_wchan)
			printf("%9o", mproc.p_wchan);
		else
			printf("         ");
#endif
	}
	if (uzero) 		/* u-block zeroed out so return */
		return(1);
	if (fflg) {		  /* STIME*/
		clock = &u.u_start;
		tim = time((time_t *) 0);
		tloc = &tim;
		s1 = ctime(tloc);
		strcpy(curtim,s1);
		sttim = ctime(clock);
		prtim(curtim, sttim);
	}
	printf(" %2.2s", tp);	/* TTY */
	tm = (u.u_utime + u.u_stime + 30)/60;	/* TIME */
	printf(" %2ld:", tm/60);
	tm %= 60;
	printf(tm<10?"0%ld":"%ld", tm);
	if (mproc.p_pid==0) {
		printf(" swapper");
		return(1);
	}
	/* if fflg not set, print command from u_block */
	if (!fflg) {		/* CMD */
		printf(" %.8s", u.u_comm);
		return(1);
	}
	/* set up address maps for user pcs */
#ifdef pdp11
	txtsiz = ctob(u.u_tsize);
	datsiz = ctob(u.u_dsize);
	stksiz = ctob(u.u_ssize);
	septxt = u.u_sep;
	datmap.b1 = (septxt ? 0 : round(txtsiz,TXTRNDSIZ));
	datmap.e1=datmap.b1+datsiz;
	datmap.f1 = ctob(USIZE)+addr;
	datmap.b2 = stackbas(stksiz);
	datmap.e2 = stacktop(stksiz);
	datmap.f2 = ctob(USIZE)+(datmap.e1-datmap.b1)+addr;

	/* determine if process is a shell or not */ 
	/* if last word is null then shell */
	
	addr += ctob(mproc.p_size) - BSIZE;
	l_lseek(file, addr+BSIZE-sizeof(int), 0);
	if (read(file, (char *)abuf, sizeof(int)) != sizeof(int))
		return(1);
	if (abuf[0]&0177400) {
		char b[82];
		char *bp = b;
		char **ap = abuf[0];
		char *cp;
	
		*bp++ = ' ';
		badflg = 0;
		while((cp=(char *)getword(ap++)) != -1 && cp && (bp < b+lw)){
			nbad = 0;
			while((c = getbyte(cp++)) && (int)(cp) != 0177777 && (bp < b + lw)){
				badflg++;
				if (c < ' ' || c > '~') {
					if (nbad++ > 3)
						break;
					continue;
				}
				*bp++ = c;
			}
			*bp++ = ' ';
		}
		*bp++ = '\0';
		if ( badflg == 0 || nbad != 0 || *b == '\0' )
			printf(" [ %.8s ]",u.u_comm);
		else
			printf("%.20s",b);
		return(1);
	}
	l_lseek(file, addr, 0);
	if (read(file, (char *)abuf, sizeof(abuf)) != sizeof(abuf))
		return(1);
#endif
#ifdef vax
	c = mproc.p_size - btoc(512);
	if ((mproc.p_flag & SLOAD) == 0) {
		addr += ctob(c);
		l_lseek(mf, addr, 0);
		if (read(mf, (char *)abuf, sizeof(abuf)) != sizeof(abuf))
			return(1);
	} else {
		if (u.u_pcb.pcb_szpt<1 || u.u_pcb.pcb_szpt>20)
			return(1);
		c = ctob((u.u_ptable[u.u_pcb.pcb_szpt-1] & 0x1fffff));
		l_lseek(swmem,(long)c,0);
		if (read(swmem,(char *)pagetbl,512) != 512)	/* get last page table */
			return(1);
		l_lseek(swmem,ctob((pagetbl[127] & 0x1fffff)),0);
		if (read(swmem,(char *)abuf,sizeof(abuf)) != sizeof(abuf))
			return(1);
	}
#endif
	badflg = 0;
	for (ip = &abuf[BSIZE/sizeof(int)-sizeof(int)]; ip > abuf;) {
		if (*--ip == -1 || *ip == 0) {
			cp = (char *)(ip+1);
			if (*cp==0)
				cp++;
			nbad = 0;
			for (cp2 = cp1 = cp; cp1 < (char *)&abuf[BSIZE/sizeof(int)]; cp1++) {
				badflg++;
				c = *cp1&0177;
				if (c==0) {
					*cp1 = ' ';
					cp2 = cp1;
				}
				else if (c < ' ' || c > '~') {
					if (++nbad >= 3) {
						*cp1++ = ' ';
						break;
					}
					*cp1 = '?';
				}
				if (c == '=') {
					cp1 = cp2;
					*cp1++ = 0;
					break;
				}
			}
			while (*--cp1==' ')
				*cp1 = 0;
			if ( badflg == 0 || nbad != 0 || *cp == '\0')
				printf(" [ %.8s ]",u.u_comm);
			else
				printf(lflg?" %.35s":" %.80s", cp);
			return(1);
		}
	}
	printf(" [ %.8s ]",u.u_comm);
	return(1);
}


/* file handling and access routines */

getbyte(adr)
	pos	adr;
{
	return((int)access(adr,1));
}

getword(adr)
	pos	adr;
{
	return((int)access(adr,sizeof(int*)));
}

access(aadr,size)
pos aadr;
int size;
{
	int *word = 0;
	register struct map *amap = &datmap;
	long adr = aadr;

	if(!within(aadr,amap->b1,amap->e1)) {
		if(within(aadr,amap->b2,amap->e2)) 
			adr += (amap->f2)-(amap->b2);
		else
			return(0);
	}
	else {
		adr += (amap->f1)-(amap->b1);
	}
	if(lseek(file,adr,0)==-1 || read(file,(char *)&word,size)<size) {
		return(0);
	}

	return(word);
}


within(adr,lbd,ubd)
	pos	adr;
	long	lbd, ubd;
{
	return(adr>=lbd && adr<ubd);
}

done(exitno)
{
	exit(exitno);
}

/* search returns 1 if arg is found in array arr */
/* which has length num, and returns 0 if not found */

search(arr, num, arg)
int arr[];
int num;
int arg;
{
	int i;
	for (i = 0; i < num; i++)
		if (arg == arr[i])
			return(1);
	return(0);
}

/* uopt is used for the fancy version of the u option where either */
/* user name or number may be an argument.  The arrays uid_name & */
/* uid_num store the associated names and numbers.  ( these arrays are */
/* later used for printing UID ). The array uid_tbl stores */
/* ptrs (index) into the name & number arrays for arguments */
/* after the u option */

#include <pwd.h>
uopt(oarg)
char *oarg;
{
	int found = -1;

	struct passwd *pwd, *getpwuid(), *getpwname();
	char *pwname;
	char *p, *malloc();
	unsigned size;
	int pwuid;
	int i;

	/* search thru name array for oarg */
	for (i=0; i<uidn; i++) {
		if (strcmp(oarg,uid_name[i])==0) {
			found = i;
			break;
		}
	}
	/* if not found then search through number array */
	if (found < 0) {
		pwuid = atoi(oarg);
		for (i=0; i<uidn; i++) {
			if (pwuid == uid_num[i]) {
				found = i;
				break;
			}
		}
	}
	/* if found then enter found index into tbl array */
	if ( found != -1 ) {
		if (nuids >= SIZ) return;
		uid_tbl[nuids++] = found;
		return;
	}
	/* oarg was not found in uid arrays so search through /etc/passwd */
	/* for name and number.  If found, enter name and number in arrays */
	/* and then put values in table */

	pwname = oarg;
	if(pwd = getpwname(pwname)) {	/* not null so found */
		pwuid = pwd->pw_uid;
	}
	else {
		pwuid = atoi(oarg);
	/* rewrite an atoi - this is kludge */
		if (( pwuid == 0) && (strcmp(oarg,"0") != 0))
			return;
		if (pwd = getpwuid(pwuid)) {
			pwname = pwd->pw_name;
		}
		else {
		/* not found so name or number is invalid */
		return;
		}
	}

	/* put nuid name and number in table */
	if (( uidn >= TSIZE) || (nuids >= SIZ))
		return;
	uid_num[uidn] = pwuid;
	size = strlen(pwname);
	if ((p = malloc(++size)) == 0) {
		fprintf(stderr,"ps: no memory\n");
		done(1);
	}
	strcpy(p,pwname);
	uid_name[uidn] = p;
	uid_tbl[nuids++] = uidn;
	uidn++;
	return;
}

/* for full command (-f flag) print user name instead of number */
/* search thru existing table of userid numbers and if puid is found, */
/* return corresponding name.  Else search thru /etc/passwd */

getunam(puid)
int puid;
{
	struct passwd *pwd, *getpwuid();
	char *p, *malloc();
	unsigned size;
	char *uname;
	int i;

	for (i=0; i<uidn; i++)
		if (uid_num[i] == puid)
			return(i);
	/* not found in table so search thru /etc/passwd for number & return name */
	if (pwd = getpwuid(puid))
		uname = pwd->pw_name;
	else
		return(-1);
	if (uidn >= TSIZE) return(-1);
	uid_num[uidn] = puid;
	size = strlen(uname);
	if ((p = malloc(++size)) == 0) {
		fprintf(stderr,"ps: no memory\n");
		done(1);
	}
	strcpy(p,uname);
	uid_name[uidn++] = p;
	return(uidn-1);
}

/* ufind will return 1 if puid is in table ; if not return 0 */
ufind(puid)
int puid;
{
int	i, j;
	for (i=0; i<nuids; i++){
		j = uid_tbl[i];
		if (uid_num[j] == puid)
			return(1);
	}
	return(0);
}

/* lseek with error checking */
l_lseek(fd, offset, whence)
int fd, whence;
long	offset;
{
	if (lseek(fd, offset, whence) == -1) {
		fprintf(stderr, "ps: error on lseek\n");
		done(1);
	}
}

/* read with error checking */
r_read (fd, buf, nbytes)
int	fd, nbytes;
char	*buf;
{
	if (read(fd, buf, nbytes) != nbytes) {
		fprintf(stderr, "ps: error on read\n");
		done(1);
	}
}
/* print starting time of process unless process started more */
/* than 24 hours ago in which case date is printed   */
/* sttim is start time and it is compared to curtim (current time ) */

prtim(curtim, sttim)
char *curtim, *sttim;
{
	char *p1, *p2;
	char dayst[3], daycur[3];
	if ( strncmp(curtim, sttim, 11) == 0) {
		p1 = sttim + 11;
		p2 = p1 + 8;
	}
	else {
		p1 = sttim + 4;
		p2 = p1 + 7;
		/* if time is < 24 hours different, then print time */
		if (strncmp(curtim+4, sttim+4, 3) == 0) {
			strncpy(dayst,sttim+8, 2);
			strcat(dayst,"");
			strncpy(daycur,curtim+8,2);
			strcat(daycur,"");
			if ((atoi(dayst) +1 == atoi(daycur)) &&
				 (strncmp(curtim+11,sttim+11,8)<=0)) {
				p1 = sttim + 11;
				p2 = p1 + 8;
			}
		}
	}
	*p2 = '\0';
	printf("%9s",p1);
}
przom(puid)
/* print zombie process - zproc overlays mproc */
int puid;
{
	int i;
	long tm;

	if (lflg)
		printf("%3o %c", zproc.xp_flag&0377, "OSWRIZT"[zproc.xp_stat]);	/* F S */
	if (fflg) {
		i = getunam(puid);
		if (i >= 0)
			printf("%7s", uid_name[i]);
		else
			printf("%7d", puid);
	}
	else if (lflg)
		printf("%6d", puid);
	printf("%6u",zproc.xp_pid);	/* PID */
	if (lflg || fflg)
		printf("%6u%3d", zproc.xp_ppid, zproc.xp_cpu&0377);	/* PPID  CPU */
	if (lflg)
		printf("%4d%3d",zproc.xp_pri, zproc.xp_nice);	/* PRI  NICE */
	if (fflg) printf("         ");
	if (lflg) printf("                    ");
	tm = (zproc.xp_utime + zproc.xp_stime + 30)/60;	/* TIME */
	printf("    %2ld:", tm/60);
	tm %= 60;
	printf(tm<10?"0%ld":"%ld", tm);
	printf(" <defunct>");
	return;
}