Path: utzoo!utgpu!cs.utexas.edu!asuvax!noao!rutgers!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: alt.sources Subject: kstuff 0.18 (part 6/6) Message-ID: <6224:May705:05:0691@kramden.acf.nyu.edu> Date: 7 May 91 05:05:06 GMT Followup-To: alt.sources.d Organization: IR Lines: 1222 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'pff.c' <<'END_OF_FILE' X/* History: X5/3/91 DJB various changes X5/1/91 DJB baseline public domain X*/ X/* XXX: Should allow for process gids... */ X X#include X#include "structfile.h" X#include "structtext.h" X#include "structucred.h" X#include "structuser.h" X#include "structproc.h" /*XXX: must be after structuser for BSD-Tahoe dorks*/ X#include "structxnode.h" X#include "printfflag.h" X#include "printftype.h" X#include "printpstat.h" X#include "printrlimits.h" X#include "printrusage.h" X#include "printucred.h" X#include "getdevicename.h" X#include "getfcred.h" X#include "getnode.h" X#include "getopt.h" X#include "getpcred.h" X#include "getsocket.h" X#include "getuser.h" X#include "getvmseg.h" X#include "confhaveppid.h" X#include "confhaveusigintr.h" X#include "confmajorminor.h" X#include "confnfs.h" X#include "confodofe.h" X#include "confopalf.h" X#include "confpsess.h" X#include "confregion.h" X#include "conftext.h" X#include "confttyvp.h" X#include "confuofile.h" X#include "filetable.h" X#include "proctable.h" X#include "revnamei.h" X#include "portname.h" X#include "username.h" X#include "mallocfree.h" X#include "numeric.h" X#include "mntops.h" X#include "strerr.h" X#include "kmem.h" X#include X#ifndef ITIMER_REAL X#include X#endif X#ifndef RLIM_NLIMITS X#include X#endif X#include X X#define STYLE_BRIEF 0 X#define STYLE_DEFAULT 1 X#define STYLE_LONG 2 X#define STYLE_UIDLONG 3 X#define STYLE_FULL 4 X#define STYLE_TINY 5 X#define STYLE_PIDS 6 X#define STYLE_NAME 7 X X#define two(i) (1 << i) /* table if necessary */ X Xchar progname[] = "pff"; X Xstatic int flagall = 0; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X struct proc *pt; X struct file *ft; X struct nodebuf buf; X struct socketbuf sbuf; X int i; X int style; X int opt; X struct stat st; X struct mounted *mt; X struct statlist *fsstats; X int security; X int uid; X int ppflags; X int offlags; X int pnflags; X X#ifdef SECURITY X security = 1; X#else X security = 0; X#endif X uid = getuid(); X if (!uid) X security = 0; X if (getgid() == getegid()) X security = 0; X X getnodeinit(); X seginit(); X get_mntlist(); X proctableinit(); X filetableinit(); X pt = getproctable(); X if (!pt) X { fprintf(stderr,"%s: cannot get process table: %s\n", X progname,strerr(proctablestrerr)); exit(1); } X ft = getfiletable(); X if (!ft) X { fprintf(stderr,"%s: cannot get file table: %s\n", X progname,strerr(filetablestrerr)); exit(1); } X X style = STYLE_DEFAULT; X while ((opt = getopt(argc,argv,"as:f:d:i:u:p:xX")) != EOF) X switch(opt) X { X case 'a': flagall = 1; break; /*XXX: inverse?*/ X case 's': switch(*optarg) X { X case 'd': style = STYLE_DEFAULT; break; X case 'f': style = STYLE_FULL; break; X case 'b': style = STYLE_BRIEF; break; X case 'p': style = STYLE_PIDS; break; X case 'u': style = STYLE_UIDLONG; break; X case 'l': style = STYLE_LONG; break; X case 't': style = STYLE_TINY; break; X case 'n': style = STYLE_NAME; break; X case 'A': style = STYLE_BRIEF; break; /* : deprecated */ X case 'D': style = STYLE_TINY; break; /* Dupuy: deprecated */ X case 'F': style = STYLE_LONG; break; /* Fstat: deprecated */ X case 'h': fprintf(stderr, X"full\nuidlong\nlong\nname\ndefault\nbrief\ntiny\npids\n"); exit(1); X case 'H': fprintf(stderr,"\ Xfull: all information available, in a relatively unstructured format\n\ Xuidlong: like long, but prints users by name where possible\n\ Xlong: like default, but includes file reference count, offset, credentials\n\ Xname: like default, but prints filenames instead of device/inode\n\ Xdefault: like short, but includes file descriptor type and flags\n\ Xbrief: one open file per line, basic information\n\ Xtiny: all open files for one process per line\n\ Xpids: process ids only\n\ X" X ); exit(1); X default: ; /*XXX*/ X } X break; X case 'p': if (!numeric(optarg)) X { X fprintf(stderr,"%s: fatal: pid %s not numeric\n" X ,progname,optarg); X exit(1); X } X procaddpid(atoi(optarg)); flagall = 1; X break; X case 'u': if (username2uid(optarg,&i) == -1) X { X fprintf(stderr,"%s: fatal: username %s not found\n" X ,progname,optarg); X exit(1); X } X procadduid(i); flagall = 1; X break; X case 'f': if (stat(optarg,&st) == -1) X { X fprintf(stderr,"%s: fatal: cannot stat %s: %s\n" X ,progname,optarg,strerr(strerrno)); X exit(1); X } X /* XXX: keep track of filename? */ X /* XXX: print filename? */ X if (((st.st_mode & S_IFMT) == S_IFBLK) X ||((st.st_mode & S_IFMT) == S_IFCHR)) X { X buf.flagdev = NODE_ID_DEV; X buf.id.dev.maj = major(st.st_rdev); X buf.id.dev.min = minor(st.st_rdev); X } X else X { X buf.flagdev = NODE_ID_INO; X buf.id.ino.inum = st.st_ino; X buf.id.ino.dev = st.st_dev; X } X validadd(&buf); X break; X case 'd': mt = getmntname(optarg); X if (!mt) X { X fprintf(stderr,"%s: fatal: cannot find mount of %s\n" X ,progname,optarg); X exit(1); X } X for (fsstats = stats;fsstats;fsstats = fsstats->next) X if (!strncmp(mt->filesystem,fsstats->fsname,MNTMAXSTR)) X { X buf.flagdev = NODE_ID_INO; X buf.id.ino.inum = 0; X buf.id.ino.dev = fsstats->device; X validadd(&buf); X break; X } X break; X case 'i': sbuf.fsw = FSW_INET; X if (portname2port(optarg,&sbuf.fu.inet.lp) == -1) X { X fprintf(stderr,"%s: fatal: port %s not found\n" X ,progname,optarg); X exit(1); X } X validsadd(&sbuf); X break; X case 'x': if (!uid) security = 1; break; X case 'X': if (!uid) security = 0; break; X case '?': exit(1); /*XXX*/ X } X argc -= optind; argv += optind; X X for (;*argv;++argv) X { X int guess; X /* ambiguity time */ X guess = 1; X if (((*argv)[0] == '/') || ((*argv)[0] == '.')) X guess = 1; X else if (argv[0][0] == '#') X { X guess = 2; X ++*argv; X } X else if (numeric(*argv)) X guess = 2; X /* XXX: any other choices? */ X X if (guess == 1) X { X i = 0; /* becomes 1 if we shouldn't warn about failing getmntname */ X if (stat(*argv,&st) == -1) X fprintf(stderr,"%s: warning: cannot stat %s: %s\n" X ,progname,*argv,strerr(strerrno)); X else X { X i = 1; X if (((st.st_mode & S_IFMT) == S_IFBLK) X ||((st.st_mode & S_IFMT) == S_IFCHR)) X { X buf.flagdev = NODE_ID_DEV; X buf.id.dev.maj = major(st.st_rdev); X buf.id.dev.min = minor(st.st_rdev); X } X else X { X buf.flagdev = NODE_ID_INO; X buf.id.ino.inum = st.st_ino; X buf.id.ino.dev = st.st_dev; X } X validadd(&buf); X } X mt = getmntname(*argv); X if (!mt) X { X if (!i) X fprintf(stderr,"%s: warning: cannot find mount of %s\n" X ,progname,*argv); X } X else X { X for (fsstats = stats;fsstats;fsstats = fsstats->next) X if (!strncmp(mt->filesystem,fsstats->fsname,MNTMAXSTR)) X { X buf.flagdev = NODE_ID_INO; X buf.id.ino.inum = 0; X buf.id.ino.dev = fsstats->device; X validadd(&buf); X break; X } X } X } X else if (guess == 2) X { X flagall = 1; X if (!numeric(*argv)) X { X /* this can never happen with the current guess structure */ X fprintf(stderr,"%s: fatal: pid %s not numeric\n",progname,*argv); X exit(1); X } X procaddpid(atoi(*argv)); X } X } X X ppflags = 8064; X offlags = 64; X pnflags = 0; X X /* XXX: use 128 for fd creds by name? */ X X switch(style) X { X case STYLE_BRIEF: X puts(" CMD PID UID FD TYPE INODE FS"); X ppflags += 1; X offlags += 0; X pnflags += 0; X break; X case STYLE_DEFAULT: X puts(" CMD PID UID FD D FLAGS TYPE INODE FS"); X ppflags += 1; X offlags += 16 + 4; X pnflags += 0; X break; X case STYLE_LONG: X puts(" CMD PID UID FD REF D OFFSET FLAGS CRED TYPE INODE FS"); X ppflags += 16384 + 1; X offlags += 16 + 4 + 2 + 8 + 32; X pnflags += 0; X break; X case STYLE_UIDLONG: X puts(" CMD PID USERNAME FD REF D OFFSET FLAGS CRED TYPE INODE FS"); X ppflags += 32768 + 1; X offlags += 16 + 4 + 2 + 8 + 32; X pnflags += 0; X break; X case STYLE_FULL: X ppflags += 8192 + 126; X offlags += 16 + 4 + 2 + 8 + 32; X pnflags += 0; X break; X case STYLE_TINY: X puts(" CMD PID USERNAME OFILES"); X ppflags += 8192 + 32768 + 65536 + 131072 + 262144 + 1048576 + 1; X offlags += 16 + 4 + 2 + 8 + 32; X pnflags += 0; X break; X case STYLE_NAME: X puts(" CMD PID UID FD D FLAGS TYP FILENAME"); X ppflags += 1; X offlags += 16 + 4; X pnflags += 6; X break; X case STYLE_PIDS: X default: /* default should never happen */ X style = STYLE_PIDS; X ppflags += 524288; X offlags += 16 + 4 + 2 + 8 + 32; X pnflags += 2; X break; X } X X for (i = 0;i < mynproc;++i) X if (pt[i].p_pid) /*XXX*/ X if (!security || (uid == pt[i].p_uid)) X if (procmatch(&(pt[i]))) X printproc(&(pt[i]),&(myproc[i]),ft,ppflags,offlags,pnflags); X if (style == STYLE_PIDS) X putchar('\n'); X exit(0); X} X X/* flags: X1 put process identification before each fd line X 16384 allow 17 chars rather than 12 for command name X2 print basic process information X4 print process status X8 print process resource usage X16 print process limits X32 print process credentials X64 print process signal handling X128 show text segment as fd, when it exists X256 show controlling tty as fd, when it exists X512 show cwd as fd X1024 show root dir as fd, when it exists X2048 show all open file descriptors X4096 show all mmap segments X8192 print extra newline X32768 show uids as usernames wherever possible X65536 don't space-fill fd labels (like cwd, 0, 1, 2, etc.) X131072 don't actually print fd descriptions with newline X262144 print preliminary prefd at most once before all fds X524288 print just pid, return as fast as possible XXX: how interact w/others? X1048576 under 1 + 8192 + 262144, don't print newline unless prefd has been used X*/ X Xprintproc(p,preal,ft,flags,offlags,pnflags) Xstruct proc *p; Xstruct proc *preal; Xstruct file *ft; Xint flags; Xint offlags; Xint pnflags; X{ X#ifdef OPALF X static struct file *(fof[NOFILE]); X#endif X#ifdef ODOFE X static struct ofile_ext oe; X#endif X static struct nodebuf buf; X static struct socketbuf sbuf; X static char prefd[80]; X struct user *u; X struct ucred *uc; X int i; X X /* printf("xstat %d ",p->p_xstat); */ X /* printf("pri %d %d ",p->p_usrpri,p->p_pri); */ X /* printf("time %d %d %d",p->p_slptime,p->p_time,(int) p->p_pctcpu); */ X /* XXX: handle pctcpu? */ X /* char *p_wchan */ X /* XXX: u_timer[] */ X /* XXX: u_start, on machines that have it */ X /*XXX:p_tsize,p_dsize,p_ssize,p_rssize, p_maxrss===u.u_limit[MAXRSS],p_swrss*/ X X if (p->p_stat == 0) X return; X if (p->p_stat == SZOMB) X return; X#ifdef SIDL X if (p->p_stat == SIDL) X return; X#endif X X u = getuser(p); X if (!u) X { X#ifdef notdef /* sigh */ X fprintf(stderr,"%s: warning: getuser failed on proc %d: %s\n" X ,progname X ,p->p_pid X ,strerr(getuserstrerr) X ); X#endif X return; X } X if (u->u_procp != preal) X { X /* XXX: warn? */ X return; X } X X uc = getpcred(p,u); X if (!uc) X return; X X if (flags & 1) X { X sprintf(prefd X ,((flags & 16384) ? "%17.17s %5d %s " : "%12.12s %5d %s ") X ,u->u_comm X ,p->p_pid X ,printucred(uc,1,2,0,(flags & 32768) ? 1 : 0) /* XXX: should use names here */ X ); X } X X if (flags & 2) X { X printf("proc %8x ",preal); X printf("pid %d ",p->p_pid); X#ifdef HAVE_PPID X printf("ppid %d ",p->p_ppid); X#endif X printf("pgrp %d ",p->p_pgrp); /* XXX: p_sgid under POSIX */ X printf("uid %d",p->p_suid); X if (p->p_uid != p->p_suid) printf("/%d",p->p_uid); X printf(" nice %d ",p->p_nice); X printf("umask %o ",u->u_cmask); X puts(u->u_comm); X } X X if (flags & 4) X printf("status: %s\n",printpstat(p)); X X if (flags & 8) X { X printf("self: %s\n",printrusage(&(u->u_ru))); X printf("kids: %s\n",printrusage(&(u->u_cru))); X } X if (flags & 16) X printf("rlimits: %s\n",printrlimits(u->u_rlimit)); X X if (flags & 32) X { X if (uc) printf("cred: %s\n",printucred(uc,0,0,1,(flags & 32768) ? 1 : 0)); X } X X if (flags & 64) X { X printf("signals:"); X for (i = 0;i < NSIG;++i) X { X if (!(i % 8)) putchar(' '); X if (u->u_signal[i] == SIG_DFL) putchar('d'); X else if (u->u_signal[i] == SIG_IGN) putchar('i'); X else putchar('C'); X#ifdef HAVE_USIGINTR X if (u->u_sigintr & two(i)) X if (p->p_sigmask & two(i)) putchar(';'); else putchar(','); X else X#endif X if (p->p_sigmask & two(i)) putchar(':'); else putchar('.'); X /* any other flags to include? */ X } X putchar('\n'); X } X X#ifdef REGION X if (flags & 128) X { X /* XXX: This is totally, absolutely undocumented to work. */ X struct vm_vspace vs; X struct vm_object vo; X int i; X for (i = 0;i < sizeof(vs.vs_regiontab) / sizeof(vs.vs_regiontab[0]);++i) X { X kmemcpy(&vs,p->p_vspace,sizeof(vs)); X kmemcpy(&vo,vs.vs_regiontab[i].re_object,sizeof(vo)); X if (vo.ob_vp && validnode(vo.ob_vp,&buf,0)) X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("text "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X break; X } X } X } X#else X#ifdef TEXT X if (flags & 128) X { X struct text text; X kmemcpy(&text,p->p_textp,sizeof(text)); X if (validnode(text.x_Xptr,&buf,0)) X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("text "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X } X#endif X#endif X X if (flags & 256) X { X#ifdef TTYVP X#ifdef PSESS X static struct sess pse; X kmemcpy(&pse,p->p_sessp,sizeof(pse)); X if (pse.s_vp && validnode(pse.s_vp,&buf,0)) X#else X if (u->u_ttyvp && validnode(u->u_ttyvp,&buf,0)) X#endif X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("ctty "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X#else X if (u->u_ttyd) X { X char *s; X s = getttydevname(u->u_ttyd); X if (s) X { X buf.type = "chr"; /*XXX: breaks virtype encapsulation */ X buf.flagdev = NODE_ID_DEV; X buf.id.dev.maj = 0; /*XXX*/ X buf.id.dev.min = 0; /*XXX*/ X buf.id.dev.name = s; X if (validnode(0,&buf,1)) /* XXX: does this work? */ X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("ctty "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X } X } X#endif X } X X if (flags & 512) X if (u->u_cdir && validnode(u->u_cdir,&buf,0)) X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X if (flags & 65536) X printf("cwd "); X else X printf(" cwd "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X if (flags & 1024) X if (u->u_rdir && validnode(u->u_rdir,&buf,0)) X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("rdir "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X X if (flags & 2048) X { X#ifdef OPALF X if (u->u_lastfile >= NOFILE) /* XXX: ever? */ X kmemcpy(fof,u->u_ofile,sizeof(struct file *) * NOFILE); X else X kmemcpy(fof,u->u_ofile,sizeof(struct file *) * (u->u_lastfile + 1)); X u->u_ofile = fof; /* ensures that we're dealing with a pointer */ X#endif X#ifdef ODOFE X if (u->u_ofile_ext) X { X kmemcpy(&oe,u->u_ofile_ext,sizeof(oe)); X u->u_nofile = oe.oe_nofile; X } X#endif X for (i = 0;i < NUOFILE(u);++i) X { X#ifdef ODOFE X if (u->u_ofile_ext) X kmemcpy(u->u_lofile,oe.oe_ofile + i,sizeof(struct ofile)); X /* XXX: this is slow as molasses */ X else X u->u_lofile[0] = u->u_lofile[i]; /* XXX: structure copying */ X#endif X if (UOFILE(u,i)) X if (ft[UOFILE(u,i) - myfile].f_data) X { X switch(ft[UOFILE(u,i) - myfile].f_type) X { X case DTYPE_INODE: X if (!validnode(ft[UOFILE(u,i) - myfile].f_data,&buf,0)) X continue; X break; X case DTYPE_SOCKET: X if (!validsocket(ft[UOFILE(u,i) - myfile].f_data,&sbuf)) X continue; X break; X default: /* including SPU, PROCESS */ X if (!validother(ft[UOFILE(u,i) - myfile].f_data)) X continue; X } X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X if (flags & 65536) X printf("%d ",i); X else X printf("%4d ",i); X if (!(flags & 131072)) X printfile(ft + (UOFILE(u,i) - myfile),offlags,pnflags,&buf,&sbuf); X } X } X } X X if (flags & 4096) X { X struct vnode **segvns; X segvns = getvmseg(p); X for (i = 0;segvns[i] && (i < vmsegmax);++i) X { X if (validnode(segvns[i],&buf,0)) X { X if (flags & 524288) X { X printf("%d ",p->p_pid); X return; X } X if (flags & 1) X fputs(prefd,stdout); X if (flags & 262144) X prefd[0] = 0; X printf("mmap "); X if (!(flags & 131072)) X { X spacenode(offlags); X printbuf(&buf,pnflags); X } X } X } X } X X if (flags & 8192) X if (!prefd[0] || !(flags & 1) || !(flags & 1048576) || !(flags & 262144)) X putchar('\n'); X} X X/* offlags: X1 print file data location, 9 chars X2 print reference count, 6 chars X4 print file type, 2 chars X8 print file offset, 11 chars X16 print file flags, 9 chars X32 print file credentials as uids, 12 chars (or 18 chars with usernames) X64 print extended file information, free format X128 use usernames rather than uids X*/ X Xint printfile(f,offlags,pnflags,buf,sbuf) Xstruct file *f; Xint offlags; Xint pnflags; Xstruct nodebuf *buf; Xstruct socketbuf *sbuf; /*XXX*/ X{ X struct ucred *uc; X /* XXX: f_ops? f_msgcount? */ X if (offlags & 1) X printf("%8x ",f->f_data); X if (offlags & 2) X printf("%5d ",(int) f->f_count); X if (offlags & 4) X printf("%s ",printftype(f)); /* could also do numeric */ X if (offlags & 8) X printf("%10lu ",(unsigned long) f->f_offset); X if (offlags & 16) X printf("%s ",printfflag(f,4)); /* XXX: could also use 1,2,3 */ X if (offlags & 32) X { X uc = getfcred(f); X if (uc) printf("%s ",printucred(uc,1,0,0,(offlags & 128) ? 1 : 0)); X } X if (offlags & 64) X if (f->f_type == DTYPE_SOCKET) X printsbuf(sbuf); X else if (f->f_type == DTYPE_INODE) X printbuf(buf,pnflags); X#ifdef DTYPE_SPU X else if (f->f_type == DTYPE_SPU) X printf("(spu io)"); X#endif X#ifdef DTYPE_PROCESS X else if (f->f_type == DTYPE_PROCESS) X { X static struct proc p; X kmemcpy(&p,f->f_data,sizeof(p)); X printf("(process %d)",p.p_pid); X } X#endif X /* XXX: other types? */ X else X printf("unk type %d %8x\n",f->f_type,f->f_data); X else X putchar('\n'); X} X Xint spacenode(offlags) /*XXX this whole routine */ Xint offlags; X{ X if (offlags & 1) X printf("%8s ",""); X if (offlags & 2) X printf("%5s ",""); X if (offlags & 4) X printf("I "); /*XXX*/ X if (offlags & 8) X printf("%10s ",""); X if (offlags & 16) X printf("%s ","---------"); /*XXX*/ X if (offlags & 32) X printf("%s ",(offlags & 128) ? " " : " "); /*XXX*/ X} X Xprintbuf(buf,pnflags) Xstruct nodebuf *buf; Xint pnflags; X{ X printf("%s",buf->type); X switch(buf->flagdev) X { X case NODE_ID_FIFO: X printf(" (named pipe)\n"); X break; X case NODE_ID_FIFOINO: X printf(" (named pipe)"); X case NODE_ID_INO: X if (!(pnflags & 4)) X { X printf((pnflags & 1) ? " inode %d" : " ino %7d",buf->id.ino.inum); X if (buf->id.ino.name) X if ((pnflags & 1)) X printf(" %s fs %x (%s)",buf->id.ino.flagnfs ? "nfs" : "local" X ,buf->id.ino.dev,buf->id.ino.name); X else X printf(" %5x (%s)",buf->id.ino.dev,buf->id.ino.name); X else X if ((pnflags & 1)) X printf(" block dev %x",buf->id.ino.dev); X else X printf(" %5x",buf->id.ino.dev); X } X if (pnflags & 2) X { X putchar(' '); if (!(pnflags & 4)) putchar('('); X revnamei((unsigned long) buf->id.ino.inum,(unsigned long) buf->id.ino.dev); X if (!(pnflags & 4)) putchar(')'); X /* XXX: should do the printing right here */ X } X putchar('\n'); X break; X case NODE_ID_DEV: X if (pnflags & 4) X { X if (buf->id.dev.name) X printf(" %s\n",buf->id.dev.name); X else X printf(" dev (%d,%d)\n",buf->id.dev.maj,buf->id.dev.min); X } X else X { X if (buf->id.dev.name) X printf(" dev (%s)\n",buf->id.dev.name); X else X printf(" dev (%d,%d)\n",buf->id.dev.maj,buf->id.dev.min); X } X break; X default: X printf(" \n"); /*XXX*/ X } X return; X} X Xprintsbuf(sbuf) Xstruct socketbuf *sbuf; X{ X printf("("); X X if (sbuf->strsockt) printf("%s ",sbuf->strsockt); X else printf("unknown socket type %d ",sbuf->socktype); X X if (sbuf->flagaccept) printf("accept "); X if (sbuf->flagreuse) printf("reuse "); X if (sbuf->flaghead) printf("head "); X X if (sbuf->famname) printf("%s",sbuf->famname); X else printf("unknown family %d",sbuf->family); X X switch(sbuf->fsw) X { X case FSW_UNK: X break; X case FSW_INET: X if (sbuf->fu.inet.strpro) printf(" %s ",sbuf->fu.inet.strpro); X else printf(" protocol %d ",sbuf->fu.inet.proto); X if (sbuf->fu.inet.r0 || sbuf->fu.inet.r1 || sbuf->fu.inet.r2 || sbuf->fu.inet.r3) X printf("%u.%u.%u.%u",sbuf->fu.inet.r0,sbuf->fu.inet.r1,sbuf->fu.inet.r2,sbuf->fu.inet.r3); X else printf("*"); X if (sbuf->fu.inet.rp) printf(":%d",sbuf->fu.inet.rp); X else printf(":*"); X if (sbuf->fu.inet.l0 || sbuf->fu.inet.l1 || sbuf->fu.inet.l2 || sbuf->fu.inet.l3) X printf(" %u.%u.%u.%u",sbuf->fu.inet.l0,sbuf->fu.inet.l1,sbuf->fu.inet.l2,sbuf->fu.inet.l3); X /* XXX: always print local host as uname? */ X else printf(" *"); X if (sbuf->fu.inet.lp) printf(":%d",sbuf->fu.inet.lp); X else printf(":*"); X break; X case FSW_UNIX: X printf(" unpcb %x inode %x conn %x",sbuf->fu.un.unpcb,sbuf->fu.un.node,sbuf->fu.un.conn); X /* XXX: print that vnode? print that unpcb? */ X printf("%s",sbuf->fu.un.path); X break; X default: X break; /*XXX*/ X } X X printf(")\n"); X} X Xstruct validlist X { X struct validlist *next; X int type; /* 1 for node, 2 for socket */ X union X { X struct nodebuf n; X struct socketbuf s; X } X v; X } X; X Xstatic struct validlist *validhead = 0; X Xint validsmatch(v,sbuf) Xstruct socketbuf *v; Xstruct socketbuf *sbuf; X{ X /* XXX: many more match types are possible */ X /* socktype, family, fsw */ X X if (v->fsw == FSW_UNK) /* no sockets at all */ X return 0; X if (sbuf->fsw != v->fsw) /* must match nonzero fsw */ X return 0; X if (v->fsw == FSW_INET) X if (v->fu.inet.lp && (v->fu.inet.lp != sbuf->fu.inet.lp)) X return 0; X return 1; X} X Xint validmatch(v,buf) Xstruct nodebuf *v; Xstruct nodebuf *buf; X{ X if (v->flagdev == NODE_ID_DEV) X if (buf->flagdev == NODE_ID_DEV) X return (v->id.dev.maj == buf->id.dev.maj) && (v->id.dev.min == buf->id.dev.min); X else X return 0; X if ((buf->flagdev == NODE_ID_INO) || (buf->flagdev == NODE_ID_FIFOINO)) X { X /* It would be wrong to check NFS here: stat doesn't indicate NFS. */ X if (v->id.ino.inum) X if (v->id.ino.inum != buf->id.ino.inum) X return 0; X if (v->id.ino.dev != buf->id.ino.dev) X return 0; X return 1; X } X return 0; X} X Xstatic struct socketbuf sockcache[256]; Xstatic int sockcacheok[256]; /* had better be initialized to 0 */ Xstatic char *sockcachepos[256]; X Xint cachegetsocket(sock,buf) Xchar *sock; Xstruct socketbuf *buf; X{ X int hash; X hash = ((char *) &sock)[0] + ((char *) &sock)[3]; X /* XXX: major XXX: we had better have 4-byte addresses here */ X hash = hash & 255; /* okay, at least this is in the right range */ X if (sockcacheok[hash]) X if (sockcachepos[hash] == sock) X { X *buf = sockcache[hash]; /* XXX: structure copying */ X return 0; X } X if (getsocket(sock,buf) == -1) X return -1; X sockcache[hash] = *buf; /* XXX: structure copying */ X sockcacheok[hash] = 1; X sockcachepos[hash] = sock; X return 0; X} X Xint validsocket(sock,sbuf) Xchar *sock; Xstruct socketbuf *sbuf; X{ X struct validlist *v; X if (getsocket(sock,sbuf) == -1) X return 0; X if (!validhead) X return flagall; X for (v = validhead;v;v = v->next) X if (v->type == 2) X if (validsmatch(&(v->v.s),sbuf)) X return 1; X return 0; X} X Xstatic struct nodebuf nodecache[256]; Xstatic int nodecacheok[256]; /* had better be initialized to 0 */ Xstatic char *nodecachepos[256]; X Xint cachegetnode(node,buf) Xchar *node; Xstruct nodebuf *buf; X{ X int hash; X hash = ((char *) &node)[0] + ((char *) &node)[3]; X /* XXX: major XXX: we had better have 4-byte addresses here */ X hash = hash & 255; /* okay, at least this is in the right range */ X if (nodecacheok[hash]) X if (nodecachepos[hash] == node) X { X *buf = nodecache[hash]; /* XXX: structure copying */ X return 0; X } X if (getnode(node,buf) == -1) X return -1; X nodecache[hash] = *buf; /* XXX: structure copying */ X nodecacheok[hash] = 1; X nodecachepos[hash] = node; X return 0; X} X Xint validnode(node,buf,gndone) Xchar *node; Xstruct nodebuf *buf; Xint gndone; X{ X struct validlist *v; X if (!gndone) X if (cachegetnode(node,buf) == -1) X return 0; X if (!validhead) X return flagall; X for (v = validhead;v;v = v->next) X if (v->type == 1) X if (validmatch(&(v->v.n),buf)) X return 1; X return 0; X} X Xint validsadd(sbuf) Xstruct socketbuf *sbuf; X{ X struct validlist *v; X v = (struct validlist *) malloc(sizeof(struct validlist)); X if (!v) X return -1; X v->next = validhead; X v->type = 2; X v->v.s = *sbuf; /* XXX: requires struct copying */ X validhead = v; X return 0; X} X Xint validadd(buf) Xstruct nodebuf *buf; X{ X struct validlist *v; X v = (struct validlist *) malloc(sizeof(struct validlist)); X if (!v) X return -1; X v->next = validhead; X v->type = 1; X v->v.n = *buf; /* XXX: requires struct copying */ X validhead = v; X return 0; X} X Xint validother(node) Xchar *node; X{ X if (validhead) X return 0; X return flagall; X} X Xstruct proclist X { X struct proclist *next; X int type; /* 1 for pid, 2 for uid */ X union X { X int pid; X int uid; X } X u; X } X; X Xstatic struct proclist *prochead = 0; X Xint procmatch(proc) Xstruct proc *proc; X{ X struct proclist *p; X if (!prochead) X return 1; X for (p = prochead;p;p = p->next) X { X if (p->type == 1) X if (proc->p_pid == p->u.pid) X return 1; X if (p->type == 2) X if (proc->p_uid == p->u.uid) X return 1; X /*XXX: more types? */ X } X return 0; X} X Xint procaddpid(pid) Xint pid; X{ X struct proclist *p; X p = (struct proclist *) malloc(sizeof(struct proclist)); X if (!p) X return -1; X p->next = prochead; X p->type = 1; X p->u.pid = pid; X prochead = p; X return 0; X} X Xint procadduid(uid) Xint uid; X{ X struct proclist *p; X p = (struct proclist *) malloc(sizeof(struct proclist)); X if (!p) X return -1; X p->next = prochead; X p->type = 2; X p->u.uid = uid; X prochead = p; X return 0; X} END_OF_FILE if test 27865 -ne `wc -c <'pff.c'`; then echo shar: \"'pff.c'\" unpacked with wrong size! fi # end of 'pff.c' fi echo shar: End of archive 6 \(of 6\). cp /dev/null ark6isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0