[comp.os.minix] ps for minix

mwalls@unirot.UUCP (monty walls) (12/19/87)

Enclosed is my implementation of PS for minix.  Please excuse the 
strange coding style. PS expects a native minix maintence enviornment(
minix c compiler, asld, ...).  For a cross compiler based minix it
will require some changes.  This version of PS is based on the V7 
documentation with some slight changes in the output
for minix.
---------------------cut here ----------------------------------------
echo x - maint.info
gres '^X' '' > maint.info << '/'
XB 71C6 _proc
XB 8216 _aout
XB 3076 _mproc
XB 5CC2 _fproc
/
echo x - maint.sh
gres '^X' '' > maint.sh << '/'
Xgrep '_proc$'  ../kernel/kernel.map >/etc/maint.info
Xgrep _aout  ../kernel/kernel.map >>/etc/maint.info
Xgrep _mproc ../mm/mm.map >>/etc/maint.info
Xgrep _fproc ../fs/fs.map >>/etc/maint.info
Xcat /etc/maint.info
/
echo x - makefile
gres '^X' '' > makefile << '/'
X#	ps needs offsets for
X#	1). proc(kernel)
X#	2). aout(kernel)
X#	3). fproc(fs)
X#	4). mproc(mm)
X#	5). getopts 
X#
X#	These do not normally change except after maintence to the
X#	the system(fs,bootblok,mm,kernel) that adds or deletes variables
X#	from working storage.  What I do is maintain an info file containing
X#	the kernel, mm, fs offsets that are automatically generated by making
X#	the system software(examine maint.sh).  
X#
X#
X#	ps needs the setuid bit set & 4096 bytes of memory
X#
Xl=/usr/lib
Xi=/usr/include
XCFLAGS=  -Di8088
X
Xpsobj = ps.s psutil.s ps_mm.s ps_k.s ps_fs.s ps_aout.s
Xps:	$(psobj) 
X	@asld -T. -o ps $l/crtso.s $(psobj) $l/libaux.a $l/libc.a $l/end.s
X
/
echo x - ps.c
gres '^X' '' > ps.c << '/'
X/*
X * ps: display processes 
X *     options: 
X *	a: -	wants information about all processes with terminals
X *	l: -	long listing
X *	x: -	even processes with no terminals
X *	
X * author:	Monty Walls
X * written:	11/18/87
X * Copyright:	Copyright (c) 1987 by Monty Walls.
X *		Not derived from licensed software.
X *
X *		Permission to copy and/or distribute granted under the
X *		following conditions:
X *	
X *		1). This notice must remain intact.
X *		2). The author is not responsible for the consequences of use
X *			this software, no matter how awful, even if they
X *			arise from defects in it.
X *		3). Altered version must not be represented as being the 
X *			original software.
X *
X * change log:
X *
X * mrw(12/1/87)	-	1) changed method for determining offsets for 
X *			   kernel(aout, proc), mm(mproc), fs(fproc).
X *			   now we read it from file(no longer maintence
X *			   level dependent).
X */
X
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/type.h"
X#include "/usr/src/h/callnr.h"
X#include "/usr/src/h/com.h"
X#include "/usr/src/h/error.h"
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xint errflag = 0;
Xlong _aout, _kproc, _mproc, _fproc;
Xlong mm_offset, fs_offset;
X
Xextern int getopt(), ps_k();
Xextern int ps_fs(), ps_mm();
Xextern int print_ps();
Xextern long getlong(), getblock();
Xextern FILE *fopen();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	FILE *fd;
X	int c, n, opt = 0;
X	unsigned ptr;
X	struct proc fs_proc, mm_proc;
X	struct process_status p;
X	char seg_flag[2];
X	char verify_name[MAXSTR];
X
X	while ((c = getopt(argc, argv, OPTIONS)) != EOF) {
X		switch (c) {
X			case 'a':
X				opt |= ALL;
X				break;
X			case 'l':
X				opt |= VERBOSE;
X				break;
X			case 'x':
X				opt |= TERMINALS;
X				break;
X			case '?':
X			default:
X				errflag++;
X				break;
X		}
X	}
X	if (errflag) {
X		fprintf(stderr,"USAGE: %s [-%s ]\n",argv[0],OPTIONS);
X		exit(2);
X	}
X	if ((fd = fopen(MAINT_INFO,"r")) != NULL) {
X		/* get maintence dependent kernel info or panic */
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(PROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for proc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_kproc = ptr + KERNELBASE;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning kernel info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(AOUT,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for aout(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else 
X				_aout = ptr + KERNELBASE;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning kernel info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		/* get maintence dependent mm info or panic */
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(MPROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for mproc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_mproc = ptr;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning MM info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		/* get maintence dependent fs info or panic */		
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(FPROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for fproc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_fproc = ptr;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning FS info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		fclose(fd);
X	}
X	else {
X		fprintf(stderr,"ERROR: %s could not open %s\n",argv[0],MAINT_INFO);
X		exit(1);
X	}
X	
X	if ((fd = fopen(KERNEL,"r")) != NULL) {
X		/* compute the mem offsets for mm and fs */
X		getblock(fd, _kproc+(MM_SLOT)*sizeof(struct proc), &mm_proc, sizeof(struct proc));
X		getblock(fd, _kproc+(FS_SLOT)*sizeof(struct proc), &fs_proc, sizeof(struct proc));
X		mm_offset = _mproc+mm_proc.p_map[D].mem_phys*CLICK_SIZE;
X		fs_offset = _fproc+fs_proc.p_map[D].mem_phys*CLICK_SIZE;
X		
X		print_hdr(stdout,opt);
X		/* now loop through slots telling about them */
X		for (n = 0; n < NR_PROCS; n++) {
X			if (ps_k(fd, n+NR_TASKS, &p)) {		/* get kernel ps info */
X				ps_mm(fd, n, &p);	/* get mm ps info */
X				ps_fs(fd, n, &p);	/* get fs ps info */
X				ps_aout(fd, n, &p);	/* get cmd */
X				print_ps(stdout, opt, &p);
X			}
X		}
X	}
X	else {
X		perror(argv[0]);
X		exit(2);
X	}
X} 
X
Xprint_ps(fd, opt, p)
XFILE *fd;
Xint opt;
Xstruct process_status *p;
X{
X	if (p->tty || (opt & TERMINALS)) {
X		if (opt & VERBOSE) {	/* flags & status */
X			fprintf(fd," %2.2o",p->flag);
X			fprintf(fd,"  %c",p->status);
X			if (p->real_uid != -1)
X				fprintf(fd, "  %4.4d",p->real_uid);
X			else	
X				fputs("  ----",fd);				
X		}
X		
X		fprintf(fd,"  %4.4d",p->pid);
X	
X		if (opt & VERBOSE) {
X			fprintf(fd,"  %4.4d",p->owner);
X			showname(fd, "  ", p->getfrom);
X			fprintf(fd," %5.5X",p->addr);
X			fprintf(fd,"  %2.2x",p->size);
X		}
X
X		if (p->tty)
X			fprintf(fd, "  tty%1.1d", (int)((p->tty >> MINOR) & 0377));
X		else		
X			fputs("     ?",fd);
X
X		fprintf(fd, "  %2.2d:%02.2d", (int)(p->time / 3600),(int)(p->time / 60 % 60));
X	
X		if (p->pgm) {
X			fprintf(fd,"  %s",p->pgm);
X			free(p->pgm);
X		}
X		else {
X			showname(fd,"  ",p->slot-NR_TASKS);
X		}
X		fputc('\n',fd);
X		fflush(fd);
X	}
X}
X
Xprint_hdr(fd, opt)
XFILE *fd;
Xint opt;
X{
X	if (opt & VERBOSE) {	/* flags & status */
X		fputs("  F  S   UID",fd);
X	}
X	fputs("   PID",fd);
X	if (opt & VERBOSE) 
X		fputs("  PPID  WCHAN   ADDR  SZ",fd);
X	fputs("   TTY   TIME  CMD\n",fd); 
X	fflush(fd);
X}
/
echo x - ps.h
gres '^X' '' > ps.h << '/'
X/*
X *	ps : display process status for executing process
X */
X
X/* device name for main memory	*/ 
X#define KERNEL		"/dev/mem"
X
X/* info filename for system */
X#define MAINT_INFO	"/etc/maint.info"
X
X/* variable names */
X#define PROC		"_proc"
X#define AOUT		"_aout"
X#define MPROC		"_mproc"
X#define FPROC		"_fproc"
X
X/* KERNEL BASE ADDRESS */
X#define KERNELBASE	((long)03000)
X
X/* slot indexes for fs & mm */
X#define FS_SLOT		(NR_TASKS+FS_PROC_NR)	/* slot number in proc table of fs */
X#define MM_SLOT		(NR_TASKS+MM_PROC_NR)	/* slot number in proc table of mm */
X
X/* ps: options 
X *	a: -	wants information about all processes with terminals
X *	l: -	long listing
X *	x: -	even processes with no terminals
X */
X#define OPTIONS		"alx"
X
X/* bit patterns for selected options */
X#define VERBOSE		0x04
X#define ALL		0x08
X#define TERMINALS	0x10
X
X#define MAXSTR		256
X
Xstruct process_status {
X	int pid;		/* process pid */
X	int slot;		/* kernel slot number */
X	int getfrom;		/* slot of who task wants to receive from */
X	int owner;		/* pid of parent process */
X	uid real_gid;		
X	uid real_uid;
X	uid effective_gid;
X	uid effective_uid;
X	real_time time;
X	dev_nr tty;
X	int size;		/* bytes total for process */
X	long addr;		/* physical base address of process */
X	char *pgm;		/* pointer to cmd name */
X	int pflag;		/* kernel process flags */
X	unsigned flag;		/* flag: IN_USE, WAITING, HANGING, PAUSED .. */
X	char status;		/* flag: NOT_SUSPENDED, SUSPENDED, NOT_REVIVED, REVIVING */
X};
/
echo x - ps_aout.c
gres '^X' '' > ps_aout.c << '/'
X/*
X * get aout table entry corresponding to n
X */
X
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/type.h"
X#include "/usr/src/h/callnr.h"
X#include "/usr/src/h/com.h"
X#include "/usr/src/h/error.h"
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xextern long getlong();
Xextern char *strsave();
Xextern long _aout;
X
Xps_aout(fd, n, p)
XFILE *fd;
Xint n;
Xstruct process_status *p;
X{
X	long where;
X	int limit = MAXSTR;
X	char buf[MAXSTR], *bp = buf;
X
X	if (n == LOW_USER + 1) {
X		p->pgm = strsave("/bin/sh");
X	}
X	else {
X		where = getlong(fd, (_aout+n*sizeof(long)));
X		if (where) {
X			fseek(fd, where, 0);
X			while (*bp++ = fgetc(fd)) 
X				if (--limit == 0)
X					break;
X			if (bp == buf)
X				p->pgm = NULL;
X			else
X				p->pgm = strsave(buf);
X		}
X		else
X			p->pgm = NULL;
X	}
X}
X
/
echo x - ps_fs.c
gres '^X' '' > ps_fs.c << '/'
X/*
X * ps_fs: get information for ps from fs
X */
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/type.h"
X#include "/usr/src/h/stat.h"
X#include "/usr/src/fs/const.h"
X#include "/usr/src/fs/type.h"
X#include "/usr/src/fs/fproc.h"
X
X#include "ps.h"
X#include <stdio.h>
X
Xextern getblock();
Xextern long fs_offset;
X
Xps_fs(fd, n, p)
XFILE *fd;
Xint n;
Xstruct process_status *p;
X{
X	long fp;
X	struct fproc fs_info;
X	
X	/* on entry n contains the slot number we are to look up */
X	fp = fs_offset + (n * sizeof(struct fproc));
X	getblock(fd, fp, &fs_info, sizeof(struct fproc));
X	
X	/* no reliable way to check if this is right task we are looking at */
X	p->tty = fs_info.fs_tty;
X	if (fs_info.fp_suspended) 
X		p->status = 'w';
X	else
X		p->status = 'r';
X	return;
X}
/
echo x - ps_k.c
gres '^X' '' > ps_k.c << '/'
X/*
X * ps: kernel dependent information retieval 
X */
X 
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/type.h"
X#include "/usr/src/h/callnr.h"
X#include "/usr/src/h/com.h"
X#include "/usr/src/h/error.h"
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xextern getblock();
Xextern long _kproc;
X
Xint
Xps_k(fd, n, p)
XFILE *fd;
Xint n;
Xstruct process_status *p;
X{
X	long kp;
X	struct proc k_info, k_getfrom;
X	
X	/* on entry n contains the slot number were do look ups on */
X	kp = _kproc + (n * sizeof(struct proc));
X	
X	/* copy mem to us for looking at */
X	getblock(fd, kp, &k_info, sizeof(struct proc));
X	
X	if (k_info.p_flags & P_SLOT_FREE) 
X		return (0);
X	else {
X		/* valid slot */
X		p->pid = k_info.p_pid;
X		p->slot = n;
X		p->pflag = k_info.p_flags;
X		p->time = k_info.user_time + k_info.sys_time;
X		p->addr = (long)k_info.p_map[T].mem_phys*CLICK_SIZE;
X		p->size = ((long)k_info.p_map[T].mem_len+(long)k_info.p_map[D].mem_len+(long)k_info.p_map[S].mem_len)*CLICK_SIZE/BLOCK_SIZE;
X		p->getfrom = k_info.p_getfrom;
X		return (1);
X	}
X}
/
echo x - ps_mm.c
gres '^X' '' > ps_mm.c << '/'
X/*
X * ps_mm: get information for ps from mm
X */
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/type.h"
X#include "/usr/src/h/stat.h"
X#include "/usr/src/mm/const.h"
X#include "/usr/src/mm/mproc.h"
X
X#include "ps.h"
X#include <stdio.h>
X
Xextern getblock();
Xextern long mm_offset;
X
Xps_mm(fd, n, p)
XFILE *fd;
Xint n;
Xstruct process_status *p;
X{
X	static __ps_mm_descent;		/* stop recursion */
X	long mp;
X	struct mproc mm_info, mm_parent;
X
X	/* on entry n contains the slot number were do look ups on */
X	mp = mm_offset + (n * sizeof(struct mproc));
X	
X	/* get copy of this proc entry for us */
X	getblock(fd, mp, &mm_info, sizeof(struct mproc));
X	
X	if (p->pid == mm_info.mp_pid) {				/* safety */
X		if (!__ps_mm_descent) {
X			/* get the pid of the parent process */
X			__ps_mm_descent = 1;
X			ps_mm(fd, mm_info.mp_parent, &mm_parent);
X			p->owner = mm_parent.mp_pid;
X		}
X		else
X			__ps_mm_descent = 0;
X		/* fill in the normal info */
X		p->real_gid = mm_info.mp_realgid;
X		p->real_uid = mm_info.mp_realuid;
X		p->effective_gid = mm_info.mp_effgid;
X		p->effective_uid = mm_info.mp_effuid;
X		p->flag = mm_info.mp_flags;
X	}
X	else {
X		p->owner = -1;
X		p->real_gid = -1;
X		p->real_uid = -1;
X		p->effective_gid = -1;
X		p->effective_uid = -1;
X		p->flag = 0;
X	}
X	return;
X}
X
/
echo x - psutil.c
gres '^X' '' > psutil.c << '/'
X/*
X * utility routines for ps 
X */
X
X#include "/usr/src/h/const.h"
X#include "/usr/src/h/com.h"
X#include <stdio.h>
X
Xunsigned 
Xgetword(fd, offset)
XFILE *fd;
Xlong offset;
X{
X	int n;
X	
X	fseek(fd, offset, 0);
X	fread(&n, sizeof(int), 1, fd);
X	return (n);
X} 
X
Xlong 
Xgetlong(fd, offset)
XFILE *fd;
Xlong offset;
X{
X	long n;
X	
X	fseek(fd, offset, 0);
X	fread(&n, sizeof(long), 1, fd);
X	return (n);
X} 
X
Xunsigned
Xgetblock(fd, offset, p, cnt)
XFILE *fd;
Xlong offset;
Xchar *p;
Xint cnt;
X{
X	fseek(fd, offset, 0);
X	fread(p, cnt, 1, fd);
X	return (offset);
X}
X
X/* fast and simple way of showing the process name */
X
Xstatic char *taskname[] = {
X	"MM    ",
X	"FS    ",
X	"INIT  "
X};
X
Xshowname(fd,pad,n)
XFILE *fd;
Xchar *pad;
Xint n;
X{
X	if (pad)
X		fputs(pad,fd);
X	if (n >= ANY || n < 0) 
X		fputs("ANY   ",fd);
X	else if (n <= LOW_USER)
X		fprintf(fd,"%6.6s",taskname[n]);
X	else
X		fprintf(fd,"%4.4d", n);
X}	
X
/
`
X{
X	
X{
X	
.
X.
X.x %sTTTTT2T,fop[T]) == ) == )ty defi/* spo	2ep->st by by upare('w* n>ra s\ns\nssusr/src* n>fi/'
X//'
X//

walls@killer.DALLAS.TX.US (Monty Walls) (10/28/88)

--------------------------------------------------------------------------
	Enclosed is a version of 'ps' I have been using for the
past year.  It still needs some work in the way it handles the magic
addresses for the fs, mm, and kernel process tables,  but it works as
is even though it's kind of crude in places. One word of warning: the 
include files for MINIX are hard coded into the files, so you will
probably have to change them for your system.

	- Monty Walls

---------------------------cut here---------------------------------------
echo x - maint.info
sed '/^X/s///' > maint.info << '/'
XB 8898 _proc
XB 91A8 _aout
XB 2B46 _mproc
XB 5582 _fproc
/
echo x - maint.sh
sed '/^X/s///' > maint.sh << '/'
Xgrep '_proc$'  ../kernel/kernel.map >/etc/maint.info
Xgrep _aout  ../kernel/kernel.map >>/etc/maint.info
Xgrep _mproc ../mm/mm.map >>/etc/maint.info
Xgrep _fproc ../fs/fs.map >>/etc/maint.info
Xcat /etc/maint.info
/
echo x - makefile
sed '/^X/s///' > makefile << '/'
X#	ps needs offsets for
X#	1). proc(kernel)
X#	2). aout(kernel)
X#	3). fproc(fs)
X#	4). mproc(mm)
X#
X#	These offsets are stored in my system in /etc/maint.info.
X#
X#	These do not normally change except after maintence to the
X#	the system(fs,bootblok,mm,kernel) that adds or deletes variables
X#	from working storage.  What I do is maintain an info file containing
X#	the kernel, mm, fs offsets that are automatically generated by making
X#	the system software(examine maint.sh).  
X#
X#
X#	ps needs the setuid bit set & 6144 bytes of memory
X#	ps uses the library routine getopts.c
X#
X#
Xl=/usr/lib
Xi=/usr/include
Xk=/usr/src/kernel
XCFLAGS=  -Di8088 -O
X
Xpsobj = ps.s psutil.s ps_mm.s ps_k.s ps_fs.s ps_aout.s strsave.s
Xps:	$(psobj) 
X	@asld -T. -o ps $l/crtso.s $(psobj) $l/libaux.a $l/libc.a $l/end.s
X
Xps.s:		$i/minix/const.h
Xps.s:		$i/minix/type.h
Xps.s:		$i/minix/callnr.h
Xps.s:		$i/minix/com.h
Xps.s:		$i/minix/error.h
Xps.s:		$k/const.h
Xps.s:		$k/type.h
Xps.s:		$k/glo.h
Xps.s:		$k/proc.h
Xps.s:		ps.h
X
Xps_k.s:		$i/minix/const.h
Xps_k.s:		$i/minix/type.h
Xps_k.s:		$i/minix/callnr.h
Xps_k.s:		$i/minix/com.h
Xps_k.s:		$i/minix/error.h
Xps_k.s:		$k/const.h
Xps_k.s:		$k/type.h
Xps_k.s:		$k/glo.h
Xps_k.s:		$k/proc.h
Xps_k.s:		ps.h
X
Xps_aout.s:	$i/minix/const.h
Xps_aout.s:	$i/minix/type.h
Xps_aout.s:	$i/minix/callnr.h
Xps_aout.s:	$i/minix/com.h
Xps_aout.s:	$i/minix/error.h
Xps_aout.s:	$k/const.h
Xps_aout.s:	$k/type.h
Xps_aout.s:	$k/glo.h
Xps_aout.s:	$k/proc.h
Xps_aout.s:	ps.h
X
Xps_mm.s:	$i/minix/const.h
Xps_mm.s:	$i/minix/type.h
Xps_mm.s:	$i/minix/stat.h
Xps_mm.s:	$i/mm/const.h
Xps_mm.s:	$i/mm/mproc.h
Xps_mm.s:	ps.h
X
Xps_fs.s:	$i/minix/const.h
Xps_fs.s:	$i/minix/type.h
Xps_fs.s:	$i/minix/stat.h
Xps_fs.s:	$i/fs/const.h
Xps_fs.s:	$i/fs/fproc.h
Xps_fs.s:	ps.h
X
Xpsutil.s:	$i/minix/const.h
Xpsutil.s:	$i/minix/com.h
X
/
echo x - ps.1
sed '/^X/s///' > ps.1 << '/'
XNAME
X	ps - process status
X
XSYNOPSIS
X	ps [-alx ]
X
XDESCRIPTION
X	PS prints information about active processes. It does so by
X	examining kernel, mm, and fs address spaces.  The 'a' option
X	asks for information about all processes with terminals
X	(normally only your processes are displayed); 'x' displays
X	processes even without terminals; 'l' asks for the long listing.
X	The normal short listing contains the PID, TTY, TIME, and the CMD.
X
X	The long listing contains:
X
X	F	-	01:  in use; 02:  waiting; 04:  hanging; 10:  paused;
X			20:  alarm on;  40: seperate I & D spaces.
X
X	S	-	s - suspended, r - running (process FS status)
X
X	UID	-	owners uid
X
X	PID	-	process id
X
X	PPID	-	parents process id
X
X	ADDR	-	core address(in hex)
X
X	SZ	-	size of code+data+stack(in hex)
X
X	WCHAN	-	the pid or name of the process its waiting on
X
X	TTY	-	owning tty
X
X	TIME	-	system & user time in seconds for the process
X
X	CMD	-	command name of process
X	
X
XFILES
X	/dev/mem	core memory
X	/etc/maint.info	kernel, fs, and mm maintence info
X
XPORTABILITY
X
X	Heavily dependent on the basic structure of minix on 8088.
X
XSEE ALSO
X	kill(1)
X
/
echo x - ps.c
sed '/^X/s///' > ps.c << '/'
X/*
X * ps: display processes 
X *     options: 
X *	a: -	wants information about all processes with terminals
X *	l: -	long listing
X *	x: -	even processes with no terminals
X *	
X * author:	Monty Walls
X * written:	11/18/87
X * Copyright:	Copyright (c) 1987 by Monty Walls.
X *		Not derived from licensed software.
X *
X *		Permission to copy and/or distribute granted under the
X *		following conditions:
X *	
X *		1). This notice must remain intact.
X *		2). The author is not responsible for the consequences of use
X *			this software, no matter how awful, even if they
X *			arise from defects in it.
X *		3). Altered version must not be represented as being the 
X *			original software.
X *
X * change log:
X *
X * mrw(12/1/87) -	1) changed method for determining offsets for 
X *			   kernel(aout, proc), mm(mproc), fs(fproc).
X *			   now we read it from file(no longer maintence
X *			   level dependent).
X * mrw(6/2/88) -	2) changed file names for system upgrade.
X * mrw(10/23/88) -	3) fixed method of computing ppid.
X */
X
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/callnr.h>
X#include <minix/com.h>
X#include <minix/error.h>
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xint errflag = 0;
Xlong _aout, _kproc, _mproc, _fproc;
Xlong mm_offset, fs_offset;
X
Xextern int getopt(), ps_k();
Xextern int ps_fs(), ps_mm();
Xextern int print_ps();
Xextern long getlong(), getblock();
Xextern FILE *fopen();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	FILE *fd;
X	int c, n, opt = 0;
X	unsigned ptr;
X	struct proc fs_proc, mm_proc;
X	struct process_status p;
X	char seg_flag[2];
X	char verify_name[MAXSTR];
X
X	while ((c = getopt(argc, argv, OPTIONS)) != EOF) {
X		switch (c) {
X			case 'a':
X				opt |= ALL;
X				break;
X			case 'l':
X				opt |= VERBOSE;
X				break;
X			case 'x':
X				opt |= TERMINALS;
X				break;
X			case '?':
X			default:
X				errflag++;
X				break;
X		}
X	}
X	if (errflag) {
X		fprintf(stderr,"USAGE: %s [-%s ]\n",argv[0],OPTIONS);
X		exit(2);
X	}
X	if ((fd = fopen(MAINT_INFO,"r")) != NULL) {
X		/* get maintence dependent kernel info or panic */
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(PROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for proc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_kproc = ptr + KERNELBASE;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning kernel info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(AOUT,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for aout(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else 
X				_aout = ptr + KERNELBASE;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning kernel info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		/* get maintence dependent mm info or panic */
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(MPROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for mproc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_mproc = ptr;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning MM info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		/* get maintence dependent fs info or panic */		
X		if (fscanf(fd, "%1s %x %s", seg_flag, &ptr, verify_name) == 3) {
X			if (strcmp(FPROC,verify_name)) {
X				fprintf(stderr,"ERROR: %s - invalid specification for fproc(%s) in %s\n", argv[0], verify_name, MAINT_INFO);
X				exit(1);
X			}
X			else
X				_fproc = ptr;
X		}
X		else {
X			fprintf(stderr,"ERROR: %s - EOF on scanning FS info in %s\n", argv[0], MAINT_INFO);
X			exit(1);
X		}
X		fclose(fd);
X	}
X	else {
X		fprintf(stderr,"ERROR: %s could not open %s\n",argv[0],MAINT_INFO);
X		exit(1);
X	}
X	
X	if ((fd = fopen(KERNEL,"r")) != NULL) {
X		/* compute the mem offsets for mm and fs */
X		getblock(fd, _kproc+(MM_SLOT)*sizeof(struct proc), &mm_proc, sizeof(struct proc));
X		getblock(fd, _kproc+(FS_SLOT)*sizeof(struct proc), &fs_proc, sizeof(struct proc));
X		mm_offset = _mproc+mm_proc.p_map[D].mem_phys*CLICK_SIZE;
X		fs_offset = _fproc+fs_proc.p_map[D].mem_phys*CLICK_SIZE;
X		
X		print_hdr(stdout,opt);
X		/* now loop through slots telling about them */
X		for (n = 0; n < NR_PROCS; n++) {
X			if (ps_k(fd, n+NR_TASKS, &p)) {		/* get kernel ps info */
X				ps_mm(fd, n, &p);	/* get mm ps info */
X				ps_fs(fd, n, &p);	/* get fs ps info */
X				ps_aout(fd, n, &p);	/* get cmd */
X				print_ps(stdout, opt, &p);
X			}
X		}
X	}
X	else {
X		perror(argv[0]);
X		exit(2);
X	}
X} 
X
Xprint_ps(fd, opt, p)
Xregister FILE *fd;
Xint opt;
Xregister struct process_status *p;
X{
X	if (p->tty || (opt & TERMINALS)) {
X		if (opt & VERBOSE) {	/* flags & status */
X			fprintf(fd," %2.2o",p->flag);
X			fprintf(fd,"  %c",p->status);
X			if (p->real_uid != -1)
X				fprintf(fd, "  %4.4d",p->real_uid);
X			else	
X				fputs("  ----",fd);				
X		}
X		
X		fprintf(fd,"  %4.4d",p->pid);
X	
X		if (opt & VERBOSE) {
X			fprintf(fd,"  %4.4d",p->owner);
X			showname(fd, "  ", p->getfrom);
X			fprintf(fd," %5.5X",p->addr);
X			fprintf(fd,"  %2.2x",p->size);
X		}
X
X		if (p->tty)
X			fprintf(fd, "  tty%1.1d", (int)((p->tty >> MINOR) & 0377));
X		else		
X			fputs("     ?",fd);
X
X		fprintf(fd, "  %2.2d:%02.2d", (int)(p->time / 3600),(int)(p->time / 60 % 60));
X	
X		if (p->pgm) {
X			fprintf(fd,"  %s",p->pgm);
X			free(p->pgm);
X		}
X		else {
X			showname(fd,"  ",p->slot-NR_TASKS);
X		}
X		fputc('\n',fd);
X		fflush(fd);
X	}
X}
X
Xprint_hdr(fd, opt)
XFILE *fd;
Xint opt;
X{
X	if (opt & VERBOSE) {	/* flags & status */
X		fputs("  F  S   UID",fd);
X	}
X	fputs("   PID",fd);
X	if (opt & VERBOSE) 
X		fputs("  PPID  WCHAN   ADDR  SZ",fd);
X	fputs("   TTY   TIME  CMD\n",fd); 
X	fflush(fd);
X}
/
echo x - ps.h
sed '/^X/s///' > ps.h << '/'
X/*
X *	ps : display process status for executing process
X */
X
X/* device name for main memory	*/ 
X#define KERNEL		"/dev/mem"
X
X/* info filename for system */
X#define MAINT_INFO	"/etc/maint.info"
X
X/* variable names */
X#define PROC		"_proc"
X#define AOUT		"_aout"
X#define MPROC		"_mproc"
X#define FPROC		"_fproc"
X
X/* KERNEL BASE ADDRESS */
X#define KERNELBASE	((long)03000)
X
X/* slot indexes for fs & mm */
X#define FS_SLOT		(NR_TASKS+FS_PROC_NR)	/* slot number in proc table of fs */
X#define MM_SLOT		(NR_TASKS+MM_PROC_NR)	/* slot number in proc table of mm */
X
X/* ps: options 
X *	a: -	wants information about all processes with terminals
X *	l: -	long listing
X *	x: -	even processes with no terminals
X */
X#define OPTIONS		"alx"
X
X/* bit patterns for selected options */
X#define VERBOSE		0x04
X#define ALL		0x08
X#define TERMINALS	0x10
X
X#define MAXSTR		256
X
Xstruct process_status {
X	int pid;		/* process pid */
X	int slot;		/* kernel slot number */
X	int getfrom;		/* slot of who task wants to receive from */
X	int owner;		/* pid of parent process */
X	uid real_gid;		
X	uid real_uid;
X	uid effective_gid;
X	uid effective_uid;
X	real_time time;
X	dev_nr tty;
X	int size;		/* bytes total for process */
X	long addr;		/* physical base address of process */
X	char *pgm;		/* pointer to cmd name */
X	int pflag;		/* kernel process flags */
X	unsigned flag;		/* flag: IN_USE, WAITING, HANGING, PAUSED .. */
X	char status;		/* flag: NOT_SUSPENDED, SUSPENDED, NOT_REVIVED, REVIVING */
X};
/
echo x - ps_aout.c
sed '/^X/s///' > ps_aout.c << '/'
X/*
X * get aout table entry corresponding to n
X */
X
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/callnr.h>
X#include <minix/com.h>
X#include <minix/error.h>
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xextern long getlong();
Xextern char *strsave();
Xextern long _aout;
X
Xps_aout(fd, n, p)
XFILE *fd;
Xint n;
Xregister struct process_status *p;
X{
X	long where;
X	int limit = MAXSTR;
X	char buf[MAXSTR];
X	register char *bp = buf;
X
X	if (n == LOW_USER + 1) {
X		p->pgm = strsave("/bin/sh");
X	}
X	else {
X		where = getlong(fd, (_aout+n*sizeof(long)));
X		if (where) {
X			fseek(fd, where, 0);
X			while (*bp++ = fgetc(fd)) 
X				if (--limit == 0)
X					break;
X			if (bp == buf)
X				p->pgm = NULL;
X			else
X				p->pgm = strsave(buf);
X		}
X		else
X			p->pgm = NULL;
X	}
X}
X
/
echo x - ps_fs.c
sed '/^X/s///' > ps_fs.c << '/'
X/*
X * ps_fs: get information for ps from fs
X */
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/stat.h>
X#include <fs/const.h>
X#include <fs/type.h>
X#include <fs/fproc.h>
X
X#include "ps.h"
X#include <stdio.h>
X
Xextern getblock();
Xextern long fs_offset;
X
Xps_fs(fd, n, p)
XFILE *fd;
Xint n;
Xregister struct process_status *p;
X{
X	long fp;
X	struct fproc fs_info;
X	
X	/* on entry n contains the slot number we are to look up */
X	fp = fs_offset + (n * sizeof(struct fproc));
X	getblock(fd, fp, &fs_info, sizeof(struct fproc));
X	
X	/* no reliable way to check if this is right task we are looking at */
X	p->tty = fs_info.fs_tty;
X	if (fs_info.fp_suspended) 
X		p->status = 'w';
X	else
X		p->status = 'r';
X	return;
X}
/
echo x - ps_k.c
sed '/^X/s///' > ps_k.c << '/'
X/*
X * ps: kernel dependent information retieval 
X */
X 
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/callnr.h>
X#include <minix/com.h>
X#include <minix/error.h>
X#include "/usr/src/kernel/const.h"
X#include "/usr/src/kernel/type.h"
X#include "/usr/src/kernel/glo.h"
X#include "/usr/src/kernel/proc.h"
X
X#include <stdio.h> 
X#include "ps.h"
X
Xextern getblock();
Xextern long _kproc;
X
Xint
Xps_k(fd, n, p)
XFILE *fd;
Xint n;
Xregister struct process_status *p;
X{
X	long kp;
X	struct proc k_info, k_getfrom;
X	
X	/* on entry n contains the slot number were do look ups on */
X	kp = _kproc + (n * sizeof(struct proc));
X	
X	/* copy mem to us for looking at */
X	getblock(fd, kp, &k_info, sizeof(struct proc));
X	
X	if (k_info.p_flags & P_SLOT_FREE) 
X		return (0);
X	else {
X		/* valid slot */
X		p->pid = k_info.p_pid;
X		p->slot = n;
X		p->pflag = k_info.p_flags;
X		p->time = k_info.user_time + k_info.sys_time;
X		p->addr = (long)k_info.p_map[T].mem_phys*CLICK_SIZE;
X		p->size = ((long)k_info.p_map[T].mem_len+(long)k_info.p_map[D].mem_len+(long)k_info.p_map[S].mem_len)*CLICK_SIZE/BLOCK_SIZE;
X		p->getfrom = k_info.p_getfrom;
X		return (1);
X	}
X}
/
echo x - ps_mm.c
sed '/^X/s///' > ps_mm.c << '/'
X/*
X * ps_mm: get information for ps from mm
X */
X#include <minix/const.h>
X#include <minix/type.h>
X#include <minix/stat.h>
X#include <mm/const.h>
X#include <mm/mproc.h>
X
X#include "ps.h"
X#include <stdio.h>
X
Xextern getblock();
Xextern long mm_offset;
X
Xps_mm(fd, n, p)
XFILE *fd;
Xint n;
Xregister struct process_status *p;
X{
X	long mp;
X	struct mproc mm_info;
X
X	/* on entry n contains the slot number were do look ups on */
X	mp = mm_offset + (n * sizeof(struct mproc));
X	
X	/* get copy of this proc entry for us */
X	getblock(fd, mp, &mm_info, sizeof(struct mproc));
X	
X	if (p->pid == mm_info.mp_pid) {				/* safety */
X		p->owner = ps_mm_parent(fd, mm_info.mp_parent);
X		/* fill in the normal info */
X		p->real_gid = mm_info.mp_realgid;
X		p->real_uid = mm_info.mp_realuid;
X		p->effective_gid = mm_info.mp_effgid;
X		p->effective_uid = mm_info.mp_effuid;
X		p->flag = mm_info.mp_flags;
X	}
X	else {
X		p->owner = -1;
X		p->real_gid = -1;
X		p->real_uid = -1;
X		p->effective_gid = -1;
X		p->effective_uid = -1;
X		p->flag = 0;
X	}
X	return;
X}
X
Xint
Xps_mm_parent(fd, n)
XFILE *fd;
Xint n;
X{
X	long mp;
X	struct mproc mm_info;
X
X	/* on entry n contains the slot number were do look ups on */
X	mp = mm_offset + (n * sizeof(struct mproc));
X	
X	/* get copy of this proc entry for us */
X	getblock(fd, mp, &mm_info, sizeof(struct mproc));
X	
X	return (mm_info.mp_pid);
X}
/
echo x - psutil.c
sed '/^X/s///' > psutil.c << '/'
X/*
X * utility routines for ps 
X */
X
X#include <minix/const.h>
X#include <minix/com.h>
X#include <stdio.h>
X
Xunsigned 
Xgetword(fd, offset)
XFILE *fd;
Xlong offset;
X{
X	int n;
X	
X	fseek(fd, offset, 0);
X	fread(&n, sizeof(int), 1, fd);
X	return (n);
X} 
X
Xlong 
Xgetlong(fd, offset)
XFILE *fd;
Xlong offset;
X{
X	long n;
X	
X	fseek(fd, offset, 0);
X	fread(&n, sizeof(long), 1, fd);
X	return (n);
X} 
X
Xunsigned
Xgetblock(fd, offset, p, cnt)
XFILE *fd;
Xlong offset;
Xchar *p;
Xint cnt;
X{
X	fseek(fd, offset, 0);
X	fread(p, cnt, 1, fd);
X	return (offset);
X}
X
X/* fast and simple way of showing the process name */
X
Xstatic char *taskname[] = {
X	"MM    ",
X	"FS    ",
X	"INIT  "
X};
X
Xshowname(fd,pad,n)
XFILE *fd;
Xchar *pad;
Xint n;
X{
X	if (pad)
X		fputs(pad,fd);
X	if (n >= ANY || n < 0) 
X		fputs("ANY   ",fd);
X	else if (n <= LOW_USER)
X		fprintf(fd,"%6.6s",taskname[n]);
X	else
X		fprintf(fd,"%4.4d", n);
X}	
X
/
echo x - strsave.c
sed '/^X/s///' > strsave.c << '/'
Xextern char *malloc(), *strcpy();
Xextern int strlen();
X
Xchar *
Xstrsave(s)
Xregister char *s;
X{
X    register char *hold;
X
X    hold = malloc(strlen(s)+1);
X    return (strcpy(hold,s));
X}
X
/
---------------------------end here---------------------------------------

Monty Walls
MIS Division, Tech. Support
Oklahoma Tax Commission
2501 N. Lincoln
OKC, OK, 73194