brandon@tdi2.UUCP (Brandon Allbery) (11/06/86)
Quoted from <388@cullvax.UUCP> ["ps and systat"], by news@cullvax.UUCP (Mail and USENET News System maintenance account)... +--------------- | Has anyone out there written a "system status" program (like ps) that | presents things in a better format, like (1) process id, (2) state, | (3) user, (4) command, (5) tty, and (6) shows the tree structure of | the selected processes. I've written a post-processor for ps that | shows the tree structure, but the ps options that I have to use (-xal, | or some such) only list the first 14 or so characters of the command, | and don't list the user name. Is there a better way, or do I have to | do it myself? +--------------- 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