/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ /* * Print system stats * * Modified to understand new file flags from <sys/file.h> * Specifically the elimination of the FPIPE flags and * the addition of FNDELAY and FAPPEND. * Pipes are now flagged in the inode struct (IFIFO == 010000) * Bill Burns 3/15/85 * * Modified to read NPROC, NINODE, NTEXT, NOFILE, * NSIG, and NFILE from the kernel via nlist(3) and * the /dev/mem driver. Modified to use malloc() * to allocate it's tables dynamically. This was done in * order to free pstat from it's dependence on param.h . * Also modified to report on tty lines (-t) for DZ11. * Also modified to support multiple kl & dl lines. * Also modified to report on dhu/dhv lines - Bill 3/84 * * The tty structures are no longer hard wired to the drivers, * they are now associated by logical assignment. * * Fred Canter 11/11/82 */ static char Sccsid[] = "@(#)pstat.c 3.0 (ULTRIX-11) 4/22/86"; #define mask(x) (x&0377) #include <nlist.h> #include <sys/param.h> #include <sys/conf.h> #include <sys/tty.h> #include <sys/inode.h> #include <sys/text.h> #include <sys/proc.h> #include <sys/file.h> #include <sys/dir.h> #include <sys/user.h> #include <sys/callo.h> char *fcore = "/dev/mem"; char *fnlist = "/unix"; int fc; struct nlist setup[] = { #define SINODE 0 #define SNINODE 1 { "_inode", 0, 0, }, { "_ninode", 0, 0, }, #define STEXT 2 #define SNTEXT 3 { "_text", 0, 0, }, { "_ntext", 0, 0, }, #define SPROC 4 #define SNPROC 5 { "_proc", 0, 0, }, { "_nproc", 0, 0, }, #define SDH 6 { "_dh11", 0, 0, }, #define SNDH 7 { "_ndh11", 0, 0, }, #define SKL 8 { "_kl11", 0, 0, }, #define SNKL 9 { "_nkl11", 0, 0, }, #define SNDL 10 { "_ndl11", 0, 0, }, #define SFIL 11 #define SNFILE 12 { "_file", 0, 0, }, { "_nfile", 0, 0, }, #define SNOFILE 13 { "_nofile", 0, 0, }, #define SNSIG 14 { "_nsig", 0, 0, }, #define SDZ 15 { "_dz_tty", 0, 0, }, #define SNDZ 16 { "_dz_cnt", 0, 0, }, #define SUH 17 { "_uh11", 0, 0, }, #define SNUH 18 { "_nuh11", 0, 0, }, #define SPTY 19 { "_pt_tty", 0, 0, }, #define SNPTY 20 { "_npty", 0, 0, }, #define SCALLO 21 #define SNCALLO 22 { "_callout" }, { "_ncall" }, #define SBOOT 23 { "_boottime" }, #define STIME 24 { "_time" }, 0, }; int inof; int txtf; int prcf; int ttyf; int usrf; long ubase; int filf; int allflg; int nofile; int nsig; int nfile; int ninode, ntext, nproc; int uptime, resource; main(argc, argv) char **argv; { while (--argc && **++argv == '-') { while (*++*argv) switch (**argv) { case 'a': allflg++; break; case 'i': inof++; break; case 'x': txtf++; break; case 'p': prcf++; break; case 't': ttyf++; break; case 'u': if (--argc == 0) break; ubase = oatoi(*++argv); --argv; if(ubase == 'e') { /* err, arg not octal number */ argc++; break; } usrf++; break; case 'f': filf++; break; case 'T': resource++; break; case 'U': uptime++; break; default: printf("Unknown flag '%c'\n", **argv); break; } } if(usrf) ++argv; if (argc>0) fcore = argv[0]; if ((fc = open(fcore, 0)) < 0) { printf("Can't find %s\n", fcore); exit(1); } if (argc>1) fnlist = argv[1]; nlist(fnlist, setup); if (setup[SINODE].n_type == 0) { printf("no namelist\n"); exit(1); } if (uptime) douptime(); if (inof) doinode(); if (txtf) dotext(); if (ttyf) dotty(); if (prcf) doproc(); if (usrf) dousr(); if (filf) dofil(); if (resource) doresource(); } doinode() { register struct inode *ip; struct inode *xinode; register int nin, loc; int i; char *calloc(); lseek(fc, (long)setup[SNINODE].n_value, 0); read(fc, (char *)&ninode, sizeof(ninode)); nin = 0; xinode = (struct inode *) calloc(ninode, sizeof(struct inode)); lseek(fc, (long)setup[SINODE].n_value, 0); read(fc, (char *)xinode, (sizeof(struct inode) * ninode)); for (ip=xinode, i=0; i<ninode; ip++, i++) if (ip->i_count) nin++; printf("\n%d active inodes\n", nin); printf(" LOC FLAGS CNT DEVICE INO MODE NLK UID SIZE/DEV\n"); loc = setup[SINODE].n_value; for (ip=xinode, i=0; i<ninode; ip++, i++, loc += sizeof(*xinode)) { if (ip->i_count == 0) continue; printf("%7.1o ", loc); putf(ip->i_flag&ILOCK, 'L'); putf(ip->i_flag&IUPD, 'U'); putf(ip->i_flag&IACC, 'A'); putf(ip->i_flag&IMOUNT, 'M'); putf(ip->i_flag&IWANT, 'W'); putf(ip->i_flag&ITEXT, 'T'); printf("%6d", ip->i_count); printf("%3d,%3d", major(ip->i_dev), minor(ip->i_dev)); printf("%6u", ip->i_number); printf("%7o", ip->i_mode); printf("%4d", ip->i_nlink); printf("%4d", ip->i_uid); if ((ip->i_mode&IFMT)==IFBLK || (ip->i_mode&IFMT)==IFCHR) printf("%6d,%3d", major(ip->i_rdev), minor(ip->i_rdev)); else printf("%10ld", ip->i_size); printf("\n"); } } putf(v, n) { if (v) printf("%c", n); else printf(" "); } dotext() { register struct text *xp; struct text *xtext; register loc, i; int ntx; char *calloc(); lseek(fc, (long)setup[STEXT].n_value, 0); read(fc, (char *)&ntext, sizeof(ntext)); ntx = 0; xtext = (struct text *) calloc(ntext, sizeof(struct text)); lseek(fc, (long)setup[STEXT].n_value, 0); read(fc, (char *)xtext, (sizeof(struct text) * ntext)); for (xp=xtext, i=0; i<ntext; xp++, i++) if (xp->x_iptr!=NULL) ntx++; printf("\n%d text segments\n", ntx); printf(" LOC FLAGS DADDR CADDR SIZE IPTR CNT CCNT LCNT\n"); loc = setup[STEXT].n_value; for (xp=xtext, i=0; i<ntext; xp++, i++, loc += sizeof(*xtext)) { if (xp->x_iptr == NULL) continue; printf("%7.1o", loc); printf(" "); putf(xp->x_flag&XTRC, 'T'); putf(xp->x_flag&XWRIT, 'W'); putf(xp->x_flag&XLOAD, 'L'); putf(xp->x_flag&XLOCK, 'K'); putf(xp->x_flag&XWANT, 'w'); printf("%5u", xp->x_daddr); printf("%7.1o", xp->x_caddr); printf("%5d", xp->x_size); printf("%8.1o", xp->x_iptr); printf("%4d", xp->x_count&0377); printf("%5d", xp->x_ccount); printf("%5d", xp->x_lcount); printf("\n"); } } doproc() { struct proc *xproc; register struct proc *pp; register loc, np; int i; char *calloc(); lseek(fc, (long)setup[SNPROC].n_value, 0); read(fc, (char *)&nproc, sizeof(nproc)); xproc = (struct proc *) calloc(nproc, sizeof(struct proc)); lseek(fc, (long)setup[SPROC].n_value, 0); read(fc, (char *)xproc, (sizeof(struct proc) * nproc)); np = 0; for (pp=xproc, i=0; i<nproc; pp++, i++) if (pp->p_stat) np++; printf("\n%d processes\n", np); printf(" LOC S F PRI SIGNAL UID TIM CPU NI PGRP PID PPID ADDR SIZE WCHAN LINK TEXTP CLKT\n"); for (loc=setup[SPROC].n_value,pp=xproc,i=0; i<nproc; pp++, i++, loc+=sizeof(*xproc)) { if (pp->p_stat==0 && allflg==0) continue; printf("%6o", loc); printf("%2d", pp->p_stat); printf("%5o", pp->p_flag); printf("%4d", pp->p_pri); printf("%7O", (long)pp->p_sig); printf("%4d", pp->p_uid&0377); printf("%4d", pp->p_time&0377); printf("%4d", pp->p_cpu&0377); printf("%3d", pp->p_nice); printf("%6d", pp->p_pgrp); printf("%6d", pp->p_pid); printf("%6d", pp->p_ppid); /* * If process in memory (SLOAD flag set), * addr & size are in 64 byte clicks, otherwise * addr is block number in swap area and size is * size of image in 512 byte blocks. The paddr-1 is * because p_addr is swap block number +1. */ if(pp->p_flag&SLOAD) { printf("%7o", pp->p_addr); printf("%5d", pp->p_size); } else { if(pp->p_addr) printf("%7d", pp->p_addr - 1); else printf("%7d", pp->p_addr); /* proc slot empty */ printf("%5d", (pp->p_size+7)>>3); } printf("%7o", pp->p_wchan); printf("%7o", pp->p_link); printf("%7o", pp->p_textp); printf(" %u", pp->p_clktim); printf("\n"); } } /* * tty structures must be handled on a per line basis * because the may not be contiguous. */ dotty() { struct tty *ttyp[128]; /* MAX of 8 DH11 */ /* contains address of tty structure */ int ndh, ndz, nkl, ndl, nuh, npty; register char *mesg; register int i; lseek(fc, (long)setup[SNKL].n_value, 0); read(fc, (char*)&nkl, sizeof(nkl)); lseek(fc, (long)setup[SNDL].n_value, 0); read(fc, (char*)&ndl, sizeof(ndl)); lseek(fc, (long)setup[SKL].n_value, 0); read(fc, (char *)ttyp, sizeof(int) * (nkl + ndl)); mesg = " # RAW CAN OUT MODE ADDR DEL COL STATE PGRP ERRCNT LASTEC\n"; printf("\n%d kl lines\n", nkl); printf(mesg); for(i=0; i<nkl; i++) ttyprt(i, ttyp[i]); if(ndl) { printf("%d dl lines\n", ndl); printf(mesg); for(i=nkl; i<(nkl+ndl); i++) ttyprt(i, ttyp[i]); } if (setup[SNDH].n_type != 0) { lseek(fc, (long)setup[SNDH].n_value, 0); read(fc, (char *)&ndh, sizeof(ndh)); printf("%d dh lines\n", ndh); printf(mesg); lseek(fc, (long)setup[SDH].n_value, 0); read(fc, (char *)ttyp, sizeof(int) * ndh); for(i=0; i<ndh; i++) ttyprt(i, ttyp[i]); } if (setup[SNUH].n_type != 0) { lseek(fc, (long)setup[SNUH].n_value, 0); read(fc, (char *)&nuh, sizeof(nuh)); printf("%d dhu/dhv lines\n", nuh); printf(mesg); lseek(fc, (long)setup[SUH].n_value, 0); read(fc, (char *)ttyp, sizeof(int) * nuh); for(i=0; i<nuh; i++) ttyprt(i, ttyp[i]); } if (setup[SNDZ].n_type != 0) { lseek(fc, (long)setup[SNDZ].n_value, 0); read(fc, (char *)&ndz, sizeof(ndz)); printf("%d dz lines\n", ndz); printf(mesg); lseek(fc, (long)setup[SDZ].n_value, 0); read(fc, (char *)ttyp, sizeof(int) * ndz); for(i=0; i<ndz; i++) ttyprt(i, ttyp[i]); } if (setup[SNPTY].n_type != 0) { lseek(fc, (long)setup[SNPTY].n_value, 0); read(fc, (char *)&npty, sizeof(npty)); printf("%d pseudo ttys\n", npty); printf(mesg); lseek(fc, (long)setup[SPTY].n_value, 0); read(fc, (char *)ttyp, sizeof(int) * npty); for(i=0; i<npty; i++) ttyprt(i, ttyp[i]); } } ttyprt(n, atp) caddr_t atp; { register struct tty *tp; struct tty tty_ts; if(atp == 0) return; lseek(fc, (long)atp, 0); /* find actual tty struct for line */ read(fc, (char *)&tty_ts, sizeof(struct tty)); tp = &tty_ts; printf("%2d", n); printf("%4d", tp->t_rawq.c_cc); printf("%4d", tp->t_canq.c_cc); printf("%4d", tp->t_outq.c_cc); printf("%8.1o", tp->t_flags); printf("%8.1o", tp->t_addr); printf("%3d", tp->t_delct); printf("%4d ", tp->t_col); putf(tp->t_state&TIMEOUT, 'T'); putf(tp->t_state&WOPEN, 'W'); putf(tp->t_state&ISOPEN, 'O'); putf(tp->t_state&CARR_ON, 'C'); putf(tp->t_state&BUSY, 'B'); putf(tp->t_state&ASLEEP, 'A'); putf(tp->t_state&XCLUDE, 'X'); putf(tp->t_state&TTSTOP, 'S'); putf(tp->t_state&TBLOCK, 'M'); putf(tp->t_state&HUPCLS, 'H'); printf("%6d", tp->t_pgrp); printf(" %6u %6o", tp->t_errcnt, tp->t_lastec); printf("\n"); } dousr() { union { struct user rxu; char fxu[ctob(USIZE)]; } xu; register struct user *up; register i; int nofile, nsig; lseek(fc, (long)setup[SNOFILE].n_value, 0); read(fc, (char *)&nofile, sizeof(nofile)); lseek(fc, (long)setup[SNSIG].n_value, 0); read(fc, (char *)&nsig, sizeof(nsig)); lseek(fc, ubase<<6, 0); read(fc, (char *)&xu, sizeof(xu)); up = &xu.rxu; printf("\nrsav %.1o %.1o\n", up->u_rsav[0], up->u_rsav[1]); printf("segflg, error %d, %d\n", up->u_segflg, up->u_error); printf("uids %d,%d,%d,%d\n", up->u_uid,up->u_gid,up->u_ruid,up->u_rgid); printf("procp %.1o\n", up->u_procp); printf("base, count, offset %.1o %.1o %ld\n", up->u_base, up->u_count, up->u_offset); printf("cdir %.1o\n", up->u_cdir); printf("dbuf %.14s\n", up->u_dbuf); printf("dirp %.1o\n", up->u_dirp); printf("dent %d %.14s\n", up->u_dent.d_ino, up->u_dent.d_name); printf("pdir %.1o\n", up->u_pdir); printf("dseg"); for (i=0; i<8; i++) printf("%8.1o", up->u_uisa[i]); printf("\n "); for (i=0; i<8; i++) printf("%8.1o", up->u_uisd[i]); if (up->u_sep) { printf("\ntseg"); for (i=8; i<16; i++) printf("%8.1o", up->u_uisa[i]); printf("\n "); for (i=8; i<16; i++) printf("%8.1o", up->u_uisd[i]); } printf("\nfile"); for (i=0; i<10; i++) printf("%8.1o", up->u_ofile[i]); printf("\n "); for (i=10; i<nofile; i++) printf("%8.1o", up->u_ofile[i]); printf("\nargs"); for (i=0; i<5; i++) printf(" %.1o", up->u_arg[i]); printf("\nsizes %.1o %.1o %.1o\n", up->u_tsize, up->u_dsize, up->u_ssize); printf("sep %d\n", up->u_sep); printf("qsav %.1o %.1o\n", up->u_qsav[0], up->u_qsav[1]); printf("ssav %.1o %.1o\n", up->u_ssav[0], up->u_ssav[1]); printf("sigs"); for (i=0; i<nsig; i++) printf(" %.1o", up->u_signal[i]); printf("\ntimes %ld %ld\n", up->u_utime/60, up->u_stime/60); printf("ctimes %ld %ld\n", up->u_cutime/60, up->u_cstime/60); printf("ar0 %.1o\n", up->u_ar0); /* printf("prof"); for (i=0; i<4; i++) printf(" %.1o", up->u_prof[i]); */ printf("\nintflg %d\n", up->u_intflg); printf("ttyp %.1o\n", up->u_ttyp); printf("ttydev %d,%d\n", major(up->u_ttyd), minor(up->u_ttyd)); printf("comm %.14s\n", up->u_comm); } oatoi(s) char *s; { register v; v = 0; while (*s) { if((*s < '0') || (*s > '7')) return('e'); /* error, not octal digit */ v = (v<<3) + *s++ - '0'; } return(v); } dofil() { struct file *xfile; register struct file *fp; register nf; int loc; int i; char *calloc(); lseek(fc, (long)setup[SNFILE].n_value, 0); read(fc, (char *)&nfile, sizeof(nfile)); nf = 0; xfile = (struct file *) calloc(nfile, sizeof(struct file)); lseek(fc, (long)setup[SFIL].n_value, 0); read(fc, (char *)xfile, (sizeof(struct file) * nfile)); for (fp=xfile, i=0; i<nfile; fp++, i++) if (fp->f_count) nf++; printf("\n%d open files\n", nf); printf(" LOC FLG CNT INO OFFS\n"); for (fp=xfile,loc=setup[SFIL].n_value,i=0; i<nfile; fp++, i++, loc+=sizeof(*xfile)) { if (fp->f_count==0) continue; printf("%7.1o ", loc); putf(fp->f_flag&FREAD, 'R'); putf(fp->f_flag&FWRITE, 'W'); putf(fp->f_flag&FNDELAY, 'D'); putf(fp->f_flag&FAPPEND, 'A'); putf(fp->f_flag&FSOCKET, 'S'); putf(fp->f_flag&FPENDING, 'P'); printf("%6d", fp->f_count); printf("%8.1o", fp->f_inode); printf(" %ld\n", fp->f_un.f_offset); } } douptime() { long boottime, curtime; lseek(fc, (long)setup[SBOOT].n_value, 0); read(fc, &boottime, sizeof(boottime)); lseek(fc, (long)setup[STIME].n_value, 0); read(fc, &curtime, sizeof(curtime)); curtime -= boottime; if (!strcmp(fcore, "/dev/mem")) printf("System up "); else printf("System ran for "); if (curtime >= 60L*60L*24L) { printf("%d days ", (int)(curtime/(60L*60L*24L))); curtime %= (60L*60L*24L); } printf("%d hours ", (int)(curtime/(60L*60L))); curtime %= 60L*60L; printf("%d minutes\n", (int)((curtime+59)/60L)); } #define INUSE 0 #define FREE 1 #define NOTUSED 2 int c_proc(), c_text(), c_inode(), c_file(), c_callo(); struct tab { int (*func)(); unsigned loc; unsigned size; unsigned count; char *name; } tab[] = { c_file, SFIL, sizeof(struct file), 0, "files", c_inode, SINODE, sizeof(struct inode), 0, "inodes", c_proc, SPROC, sizeof(struct proc), 0, "processes", c_text, STEXT, sizeof(struct text), 0, "texts", c_callo, SCALLO, sizeof(struct callo), 0, "callouts", 0 }; doresource() { register struct tab *tp; #ifdef notdef printf("Table Slots In Use Free Never Used\n"); printf("----- ----- ------ ---- ----------\n"); #endif notdef for (tp = tab; tp->func; tp++) { if (tp->count == 0) { lseek(fc, (long)setup[tp->loc+1].n_value, 0); read(fc, &tp->count, sizeof(tp->count)); } tp->loc = setup[tp->loc].n_value; sumup(tp); } return(0); } sumup(tp) register struct tab *tp; { char buf[512]; register int i, inuse = 0, free = 0, notused = 0; lseek(fc, (long)tp->loc, 0); for (i = tp->count; i > 0; --i) { read(fc, &buf, tp->size); switch ((*tp->func)(&buf)) { case INUSE: ++inuse; break; case NOTUSED: ++notused; /*FALLTHROUGH*/ case FREE: ++free; break; } } #ifdef notdef printf("%-8.8s %5d %5d %3d%% %5d %3d%% %5d %3d%%\n", tp->name, tp->count, inuse, (inuse*200 + tp->count)/(2*tp->count), free, (free*200 + tp->count)/(2*tp->count), notused, (notused*200 + tp->count)/(2*tp->count)); #endif notdef printf("%4d/%4d %-9.9s %4d never used (%2d%%)\n", inuse, tp->count, tp->name, notused, (notused*200 + tp->count)/(2*tp->count)); } c_proc(p) register struct proc *p; { if (p->p_stat) return(INUSE); if (!p->p_nice && !p->p_pri) return(NOTUSED); return(FREE); } c_text(tp) register struct text *tp; { if (tp->x_iptr) return(INUSE); if (!tp->x_daddr && !tp->x_caddr) return(NOTUSED); return(FREE); } c_inode(ip) register struct inode *ip; { if (ip->i_count) return(INUSE); if (!ip->i_mode && !ip->i_nlink && !ip->i_dev && !ip->i_size && !ip->i_uid && !ip->i_gid) return(NOTUSED); return(FREE); } c_file(fp) register struct file *fp; { if (fp->f_count) return(INUSE); if (!fp->f_flag && !fp->f_inode && !fp->f_un.f_offset) return(NOTUSED); return(FREE); } c_callo(cp) register struct callo *cp; { if (cp->c_time) return(INUSE); if (!cp->c_func) return(NOTUSED); return(FREE); }