#/* Installation: if $1e = finale goto final cc ps.c -lj if ! -r a.out exit chmod 2755 a.out su chgrp system a.out exit : final cc -s -O ps.c -lj if ! -r a.out exit su rm -f /bin/ps su cp a.out /bin/ps su chmod 2555 /bin/ps su chown bin /bin/ps su chgrp system /bin/ps rm -f a.out * ps -bB must be run once per reboot or modification * to /dev/tty? * * Derived from the orignal ps program (BTL ?) by J.S.Kravitz at * University of Illinois. This program is somewhat faster than the * original since scan of /dev for swapdev and tty correspondence * is performed only once per re-boot. * ps -b should be run as part of the start up procedure. * With the -s and -k switches, ps builds a new internal table each time. * The switches -t and -n * have been added. * -tx where is is a tty letter gets you the process for that terminal. * -nxxx where xxx is a process id gets you the process info for * that process. * * added 30Jun77 -p flag.. lets you set nice value for process * added 8Jul77 -c flag... lets you see children of a process * added 27Sep77 fout cludge to speed it up RJB * added 30Sep77 consistency check on U structure RJB * added 30Sep77 Corrected time print RJB * added 12Dec77 Replaced heuristic to get arg list RJB * added 15Dec77 Fixed psinfo to have _PROC and swapdev name * added 14Jan78 Merged ps.h ps.c psinfo.h, added -b(uild) flag */ #define MAJ_KL11 0 /* major device number of KL11 */ /* We don't have a DC11.... #define MAJ_DC11 3 /* major device number of DC11 */ #define MAJ_DH11 2 /* major device number of DH11 */ #define MAJ_PTY 8 /* major device number of psuedo-TTYs */ #include "/usr/sys/h/param.h" #define NO_U X #include "/usr/sys/h/user.h" #include "/usr/sys/h/proc.h" #include "/usr/sys/h/tty.h" struct statbuf { char s_minor; char s_major; int s_inumber; int s_flags; char s_nlinks; char s_uid; char s_gid; char s_size0; int s_size1; int s_addr[8]; long s_actime; long s_modtime; }; struct syment { char name[8]; int type; int value; }; #define NTTYI 62 struct psinfo { struct ttyinf { int devname; char *pgrpaddr; int pgrpval; int devno; }ttyinfo[NTTYI]; char swapname [28]; char *procbase; } psinfo; int ua[256] ,uid ,lflg ,cflg ,pgrpcnt #define PGRPMAX 25 ,pgrpinx[PGRPMAX] ,pgrp[PGRPMAX] ,bflg ,Bflg ,xflg ,aflg ,wflg ,nflg ,pflg ,qflg ,mem ,pcount ,headed ,swmem ,swap ,psfid ; char *coref "/dev/mem" ,*symref "/unix" ; char infoname[] "/etc/psinfo1"; main(ac, av) char **av; { int n, b; register int i, c; register char *ap; int infofid; int argc; char **argv; extern int fout; fout = dup(1); argc = ac; argv = av; while (argc > 1) { argc--; ap = *++argv; while (*ap) switch (*ap++) { case 'a': /* all uid's */ aflg++; break; case 'b': /* build flag */ bflg++; break; case 'B': Bflg++; /* save built info */ break; case 'c': /* specific child of parent */ cflg = atoi(ap); ap = scan(ap); aflg++; xflg++; break; case 'k': /* use sysdump for core */ coref = "sysdump"; break; case 'K': /* use specified file for core */ if(argc < 1) break; argc--; coref = *++argv; break; case 'l': /* long format */ lflg++; break; case '0': /* number -- assume specific pid */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ap--; case 'n': /* specific pid */ nflg = atoi(ap); ap = scan(ap); aflg++; xflg++; break; case 'p': /* poke process's nice value */ pflg = atoi(ap); ap = scan(ap); break; case 'q': /* suppress headers (quiet) */ qflg++; break; case 's': /* use specified file for symbol table */ if(argc < 1) break; argc--; symref = *++argv; bflg++; break; case 't': /* for the specified tty only */ c = maptty (*ap); if (c < 0) continue; ap++; pgrpinx [pgrpcnt++] = c; if (pgrpcnt >= PGRPMAX) { printf ("Too may 't' arguments\n"); done (0); } aflg++; break; case 'w': /* print out symbol names */ wflg++; lflg++; break; case 'x': /* include procs with no process group */ xflg++; break; default: printf("Unknown flag: %c\n", ap[-1]); case '-': /* ignore this */ break; } } if ((mem = open(coref, pflg?3:0)) < 0) { printf("No mem\n"); done (0); } swmem = open(coref, 0); if (bflg || ( (psfid = open (infoname, 0)) < 0 ) || ( read (psfid, &psinfo, sizeof psinfo) != sizeof psinfo ) ) { getpsinfo (); } else { close (psfid); } chdir ("/"); for (i = 0; i < pgrpcnt; i++) { seek (mem, psinfo.ttyinfo[pgrpinx[i]].pgrpaddr, 0); read (mem, &pgrp[i], 2); } swap = open (psinfo.swapname, 0); if (swap < 0) { printf ("Can't open %s for swap device\n" ,psinfo.swapname); done (0); } if (wflg) syminit(); /* * Read in proc table */ if(pflg) { if ( nflg == 0) { printf ("Must specify process id\n"); done (0); } procprint (mappid (nflg), 1); setprio (psinfo.procbase ,&proc[0] ,&proc[mappid (nflg)].p_nice ,mem ,pflg ); procprint (mappid (nflg), 1); done (0); } uid = getuid() & 0377; if (nflg) { procprint (mappid (nflg), lflg); done (0); } seek(mem, psinfo.procbase, 0); read(mem, proc, sizeof proc); cprint(0); if (headed) printf ("\n%d used, %d unused\n", pcount, NPROC-pcount); done (0); } cprint(parent) int parent; { register int i; for(i = 0; i < NPROC; i++) { if(proc[i].p_stat == 0) continue; if(proc[i].p_ppid == parent) { pcount++; if(okprint(i)) procprint(i, lflg); if(proc[i].p_pid) cprint(proc[i].p_pid); } } } okprint(pid) { register int i, j; i = pid; if (proc[i].p_stat==0) return 0; if (pgrpcnt) { for (j = 0; ; j++) { if (j >= pgrpcnt) return 0; if (pgrp[j] == proc[i].p_pgrp) break; } } else { if ( (proc[i].p_pgrp==0 && xflg==0) || (nflg && nflg != proc[i].p_pid) || (cflg && cflg != proc[i].p_ppid) ) return 0; } if (uid != proc[i].p_uid & 0377 && aflg==0) return 0; return 1; /* say OK */ } procprint (pid, verbose) { register i; seek (mem, psinfo.procbase+(pid * sizeof proc[0]), 0); read (mem, &proc[pid], sizeof proc[0]); if(!okprint(i = pid)) return; /* validate that it hasn't changed */ if (!qflg && !headed) { headed++; if(verbose) printf( " F S UID PPID NCE CPU PRI ADDR SZ WCHAN%s PID TTY TIME COMMAND\n" ,wflg?" ":""); else printf( " PID TTY TIME COMMAND\n" ); } if (verbose) { printf(proc[i].p_flag?"%3o":" ",proc[i].p_flag); printf("%c%4d%6l" ,"0SWRIZT"[proc[i].p_stat] ,proc[i].p_uid & 0377 ,proc[i].p_ppid ); printf("%4d%4d%4d%6d%4d" ,proc[i].p_nice ,proc[i].p_cpu&0377 ,proc[i].p_pri ,proc[i].p_addr ,(proc[i].p_size+7)>>3 ); if (proc[i].p_wchan) { if (wflg) { symbol (proc[i].p_wchan); } else { printf("%7o", proc[i].p_wchan); } } else { printf (wflg?" ":" "); } putchar(' '); } printf("%5l", proc[i].p_pid); if (proc[i].p_stat==SZOMB) printf(" <defunct>"); else prcom(i, verbose); printf("\n"); flush(); } prcom(procnum, verbose) { #define UASIZE sizeof ua #define XSIZE 1024 int baddr, laddr, mf; register int *ip; register char *cp, *cp1; int c, nbad; long clong, clong1, ; struct { int integer[]; }; baddr = 0; laddr = 0; if (proc[procnum].p_flag&SLOAD) { laddr = proc[procnum].p_addr; mf = swmem; } else { baddr = proc[procnum].p_addr; mf = swap; } baddr =+ laddr>>3; laddr = (laddr&07)<<6; seek(mf, baddr, 3); seek(mf, laddr, 1); /* * The following expression is logically a series of ors, but * the V6 C compiler gets an expression overflow if we don't * hack it this way. */ if (read(mf, ua, UASIZE) != UASIZE) goto nope; if (ua->u_dsize+ua->u_ssize+USIZE != proc[procnum].p_size) goto nope; if (ua->u_tsize<0 || ua->u_dsize<0 || ua->u_ssize<0) goto nope; if (ua->u_tsize>XSIZE || ua->u_dsize>XSIZE || ua->u_ssize>XSIZE) { nope: printf(" <unavailable>"); return 0; } printf(" %c", gettty()); clong.integer[0] = ua->u_utime[0]; clong.integer[1] = ua->u_utime[1]; clong1.integer[0] = ua->u_stime[0]; clong1.integer[1] = ua->u_stime[1]; clong1 =+ clong; if(clong1!=0) prclock(clong1); else printf(" "); if(procnum == 0) goto sched; c = proc[procnum].p_size - 8; laddr =+ (c&07)<<6; baddr =+ c>>3; seek(mf, baddr, 3); seek(mf, laddr, 1); if (read(mf, ua, sizeof ua) != sizeof ua) return(0); for (ip = &ua[256]; ip > &ua[0]; ) { if ((*--ip)&0100200) /* nonascii? */ { cp = ip+1; while (*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; sched: printf(verbose?" %.16s":" %.64s" ,procnum?cp:"scheduler"); return(1); } } return(0); } gettty() { register i; if (ua->u_ttyp==0) return(' '); for (i=0; i<=NTTYI; i++) if ( (psinfo.ttyinfo[i].devno == ua[0].u_ttyd) && psinfo.ttyinfo[i].devname ) return(psinfo.ttyinfo[i].devname); return('?'); } #define HSIZE 16 /* executable file header size */ int buf[HSIZE]; int sym; struct syment *symtab; struct syment *maxsym; syminit() { register int i, j; sym = open(symref,0); if (sym < 0) { printf("Can't open %s\n",symref); done(1); } else { read(sym,buf,HSIZE); if (buf[0]!=0407 && buf[0]!=0410 && buf[0]!=0411) { printf("Format error in %s\n",symref); done(1); } seek(sym,buf[1],1); seek(sym,buf[2],1); if (buf[7] != 1) { seek(sym,buf[1],1); seek(sym,buf[2],1); } i = buf[4]; i = buf[4]/12; j = i*12; if (i == 0) { printf("No namelist in %s\n",symref); done(1); } symtab = sbrk(j); seek (sym, HSIZE + (buf[7]?1:2)*(buf[1]+buf[2]), 0); read(sym,symtab,j); maxsym = symtab + i; close(sym); } } symbol(val) char *val; { register char *v; register struct syment *i; register char *mindif; char *minptr; char *thisdif; v = val; mindif = 077777; minptr = 0; for(i=symtab; i<maxsym; i++) { if (((i->type&077) != 043) && ((i->type&077) != 044)) continue; if (i->value > v) continue; thisdif = v - i->value; if (thisdif >= mindif) continue; mindif = thisdif; minptr = i; } if (minptr == 0) return(0); printf( mindif>0? "%5o+" : " " , mindif ); printf ("%-6.6s" , minptr->name+1 ); return(minptr); } scan(pp) char * pp; { register char * p; register char c; for(p = pp; (c = *p++) >= '0' && c <= '9'; ); return (--p); } done(i) int i; { flush(); exit(i); } /* * setprio (kerprocbase, psprocbase, psniceaddr, memfile, niceval) * lets the super-user change the priority of a job */ setprio (kerprocbase, psprocbase, psniceaddr, memfile, niceval) char *kerprocbase, *psprocbase, *psniceaddr; int niceval; { extern int errorr; register char *niceaddr; if (getuid () != 0) { printf ("Forbidden\n"); done (0); } niceaddr = kerprocbase + (psniceaddr - psprocbase); if ( store(niceaddr, niceval & 0177, memfile) < 0 ) return (-1); if (errorr == -1) return (-1); return (sizeof niceval); } char * load (addr, memfile) char * addr; { extern int errorr; char * val; errorr = 0; return ( seek(memfile,addr,0)<0 || sizeof val != read(memfile,&val,sizeof val) ? (errorr = -1) : val ); } store(addr,contents, memfile) char * addr; char contents; { extern int errorr; errorr = 0; return ( seek(memfile,addr,0)<0 || sizeof contents != write(memfile,&contents,sizeof contents) ? (errorr = -1) : contents ); } prclock(l) long l; { if(l<0) { printf("-"); l = -l; } l =/ HZ; /* make it seconds */ #define SEC_MIN 60 #define MIN_HR 60 if(l/(SEC_MIN*MIN_HR)>0) /* greater than one hour? */ { printf("%D:%02D:%02D" ,l/(SEC_MIN*MIN_HR) /* hours */ ,(l/MIN_HR)%SEC_MIN /* minutes */ ,l % MIN_HR /* seconds */ ); } else { printf("%2D:%02D" ,(l/MIN_HR)%SEC_MIN /* minutes */ ,l % SEC_MIN /* seconds */ ); } } int errorr; mappid (mappedid) { register int i; if( (i = mappedid & 0377) < NPROC) return i; printf("Error, %l is not a legal process id\n", mappedid); done(1); } /* * Build the tables required * */ #include "/usr/sys/h/conf.h" struct syment nl [6]; #define _KL11 0 #define _DC11 1 #define _DH11 2 #define _PTY 3 #define _PROC 4 #define _SWAPDEV 5 struct tty tty; int swapdev; getpsinfo () { register int infofid; register int symfid; setup (&nl[_KL11], "_kl11"); setup (&nl[_DC11], "_dc11"); setup (&nl[_DH11], "_dh11"); setup (&nl[_PTY], "_pty"); setup (&nl[_PROC], "_proc"); setup (&nl[_SWAPDEV], "_swapdev"); nlist (symref, nl); if (nl[_KL11].type==0) { printf("No namelist\n"); done (0); } psinfo.procbase = nl[_PROC].value; symfid = open (symref, 0); if (symfid < 0) { printf ("Can't open %s (symbols and swap #)\n", symref); done (0); } seek (symfid, nl[_SWAPDEV].value + HSIZE, 0); read (symfid, &swapdev, 2); getdev (); close (symfid); if (Bflg) { if ((infofid = creat (infoname, 0644)) < 0) printf ("Can't create psinfo\n"); else write (infofid, &psinfo, sizeof psinfo); done(0); } } getdev() { register struct { int dir_ino; char dir_n[14]; } *p; register i; register char c; struct ttyinf *ttyp; char *charp; int swapfound; int f; char dbuf[512]; struct statbuf statbuf; swapfound = -1; if (chdir ("/dev") < 0) { printf ("Can't chdir to /dev\n"); done (0); } f = open("", 0); if(f < 0) { printf("Can't open /dev\n"); done (0); } if (Bflg) printf ("Procbase is %6o\n", psinfo.procbase); loop: i = read(f, dbuf, sizeof dbuf); if (i <= 0) { close(f); return; } while (i < sizeof dbuf) dbuf[i++] = 0; for(p = dbuf; p < dbuf+sizeof dbuf; p++) { if(p->dir_ino == 0) continue; if(p->dir_n[0] == 't' && p->dir_n[1] == 't' && p->dir_n[2] == 'y' && p->dir_n[4] == 0 && p->dir_n[3] != 0) { if(stat(p->dir_n, &statbuf) < 0) continue; c = maptty (p->dir_n[3]); ttyp = &psinfo.ttyinfo [c]; ttyp->devname = p->dir_n[3]; ttyp->devno = statbuf.s_addr[0]; switch (ttyp->devno.d_major) { #ifdef MAJ_KL11 case MAJ_KL11: ttyp->pgrpaddr = nl[_KL11].value; break; #endif #ifdef MAJ_DC11 case MAJ_DC11: ttyp->pgrpaddr = nl[_DC11].value; break; #endif #ifdef MAJ_DH11 case MAJ_DH11: ttyp->pgrpaddr = nl[_DH11].value; break; #endif #ifdef MAJ_PTY case MAJ_PTY: ttyp->pgrpaddr = nl[_PTY].value; break; #endif } ttyp->pgrpaddr =+ (((sizeof tty)*(ttyp->devno.d_minor+1))-2); if (Bflg) printf ("tty%c %2d %2d %6o\n" ,ttyp->devname ,ttyp->devno.d_major ,ttyp->devno.d_minor ,ttyp->pgrpaddr ); continue; } else if (swapfound < 0) { if(stat(p->dir_n, &statbuf) < 0) continue; if((statbuf.s_flags & 060000) != 060000) /* IFBLK */ continue; if(statbuf.s_addr[0] == swapdev) { charp = setup (psinfo.swapname, "/dev/"); setup (charp, p->dir_n); swapfound++; if (Bflg) printf ("Swapdev is %s\n", psinfo.swapname); } } } goto loop; } setup (p, s) char *p, *s; { while (*p++ = *s++); return (--p); } maptty (cc) char cc; { register int c; c = cc; if ((c >= 'A') && (c <= 'Z')) c =- 'A'-26; else if ((c >= 'a') && (c <= 'z')) c =- 'a'; else if ((c >= '0') && (c <= '9')) c =- '0'-52; else if (c=='.') c = maptty(ttyn(0)); else { printf ("tty%c ?\n", c); c = -1; } return (c); }