home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
unix
/
volume18
/
ofiles
< prev
next >
Wrap
Text File
|
1989-10-15
|
37KB
|
1,534 lines
Article 315 of comp.sources.unix:
Path: mentor.cc.purdue.edu!purdue!mailrus!bbn!bbn.com!rsalz
From: rsalz@uunet.uu.net (Rich Salz)
Newsgroups: comp.sources.unix
Subject: v18i056: Find who has files open on BSD, Sun, etc.
Message-ID: <1604@fig.bbn.com>
Date: 22 Mar 89 23:06:51 GMT
Lines: 1521
Approved: rsalz@uunet.UU.NET
Submitted-by: abe@mace.cc.purdue.edu (Vic Abell)
Posting-number: Volume 18, Issue 56
Archive-name: ofiles
[ Just the thing to see who's preventing you from unmounting that disk...
--r$ ]
Show owner of open file or network connection. Reports owner, process ID,
access type, command and inode number. The update looks up the owner of a
network connection from its Protocol Control Block address (netstat -A).
The program also underwent a general cleanup and lint was removed. The
man page was redone. Ofiles compiles and runs on 4.3BSD, DYNIX 3.0.12
(Balance) and 3.0.14 (Symmetry), SunOS 4.0 and ULTRIX 2.2.
Vic Abell, Purdue University Computing Center, abe@mace.cc.purdue.edu
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# README
# Makefile
# ofiles.c
# ofiles.8l
# 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 '(24404 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.5 89/01/26 16:20:11 vik Exp $";
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 "/usr/src/sys/specfs/snode.h"
XX#include <ufs/inode.h>
XX#include <kvm.h>
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 24404 -ne "`wc -c ofiles.c`"
then
echo shar: error transmitting ofiles.c '(should have been 24404 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.