Dale
Well, here's part of it... It's written for System V, but should be convert-
able for BSD, etc. (but don't ask me how!). One warning: the constant 9 is
coded in a few places dealing with disk addresses on swap. This is because
of what appears to be a bug in the Plexus kernel: BSHIFT is 10, but the
actual shift used to read swap is 9.
Sample output:
% utree
USER TTY PID COMMAND
brandon tty2 3927 csh
5121 UNIFY
5122 ENTER
5124 csh
6308 rn
6312 sh
6313 sh
6332 emacs
6339 sh
6340 utree
lori tty8 4477 sh
4504 UNIFY
4509 ENTER
6333 unisys
joni tty23 6218 sh
6246 UNIFY
6249 ENTER
matt tty15 6105 sh
6113 runcobol
glenn tty17 6025 sh
6056 runcobol
jeff tty14 5665 sh
6016 UNIFY
6019 ENTER
6080 runcobol
scott tty18 6063 csh
6074 UNIFY
6295 unisys
6076 ENTER
lori tty10 4930 sh
4939 UNIFY
4941 ENTER
gregs tty24 4557 sh
6115 UNIFY
6118 ENTER
6268 runcobol
bobw tty25 1650 csh
karen tty20 3577 sh
4641 runcobol
lorib tty19 4596 sh
5975 runcobol
6336 unisys
scott tty16 4938 csh
4951 UNIFY
4954 ENTER
brian tty21 4986 UNIFY
6238 ENTER
6239 unisys
bill tty26 4780 sh
4791 UNIFY
5900 unisys
4793 ENTER
rich tty30 3633 sh
6138 sh
6142 cu
6143 cu
%
++Brandon
------------------- CUT HERE -------------- NOT A SHAR -----------------------
#include <stdio.h>
#include <fcntl.h>
#include <a.out.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/var.h>
#include <sys/dir.h>
#include <sys/signal.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/sysmacros.h>
#include <utmp.h>
struct nlist k[] = {
#define VAR 0
{"_v"},
#define PROC 1
{"_proc"},
#define SWPLO 2
{"_swplo"},
{0},
};
char swapname[128] = "/dev/swap";
char kmemname[128] = "/dev/kmem";
char memname[128] = "/dev/mem";
char kernel[128] = "/unix";
extern void setutent(), exit();
extern struct utmp *getutent();
main(argc, argv)
char **argv; {
int mem, swap, kmem;
daddr_t swplo;
short opt, initial;
extern int optind;
extern char *optarg;
struct utmp *user;
struct var var;
while ((opt = getopt(argc, argv, "s:k:m:n:")) != EOF)
switch (opt) {
case 's':
strcpy(swapname, optarg);
break;
case 'k':
strcpy(kmemname, optarg);
break;
case 'm':
strcpy(memname, optarg);
break;
case 'n':
strcpy(kernel, optarg);
break;
default:
fprintf(stderr, "usage: %s [-k kmemname] [-s swapname] [-m memname] [-n namelist]\n", argv[0]);
exit(1);
}
if (nlist(kernel, k) != 0) {
perror(kernel);
exit(2);
}
if ((kmem = open(kmemname, O_RDONLY)) == -1) {
perror(kmemname);
exit(3);
}
if ((mem = open(memname, O_RDONLY)) == -1) {
perror(memname);
exit(4);
}
if ((swap = open(swapname, O_RDONLY)) == -1) {
perror(swapname);
exit(5);
}
if (lseek(kmem, k[VAR].n_value, 0) == -1L) {
perror(kmemname);
exit(6);
}
if (read(kmem, (char *) &var, sizeof var) == -1) {
perror(kmemname);
exit(7);
}
if (lseek(kmem, k[SWPLO].n_value, 0) == -1L) {
perror(kmemname);
exit(8);
}
if (read(kmem, (char *) &swplo, sizeof swplo) == -1) {
perror(kmemname);
exit(9);
}
initial = 1;
while ((user = getutent()) != (struct utmp *) 0) {
if (user->ut_type != USER_PROCESS)
continue;
if (initial) {
initial = 0;
printf("USER TTY PID COMMAND\n");
}
else
putchar('\n');
printf("%-8.*s %-8s ", sizeof user->ut_user, user->ut_user, user->ut_line);
ptree(kmem, mem, swap, user->ut_pid, swplo, k[PROC].n_value, 0, var.v_proc);
}
exit(0);
/*NOTREACHED*/
}
ptree(kmem, mem, swap, pid, swplo, procaddr, depth, nproc)
daddr_t swplo;
ushort pid;
long procaddr, nproc; {
struct proc process;
long cnt, here;
if (lseek(kmem, procaddr, 0) == -1L) {
perror(kmemname);
exit(10);
}
for (cnt = 0; cnt < nproc; cnt++) {
if (read(kmem, &process, sizeof process) == -1) {
perror(kmemname);
exit(11);
}
if (process.p_stat == 0)
continue;
if ((depth == 0? process.p_pid: process.p_ppid) == pid) {
if (depth != 0)
printf(" ");
emit(&process, mem, swap, swplo, depth);
if ((here = lseek(kmem, 0L, 1)) == -1L) {
perror(kmemname);
exit(12);
}
ptree(kmem, mem, swap, process.p_pid, swplo, procaddr, depth + 1, nproc);
if (lseek(kmem, here, 0) == -1L) {
perror(kmemname);
exit(13);
}
}
}
}
emit(process, mem, swap, swplo, depth)
struct proc *process;
long swplo; {
struct user command;
if (process->p_flag & SLOAD) {
if (lseek(mem, ctob(process->p_addr), 0) == -1L) {
perror(memname);
exit(14);
}
if (read(mem, (char *) &command, sizeof command) == -1) {
perror(memname);
exit(15);
}
}
else {
if (lseek(swap, (swplo + process->p_swaddr + ctod(process->p_swsize) - ctod(USIZE)) << 9, 0) == -1L) {
perror(swapname);
exit(16);
}
if (read(swap, (char *) &command, sizeof command) == -1) {
perror(swapname);
exit(17);
}
}
printf("%5d %*s%.*s\n", process->p_pid, depth * 2, "", DIRSIZ, command.u_comm);
}
================================== CUT HERE ===================================
--
/-----------//***/ Brandon S. Allbery cbosgd!cwruecmp!ncoast!allbery
/--- -----//***/ Tridelta Industries, Inc. ihnp4!tft2!tdi2!brandon
/ //---, /---/ 7350 Corporate Blvd. !ncoast!allbery
/ // / / / Mentor, OH 44060
/--//---' /---/ +1 216 255 1080 HOME: +1 216 974 9210