rsalz@uunet.uu.net (Rich Salz) (03/25/89)
Submitted-by: abe@mace.cc.purdue.edu (Vic Abell) Posting-number: Volume 18, Issue 57 Archive-name: ofiles.new Here's a new shar of ofiles. When I saw how little ofiles needed from /usr/src/sys/specfs/snode.h, I decided to define it in ofiles.c. This version should now compile for folks who do not have Sun sources. Sorry for the problem. I'm just about done with fstat, and I have made sure it doesn't have the same difficulty. Vic Abell # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # README # Makefile # ofiles.c # ofiles.8l # This archive created: Thu Mar 23 19:42:54 1989 # By: Vic Abell (Purdue University) echo shar: extracting README '(1315 characters)' sed 's/^XX//' << \SHAR_EOF > README XXOfiles shows the owner of an open file or network connection. XX XXC. Spencer is the original author of ofiles. Michael Ditto, Tom Dunigan, XXAlexander Dupuy, Gary Nebbett and Richard Tobin made contributions. Mike XXSpitzer, Ray Moody and Vik Lall of the Purdue University Computing Center XX(PUCC) adapted ofiles to a number of different UNIX environments. I added XXthe network connection option. XX XXOfiles compiles and runs on 4.3BSD, DYNIX 3.0.12 (Balance) and 3.0.14 XX(Symmetry), SunOS 4.0 and ULTRIX 2.2. It is free of lint on those systems XXaccording to the lint libraries in use at PUCC. XX XXSpecial notes: XX XX 1. A "generic" Makefile is included. You may have to adjust it XX to your local conditions. XX XX 2. SunOS 4.0 loading requires "-lkvm", so modify the Makefile XX accordingly when you port ofiles to your Sun system. XX XX 3. Ofiles needs permission to read /dev/drum (swap files), /dev/kmem XX and /dev/mem. PUCC uses a "setgid kmem" approach - i. e., XX /dev/{drum,kmem,mem} are in the kmem group and ofiles has mode XX 2755, group kmem. The Makefile install rule implements this XX convention. XX XXThe ofiles distribution includes: XX XX README this file XX Makefile a generic Makefile XX ofiles.c source XX ofiles.8l man page XX XXVic Abell, abe@mace.cc.purdue.edu XXPurdue University Computing Center XXMarch 22, 1989 SHAR_EOF if test 1315 -ne "`wc -c README`" then echo shar: error transmitting README '(should have been 1315 characters)' fi echo shar: extracting Makefile '(738 characters)' sed 's/^XX//' << \SHAR_EOF > Makefile XX# XX# Makefile for ofiles XX# XX XXPROG= ofiles XXBIN= ${DESTDIR}/usr/local/etc XX XXI=/usr/include XXS=/usr/include/sys XXL=/usr/include/local XX XXINCLUDE= XXDEBUG= -O XXCDEFS= XXCFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE} XX XXHDR= XXONEC= ofiles.c XXOTHER= XXSOURCE= Makefile ${HDR} ${ONEC} ${OTHER} XX XXall: ${PROG} XX XX# SunOS 4.0 needs -lkvm in the following rule XX XX${PROG}: XX ${CC} -o $@ ${CFLAGS} ${ONEC} XX XXclean: FRC XX rm -f Makefile.bak ${PROG} *.o a.out core errs tags XX XXinstall: all FRC XX install -cs -m 2755 -g kmem ${PROG} ${BIN} XX XXlint: ${HDR} ${ONEC} FRC XX lint ${CDEFS} ${INCLUDE} ${ONEC} XX XXprint: source FRC XX lpr -J'${PROG} source' ${SOURCE} XX XXsource: ${SOURCE} XX XXspotless: clean XX rcsclean ${SOURCE} XX XXtags: ${HDR} ${ONEC} XX ctags -t ${HDR} ${ONEC} XX XX${SOURCE}: XX co -q $@ XX XXFRC: XX SHAR_EOF if test 738 -ne "`wc -c Makefile`" then echo shar: error transmitting Makefile '(should have been 738 characters)' fi echo shar: extracting ofiles.c '(24522 characters)' sed 's/^XX//' << \SHAR_EOF > ofiles.c XX/* ofiles.c XX * XX * ofiles [-d ] [-k nlist core] [-n] [-p] args XX * XX * Show owner of open file or network connection. XX * XX * Reports owner, process ID, access type, command and inode number. XX * XX * -d select verbose debugging output XX * XX * -k nlist core specifies alternative name list and core files XX * (DYNIX only) XX * XX * -n interpret names as network connection, hexadecimal XX * Protocol Control Block (PCB) addresses XX * XX * -p gives brief (pids only) report XX * XX * names file names, file system names or network connection XX * PCB addresses XX * XX * Stat each file or file system argument and scan the process table, XX * looking for a match in the associated user structure's file lists. XX * XX * Follow each PCB arg to the Internet Protocol Control Block (INPCB), XX * thence to the socket; then scan the file table to find the file XX * structure address associated with the socket; finally, scan the XX * process table, looking for a nacth in the associated user structure's XX * file lists. XX * XX * Doesn't handlle remote NFS files. XX */ XX XX/* XX * Authors: XX * XX * The orignal author is: XX * XX * C. Spencer XX * XX * Contributors include: XX * XX * Michael Ditto XX * Tom Dunigan XX * Alexander Dupuy XX * Greg Nebbett XX * Richard Tobin XX * XX * From the Purdue University Computing Center: XX * XX * Mike Spitzer converted to 4.3BSD, DYNIX 3.0.1[24] XX * Ray Moody SunOS 4.0 and ULTRIX 2.2 XX * Vik Lall XX * XX * Vic Abell added socket option and removed lint XX * XX */ XX XX#ifndef lint XXstatic char rcsid[]="$Header: /usr/src/local/etc/ofiles/RCS/ofiles.c,v 1.8 89/03/21 12:29:30 abe Exp Locker: abe $"; XX#endif /* lint */ XX XX#include <sys/param.h> XX#include <sys/dir.h> XX#include <sys/user.h> XX XX#ifdef DYNIX XX#define KERNEL XX#include <sys/file.h> XX#include <sys/vnode.h> XX#include <sys/inode.h> XX#undef KERNEL XX#else XX#define KERNEL XX#include <sys/file.h> XX#ifndef sun XX#include <sys/inode.h> XX#endif XX#undef KERNEL XX#endif XX XX#include <machine/pte.h> XX#if !defined(ultrix) && !defined(sun) XX#include <machine/machparam.h> XX#endif XX#include <sys/proc.h> XX#include <nlist.h> XX#include <sys/stat.h> XX#include <pwd.h> XX#include <fstab.h> XX#include <sys/vmmac.h> XX#include <stdio.h> XX XX#ifdef sun XX#include <sys/vnode.h> XX#include <ufs/inode.h> XX#include <kvm.h> XXstruct snode { XX struct snode *s_next; XX struct vnode s_vnode; XX struct vnode *s_realvp; XX struct vnode *s_bdevvp; XX u_short s_flag; XX dev_t s_dev; XX}; XXkvm_t *kd; XX#endif XX XX#ifdef ultrix XX#include <sys/gnode.h> XX#include <sys/gnode_common.h> XX#include <machine/param.h> XX#endif XX XX#include <sys/socket.h> XX#include <sys/socketvar.h> XX#include <net/route.h> XX#include <netinet/in.h> XX#include <netinet/in_pcb.h> XX#include <netinet/tcp.h> XX#include <netinet/tcp_fsm.h> XX#include <netinet/tcp_timer.h> XX#include <netinet/tcp_var.h> XX XX#define CDIR 01 XX#define OFILE 02 XX#define RDIR 04 XX#define SHFILE 010 XX#define EXFILE 020 XX#define SOCKET 040 XX XXchar *namelist; XXchar *corefile; XXint k_opt = 0; XXint n_opt = 0; XX XX#ifdef ultrix XX#define ls_t long XX#else XX#define ls_t off_t XX#endif XX XX#ifdef sun XXchar *sprintf(); XX#endif XX XXls_t lseek(), vtophys(); XX XXvoid eread(), eseek(); XX#ifdef ultrix XXvoid exit(), nlist(), perror(); XX#endif XX XXint nproc; /* number of entries in proc table */ XXint mem; /* fd for /dev/mem */ XXint kmem; XXint swap; /* fd for /dev/swap */ XXlong procbase; XXint ppid = -1; /* previously display PID */ XX XXint dirinode; /* directory (CDIR or RDIR) inode */ XXint opninode; /* save inode of open file */ XXint pids_only = 0; /* if non-zero, only output process ids */ XX XXchar *progname; XXstruct nlist nl[] = { XX#define X_PROC 0 XX { "_proc" }, XX#define X_NPROC 1 XX {"_nproc"}, XX#define X_USRPTMA 2 XX {"_Usrptmap"}, XX#define X_USRPT 3 XX {"_usrpt"}, XX#define X_SYSMAP 4 XX {"_Sysmap"}, XX#define SFIL 5 XX { "_file" }, XX#define SNFILE 6 XX { "_nfile" }, XX { "" }, XX}; XX XX#ifndef DYNIX XXstruct pte *usrpt, *Usrptma; XX#endif XX XXint debug; XX XXmain(argc, argv) XX int argc; XX char *argv[]; XX{ XX XX#ifdef ultrix XX struct gnode *i, *getinode(); XX#else XX struct inode *i, *getinode(); XX#endif XX struct stat s; XX struct user *u, *getuser(); XX struct proc p; XX register int filen, flags, procn; XX register char *filename, *fsname; XX struct fstab *fs, *getfsfile(), *getfsspec(); XX char *getsockfp(), *rindex(); XX struct file *fp; XX int ax, err, findf, nmct; XX char *ap; XX int exitval = 0; XX XX#ifdef lint XX/* XX * The following code satisfies lint for KERNEL symbols. XX * This program is lint-free under 4.3BSD, DYNIX 3.0.1[24], SunOS 4.0 XX * and ULTRIX 2.2, using the lint libraries of the systems at the XX * Purdue University Computing Center. XX */ XX#if !defined(ultrix) && !defined(DYNIX) && !defined(sun) XX long lintlong; XX#endif XX#ifdef ultrix XX struct nch *lintnch; XX float lintfloat; XX#endif XX#if !defined(DYNIX) XX file = fileNFILE = NULL; XX fp = file; XX fp = fileNFILE; XX nfile = 0; XX filen = nfile; XX#endif XX#if !defined(ultrix) && !defined(DYNIX) && !defined(sun) XX inode = inodeNINODE = rootdir = NULL; XX i = inode; XX i = inodeNINODE; XX i = rootdir; XX ninode = 0; XX nextinodeid = 0l; XX lintlong = nextinodeid; XX nextinodeid = lintlong; XX filen = ninode; XX#endif XX#ifdef sun XX tcp_ttl = 0; XX filen = tcp_ttl; XX#endif XX#ifdef ultrix XX nch = NULL; XX lintnch = nch; XX nch = lintnch; XX nchsize = 0; XX filen = nchsize; XX tcp_alpha = tcp_beta = 0.0; XX lintfloat = tcp_alpha; XX lintfloat = tcp_beta; XX tcp_alpha = lintfloat; XX#endif XX#endif /* lint */ XX XX if ((progname = rindex(argv[0], '/'))) XX progname++; XX else XX progname = argv[0]; XX XX if (argc == 1) { XX XXusage: XX XX#ifdef DYNIX XX (void) fprintf(stderr, XX "usage: %s [-d ] [-k nlist core] [-n] [-p] names\n", XX progname); XX#else XX (void) fprintf(stderr, XX "usage: %s [-d ] [-n] [-p] names\n", progname); XX#endif XX (void) fprintf(stderr, "\t-d = select verbose debugging output\n"); XX#ifdef DYNIX XX (void) fprintf(stderr, XX "\t-k = use specified nlist and core files\n"); XX#endif XX (void) fprintf(stderr, XX "\t-n = interpret names as network connection, hexadecimal,\n"); XX (void) fprintf(stderr, XX "\t Protocol Control Block (PCB) addresses, as supplied\n"); XX (void) fprintf(stderr, XX "\t by netstat's -A option\n"); XX (void) fprintf(stderr, "\t-p = print only process IDs\n"); XX (void) fprintf(stderr, XX "\tnames = file names or PCB addresses\n"); XX exit(exitval); XX } XX XX /* check for switches */ XX for (err = 0, ax = 1; ax < argc; ax++) { XX ap = argv[ax]; XX if (*ap++ != '-') XX break; XX while (*ap) { XX switch (*ap++) { XX XX case 'd': XX debug = 1; XX break; XX#ifdef DYNIX XX case 'k': XX if ((ax + 2) >= argc) { XX (void) fprintf(stderr, XX "%s: no nlist/core after -k\n", XX progname); XX err++; XX } else { XX namelist = argv[++ax]; XX corefile = argv[++ax]; XX k_opt = 1; XX continue; XX } XX break; XX#endif XX case 'n': XX n_opt++; XX break; XX XX case 'p': XX pids_only = 1; XX break; XX XX default: XX (void) fprintf(stderr, XX "%s: unknown switch - %c\n", XX progname, *(ap - 1)); XX err++; XX } XX } XX } XX if (ax >= argc) { XX (void) fprintf(stderr, "%s: no names specified\n", progname); XX err++; XX } XX if (err) { XX exitval = 1; XX goto usage; XX } XX XX#ifdef sun XX if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY)) == 0) { XX (void) fprintf(stderr, "%s: can't access memory: ", XX progname); XX perror (""); XX exit(1); XX } XX#endif XX if ((mem = open("/dev/mem", 0)) < 0) { XX (void) fprintf(stderr, "%s: /dev/mem: ", progname); XX perror(""); XX exit(1); XX } XX if (k_opt) { XX if ((kmem = open(corefile, 0)) < 0) { XX (void) fprintf(stderr, "%s: %s: ", XX progname, corefile); XX perror(""); XX exit(1); XX } XX } else { XX if ((kmem = open("/dev/kmem", 0)) < 0) { XX (void) fprintf(stderr, "%s: /dev/kmem: ", progname); XX perror(""); XX exit(1); XX } XX } XX if (!k_opt) XX if ((swap = open("/dev/drum", 0)) < 0) { XX (void) fprintf(stderr, "%s: /dev/drum: ", progname); XX perror(""); XX exit(1); XX } XX XX getsyms(); XX XX for (err = 0, nmct = argc - ax; ax < argc; ax++) { XX /* if -n, then arg is a PCB */ XX if (n_opt) { XX if ((filename = getsockfp(argv[ax], &fp)) == NULL) { XX err++; XX continue; XX } XX fsname = ""; XX } else { XX /* assume arg is a filesystem */ XX if ((fs = getfsfile(argv[ax])) != NULL) { XX fsname = argv[ax]; XX if (strcmp(".", argv[ax]) == 0) XX filename = argv[ax]; XX else XX filename = fs->fs_spec; XX /* maybe it's the device name for a filesystem */ XX } else if ((fs = getfsspec(argv[ax])) != NULL) { XX filename = argv[ax]; XX fsname = fs->fs_file; XX /* probably a regular file */ XX } else { XX filename = argv[ax]; XX fsname = ""; XX } XX if (stat(filename, &s)) { XX (void) fprintf(stderr, "%s: can't stat %s: ", XX progname, filename); XX perror(""); XX err++; XX continue; XX } XX if (debug) XX (void) printf( XX "stat dev %x ino %d mode %x rdev %x\n", XX s.st_dev, s.st_ino, s.st_mode, XX s.st_rdev); XX } XX if (! pids_only) { XX (void) printf("%s\t%s", filename, fsname); XX if (!n_opt) { XX if ((s.st_mode & S_IFMT) == S_IFDIR) XX (void) printf("(directory)"); XX } XX (void) printf("\n%-8.8s %5s %-6.6s FD %-14.14s", XX "USER", "PID", "TYPE", "CMD"); XX if (!n_opt) XX (void) printf(" INODE"); XX (void) printf("\n"); XX } XX for (findf = procn = 0; procn < nproc; procn++) { XX procslot(procn, &p); XX flags = 0; XX if (p.p_stat == 0 || p.p_stat == SZOMB) XX continue; XX#ifdef sun XX u = kvm_getu(kd, &p); XX#else XX u = getuser(&p); XX#endif XX XX if ( u == (struct user *)NULL) XX continue; XX if (debug) XX (void) printf("pid %d uid %d cmd %s\n", p.p_pid, XX p.p_uid, u->u_comm); XX if (!n_opt) { XX i = getinode(u->u_rdir, "rdir"); XX if (check(&s, i)) { XX dirinode = s.st_ino; XX gotone(u, &p, -1, RDIR); XX findf++; XX } XX i = getinode(u->u_cdir, "cdir"); XX if (check(&s, i)) { XX dirinode = s.st_ino; XX gotone(u, &p, -1, CDIR); XX findf++; XX } XX } XX#ifdef DYNIX XX for (filen = 0; filen < u->u_nofile; filen++) XX#else XX for (filen = 0; filen < NOFILE; filen++) XX#endif XX { XX struct file f; XX XX flags = 0; XX if (n_opt) { XX#ifdef DYNIX XX if (u->u_lofile[filen].of_file != fp) XX#else XX if (u->u_ofile[filen] != fp) XX#endif XX continue; XX } else { XX#ifdef DYNIX XX if (u->u_lofile[filen].of_file == NULL) XX continue; XX#else XX if (u->u_ofile[filen] == NULL) XX continue; XX#endif XX } XX XX if (k_opt) XX#ifdef DYNIX XX eseek(kmem, vtophys((ls_t)u->u_lofile[filen].of_file), 0, "file"); XX#else XX eseek(kmem, vtophys((ls_t)u->u_ofile[filen]), 0, "file"); XX#endif XX else XX#ifdef DYNIX XX eseek(kmem, (ls_t)u->u_lofile[filen].of_file, 0, "file"); XX#else XX eseek(kmem, (ls_t)u->u_ofile[filen], 0, "file"); XX#endif XX eread(kmem, (char *)&f, sizeof(f), "file"); XX XX if (f.f_count > 0) { XX if (n_opt && f.f_type == DTYPE_SOCKET) { XX gotone(u, &p, filen, SOCKET); XX findf++; XX continue; XX } XX#if defined(DYNIX) || defined(sun) XX if (f.f_type != DTYPE_VNODE) XX#else XX if (f.f_type != DTYPE_INODE) XX#endif XX continue; XX#if defined(DYNIX) || defined(sun) XX i = getinode((struct vnode *)f.f_data, XX "ofile"); XX#else XX#ifdef ultrix XX i = getinode((struct gnode *)f.f_data, XX "ofile"); XX#else XX i = getinode((struct inode *)f.f_data, XX "ofile"); XX#endif XX#endif XX if (check(&s, i)) { XX#if !defined(ultrix) XX opninode = i->i_number; XX#else XX opninode = (int)i->g_req.gr_number; XX#endif XX flags |= OFILE; XX if (f.f_flag & FEXLOCK) { XX flags |= EXFILE; XX } XX if (f.f_flag & FSHLOCK) { XX flags |= SHFILE; XX } XX gotone(u, &p, filen, flags); XX findf++; XX } XX } XX } XX } XX if (findf) XX nmct--; XX if (! pids_only) { XX (void) printf("\n"); XX (void) fflush(stdout); XX } XX } XX if (pids_only && ppid != -1) { XX (void) printf("\n"); XX (void) fflush(stdout); XX } XX exitval = (err || nmct) ? 1 : 0; XX exit(exitval); XX} XX XX/* XX * print the name of the user owning process "p" and the pid of that process XX */ XXgotone(u, p, fd, f) XX struct user *u; XX struct proc *p; XX int fd; XX int f; XX{ XX char *ty, tybuf[8], *strcat(), *strcpy(); XX struct passwd *getpwuid(); XX register struct passwd *pw; XX XX /* only print pids and return */ XX if (pids_only) { XX if (ppid != p->p_pid) { XX if (ppid != -1) XX (void) printf(" "); XX (void) printf("%d", p->p_pid); XX (void) fflush(stdout); XX ppid = p->p_pid; XX } XX return; XX } XX pw = getpwuid((int)p->p_uid); XX if (pw) XX (void) printf("%-8.8s ", pw->pw_name ); XX else XX (void) printf("%-8d ", p->p_uid); XX (void) printf("%5d ", p->p_pid); XX if (f & OFILE) { XX (void) strcpy(tybuf, "file"); XX ty = tybuf; XX if (f & SHFILE) XX (void) strcat(ty, "/s"); XX else if (f & EXFILE) XX (void) strcat(ty, "/x"); XX } else if (f & CDIR) XX ty = "cwd"; XX else if (f & RDIR) XX ty = "rdir"; XX else if (f & SOCKET) XX ty = "sock"; XX else XX ty = ""; XX (void) printf("%-6.6s ", ty); XX if (fd >= 0) XX (void) printf("%2d ", fd); XX else XX (void) printf(" "); XX (void) printf("%-14.14s", u->u_comm); XX if (f & OFILE) XX (void) printf(" %5d", opninode); XX else if (f & (CDIR|RDIR)) XX (void) printf(" %5d", dirinode); XX (void) printf("\n"); XX return; XX} XX XX/* XX * is inode "i" on device "s"? returns TRUE or FALSE XX */ XXcheck(s, i) XX struct stat *s; XX#ifdef ultrix XX struct gnode *i; XX#else XX struct inode *i; XX#endif XX{ XX if (s == (struct stat *)NULL) XX return 0; XX#ifdef ultrix XX if (i == (struct gnode *)NULL) XX return 0; XX if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->g_dev) XX return 1; XX else if ((s->st_dev == i->g_dev) && (s->st_ino == i->g_req.gr_number)) XX return 1; XX#else XX if (i == (struct inode *)NULL) return 0; XX if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->i_dev) XX return 1; XX else if ((s->st_dev == i->i_dev) && (s->st_ino == i->i_number)) XX return 1; XX#endif XX#ifdef sun XX else if (s->st_rdev == i->i_dev && i->i_number == 0) XX return 1; XX#endif XX else return 0; XX} XX XX XX/* XX * getinode - read an inode from from mem at address "addr" XX * return pointer to inode struct. XX */ XX#if defined(DYNIX) || defined(sun) XXstruct inode * XXgetinode(ip, s) XX struct vnode *ip; XX char *s; XX{ XX static struct inode i; XX static struct vnode v; XX#ifdef sun XX struct snode sn; XX#endif XX XX if (ip == NULL) XX return(NULL); XX if (k_opt) XX eseek(kmem, vtophys((ls_t)ip), 0, "vnode"); XX else XX eseek(kmem, (ls_t)ip, 0, "vnode"); XX eread(kmem, (char *)&v, sizeof(v), "vnode"); XX if (debug) XX (void) printf("vnode %s at %x %x dev=%x vtype=%d inode@%x\n", XX s, ip, v.v_flag, v.v_rdev, v.v_type, v.v_data); XX if (k_opt) XX eseek(kmem, vtophys((ls_t)v.v_data), 0, "inode"); XX else XX eseek(kmem, (ls_t)v.v_data, 0, "inode"); XX#ifdef sun XX if (v.v_type == VBLK || v.v_type == VCHR || v.v_type == VFIFO) { XX eread(kmem, (char *)&sn, sizeof(sn), "snode"); XX if (debug) XX (void) printf( XX "snode %s at %x %x dev=%x realvp=%x bdevvp=%x\n", XX s, ip, sn.s_vnode.v_type, sn.s_dev, XX sn.s_realvp, sn.s_bdevvp); XX if (sn.s_realvp || sn.s_bdevvp) { XX eseek(kmem, XX (sn.s_realvp) ? (ls_t)sn.s_realvp XX : (ls_t)sn.s_bdevvp, XX 0, "rvnode"); XX eread(kmem, (char *)&v, sizeof(v), "rvnode"); XX eseek(kmem, (ls_t)v.v_data, 0, "rinode"); XX } XX } XX#endif XX eread(kmem, (char *)&i, sizeof(i), "inode"); XX if (debug) XX (void) printf("inode %s at %x %x dev=%x inode=%d vtype=%x\n", XX s, v.v_data, i.i_flag, i.i_dev, i.i_number, XX i.i_vnode.v_type); XX return &i; XX} XX XX#else XX/* ARGSUSED */ XX XX#ifdef ultrix XXstruct gnode * XXgetinode(ip, s) XX struct gnode *ip; XX#else XX XXstruct inode * XXgetinode(ip, s) XX struct inode *ip; XX#endif XX XX char *s; XX{ XX#if defined(ultrix) XX static struct gnode i; XX#else XX static struct inode i; XX#endif XX XX eseek(kmem, (ls_t)ip, 0, "inode"); XX eread(kmem, (char *)&i, sizeof(i), "inode"); XX return &i; XX} XX#endif XX XX#if !defined(sun) XX/* XX * get user page for proc "p" from core or swap XX * return pointer to user struct XX */ XX#ifdef DYNIX XXstruct user * XXgetuser(p) XX struct proc *p; XX{ XX int btr; XX ls_t sp; XX static struct user *u = NULL; XX char *valloc(); XX XX if (u == NULL) { XX if ((u = (struct user *) valloc(ctob(UPAGES))) == NULL) { XX (void) fprintf(stderr, XX "%s: can't allocate space for user structure\n", progname); XX exit(1); XX } XX } XX btr = ctob(UPAGES); XX if ((p->p_flag & SLOAD) == 0) { XX if (k_opt) XX return (struct user *)NULL; XX sp = (ls_t) dtob(p->p_swaddr); XX if (lseek(swap, sp, 0) != sp) { XX if (debug) { XX (void) fprintf(stderr, XX "%s: error seeking to swap for %d: ", XX progname, p->p_pid); XX perror(""); XX } XX return (struct user *)NULL; XX } XX if (read(swap, (char*)u, btr) != btr) { XX if (debug) { XX (void) fprintf(stderr, XX "%s: error reading swap for %d: ", XX progname, p->p_pid); XX perror(""); XX } XX return (struct user *)NULL; XX } XX if (debug) XX (void) printf("read swap\n"); XX } else { XX if (k_opt) XX (void) lseek(kmem, vtophys((ls_t)p->p_uarea), L_SET); XX else XX (void) lseek(kmem, (ls_t)p->p_uarea, L_SET); XX if (read(kmem, (char *)u, btr) != btr) XX return (struct user *)NULL; XX } XX return u; XX} XX#else XXstruct user * XXgetuser(p) XX struct proc *p; XX{ XX struct pte *ptep, apte; XX struct pte mypgtbl[NBPG/sizeof(struct pte)]; XX int upage; XX char *up; XX static struct user user; XX XX /* easy way */ XX if ((p->p_flag & SLOAD) == 0) { XX if (k_opt) XX return (struct user *)NULL; XX (void) lseek(swap, (ls_t)dtob(p->p_swaddr), 0); XX if (read(swap, (char *)&user, sizeof(struct user))==0) { XX (void) fprintf(stderr, XX "%s: can't get swapped user page\n", XX progname); XX return (struct user *)NULL; XX } XX if (debug) XX (void) printf("read swap\n"); XX } else { /* boo */ XX ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1]; XX XX /* get the page table for the user page */ XX (void) lseek(kmem, (ls_t)ptep, 0); XX if (read(kmem, (char *)&apte, sizeof(apte)) == 0) { XX (void) fprintf(stderr, XX "%s: can't get user page table\n", XX progname); XX return (struct user *)NULL; XX } XX XX /* now get this user's page table */ XX eseek(mem, (ls_t)ctob(apte.pg_pfnum) ,0, "page tbl"); XX if (read(mem, (char *)mypgtbl, sizeof(mypgtbl)) == 0) { XX (void) fprintf(stderr, XX "%s: can't get mypgtbl.\n", progname); XX return (struct user *)NULL; XX } XX /* now collect various pages of u area */ XX for (upage = 0, up = (char *)&user; upage < sizeof(struct user)/NBPG; upage++) { XX eseek(mem, (ls_t)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum), 0, "u page"); XX if (read(mem, up, NBPG) == 0) { XX (void) fprintf(stderr, XX "%s: can't get page %d of user area.\n", XX progname, upage); XX return(NULL); XX } XX up += NBPG; XX } XX } XX return &user; XX} XX#endif XX XX#endif XX/* XX * read with error checking XX */ XXvoid XXeread(fd, p, size, s) XX int fd; XX char *p; XX int size; XX char *s; XX{ XX char buf[100]; XX if (read(fd, p, size) != size) { XX if (!k_opt) { XX (void) fprintf(stderr, "%s: eread ", progname); XX perror(""); XX } XX (void) sprintf(buf, "read error for %s\n", s); XX error(buf); XX } XX} XX XX/* XX * seek with error checking XX */ XXvoid XXeseek(fd, off, whence, s) XX int fd; XX ls_t off; XX int whence; XX char *s; XX{ XX ls_t ret; XX char buf[100]; XX XX if (( ret = lseek(fd, off, whence)) != off) { XX (void) sprintf(buf, "seek for %s failed, wanted %o, got %o.\n", XX s, off, ret); XX error(buf); XX } XX} XX XX/* XX * print mesg "s", don't exit if we are processing a core, XX * so that corrupt entries don't prevent further uncorrupted XX * entries from showing up. XX */ XXerror(s) XX char *s; XX{ XX if (s && !k_opt) XX (void) fprintf(stderr, "%s: %s", progname, s); XX if (!k_opt) XX exit(1); XX} XX XX/* XX * get some symbols form the kernel XX */ XXgetsyms() XX{ XX register i; XX XX if (k_opt) { XX#ifdef ultrix XX (void) nlist(namelist, nl); XX#else /* not ultrix */ XX if (nlist(namelist, nl) == -1) { XX (void) fprintf(stderr, XX "%s: can't get name list from %s\n", XX progname, namelist); XX exit(1); XX } XX#endif /* ultrix */ XX } else { XX#ifdef ultrix XX (void) nlist("/vmunix", nl); XX#else /* not ultrix */ XX#ifdef DYNIX XX if (nlist("/dynix", nl) == -1) XX#else /* not DYNIX */ XX if (nlist("/vmunix", nl) == -1) XX#endif /* DYNIX */ XX { XX (void) fprintf(stderr, XX "%s: can't get name list from %s\n", XX#ifdef DYNIX XX progname, "/dynix"); XX#else /* not DYNIX */ XX progname, "/vmunix"); XX#endif /* DYNIX */ XX exit(1); XX } XX#endif /* ultrix */ XX } XX XX for (i = 0; i < (sizeof(nl)/sizeof(nl[0]))-1; i++) XX if (nl[i].n_value == 0) { XX (void) fprintf(stderr, "%s: can't nlist symbol %s\n", XX progname, nl[i].n_name); XX exit(1); XX } XX XX eseek(kmem, (ls_t)(nl[X_PROC].n_value), 0, "procbase 1"); XX eread(kmem, (char *)&procbase, sizeof(procbase), "procbase 1"); XX eseek(kmem, (ls_t)(nl[X_NPROC].n_value), 0, "nproc"); XX eread(kmem, (char *)&nproc, sizeof(nproc), "nproc"); XX XX#ifndef DYNIX XX Usrptma = (struct pte *)nl[X_USRPTMA].n_value; XX usrpt = (struct pte *)nl[X_USRPT].n_value; /* used by <vmmac.h>*/ XX#endif XX return; XX} XX XX/* XX * read proc table entry "n" into buffer "p" XX */ XXprocslot(n, p) XX int n; XX struct proc *p; XX{ XX if (k_opt) XX eseek(kmem, vtophys((ls_t)(procbase + (long)(n * sizeof(struct proc)))), 0, "proc"); XX else XX eseek(kmem, (ls_t)(procbase + (long)(n * sizeof(struct proc))), 0, "proc"); XX eread(kmem, (char *)p, sizeof(struct proc), "proc"); XX return; XX} XX XX/* XX * When looking at kernel data space through /dev/mem or XX * with a core file, do virtual memory mapping. XX */ XXls_t XXvtophys(vaddr) XX ls_t vaddr; XX{ XX u_int paddr; XX XX#ifdef i386 XX if (vaddr < 8192) XX return vaddr; XX#endif XX paddr = nl[X_SYSMAP].n_value; XX (void) lseek(kmem, (ls_t)paddr, 0); XX (void) read(kmem, (char *)&paddr, sizeof paddr); XX paddr = (int)((int *)paddr + (vaddr / NBPG)); XX (void) lseek(kmem, (ls_t)paddr, 0); XX (void) read(kmem, (char *)&paddr, sizeof paddr); XX#ifndef i386 XX# define PTBITS 0x1ff /* 512 byte pages */ XX#else XX# define PTBITS 0xfff /* 4096 byte pages */ XX#endif XX XX return ((ls_t)(paddr & ~PTBITS) | (vaddr & PTBITS)); XX} XX XX/* XX * get file pointer for socket XX */ XXchar * XXgetsockfp(cba, pfp) XX char *cba; XX struct file **pfp; XX{ XX register char *cp; XX struct file *socktofile(); XX struct inpcb inpcb; XX static char nmbuf[128]; XX struct socket sock; XX struct tcpcb tcpcb; XX long x; XX XX/* XX * Convert PCB address from ASCII to hex. XX */ XX for (cp = cba, x = 0l; *cp; cp++) { XX x <<= 4; XX if (*cp >= '0' && *cp <= '9') XX x += *cp - '0'; XX else if (*cp >= 'a' && *cp <= 'f') XX x += *cp - 'a' + 10; XX else if (*cp >= 'A' && *cp <= 'F') XX x += *cp - 'A' + 10; XX else { XX (void) fprintf(stderr, XX "%s: non-hex address, %s\n", progname, cba); XX return(NULL); XX } XX } XX/* XX * Read PCB and make sure it is in LISTEN or ESTABLISHED state. XX */ XX eseek(kmem, (ls_t)x, 0, "tcpcb"); XX eread(kmem, (char *)&tcpcb, sizeof(tcpcb), "tcpcb"); XX if (tcpcb.t_state < TCPS_LISTEN || tcpcb.t_state > TCPS_ESTABLISHED) { XX (void) fprintf(stderr, XX "%s: PCB %x not in LISTEN to ESTABLISHED state\n", XX progname, x); XX return(NULL); XX } XX if (tcpcb.t_inpcb == (struct inpcb *)0) { XX (void) fprintf(stderr, XX "%s: PCB %x has no INPCB\n", XX progname, x); XX return(NULL); XX } XX/* XX * Read INPCB for PCB and make sure it points back to the PCB. XX */ XX eseek(kmem, (ls_t)tcpcb.t_inpcb, 0, "inpcb"); XX eread(kmem, (char *)&inpcb, sizeof(inpcb), "inpcb"); XX if ((caddr_t)x != inpcb.inp_ppcb) { XX (void) fprintf(stderr, XX "%s: INPCB for PCB %x not linked to it\n", XX progname, x); XX return(NULL); XX } XX/* XX * Read the socket and make sure it points back to the INPCB. XX */ XX eseek(kmem, (ls_t)inpcb.inp_socket, 0, "socket"); XX eread(kmem, (char *)&sock, sizeof(sock), "socket"); XX if (sock.so_pcb != (caddr_t)tcpcb.t_inpcb) { XX (void) fprintf(stderr, XX "%s: socket not linked to INPCB for PCB %x\n", XX progname, x); XX return(NULL); XX } XX/* XX * Find the file structure that is linked to the socket. XX */ XX if ((*pfp = socktofile((caddr_t)inpcb.inp_socket)) == NULL) { XX (void) fprintf(stderr, XX "%s: no file structure for socket of PCB %x\n", XX progname, x); XX return(NULL); XX } XX/* XX * Construct a pseudo file name and return it. XX */ XX (void) sprintf(nmbuf, XX "file %lx of socket %lx of INPCB %lx of PCB %lx", XX (long)*pfp, (long)inpcb.inp_socket, (long)tcpcb.t_inpcb, x); XX return(nmbuf); XX} XX XX/* XX * Convert a socket address to a file address. XX */ XXstruct file * XXsocktofile(s) XX caddr_t s; XX{ XX register struct file *afile; XX char *calloc(); XX register struct file *fp; XX static struct file *ftp; XX static int nfile = -1; XX static struct file *xfile = NULL; XX XX/* XX * Read the size of file table, allocate space XX * for it, and read the file table pointer (once). XX */ XX if (nfile < 0) { XX eseek(kmem, (ls_t)(nl[SNFILE].n_value), 0, "_nfile"); XX eread(kmem, (char *)&nfile, sizeof(nfile), "_nfile"); XX xfile = (struct file *) calloc((unsigned)nfile, sizeof (struct file)); XX eseek(kmem, (ls_t)(nl[SFIL].n_value), 0, "_file"); XX eread(kmem, (char *)&ftp, sizeof(ftp), "_file"); XX } XX/* XX * Read the file table and search for an in-use XX * socket file with a matching data address. XX */ XX eseek(kmem, (ls_t)ftp, 0, "_file"); XX eread(kmem, (char *)xfile, nfile * sizeof(struct file), "_file"); XX for (fp = xfile, afile = ftp; fp < &xfile[nfile]; fp++, afile++) { XX if (fp->f_count && fp->f_type == DTYPE_SOCKET XX && s == fp->f_data) XX return(afile); XX } XX return(NULL); XX} SHAR_EOF if test 24522 -ne "`wc -c ofiles.c`" then echo shar: error transmitting ofiles.c '(should have been 24522 characters)' fi echo shar: extracting ofiles.8l '(5223 characters)' sed 's/^XX//' << \SHAR_EOF > ofiles.8l XX.TH OFILES 8L LOCAL XX.SH NAME XXofiles \- show owner of open file or network connection XX.SH SYNOPSIS XX.B ofiles XX[ XX.B \-d XX] [ XX.B \-k XX.I nlist XX.I core XX] [ XX.B \-n XX] [ XX.B \-p XX] XX.I names XX.SH DESCRIPTION XX.I Ofiles XXdisplays the owner, process identification (PID), type, command and XXthe number of the inode associated with an open instance of a file XXor a network connection. XX.PP XXAn open file may be a regular file, a file system or a directory; XXit is specified by its path name. XXWhen the path name refers to a file system, XX.I ofiles XXwill display the owners of all open instances of files in the system. XX.PP XXAn open network connection is specified by the kernel address of its XXProtocol Control Block (PCB), as displayed by XX.IR netstat (8), XXwhen its XX.B \-A XXoption is specified. XX.SH OPTIONS XX.I Ofiles XXdisplays information about its usage if no options are specified. XX.TP \w'-kXnlistXcore'u+4 XX.BI \-d XXThis option selects verbose, debugging output. XX.TP XX.BI \-k \ nlist\ core XXThis option may be used only on DYNIX hosts. XXIt sets optional name list and core file paths. XX.IP XX.I Nlist XXis the path to the file from which XX.I ofiles XXshould obtain the addresses of kernel symbols, XXinstead of from XX.IR /dynix . XX.IP XX.I Core XXis the path to the file from which XX.I ofiles XXshould obtain the value of kernel symbols, XXinstead of from XX.IR /dev/mem . XX.IP XXThis option is useful for debugging system crash dumps. XX.TP XX.B \-n XXThis option specifies that the XX.I name XXarguments identify network connections by their hexadecimal, Protocol XXControl Block (PCB) addresses. XXPCB addresses can be obtained via the XX.B \-A XXoption of XX.IR netstat (1). XX.IP XXThis option makes it possible to determine the local processes that XXare using network connections in the LISTEN through ESTABLISHED states. XX.TP XX.B \-p XXThis option specifies that XX.I ofiles XXshould print process identifiers only \- e. g., so that the output may XXbe piped to XX.IR kill (1). XX.TP XX.I names XXThese are path names of files, directories and file systems; XXor, if the XX.B \-n XXoption has been specified, network connections, identified by their XXhexadecimal Protocol Control Block (PCB) addresses. XX.SH OUTPUT XX.I Ofiles XXdisplays for each XX.IR name : XX.TP \w'name/linkages'u+4 XX.I name/linkages XXfor file paths, an interpretation of the type of name \- file, directory XXor file system; XXfor network connections, the kernel address linkages, starting with the file XXstructure and proceeding through the socket structure and the Internet XXProtocol Control Block (INPCB) structure to the PCB XX.TP XX.B USER XXthe login name of the user of the process that has XX.I name XXopen XX.TP XX.B PID XXthe identifier of the process that has XX.I name XXopen XX.TP XX.B TYPE XXa file type explanation: XX.RS XX.TP \w'file'u+4 XX.B cwd XXif XX.I name XXis the current working directory of the process XX.TP XX.B file XXif XX.I name XXis being used as a regular file by the process, optionally followed by: XX.RS XX.TP XX.B /s XXif the process has a shared lock on the file XX.TP XX.B /x XXif the process has an exclusive lock on the file XX.RE XX.TP XX.B rdir XXif XX.I name XXis the root directory of the process XX.TP XX.B sock XXif XX.I name XXis a socket XX.RE XX.TP XX.B FD XXthe file descriptor number, local to the process XX.TP XX.B CMD XXthe user command that opened XX.I name XX.TP XX.B INODE XXthe inode number of the file XX.SH EXAMPLES XXThis example shows the use of XX.I ofiles XXto discover the owner of the open, regular file, XX.IR /usr/spool/lpd/lock . XX.PP XX.RS XX.nf XX% ofiles /usr/spool/lpd/lock XX.br XX/usr/spool/lpd/lock XX.br XXUSER PID TYPE FD CMD INODE XX.br XXroot 110 file/x 3 lpd 26683 XX.fi XX.RE XX.PP XXThis example shows the use of XX.IR netstat (1), XX.IR grep (1) XXand XX.I ofiles XXto identify the local endpoint of the ``smtp'' network connection. XXThe first column of output from XX.I netstat XXis the PCB address; it is used as the XX.I name XXargument to XX.IR ofiles , XXalong with the XX.B \-n XXoption. XX.PP XX.RS XX.nf XX% netstat -aA | grep smtp XX.br XX80f6770c tcp 0 0 *.smtp *.* LISTEN XX.br XX% ofiles -n 80f6770c XX.br XXfile 80102b64 of socket 80f6758c of INPCB 80f6780c of PCB 80f6770c XX.br XXUSER PID TYPE FD CMD XX.br XXroot 105 sock 5 sendmail XX.fi XX.RE XX.SH DIAGNOSTICS XXErrors are identified with messages on the standard error file. XX.PP XX.I Ofiles XXreturns a one (1) if any error was detected, including the failure to XXlocate any XX.IR names . XXIt returns a zero (0) if no errors were detected and if it was able to XXdisplay owner information about all the specified XX.IR names . XX.SH BUGS XX.I Ofiles XXcan't identify SunOS 4.0 stream files, so it doesn't follow their file XXstructure pointers correctly when reading their inodes. XXThat results in the display of erroneous inode numbers for stream files. XX.PP XXThe XX.B \-n XXoption limits its search to network connections in the LISTEN through XXESTABLISHED states. XX.PP XXSince XX.I ofiles XXreads kernel memory in its search for open files and network connections, XXrapid changes in kernel memory may produce unsatisfactory results. XX.SH AUTHORS XXC. Spencer is the original author. XXMichael Ditto, Tom Dunigan, Alexander Dupuy, Gary Nebbett and Richard Tobin XXcontributed. XX.PP XXMichael Spitzer, Ray Moody, and Vik Lall of the Purdue University Computing XXCenter converted the program to a variety of UNIX environments. XX.PP XXVic Abell of the Purdue University Computing Center added the XX.B \-n XXoption. XX.SH SEE ALSO XXinode(5), XXmount(1), XXkill(1), XXtcp(4). SHAR_EOF if test 5223 -ne "`wc -c ofiles.8l`" then echo shar: error transmitting ofiles.8l '(should have been 5223 characters)' fi # End of shell archive exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.