home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume25
/
ofiles2
/
ofiles.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-19
|
35KB
|
1,628 lines
/* ofiles.c
*
* ofiles [-D ] [-k nlist core] [-n] [-p] [-f|d|m] 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
*
* -i print inode number (ommitted by default)
*
* -m force argument to be considered as a mount point
*
* -f force argument to be considered as a regular file
*
* -d force argument to be considered as a device
*
* 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.
*
* Now handles 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
*
* From INRIA Rocquencourt (France)
* Robert Ehrlich completely revisited in order to:
* - make it work on DECSTATIONs 3100, Pyramid
* OSX, Sony NewsOS 3.5 4.0 risc 68k
* - make it work on pre 4.0 SunOS (yes,
* my workstation runs 3.5 !)
* - find executable text files, mapped files
* under SunOS 4.0
* - make it work on remote NFS file-systems
* - simplify
*/
#ifndef lint
static char rcsid[]="$Header: /usr/src/local/etc/ofiles/RCS/ofiles.c,v 1.8 89/03/21 12:29:30 abe Exp Locker: abe $";
#endif /* lint */
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/signal.h>
#if ! BSD || BSD < 43
#include <sys/time.h>
#endif
#include <sys/user.h>
#ifdef sun
#if ! defined _user_h && ! defined _sys_user_h
#define SunOS 3
#else
#define SunOS 4
#ifdef _sys_user_h
#define SunOSrel 1
#else
define SunOSrel 0
#endif /* _sys_user_h */
#endif /* _user_h */
#endif /* sun */
#ifdef sequent
#define DYNIX
#endif
#if defined DYNIX || defined sun || defined pyr || defined sony
#define NFS
#endif
#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>
#ifndef NFS
#include <sys/inode.h>
#include <sys/mount.h>
#undef KERNEL
#else
#undef KERNEL
#include <sys/vfs.h>
#include <rpc/types.h>
#include <sys/vnode.h>
#include <ufs/inode.h>
#include <nfs/nfs.h>
#include <nfs/rnode.h>
#include <ufs/mount.h>
#endif
#endif
#include <sys/stat.h>
#ifndef pyr
#include <machine/pte.h>
#else
#include <sys/pte.h>
#include <sys/immu.h>
#endif pyr
#if !defined(ultrix) && !defined(sun) && ! defined DYNIX && ! defined pyr
#include <machine/machparam.h>
#endif
#include <sys/proc.h>
#include <nlist.h>
#ifndef O_NDELAY
#include <sys/fcntl.h>
#endif
#include <pwd.h>
#include <fstab.h>
#include <sys/vmmac.h>
#include <stdio.h>
#ifdef NFS
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 NFS
#if defined sun && SunOS >= 4
#include <kvm.h>
kvm_t *kd;
#endif
#ifdef _nfs_rnode_h /* _nfs_rnode_h only defined on recent versions of NFS */
#define r_nfsattr r_attr /* the names of these fields changed vith new version of NFS */
#define nfsfattr vattr
#define na_nodeid va_nodeid
#endif /* NFS version */
#ifdef ultrix
#include <sys/gnode.h>
#include <sys/gnode_common.h>
#include <machine/param.h>
#define i_number g_number
#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
#if (! defined sun || SunOS < 4) && ! defined DYNIX && ! defined pyr
/* no more text struct in these systems */
#include <sys/text.h>
#endif
#ifdef pyr /* maybe for all SYS V ? */
#undef r_lock
#include <sys/region.h>
#endif
/* defines for unix BSD whitout NFS */
#define x_ptr x_iptr
#define node inode
#define DTYPE_NODE DTYPE_INODE
#define FSID struct fs *
#define _fsid i_fs
#define ISROOT(n) ((n)->i_number == ROOTINO)
#define ISBDEV(n) (((n)->i_mode&IFMT) == IFBLK)
#define ISDEV(n) (((n)->i_mode&IFMT) == IFBLK || ((n)->i_mode&IFMT) == IFCHR)
#define TYPEWORD(n) ((n)->i_mode)
#define TYPEBITS(m) ((m)&IFMT)
#define NODETYPE_T unsigned short
#define TREG IFREG
#define TDIR IFDIR
#define TCHR IFCHR
#define TBLK IFBLK
#ifdef ultrix
/* defines for ultrix, i.e. DEC gfs variant of NFS */
#undef x_ptr
#undef node
#define x_ptr x_gptr
#define node gnode
#undef FSID
#define FSID struct mount *
#define i_fs g_mp
#undef ISROOT
#define ISROOT(n) ((n)->g_number == ROOTINO || isroot(n))
#define i_number g_number
#define i_mode g_mode
#define i_rdev g_rdev
#undef TREG
#undef TDIR
#undef TCHR
#undef TBLK
#define TREG GFREG
#define TDIR GFDIR
#define TCHR GFCHR
#define TBLK GFBLK
#include <sys/mount.h>
#define m_inodp m_gnodp
#undef NFS /* ultrix implememtetion of NFS doesn't fit with my defines */
#if defined P_DYING /* ultrix 4.1 */
#define p_flag p_sched
#endif /* ultrix 4.1 */
#endif ultrix
#if defined sun || defined NFS
/* defines for unix systems with NFS a la SUN */
#undef x_ptr
#undef node
#undef DTYPE_NODE
#define x_ptr x_vptr
#define node vnode
#define DTYPE_NODE DTYPE_VNODE
#undef FSID
#undef _fsid
#define FSID struct vfs *
#define _fsid v_vfsp
#undef ISROOT
#undef ISBDEV
#undef ISDEV
#define ISROOT(n) ((n)->v_flag & VROOT)
#define ISBDEV(n) (((n)->v_type) == VBLK)
#define ISDEV(n) (((n)->v_type) == VBLK || ((n)->v_type) == VCHR)
#undef TYPEWORD
#undef TYPEBITS
#undef NODETYPE_T
#undef TREG
#undef TDIR
#undef TCHR
#undef TBLK
#define TYPEWORD(n) ((n)->v_type)
#define TYPEBITS(m) m
#define NODETYPE_T enum vtype
#define TREG VREG
#define TDIR VDIR
#define TCHR VCHR
#define TBLK VBLK
#endif sun || NFS
#define TYPE(n) (TYPEBITS(TYPEWORD(n)))
typedef FSID myfsid_t;
typedef NODETYPE_T nodetype_t;
#define XFILE 0100
#define MAPPED 0200
#define MOUNTP 0400
#define STR(s) "s"
#if defined sun && SunOS >= 4
#include <vm/seg_vn.h>
#include <vm/seg.h>
#if SunOSrel > 0
#include <vm/hat.h>
#endif
#include <vm/as.h>
#endif SunOS >= 4
/*
* PEEK variants:
* KM: from /dev/kmem
* M: from /dev/mem
* A: 2nd arg is an array, don't take its address, take its size
* P: 2nd arg is a pointer, don't take its address, take size of pointed data
* E: return 0 on error instead of aborting
*/
#define KMPEEK(fromwhere, intowhat) \
(void)peek(kmem, (ls_t)(fromwhere), (char *)(&intowhat), sizeof intowhat, "intowhat", __LINE__, 0)
#define KMAPEEK(fromwhere, intowhat) \
(void)peek(kmem, (ls_t)(fromwhere), (char *)(intowhat), sizeof intowhat, "intowhat", __LINE__, 0)
#define KMPPEEK(fromwhere, intowhat) \
(void)peek(kmem, (ls_t)(fromwhere), (char *)(intowhat), sizeof *intowhat, "intowhat", __LINE__, 0)
#define MPPEEK(fromwhere, intowhat) \
(void)peek(mem, (ls_t)(fromwhere), (char *)(intowhat), sizeof *intowhat, "intowhat", __LINE__, 0)
#define EKMAPEEK(fromwhere, intowhat) \
peek(kmem, (ls_t)(fromwhere), (char *)(intowhat), sizeof intowhat, "intowhat", __LINE__, 1)
#define EMPPEEK(fromwhere, intowhat) \
peek(mem, (ls_t)(fromwhere), (char *)(intowhat), sizeof *intowhat, "intowhat", __LINE__, 1)
#if !defined NFS && ! defined ROOTINO
#ifdef ultrix
#include <ufs/fs.h>
#else
#include <sys/fs.h>
#endif
#endif
char *namelist;
char *corefile;
int k_opt = 0;
#ifdef pyr
int dflg = 0;
#endif pyr
int n_opt = 0;
#if defined ultrix || ( defined sun && SunOS < 4)
#define ls_t long
#else
#define ls_t off_t
#endif
#ifdef sun
char *sprintf();
#endif
ls_t lseek(), vtophys();
#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 */
struct proc *procbase, *procNPROC;
int ppid = -1; /* previously display PID */
int pids_only = 0; /* if non-zero, only output process ids */
int iflag = 0; /* i-numbers wanted */
char *progname;
struct nlist nl[] = {
#ifndef mips
#define SYM(s) STR(_/**/s)
#else
#define SYM(s) STR(s)
#endif
#define X_PROC 0
{ SYM(proc) },
#define X_PROCNPROC 1
{ SYM(procNPROC) },
#define X_SYSMAP 2
{ SYM(Sysmap) },
#define SFIL 3
{ SYM(file) },
#define SNFILE 4
{ SYM(nfile) },
#define X_U 5
#if sun && SunOS >= 4 && SunOSrel >= 1
{ SYM(uunix) },
#else
{ SYM(u) },
#endif /* SunOS >= 4.1 */
#if defined NFS
#define X_ROOTVFS 6
{ SYM(rootvfs) },
#else
#define X_MOUNT 6
{ SYM(mount) },
#endif
#ifdef NFS
#define X_UFSVNOPS 7
{ SYM(ufs_vnodeops) },
#define X_NFSVNOPS 8
{ SYM(nfs_vnodeops) },
#define X_SPECVNOPS 9
{ SYM(spec_vnodeops) },
#endif NFS
{ "" }
};
#if sun && SunOS >= 4 && SunOSrel >= 1
#define U_ADDR uunix
struct user *uunix;
struct file **ofilep;
struct file *ofile_arr[NOFILE];
int nofile;
#undef NOFILE
#define NOFILE nofile
#define ofile(x) ofilep[x]
#else
#define U_ADDR ((struct user *)(nl[X_U].n_value))
#endif
#ifdef pyr
#define DELTA_U ((char *)u -(char *)U_ADDR)
#define ofile(x) (((struct file **)(((char *)(u->u_ofile))+DELTA_U))[x])
#endif
#ifdef DYNIX
#define ofile(x) u->u_lofile[x].of_file
#undef NOFILE
#define NOFILE u->u_nofile
#endif
#ifndef ofile
/* normal case, "standard " unix */
#define ofile(x) u->u_ofile[x]
#endif /* normal case */
int debug;
char *filename, *fsname;
struct node *argnodep, argnode;
dev_t argdev;
nodetype_t argtype;
onalarm() {}
#ifdef ultrix
isroot(np)
struct node *np;
{
struct node *mp;
KMPEEK(&(np->g_mp->m_gnodp), mp);
return (mp == argnodep);
}
#endif ultrix
#if (defined ultrix || defined sony) && defined mips
uread(from, to)
unsigned int from, *to;
{
struct pte *paddr;
struct proc *procp;
#if 0
int pte;
#else
struct pte pte;
#endif
short pid, mypid;
mypid = getpid();
for (procp = procbase + 2; procp < procNPROC; ++procp) {
KMPEEK(&(procp->p_pid), pid);
if (pid == mypid) goto found;
}
error("My pid is not in proc table !\n");
found:
KMPEEK(&(procp->p_addr), paddr);
KMPEEK(&paddr[(from-UADDR)>>PGSHIFT], pte);
#if 0
MPPEEK((pte&PG_PFNUM) | (from & PGOFSET), to);
#else
MPPEEK((pte.pg_pfnum << PGSHIFT) | (from & PGOFSET), to);
#endif
}
#endif
ismountdev(s)
char *s;
{
register struct fstab *fs;
if ((fs = getfsspec(s)) != NULL) {
fsname = fs->fs_file;
return 1;
}
return 0;
}
getmountdev(s)
char *s;
{
register struct fstab *fs;
if ((fs = getfsfile(s)) != NULL)
filename = fs->fs_spec;
}
struct proc p;
ino_t inum;
#ifdef NFS
struct snode *vdata;
#endif
int type;
main(argc, argv)
int argc;
char *argv[];
{
struct user *u, *getuser();
struct proc *procp;
register int filen, flags;
char *getsockfp(), *rindex();
struct file *fp;
int ax, err, findf, nmct;
char *ap;
int exitval = 0;
struct mount *mountp;
#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
#if defined sun && SunOS >= 4
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] [-d|-n|-p] names\n",
progname);
#else
(void) fprintf(stderr,
"usage: %s [-D ] [-n] [-p] [-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");
(void) fprintf(stderr, "\t-d\n\t-m\n\t-f force name to be considered respectiveley\n");
(void) fprintf(stderr, "\t\t as a device, mount point or regular file\n");
exit(exitval);
}
/* check for switches */
for (err = 0, ax = 1; ax < argc; ax++) {
ap = argv[ax];
if (*ap++ != '-')
break;
while (*ap) {
type = 0;
switch (*ap++) {
case 'D':
debug = 1;
break;
#if defined DYNIX || defined pyr
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;
#ifdef pyr
if (ap[1] == 'd')
dflg = 1;
#endif pyr
continue;
}
break;
#endif DYNIX || pyr
case 'n':
n_opt++;
break;
case 'p':
pids_only = 1;
break;
case 'i':
iflag = 1;
break;
case 'm':
case 'f':
case 'd':
type = ap[-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;
}
#if defined sun && SunOS >= 4
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);
}
mem = kmem;
#ifdef pyr
if (dflg)
setdump();
#endif pyr
} else {
if ((kmem = open("/dev/kmem", 0)) < 0) {
(void) fprintf(stderr, "%s: /dev/kmem: ", progname);
perror("");
exit(1);
}
}
#ifndef pyr
if (!k_opt)
if ((swap = open("/dev/drum", 0)) < 0) {
(void) fprintf(stderr, "%s: /dev/drum: ", progname);
perror("");
exit(1);
}
#endif pyr
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 {
int argfd;
char buf[100];
filename = argv[ax];
fsname = filename;
retry:
signal(SIGALRM,onalarm);
alarm(1);
argfd = open(fsname, O_RDONLY|O_NDELAY);
alarm(0);
if (argfd == -1) {
extern int errno;
extern char *sys_errlist[];
struct stat bufstat;
if (stat(fsname, &bufstat) != -1)
switch (bufstat.st_mode & IFMT) {
case IFBLK:
argtype = TBLK;
break;
case IFCHR:
argtype = TCHR;
break;
default:
goto bad;
}
else
goto bad;
argdev = bufstat.st_rdev;
type = 'd';
goto skip;
bad:
(void) sprintf(buf, "open failed for %s (%s)\n", fsname, sys_errlist[errno]);
error(buf);
}
#if defined pyr || defined sun && SunOS >= 4 && SunOSrel >=1
#define OFILEPTR
{
struct file **ofp;
#if defined sun
KMPEEK(nl[X_U].n_value, uunix);
#endif
KMPEEK(&(U_ADDR->u_ofile), ofp);
KMPEEK(ofp+argfd, fp);
}
#endif OFILEPTR
#if defined mips && (defined ultrix || defined sony)
/* ultrix & sony mips have no access via kmem to its own user struct ! */
uread(&((U_ADDR->u_ofile)[argfd]), &fp);
#endif
#if !defined OFILEPTR && !((defined ultrix || defined sony) && defined mips)
/* the "normal case " */
KMPEEK(U_ADDR->u_ofile+argfd, fp);
#endif /* normal case */
KMPEEK(&(fp->f_data), argnodep);
KMPEEK(argnodep, argnode);
(void)close(argfd);
switch(type) {
case 0:
if (ISROOT(&argnode)) {
type = 'm';
getmountdev(filename);
} else if (ISDEV(&argnode))
if (ismountdev(fsname)) {
type = 'm';
goto retry;
} else {
type = 'd';
fsname = "";
}
else {
type = 'f';
fsname = "";
}
break;
case 'f':
switch(TYPE(&argnode)) {
case TREG:
case TDIR:
case TCHR:
case TBLK:
break;
default:
(void)sprintf(buf,
"invalid %s type for arg type '%c' arg %s\n",
STR(node),
type,
argv[ax]);
error(buf);
}
break;
case 'm':
if (!ISROOT(&argnode)) {
if (ismountdev(fsname))
goto retry;
(void)sprintf(buf,
"%s is not a root\n",
fsname);
error(buf);
}
if (fsname == filename)
getmountdev(filename);
break;
case 'd':
if(!ISDEV(&argnode)) {
(void)sprintf(buf,
"%s is not a device\n",
filename);
error(buf);
}
fsname = "";
break;
}
if (type == 'd')
#ifdef NFS
KMPEEK(&(((struct snode *)(argnode.v_data))->s_dev), argdev);
#else
argdev = argnode.i_rdev;
#endif NFS
argtype = TYPE(&argnode);
}
if (iflag && type == 'f') {
#ifdef NFS
struct node *i;
if (ISDEV(&argnode)) {
KMPEEK(&(((struct snode *)argnode.v_data)->s_realvp), i);
KMPEEK(&(i->v_data), vdata);
} else {
if ((int)argnode.v_op == nl[X_UFSVNOPS].n_value)
KMPEEK(&(((struct inode *)argnode.v_data)->i_number), inum);
else if ((int)argnode.v_op == nl[X_NFSVNOPS].n_value)
KMPEEK(&(((struct rnode *)argnode.v_data)->r_nfsattr.na_nodeid), inum);
else
inum = 0;
}
#else
inum = argnode.i_number;
#endif
}
skip:
if (! pids_only) {
(void) printf("%s\t%s", filename, fsname);
if (!n_opt) {
if (type == 'f')
if (TYPE(&argnode) == TDIR)
(void) printf(" (directory)");
else
(void) printf(" (regular file)");
else if (type == 'm')
(void) printf(" (mount point)");
else
(void) printf(" (device)");
}
(void) printf("\n%-8.8s %5s %-6.6s FD %-14.14s",
"USER", "PID", "TYPE", "CMD");
if (!n_opt && iflag)
(void) printf(" INODE");
(void) printf("\n");
}
if (!n_opt) {
struct node *i;
#if defined NFS
struct vfs *vfsp;
KMPEEK(nl[X_ROOTVFS].n_value, vfsp);
for (; vfsp; KMPEEK(&(vfsp->vfs_next), vfsp)) {
KMPEEK(&(vfsp->vfs_vnodecovered), i);
if(!i) continue;
if (check(i, type))
gotone(0,0,-1,MOUNTP,i);
}
#else
mountp = (struct mount *)nl[X_MOUNT].n_value;
for (;;) {
KMPEEK(&(mountp->m_inodp), i);
if (!i) break;
if (check(i, type))
gotone(0,0,-1,MOUNTP,i);
++mountp;
}
#endif NFS
}
for (procp = procbase, findf = 0; procp < procNPROC; ++procp) {
KMPEEK(procp, p);
flags = 0;
if (p.p_stat == 0 || p.p_stat == SZOMB)
continue;
#if defined sun && SunOS >= 4
u = kvm_getu(kd, &p);
#if SunOSrel >= 1
getuofiles(u, p.p_segu);
#endif
#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) {
struct node *txtnode;
if (check(u->u_rdir, type)) {
gotone(u, &p, -1, RDIR, u->u_rdir);
findf++;
}
if (check(u->u_cdir, type)) {
gotone(u, &p, -1, CDIR, u->u_cdir);
findf++;
}
/* check text files */
#if (! defined sun || SunOS < 4) && !defined pyr
#ifndef DYNIX
if (p.p_textp) {
KMPEEK(&(p.p_textp->x_ptr), txtnode);
if (check(txtnode, type)) {
gotone(u, &p, -1, XFILE, txtnode);
findf++;
}
}
#endif DYNIX
#endif
#ifdef pyr
{
struct pregion *prp = p.p_region;
struct region *rp;
struct node *lastv = 0;
int nreg;
for (nreg = 0; nreg <= p.p_nregion; ++nreg) {
KMPEEK(&(prp->p_reg), rp);
KMPEEK(&(rp->r_vptr), txtnode);
if (txtnode == lastv) continue;
if (check(txtnode, type)) {
gotone(u, &p, -1, XFILE, txtnode);
findf++;
}
lastv = txtnode;
}
}
#endif pyr
#if defined sun && SunOS >= 4
/* in SunOS >= 4 and DYNIX, text files are mapped files */
if (p.p_as) {
struct seg *segp, *segnext;
struct segvn_data *svd;
struct vnode *lastv = 0;
KMPEEK(&(p.p_as->a_segs), segp);
if (!segp) goto noseg;
segnext = segp;
do {
KMPEEK(&((struct segvn_data *)(segnext->s_data)), svd);
if (!svd) continue;
KMPEEK(&(svd->vp), txtnode);
if(txtnode == lastv) continue;
#if defined sun
if(((int)txtnode&0xff00000) != 0xff00000
) continue;
#endif sun
if (check(txtnode, type)) {
gotone(u, &p, -1, MAPPED, txtnode);
findf++;
lastv = txtnode;
}
} while(KMPEEK(&((struct segvn_data *)(segnext->s_next)), segnext),
segnext != segp);
noseg: ;
}
#endif SunOS < 4
}
for (filen = 0; filen < NOFILE; filen++)
{
struct file f;
flags = 0;
if (n_opt) {
if (ofile(filen) != fp)
continue;
} else {
if (ofile(filen) == NULL)
continue;
}
KMPEEK(ofile(filen), f);
if (f.f_count > 0) {
if (n_opt && f.f_type == DTYPE_SOCKET) {
gotone(u, &p, filen, SOCKET, 0);
findf++;
continue;
}
if (f.f_type != DTYPE_NODE)
continue;
if (check((struct node *)f.f_data,
type)) {
flags |= OFILE;
if (f.f_flag & FEXLOCK) {
flags |= EXFILE;
}
if (f.f_flag & FSHLOCK) {
flags |= SHFILE;
}
gotone(u, &p, filen, flags, (struct node *)f.f_data);
findf++;
}
}
}
}
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, i)
struct user *u;
struct proc *p;
int fd;
int f;
struct node *i;
{
char *ty, tybuf[8], *strcat(), *strcpy();
struct passwd *getpwuid();
register struct passwd *pw;
/* only print pids and return */
if (pids_only) {
if (!p) return;
if (ppid != p->p_pid) {
if (ppid != -1)
(void) printf(" ");
(void) printf("%d", p->p_pid);
(void) fflush(stdout);
ppid = p->p_pid;
}
return;
}
if (p) {
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";
#if SunOS < 4
else if (f & XFILE)
ty = "text";
#else /* SunOS >= 4 */
else if (f & MAPPED)
ty = "mapped";
#endif /* SunOS */
else
ty = "";
} else {
printf(" ");
if (f & MOUNTP)
ty = "mntpnt";
}
(void) printf("%-6.6s ", ty);
if (fd >= 0)
(void) printf("%2d ", fd);
else
(void) printf(" ");
(void) printf("%-14.14s", u?u->u_comm:"");
if (iflag && i) {
if (type != 'f') {
#ifdef NFS
struct vnodeops *vopp;
if (type != 'd')
KMPEEK(&(i->v_data), vdata);
KMPEEK(&(i->v_op), vopp);
if ((int)vopp == nl[X_UFSVNOPS].n_value)
KMPEEK(&(((struct inode *)vdata)->i_number), inum);
else if ((int)vopp == nl[X_NFSVNOPS].n_value)
KMPEEK(&(((struct rnode *)vdata)->r_nfsattr.na_nodeid), inum);
else if ((int)vopp == nl[X_SPECVNOPS].n_value) {
KMPEEK(&(vdata)->s_realvp, i);
KMPEEK(&(i->v_data), vdata);
KMPEEK(&(((struct inode *)vdata)->i_number), inum);
} else
inum = 0;
#else
KMPEEK(&(i->i_number), inum);
#endif
}
printf(" %5d", inum);
}
(void) printf("\n");
return;
}
/*
* is [igv]node "i"
- on the filesystem of argnode when type == 'm'
- identical to argnode when type = 'f'
- the same device as argnode when type == 'd'
?
returns TRUE or FALSE
*/
check(i, type)
struct node *i;
{
myfsid_t fsid;
dev_t dev;
nodetype_t tword;
if (type == 'f') return (i == argnodep);
if (i == (struct node *)NULL)
return 0;
if (type == 'm') {
KMPEEK(&(i->_fsid), fsid);
return (argnode._fsid == fsid);
}
KMPEEK(&TYPEWORD(i),tword);
if (TYPEBITS(tword) != argtype) return 0;
#ifndef NFS
KMPEEK(&(i->i_rdev), dev);
#else
KMPEEK(&(i->v_data), vdata);
KMPEEK(&(vdata->s_dev), dev);
#endif
return (argdev == dev);
}
#if !defined(sun) || SunOS < 4
/*
* 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 {
KMPPEEK(p->p_uarea, u);
}
return u;
}
#endif
#ifdef pyr
struct user *
getuser(p)
struct proc *p;
{
static union uuser {
struct user u_user;
char u_bytes[UPAGES*NBPG];
} uuser;
if (readublk(p->p_pid, &uuser))
return 0;
else
return &uuser.u_user;
}
#endif pyr
#if ! defined DYNIX && ! defined pyr
struct user *
getuser(p)
struct proc *p;
{
#define USERPAGES ((sizeof (struct user) + NBPG -1)/NBPG)
struct pte mypgtbl[USERPAGES];
int upage;
ls_t sp;
typedef struct { char bytes[NBPG] } page;
page *up;
static union uuser {
struct user u_user;
char u_bytes[USERPAGES*NBPG];
} uuser;
#define User uuser.u_user
/* easy way */
if ((p->p_flag & SLOAD) == 0) {
if (k_opt)
return (struct user *)NULL;
#if defined ultrix && defined P_DYING /* ultrix 4.1 */
if (p->p_smap == 0)
return (struct user *)NULL;
{
struct dmap l_dmap;
int ublkno;
KMPEEK(p->p_smap, l_dmap);
KMPEEK(l_dmap.dm_ptdaddr, ublkno);
sp = (ls_t)dtob(ublkno);
}
#else
sp = (ls_t)dtob(p->p_swaddr);
#endif /* ultrix 4.1 */
if(!peek(swap, sp, (char *)&User, sizeof(union uuser),
"swapped user page(s)", __LINE__, -1))
return (struct user *)NULL;
if (debug)
(void) printf("read swap\n");
} else { /* boo */
/* now get this user's page table */
if (! EKMAPEEK(p->p_addr, mypgtbl)) {
(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 = (page *)&User; upage < USERPAGES; upage++) {
if(! EMPPEEK(ctob(mypgtbl[upage].pg_pfnum), up)) {
(void) fprintf(stderr,
"%s: can't get page %d of user area.\n",
progname, upage);
return(NULL);
}
++up;
}
}
return &User;
}
#endif /* ! DYNIX */
#endif /* SunOS < 4 */
/*
* 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);
}
KMPEEK(nl[X_PROC].n_value, procbase);
KMPEEK(nl[X_PROCNPROC].n_value, procNPROC);
return;
}
/*
* When looking at kernel data space through /dev/mem or
* with a core file, do virtual memory mapping.
*/
ls_t
vtophys(vaddr)
#ifdef pyr
;
#else
ls_t vaddr;
{
u_int paddr;
#ifdef i386
if (vaddr < 8192)
return vaddr;
#endif
paddr = nl[X_SYSMAP].n_value;
peek(kmem, (ls_t)paddr, &paddr, sizeof paddr, "level 1 page table", __LINE__);
paddr = (int)((int *)paddr + (vaddr / NBPG));
peek(kmem, (ls_t)paddr, &paddr, sizeof paddr, "level 2 page table", __LINE__);
(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));
}
#endif pyr /* vtophys in a separate file for pyramid */
/*
* 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.
*/
KMPEEK(x, 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.
*/
KMPEEK(tcpcb.t_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.
*/
KMPEEK(inpcb.inp_socket, sock);
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) {
KMPEEK(nl[SNFILE].n_value, nfile);
xfile = (struct file *) calloc((unsigned)nfile, sizeof (struct file));
KMPEEK(nl[SFIL].n_value, ftp);
}
/*
* Read the file table and search for an in-use
* socket file with a matching data address.
*/
(void)peek(kmem, (ls_t)ftp, (char *)xfile, nfile * sizeof(struct file), "_file",
__LINE__, 0);
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);
}
peek(file, fromwhere, intowhat, size, msg, line, errflg)
char *intowhat, *msg;
ls_t fromwhere;
{
extern errno;
extern char *sys_errlist[];
int n;
#if defined sun && SunOS >= 4
if (file == kmem) {
if ((n = kvm_read(kd,
(unsigned long)(fromwhere),
(char *)(intowhat),
size
)) == -1
) goto bad;
return n;
}
#endif
if (lseek(file, k_opt?vtophys(fromwhere):fromwhere, 0) == -1) goto bad;
if ((n = read(file, intowhat, size)) == -1) goto bad;
return n;
bad:
if (errflg > 0) return 0;
(void)fprintf (
stderr,
"%s: peek from 0x%x into 0x%x failed for %s at line %d (%s)\n",
progname,
fromwhere,
intowhat,
msg,
line,
sys_errlist[errno]
);
if (error == 0) exit(1);
return 0;
}
#if defined sun && SunOS >= 4 && SunOSrel >= 1
getuofiles(locu, segu)
register struct user *locu;
register struct seguser *segu;
{
nofile = locu->u_lastfile + 1;
if (nofile <= 0) return;
ofilep = locu->u_ofile;
if (ofilep == segu->segu_u.u_ofile_arr)
ofilep = locu->u_ofile_arr;
else {
(void)peek(kmem, (ls_t)(ofilep), (char *)(ofile_arr),
nofile*sizeof (struct file *), "ofile_arr", __LINE__, 0);
ofilep = ofile_arr;
}
}
#endif