Needed: ofiles source for Pyramid
Romain Kang
romain at pyramid.pyramid.com
Thu Feb 28 22:21:54 AEST 1991
/etc/fuser should be sufficient for most applications where you'd want to
use ofiles, but...
This should run under OSx 5.0 or later. 4.4 needs a getuser() variant
more like stock BSD.
/* ofiles.c
*
* ofiles [-d ] [-k nlist core] [-n] [-p] args
*
* Show owner of open file or network connection.
*
* Reports owner, process ID, access type, command and inode number.
*
* -d select verbose debugging output
*
* -k nlist core specifies alternative name list and core files
* (DYNIX only)
*
* -n interpret names as network connection, hexadecimal
* Protocol Control Block (PCB) addresses
*
* -p gives brief (pids only) report
*
* names file names, file system names or network connection
* PCB addresses
*
* Stat each file or file system argument and scan the process table,
* looking for a match in the associated user structure's file lists.
*
* Follow each PCB arg to the Internet Protocol Control Block (INPCB),
* thence to the socket; then scan the file table to find the file
* structure address associated with the socket; finally, scan the
* process table, looking for a nacth in the associated user structure's
* file lists.
*
* Doesn't handlle remote NFS files.
*/
/*
* Authors:
*
* The orignal author is:
*
* C. Spencer
*
* Contributors include:
*
* Michael Ditto
* Tom Dunigan
* Alexander Dupuy
* Greg Nebbett
* Richard Tobin
*
* From the Purdue University Computing Center:
*
* Mike Spitzer converted to 4.3BSD, DYNIX 3.0.1[24]
* Ray Moody SunOS 4.0 and ULTRIX 2.2
* Vik Lall
*
* Vic Abell added socket option and removed lint
*
*/
#ifndef lint
static char rcsid[]="$Header: ofiles.c,v 1.8.1.2 91/02/28 03:01:30 romain Exp $";
#endif /* lint */
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#ifdef DYNIX
#define KERNEL
#include <sys/file.h>
#include <sys/vnode.h>
#include <sys/inode.h>
#undef KERNEL
#else
#define KERNEL
#include <sys/file.h>
#if !defined(sun) && !defined(pyr)
#include <sys/inode.h>
#endif
#undef KERNEL
#endif
#ifdef pyr
#else
#include <machine/pte.h>
#if !defined(ultrix) && !defined(sun)
#include <machine/machparam.h>
#endif
#endif
#include <sys/proc.h>
#include <nlist.h>
#include <sys/stat.h>
#include <pwd.h>
#include <fstab.h>
#include <sys/vmmac.h>
#include <stdio.h>
#ifdef sun
#include <kvm.h>
kvm_t *kd;
#endif
#if defined(sun) || defined(pyr)
#include <sys/vnode.h>
#include <ufs/inode.h>
struct snode {
struct snode *s_next;
struct vnode s_vnode;
struct vnode *s_realvp;
struct vnode *s_bdevvp;
u_short s_flag;
dev_t s_dev;
};
#endif
#ifdef ultrix
#include <sys/gnode.h>
#include <sys/gnode_common.h>
#include <machine/param.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#define CDIR 01
#define OFILE 02
#define RDIR 04
#define SHFILE 010
#define EXFILE 020
#define SOCKET 040
char *namelist;
char *corefile;
int k_opt = 0;
int n_opt = 0;
#ifdef ultrix
#define ls_t long
#else
#define ls_t off_t
#endif
#ifdef sun
char *sprintf();
#endif
ls_t lseek(), vtophys();
void eread(), eseek();
#ifdef ultrix
void exit(), nlist(), perror();
#endif
int nproc; /* number of entries in proc table */
int mem; /* fd for /dev/mem */
int kmem;
int swap; /* fd for /dev/swap */
long procbase;
int ppid = -1; /* previously display PID */
int dirinode; /* directory (CDIR or RDIR) inode */
int opninode; /* save inode of open file */
int pids_only = 0; /* if non-zero, only output process ids */
char *progname;
struct nlist nl[] = {
#define X_PROC 0
{ "_proc" },
#define X_NPROC 1
{"_nproc"},
#define X_USRPTMA 2
{"_Usrptmap"},
#define X_USRPT 3
{"_usrpt"},
#define X_SYSMAP 4
{"_Sysmap"},
#define SFIL 5
{ "_file" },
#define SNFILE 6
{ "_nfile" },
{ "" },
};
#ifndef DYNIX
struct pte *usrpt, *Usrptma;
#endif
int debug;
main(argc, argv)
int argc;
char *argv[];
{
#ifdef ultrix
struct gnode *i, *getinode();
#else
struct inode *i, *getinode();
#endif
#ifdef pyr
int fdspace;
struct file **fd_array;
#endif
struct stat s;
struct user *u, *getuser();
struct proc p;
register int filen, flags, procn;
register char *filename, *fsname;
struct fstab *fs, *getfsfile(), *getfsspec();
char *getsockfp(), *rindex();
struct file *fp;
int ax, err, findf, nmct;
char *ap;
int exitval = 0;
#ifdef lint
/*
* The following code satisfies lint for KERNEL symbols.
* This program is lint-free under 4.3BSD, DYNIX 3.0.1[24], SunOS 4.0
* and ULTRIX 2.2, using the lint libraries of the systems at the
* Purdue University Computing Center.
*/
#if !defined(ultrix) && !defined(DYNIX) && !defined(sun)
long lintlong;
#endif
#ifdef ultrix
struct nch *lintnch;
float lintfloat;
#endif
#if !defined(DYNIX)
file = fileNFILE = NULL;
fp = file;
fp = fileNFILE;
nfile = 0;
filen = nfile;
#endif
#if !defined(ultrix) && !defined(DYNIX) && !defined(sun)
inode = inodeNINODE = rootdir = NULL;
i = inode;
i = inodeNINODE;
i = rootdir;
ninode = 0;
nextinodeid = 0l;
lintlong = nextinodeid;
nextinodeid = lintlong;
filen = ninode;
#endif
#ifdef sun
tcp_ttl = 0;
filen = tcp_ttl;
#endif
#ifdef ultrix
nch = NULL;
lintnch = nch;
nch = lintnch;
nchsize = 0;
filen = nchsize;
tcp_alpha = tcp_beta = 0.0;
lintfloat = tcp_alpha;
lintfloat = tcp_beta;
tcp_alpha = lintfloat;
#endif
#endif /* lint */
if ((progname = rindex(argv[0], '/')))
progname++;
else
progname = argv[0];
if (argc == 1) {
usage:
#ifdef DYNIX
(void) fprintf(stderr,
"usage: %s [-d ] [-k nlist core] [-n] [-p] names\n",
progname);
#else
(void) fprintf(stderr,
"usage: %s [-d ] [-n] [-p] names\n", progname);
#endif
(void) fprintf(stderr, "\t-d = select verbose debugging output\n");
#ifdef DYNIX
(void) fprintf(stderr,
"\t-k = use specified nlist and core files\n");
#endif
(void) fprintf(stderr,
"\t-n = interpret names as network connection, hexadecimal,\n");
(void) fprintf(stderr,
"\t Protocol Control Block (PCB) addresses, as supplied\n");
(void) fprintf(stderr,
"\t by netstat's -A option\n");
(void) fprintf(stderr, "\t-p = print only process IDs\n");
(void) fprintf(stderr,
"\tnames = file names or PCB addresses\n");
exit(exitval);
}
/* check for switches */
for (err = 0, ax = 1; ax < argc; ax++) {
ap = argv[ax];
if (*ap++ != '-')
break;
while (*ap) {
switch (*ap++) {
case 'd':
debug = 1;
break;
#ifdef DYNIX
case 'k':
if ((ax + 2) >= argc) {
(void) fprintf(stderr,
"%s: no nlist/core after -k\n",
progname);
err++;
} else {
namelist = argv[++ax];
corefile = argv[++ax];
k_opt = 1;
continue;
}
break;
#endif
case 'n':
n_opt++;
break;
case 'p':
pids_only = 1;
break;
default:
(void) fprintf(stderr,
"%s: unknown switch - %c\n",
progname, *(ap - 1));
err++;
}
}
}
if (ax >= argc) {
(void) fprintf(stderr, "%s: no names specified\n", progname);
err++;
}
if (err) {
exitval = 1;
goto usage;
}
#ifdef sun
if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY)) == 0) {
(void) fprintf(stderr, "%s: can't access memory: ",
progname);
perror ("");
exit(1);
}
#endif
if ((mem = open("/dev/mem", 0)) < 0) {
(void) fprintf(stderr, "%s: /dev/mem: ", progname);
perror("");
exit(1);
}
if (k_opt) {
if ((kmem = open(corefile, 0)) < 0) {
(void) fprintf(stderr, "%s: %s: ",
progname, corefile);
perror("");
exit(1);
}
} else {
if ((kmem = open("/dev/kmem", 0)) < 0) {
(void) fprintf(stderr, "%s: /dev/kmem: ", progname);
perror("");
exit(1);
}
}
if (!k_opt)
#ifndef pyr
if ((swap = open("/dev/drum", 0)) < 0) {
(void) fprintf(stderr, "%s: /dev/drum: ", progname);
perror("");
exit(1);
}
#endif
getsyms();
for (err = 0, nmct = argc - ax; ax < argc; ax++) {
/* if -n, then arg is a PCB */
if (n_opt) {
if ((filename = getsockfp(argv[ax], &fp)) == NULL) {
err++;
continue;
}
fsname = "";
} else {
/* assume arg is a filesystem */
if ((fs = getfsfile(argv[ax])) != NULL) {
fsname = argv[ax];
if (strcmp(".", argv[ax]) == 0)
filename = argv[ax];
else
filename = fs->fs_spec;
/* maybe it's the device name for a filesystem */
} else if ((fs = getfsspec(argv[ax])) != NULL) {
filename = argv[ax];
fsname = fs->fs_file;
/* probably a regular file */
} else {
filename = argv[ax];
fsname = "";
}
if (stat(filename, &s)) {
(void) fprintf(stderr, "%s: can't stat %s: ",
progname, filename);
perror("");
err++;
continue;
}
if (debug)
(void) printf(
"stat dev %x ino %d mode %x rdev %x\n",
s.st_dev, s.st_ino, s.st_mode,
s.st_rdev);
}
if (! pids_only) {
(void) printf("%s\t%s", filename, fsname);
if (!n_opt) {
if ((s.st_mode & S_IFMT) == S_IFDIR)
(void) printf("(directory)");
}
(void) printf("\n%-8.8s %5s %-6.6s FD %-14.14s",
"USER", "PID", "TYPE", "CMD");
if (!n_opt)
(void) printf(" INODE");
(void) printf("\n");
}
for (findf = procn = 0; procn < nproc; procn++) {
procslot(procn, &p);
flags = 0;
if (p.p_stat == 0 || p.p_stat == SZOMB)
continue;
#ifdef sun
u = kvm_getu(kd, &p);
#else
u = getuser(&p);
#endif
if ( u == (struct user *)NULL)
continue;
if (debug)
(void) printf("pid %d uid %d cmd %s\n", p.p_pid,
p.p_uid, u->u_comm);
if (!n_opt) {
i = getinode(u->u_rdir, "rdir");
if (check(&s, i)) {
dirinode = s.st_ino;
gotone(u, &p, -1, RDIR);
findf++;
}
i = getinode(u->u_cdir, "cdir");
if (check(&s, i)) {
dirinode = s.st_ino;
gotone(u, &p, -1, CDIR);
findf++;
}
}
#ifdef pyr
if (u->u_fdheap) {
fdspace = sizeof(caddr_t) * u->u_rlimit[RLIMIT_FDMAX].rlim_cur;
fd_array = (struct file **)malloc(fdspace);
eseek(kmem, (ls_t)u->u_ofile, 0, "u_ofile");
eread(kmem, (char *)fd_array, fdspace, "u_ofile");
}
else
fd_array = u->u_ofile_arr;
for (filen = 0; filen < u->u_maxofile; filen++)
#else
#ifdef DYNIX
for (filen = 0; filen < u->u_nofile; filen++)
#else
for (filen = 0; filen < NOFILE; filen++)
#endif
#endif
{
struct file f;
flags = 0;
if (n_opt) {
#ifdef DYNIX
if (u->u_lofile[filen].of_file != fp)
#else
#ifdef pyr
if (fd_array[filen] != fp)
#else
if (u->u_ofile[filen] != fp)
#endif pyr
#endif
continue;
} else {
#ifdef DYNIX
if (u->u_lofile[filen].of_file == NULL)
continue;
#else
#ifdef pyr
if (fd_array[filen] == NULL)
continue;
#else
if (u->u_ofile[filen] == NULL)
continue;
#endif /* pyr */
#endif
}
if (k_opt)
#ifdef DYNIX
eseek(kmem, vtophys((ls_t)u->u_lofile[filen].of_file), 0, "file");
#else
eseek(kmem, vtophys((ls_t)u->u_ofile[filen]), 0, "file");
#endif
else
#ifdef DYNIX
eseek(kmem, (ls_t)u->u_lofile[filen].of_file, 0, "file");
#else
#ifdef pyr
eseek(kmem, (ls_t)fd_array[filen], 0, "file");
#else
eseek(kmem, (ls_t)u->u_ofile[filen], 0, "file");
#endif /* pyr */
#endif
eread(kmem, (char *)&f, sizeof(f), "file");
if (f.f_count > 0) {
if (n_opt && f.f_type == DTYPE_SOCKET) {
gotone(u, &p, filen, SOCKET);
findf++;
continue;
}
#if defined(DTYPE_VNODE)
if (f.f_type != DTYPE_VNODE)
#else
if (f.f_type != DTYPE_INODE)
#endif
continue;
#if defined(DTYPE_VNODE)
i = getinode((struct vnode *)f.f_data,
"ofile");
#else
#ifdef ultrix
i = getinode((struct gnode *)f.f_data,
"ofile");
#else
i = getinode((struct inode *)f.f_data,
"ofile");
#endif
#endif
if (check(&s, i)) {
#if !defined(ultrix)
opninode = i->i_number;
#else
opninode = (int)i->g_req.gr_number;
#endif
flags |= OFILE;
if (f.f_flag & FEXLOCK) {
flags |= EXFILE;
}
if (f.f_flag & FSHLOCK) {
flags |= SHFILE;
}
gotone(u, &p, filen, flags);
findf++;
}
}
}
#ifdef pyr
if (u->u_fdheap)
free(fd_array);
#endif
}
if (findf)
nmct--;
if (! pids_only) {
(void) printf("\n");
(void) fflush(stdout);
}
}
if (pids_only && ppid != -1) {
(void) printf("\n");
(void) fflush(stdout);
}
exitval = (err || nmct) ? 1 : 0;
exit(exitval);
}
/*
* print the name of the user owning process "p" and the pid of that process
*/
gotone(u, p, fd, f)
struct user *u;
struct proc *p;
int fd;
int f;
{
char *ty, tybuf[8], *strcat(), *strcpy();
struct passwd *getpwuid();
register struct passwd *pw;
/* only print pids and return */
if (pids_only) {
if (ppid != p->p_pid) {
if (ppid != -1)
(void) printf(" ");
(void) printf("%d", p->p_pid);
(void) fflush(stdout);
ppid = p->p_pid;
}
return;
}
pw = getpwuid((int)p->p_uid);
if (pw)
(void) printf("%-8.8s ", pw->pw_name );
else
(void) printf("%-8d ", p->p_uid);
(void) printf("%5d ", p->p_pid);
if (f & OFILE) {
(void) strcpy(tybuf, "file");
ty = tybuf;
if (f & SHFILE)
(void) strcat(ty, "/s");
else if (f & EXFILE)
(void) strcat(ty, "/x");
} else if (f & CDIR)
ty = "cwd";
else if (f & RDIR)
ty = "rdir";
else if (f & SOCKET)
ty = "sock";
else
ty = "";
(void) printf("%-6.6s ", ty);
if (fd >= 0)
(void) printf("%2d ", fd);
else
(void) printf(" ");
(void) printf("%-14.14s", u->u_comm);
if (f & OFILE)
(void) printf(" %5d", opninode);
else if (f & (CDIR|RDIR))
(void) printf(" %5d", dirinode);
(void) printf("\n");
return;
}
/*
* is inode "i" on device "s"? returns TRUE or FALSE
*/
check(s, i)
struct stat *s;
#ifdef ultrix
struct gnode *i;
#else
struct inode *i;
#endif
{
if (s == (struct stat *)NULL)
return 0;
#ifdef ultrix
if (i == (struct gnode *)NULL)
return 0;
if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->g_dev)
return 1;
else if ((s->st_dev == i->g_dev) && (s->st_ino == i->g_req.gr_number))
return 1;
#else
if (i == (struct inode *)NULL) return 0;
if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->i_dev)
return 1;
else if ((s->st_dev == i->i_dev) && (s->st_ino == i->i_number))
return 1;
#endif
#ifdef sun
else if (s->st_rdev == i->i_dev && i->i_number == 0)
return 1;
#endif
else return 0;
}
/*
* getinode - read an inode from from mem at address "addr"
* return pointer to inode struct.
*/
#if defined(DTYPE_VNODE)
struct inode *
getinode(ip, s)
struct vnode *ip;
char *s;
{
static struct inode i;
static struct vnode v;
#if defined(sun) || defined(pyr)
struct snode sn;
#endif
if (ip == NULL)
return(NULL);
if (k_opt)
eseek(kmem, vtophys((ls_t)ip), 0, "vnode");
else
eseek(kmem, (ls_t)ip, 0, "vnode");
eread(kmem, (char *)&v, sizeof(v), "vnode");
if (debug)
(void) printf("vnode %s at %x %x dev=%x vtype=%d inode@%x\n",
s, ip, v.v_flag, v.v_rdev, v.v_type, v.v_data);
if (k_opt)
eseek(kmem, vtophys((ls_t)v.v_data), 0, "inode");
else
eseek(kmem, (ls_t)v.v_data, 0, "inode");
#if defined(sun) || defined(pyr)
#ifdef pyr
if (v.v_type == VBLK || v.v_type == VCHR)
#else
if (v.v_type == VBLK || v.v_type == VCHR || v.v_type == VFIFO)
#endif
{
eread(kmem, (char *)&sn, sizeof(sn), "snode");
if (debug)
(void) printf(
"snode %s at %x %x dev=%x realvp=%x bdevvp=%x\n",
s, ip, sn.s_vnode.v_type, sn.s_dev,
sn.s_realvp, sn.s_bdevvp);
if (sn.s_realvp || sn.s_bdevvp) {
eseek(kmem,
(sn.s_realvp) ? (ls_t)sn.s_realvp
: (ls_t)sn.s_bdevvp,
0, "rvnode");
eread(kmem, (char *)&v, sizeof(v), "rvnode");
eseek(kmem, (ls_t)v.v_data, 0, "rinode");
}
}
#endif
eread(kmem, (char *)&i, sizeof(i), "inode");
if (debug)
(void) printf("inode %s at %x %x dev=%x inode=%d vtype=%x\n",
s, v.v_data, i.i_flag, i.i_dev, i.i_number,
i.i_vnode.v_type);
return &i;
}
#else
/* ARGSUSED */
#ifdef ultrix
struct gnode *
getinode(ip, s)
struct gnode *ip;
#else
struct inode *
getinode(ip, s)
struct inode *ip;
#endif
char *s;
{
#if defined(ultrix)
static struct gnode i;
#else
static struct inode i;
#endif
eseek(kmem, (ls_t)ip, 0, "inode");
eread(kmem, (char *)&i, sizeof(i), "inode");
return &i;
}
#endif
#if !defined(sun)
/*
* get user page for proc "p" from core or swap
* return pointer to user struct
*/
#ifdef DYNIX
struct user *
getuser(p)
struct proc *p;
{
int btr;
ls_t sp;
static struct user *u = NULL;
char *valloc();
if (u == NULL) {
if ((u = (struct user *) valloc(ctob(UPAGES))) == NULL) {
(void) fprintf(stderr,
"%s: can't allocate space for user structure\n", progname);
exit(1);
}
}
btr = ctob(UPAGES);
if ((p->p_flag & SLOAD) == 0) {
if (k_opt)
return (struct user *)NULL;
sp = (ls_t) dtob(p->p_swaddr);
if (lseek(swap, sp, 0) != sp) {
if (debug) {
(void) fprintf(stderr,
"%s: error seeking to swap for %d: ",
progname, p->p_pid);
perror("");
}
return (struct user *)NULL;
}
if (read(swap, (char*)u, btr) != btr) {
if (debug) {
(void) fprintf(stderr,
"%s: error reading swap for %d: ",
progname, p->p_pid);
perror("");
}
return (struct user *)NULL;
}
if (debug)
(void) printf("read swap\n");
} else {
if (k_opt)
(void) lseek(kmem, vtophys((ls_t)p->p_uarea), L_SET);
else
(void) lseek(kmem, (ls_t)p->p_uarea, L_SET);
if (read(kmem, (char *)u, btr) != btr)
return (struct user *)NULL;
}
return u;
}
#else
#ifdef pyr
struct user *
getuser(p)
struct proc *p;
{
static struct user *u = NULL;
char *valloc();
if (u == NULL) {
if ((u = (struct user *) valloc(ptob(UPAGES))) == NULL) {
(void) fprintf(stderr,
"%s: can't allocate space for user structure\n", progname);
exit(1);
}
}
if (readublk(p->p_pid, u) == -1)
return (struct user *)NULL;
else
return u;
}
#else
struct user *
getuser(p)
struct proc *p;
{
struct pte *ptep, apte;
struct pte mypgtbl[NBPG/sizeof(struct pte)];
int upage;
char *up;
static struct user user;
/* easy way */
if ((p->p_flag & SLOAD) == 0) {
if (k_opt)
return (struct user *)NULL;
(void) lseek(swap, (ls_t)dtob(p->p_swaddr), 0);
if (read(swap, (char *)&user, sizeof(struct user))==0) {
(void) fprintf(stderr,
"%s: can't get swapped user page\n",
progname);
return (struct user *)NULL;
}
if (debug)
(void) printf("read swap\n");
} else { /* boo */
ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1];
/* get the page table for the user page */
(void) lseek(kmem, (ls_t)ptep, 0);
if (read(kmem, (char *)&apte, sizeof(apte)) == 0) {
(void) fprintf(stderr,
"%s: can't get user page table\n",
progname);
return (struct user *)NULL;
}
/* now get this user's page table */
eseek(mem, (ls_t)ctob(apte.pg_pfnum) ,0, "page tbl");
if (read(mem, (char *)mypgtbl, sizeof(mypgtbl)) == 0) {
(void) fprintf(stderr,
"%s: can't get mypgtbl.\n", progname);
return (struct user *)NULL;
}
/* now collect various pages of u area */
for (upage = 0, up = (char *)&user; upage < sizeof(struct user)/NBPG; upage++) {
eseek(mem, (ls_t)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum), 0, "u page");
if (read(mem, up, NBPG) == 0) {
(void) fprintf(stderr,
"%s: can't get page %d of user area.\n",
progname, upage);
return(NULL);
}
up += NBPG;
}
}
return &user;
}
#endif /* pyr */
#endif
#endif
/*
* read with error checking
*/
void
eread(fd, p, size, s)
int fd;
char *p;
int size;
char *s;
{
char buf[100];
if (read(fd, p, size) != size) {
if (!k_opt) {
(void) fprintf(stderr, "%s: eread ", progname);
perror("");
}
(void) sprintf(buf, "read error for %s\n", s);
error(buf);
}
}
/*
* seek with error checking
*/
void
eseek(fd, off, whence, s)
int fd;
ls_t off;
int whence;
char *s;
{
ls_t ret;
char buf[100];
#ifdef pyr
if (( ret = lseek(fd, off, whence)) == -1)
#else
if (( ret = lseek(fd, off, whence)) != off)
#endif
{
(void) sprintf(buf, "seek for %s failed, wanted %o, got %o.\n",
s, off, ret);
error(buf);
}
}
/*
* print mesg "s", don't exit if we are processing a core,
* so that corrupt entries don't prevent further uncorrupted
* entries from showing up.
*/
error(s)
char *s;
{
if (s && !k_opt)
(void) fprintf(stderr, "%s: %s", progname, s);
if (!k_opt)
exit(1);
}
/*
* get some symbols form the kernel
*/
getsyms()
{
register i;
if (k_opt) {
#ifdef ultrix
(void) nlist(namelist, nl);
#else /* not ultrix */
if (nlist(namelist, nl) == -1) {
(void) fprintf(stderr,
"%s: can't get name list from %s\n",
progname, namelist);
exit(1);
}
#endif /* ultrix */
} else {
#ifdef ultrix
(void) nlist("/vmunix", nl);
#else /* not ultrix */
#ifdef DYNIX
if (nlist("/dynix", nl) == -1)
#else /* not DYNIX */
if (nlist("/vmunix", nl) == -1)
#endif /* DYNIX */
{
(void) fprintf(stderr,
"%s: can't get name list from %s\n",
#ifdef DYNIX
progname, "/dynix");
#else /* not DYNIX */
progname, "/vmunix");
#endif /* DYNIX */
exit(1);
}
#endif /* ultrix */
}
for (i = 0; i < (sizeof(nl)/sizeof(nl[0]))-1; i++)
if (nl[i].n_value == 0) {
(void) fprintf(stderr, "%s: can't nlist symbol %s\n",
progname, nl[i].n_name);
exit(1);
}
eseek(kmem, (ls_t)(nl[X_PROC].n_value), 0, "procbase 1");
eread(kmem, (char *)&procbase, sizeof(procbase), "procbase 1");
eseek(kmem, (ls_t)(nl[X_NPROC].n_value), 0, "nproc");
eread(kmem, (char *)&nproc, sizeof(nproc), "nproc");
#ifndef DYNIX
Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
usrpt = (struct pte *)nl[X_USRPT].n_value; /* used by <vmmac.h>*/
#endif
return;
}
/*
* read proc table entry "n" into buffer "p"
*/
procslot(n, p)
int n;
struct proc *p;
{
if (k_opt)
eseek(kmem, vtophys((ls_t)(procbase + (long)(n * sizeof(struct proc)))), 0, "proc");
else
eseek(kmem, (ls_t)(procbase + (long)(n * sizeof(struct proc))), 0, "proc");
eread(kmem, (char *)p, sizeof(struct proc), "proc");
return;
}
/*
* When looking at kernel data space through /dev/mem or
* with a core file, do virtual memory mapping.
*/
ls_t
vtophys(vaddr)
ls_t vaddr;
{
u_int paddr;
#ifdef i386
if (vaddr < 8192)
return vaddr;
#endif
paddr = nl[X_SYSMAP].n_value;
(void) lseek(kmem, (ls_t)paddr, 0);
(void) read(kmem, (char *)&paddr, sizeof paddr);
paddr = (int)((int *)paddr + (vaddr / NBPG));
(void) lseek(kmem, (ls_t)paddr, 0);
(void) read(kmem, (char *)&paddr, sizeof paddr);
#ifndef i386
# define PTBITS 0x1ff /* 512 byte pages */
#else
# define PTBITS 0xfff /* 4096 byte pages */
#endif
return ((ls_t)(paddr & ~PTBITS) | (vaddr & PTBITS));
}
/*
* get file pointer for socket
*/
char *
getsockfp(cba, pfp)
char *cba;
struct file **pfp;
{
register char *cp;
struct file *socktofile();
struct inpcb inpcb;
static char nmbuf[128];
struct socket sock;
struct tcpcb tcpcb;
long x;
/*
* Convert PCB address from ASCII to hex.
*/
for (cp = cba, x = 0l; *cp; cp++) {
x <<= 4;
if (*cp >= '0' && *cp <= '9')
x += *cp - '0';
else if (*cp >= 'a' && *cp <= 'f')
x += *cp - 'a' + 10;
else if (*cp >= 'A' && *cp <= 'F')
x += *cp - 'A' + 10;
else {
(void) fprintf(stderr,
"%s: non-hex address, %s\n", progname, cba);
return(NULL);
}
}
/*
* Read PCB and make sure it is in LISTEN or ESTABLISHED state.
*/
eseek(kmem, (ls_t)x, 0, "tcpcb");
eread(kmem, (char *)&tcpcb, sizeof(tcpcb), "tcpcb");
if (tcpcb.t_state < TCPS_LISTEN || tcpcb.t_state > TCPS_ESTABLISHED) {
(void) fprintf(stderr,
"%s: PCB %x not in LISTEN to ESTABLISHED state\n",
progname, x);
return(NULL);
}
if (tcpcb.t_inpcb == (struct inpcb *)0) {
(void) fprintf(stderr,
"%s: PCB %x has no INPCB\n",
progname, x);
return(NULL);
}
/*
* Read INPCB for PCB and make sure it points back to the PCB.
*/
eseek(kmem, (ls_t)tcpcb.t_inpcb, 0, "inpcb");
eread(kmem, (char *)&inpcb, sizeof(inpcb), "inpcb");
if ((caddr_t)x != inpcb.inp_ppcb) {
(void) fprintf(stderr,
"%s: INPCB for PCB %x not linked to it\n",
progname, x);
return(NULL);
}
/*
* Read the socket and make sure it points back to the INPCB.
*/
eseek(kmem, (ls_t)inpcb.inp_socket, 0, "socket");
eread(kmem, (char *)&sock, sizeof(sock), "socket");
if (sock.so_pcb != (caddr_t)tcpcb.t_inpcb) {
(void) fprintf(stderr,
"%s: socket not linked to INPCB for PCB %x\n",
progname, x);
return(NULL);
}
/*
* Find the file structure that is linked to the socket.
*/
if ((*pfp = socktofile((caddr_t)inpcb.inp_socket)) == NULL) {
(void) fprintf(stderr,
"%s: no file structure for socket of PCB %x\n",
progname, x);
return(NULL);
}
/*
* Construct a pseudo file name and return it.
*/
(void) sprintf(nmbuf,
"file %lx of socket %lx of INPCB %lx of PCB %lx",
(long)*pfp, (long)inpcb.inp_socket, (long)tcpcb.t_inpcb, x);
return(nmbuf);
}
/*
* Convert a socket address to a file address.
*/
struct file *
socktofile(s)
caddr_t s;
{
register struct file *afile;
char *calloc();
register struct file *fp;
static struct file *ftp;
static int nfile = -1;
static struct file *xfile = NULL;
/*
* Read the size of file table, allocate space
* for it, and read the file table pointer (once).
*/
if (nfile < 0) {
eseek(kmem, (ls_t)(nl[SNFILE].n_value), 0, "_nfile");
eread(kmem, (char *)&nfile, sizeof(nfile), "_nfile");
xfile = (struct file *) calloc((unsigned)nfile, sizeof (struct file));
eseek(kmem, (ls_t)(nl[SFIL].n_value), 0, "_file");
eread(kmem, (char *)&ftp, sizeof(ftp), "_file");
}
/*
* Read the file table and search for an in-use
* socket file with a matching data address.
*/
eseek(kmem, (ls_t)ftp, 0, "_file");
eread(kmem, (char *)xfile, nfile * sizeof(struct file), "_file");
for (fp = xfile, afile = ftp; fp < &xfile[nfile]; fp++, afile++) {
if (fp->f_count && fp->f_type == DTYPE_SOCKET
&& s == fp->f_data)
return(afile);
}
return(NULL);
}
More information about the Comp.sys.pyramid
mailing list