🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sys.sequent
1 messages
1 total messages Started by rsk Thu, 14 May 1987 02:17
new ofiles for vnode file systems: 4.3/nfs, sun, sequent (Msg. 2.4)
#630
Author: rsk
Date: Thu, 14 May 1987 02:17
748 lines
18247 bytes
I have taken ofiles and rewritten it to work correctly for remote filesystems,
character special devices, and block special devices (as devices).  I have
tested it on Sun 3.2 and 4.3+NFS (Wisconsin), but I'm sure I haven't got it
quite right for the sequent (we don't have one).  I certainly don't have the
#includes right.  Perhaps someone with access to a sequent could get it working
and mail me their working copy, so I can include it in the further enhancements
I am making.  I used getopt() - if you don't have a copy you can get it from
any mod.sources archive or send me mail and I'll send you a copy.

This posting doesn't include a man page - the only added flag is "-f" which
prevents looking up arguments in /etc/mtab - useful if you want to see if
anyone has your filesystems' block special devices open as devices.

Because of the the way /dev/tty is implemented, you can't say "ofiles /dev/tty"
to find processes with their controlling tty open.  But "ofiles /dev/ttya" or
"ofiles /dev/null" works fine.

@alex
---
arpanet: dupuy@columbia.edu
uucp:	...!seismo!columbia!dupuy

: This is a shar archive.  Extract with sh, not csh.
: The rest of this file will extract: 
:
:	ofiles.c
:
echo x - ofiles.c
sed 's/^X//' > ofiles.c << '//go.sysin dd *'
X#include <sys/param.h>
X#include <sys/dir.h>
X#include <sys/user.h>
X#ifdef sequent
X# define KERNEL
X# include <sys/file.h>
X# include <sys/vnode.h>
X# include <sys/vfs.h>
X# include <sys/inode.h>
X# include <rpc/types.h>
X# include <nfs/nfs.h>
X# include <netinet/in.h>
X# include <nfs/nfs_clnt.h>
X# include <nfs/rnode.h>
X# undef KERNEL
X#else
X# define KERNEL
X# include <sys/file.h>
X# undef KERNEL
X# include <sys/vnode.h>
X# include <sys/vfs.h>
X# include <ufs/inode.h>
X# include <rpc/types.h>
X# include <nfs/nfs.h>
X# include <netinet/in.h>
X# include <nfs/nfs_clnt.h>
X# include <nfs/rnode.h>
X#endif
X#include <machine/pte.h>
X#include <sys/vmmac.h>
X#include <sys/proc.h>
X#include <nlist.h>
X#include <sys/stat.h>
X#include <strings.h>
X#include <stdio.h>
X#include <mntent.h>
X#include <pwd.h>
X
Xunion fileid
X{
X    struct
X    {
X	long            fsid;
X	long            nodeid;
X    }               file;
X    struct
X    {
X	dev_t           dev;
X	enum vtype      type;
X    }               special;
X};
X
X#define CDIR	01
X#define OFILE	02
X#define RDIR	04
X
Xlong            eseek ();
Xint             eread ();
Xchar           *vtype ();
Xchar           *itype ();
Xchar           *rtype ();
Xstruct mntent  *getmntname ();
Xstruct mntent  *getmntfile ();
Xunion fileid   *getfileid ();
Xstruct user    *getuser ();
X
X#define error(s)	(perror ((s) ? (s) : ""), exit (1))
X
X#define istype(mode,type)	(((mode) & S_IFMT) == (type))
X#define ispecial(mode)	(istype ((mode), S_IFBLK) || istype ((mode), S_IFCHR))
X
X#define vspecial(vtype)	((vtype) == VCHR || (vtype) == VBLK)
X
X#define nfsdev(rdev)	(major (rdev) == 0xff)
X
X/*
X * File descriptors. 
X */
X
Xint             mem;			/* fd for /dev/mem */
Xint             kmem;			/* fd for /dev/kmem */
Xint             swap;			/* fd for /dev/drum */
X
XFILE           *mtab;			/* stdio file for /etc/mtab */
X
X/*
X * Kernel tables. 
X */
X
X#ifdef sequent
X# define UNIX "/dynix"
X#else
X# define UNIX "/vmunix"
X#endif
Xstruct nlist    nl[] =
X{
X#define X_PROC		0
X {"_proc"},
X#define X_NPROC 	1
X {"_nproc"},
X#define X_USRPTMA	2
X {"_Usrptmap"},
X#define X_USRPT		3
X {"_usrpt"},
X {0}
X};
Xlong            procbase;		/* address of process table */
Xint             nproc;			/* number of entries in proc table */
Xstruct pte     *Usrptma,		/* user page table map */
X               *usrpt;			/* user page table  */
X
Xint             inodes[NOFILE];		/* inodes of open files */
X
X/*
X * Program options. 
X */
X
Xchar           *progname;
Xint             terse = 0;		/* if non-zero, only output pids */
Xint             debug = 10;		/* turn on debugging output */
Xint             filesonly = 0;		/* match args as files, not mntents */
Xint             inode = 0;		/* if non-zero, inode to match */
X
Xmain (argc, argv)
Xint             argc;
Xchar           *argv[];
X{
X
X    char            filename[MNTMAXSTR],
X                    fsname[MNTMAXSTR];
X    struct stat     stats;
X    struct mntent  *mnt;
X
X    extern char    *optarg;
X    extern int      optind;
X    int             option;
X    int             usage = 0;
X
X    progname = argv[0];
X
X    while ((option = getopt (argc, argv, "pfd:")) != EOF)
X    {
X	switch (option)
X	{
X	  case 'p':
X	    terse = 1;
X	    break;
X
X	  case 'f':
X	    filesonly = 1;
X	    break;
X
X	  case 'd':
X	    debug = atoi (optarg);
X	    break;
X
X	  case '?':
X	    usage = 1;
X	}
X    }
X    if (!(argc -= optind) || usage)
X    {
X	fprintf (stderr, "usage: %s [-p] files\n", progname);
X	exit (1);
X    }
X
X    if ((mem = open ("/dev/mem", 0)) < 0)
X	error ("can't open /dev/mem. ");
X    if ((kmem = open ("/dev/kmem", 0)) < 0)
X	error ("can't open /dev/kmem. ");
X    if ((swap = open ("/dev/drum", 0)) < 0)
X	error ("can't open /dev/drum. ");
X
X    if ((mtab = setmntent (MOUNTED, "r")) == 0)
X	error ("can't open /etc/mtab. ");
X
X    getsyms ();
X
X    for (argv += optind; argc--; argv++)
X    {
X	/*
X	 * Check for filesystem/mountpoint vs. file. 
X	 */
X
X	if (!filesonly && (mnt = getmntname (*argv)) != NULL)
X	{
X	    inode = 0;			/* match any inode on this fs */
X	    strcpy (filename, mnt->mnt_dir);
X	    strcpy (fsname, mnt->mnt_fsname);
X	}
X	else
X	{
X	    inode = 1;			/* match only one inode */
X	    strcpy (filename, *argv);
X	}
X
X	if (stat (filename, &stats))	/* find out what it is we want */
X	{
X	    perror (filename);
X	    continue;
X	}
X
X	if (inode)			/* looking for file */
X	{
X	    inode = stats.st_ino;
X	    if ((mnt = getmntfile (&stats)) != NULL)
X		strcpy (fsname, mnt->mnt_fsname);
X	    else
X		strcpy (fsname, "unknown");
X	}
X
X	if (!terse)
X	{
X	    printf ("%s:\t%s\n", fsname, filename);
X
X	    if (debug > 5)
X		if (ispecial (stats.st_mode))
X		    printf (" %s device %d/%d\n", itype (stats.st_mode),
X			    major (stats.st_rdev), minor (stats.st_rdev));
X		else if (nfsdev (stats.st_dev))
X		    printf (" inode %d on remote fs %d (%s)\n",
X			    stats.st_ino, minor (stats.st_dev),
X			    itype (stats.st_mode));
X		else
X		    printf (" inode %d on block device %x (%s)\n",
X			    stats.st_ino, stats.st_dev, itype (stats.st_mode));
X
X	    printf ("user\t process command\ttype\tinode(s)\n");
X	}
X
X	lookfor (&stats);
X    }
X}
X
Xstruct mntent  *
Xgetmntname (name)
Xchar           *name;
X{
X    register struct mntent *mnt;
X
X    rewind (mtab);
X    while ((mnt = getmntent (mtab)) != 0)
X    {
X	if (strcmp (name, mnt->mnt_fsname) == 0)
X	    return (mnt);
X	if (strcmp (name, mnt->mnt_dir) == 0)
X	    return (mnt);
X    }
X    return (NULL);
X}
X
Xstruct mntent  *
Xgetmntfile (filestats)
Xstruct stat    *filestats;
X{
X    register struct mntent *mnt;
X    struct stat     dirstats;
X
X    rewind (mtab);
X    while ((mnt = getmntent (mtab)) != 0)
X	if ((stat (mnt->mnt_dir, &dirstats) >= 0) &&
X	    (filestats->st_dev == dirstats.st_dev))
X	    return (mnt);
X
X    return (NULL);
X}
X
Xlookfor (filestats)
Xstruct stat    *filestats;
X{
X    struct proc     p;
X    struct user    *u;
X    register int    procn,
X                    flags,
X                    filen;
X
X    for (procn = 0; procn < nproc; procn++)
X    {
X	procslot (procn, &p);
X	flags = 0;
X	if (p.p_stat == 0 || p.p_stat == SZOMB)
X	    continue;
X	u = getuser (&p);
X	if (u == (struct user *) NULL)
X	    continue;
X
X	if (debug > 10)
X	    printf ("uid %d pid %d command %s\n", p.p_uid, p.p_pid, u->u_comm);
X
X	if (u->u_rdir != NULL)
X	    if (check (filestats, getfileid (u->u_rdir, "rdir")))
X		flags |= RDIR;
X
X	if (u->u_cdir != NULL)
X	    if (check (filestats, getfileid (u->u_cdir, "cdir")))
X		flags |= CDIR;
X
X	for (filen = 0; filen < NOFILE; filen++)
X	{
X	    struct file     f;
X	    union fileid   *fid;
X
X	    inodes[filen] = 0;
X
X	    if (u->u_ofile[filen] == NULL)
X		continue;
X
X	    eseek (kmem, (long) u->u_ofile[filen], 0, "file");
X	    eread (kmem, (char *) &f, sizeof (f), "file");
X
X	    if (f.f_count > 0)
X	    {
X		if (f.f_type != DTYPE_VNODE)
X		    continue;
X
X		fid = getfileid ((struct vnode *) f.f_data, "ofile");
X		if (check (filestats, fid))
X		{
X		    flags |= OFILE;
X		    if (!ispecial (filestats->st_mode))
X			inodes[filen] = fid->file.nodeid;
X		}
X	    }
X	}
X	if (flags)
X	    gotone (u, &p, flags);
X    }
X}
X
X/*
X * Print the name of the user owning process "p" and the pid of that process 
X */
X
Xgotone (u, p, f)
Xstruct user    *u;
Xstruct proc    *p;
Xint             f;
X{
X    struct passwd  *getpwuid ();
X    register struct passwd *pw;
X    register int    filen;
X
X    if (terse)				/* only print pids and return */
X    {
X	printf ("%d ", p->p_pid);
X	fflush (stdout);
X	return;
X    }
X
X    pw = getpwuid (p->p_uid);
X    if (pw)
X	printf ("%-8.8s", pw->pw_name);
X    else
X	printf ("(%d)\t", p->p_uid);
X
X    printf (" %d\t", p->p_pid);
X
X    printf (" %-14.14s\t", u->u_comm);
X
X    if (f & CDIR)
X	putchar ('c');			/* proc's current dir is on device */
X    if (f & RDIR)
X	putchar ('r');			/* proc's root dir is on device */
X    if (f & OFILE)
X	putchar ('f');			/* proc has file(s) open on device */
X    printf ("\t");
X
X    if (f & OFILE)			/* list inodes of open file(s) */
X	for (filen = 0; filen < NOFILE; filen++)
X	    if (inodes[filen] > 0)
X		printf ("%d ", inodes[filen]);
X
X    puts ("");				/* silly way to print a newline */
X}
X
X
X/*
X * Check if file id matches stats we are searching for. 
X */
X
Xcheck (filestats, fid)
Xstruct stat    *filestats;
Xunion fileid   *fid;
X{
X    if (fid == NULL)
X	return (0);
X
X    if (ispecial (filestats->st_mode))
X    {
X	if (filestats->st_rdev == fid->special.dev
X	    && !strcmp (itype (filestats->st_mode), vtype (fid->special.type)))
X	    return (1);			/* for special devices */
X	else
X	    return (0);
X    }
X
X    if (filestats->st_dev == fid->file.fsid)
X    {
X	if (!inode)			/* if we'll match any file */
X	    return (1);
X
X	if (inode == fid->file.nodeid)
X	    return (1);
X#ifdef sun				/* not sure I understand this */
X	else if (fid->file.nodeid == 0)
X	    return (1);
X#endif
X    }
X
X    return (0);
X}
X
X/*
X * Read a vnode from /dev/kmem, return fileid (dev,ino). 
X */
X
Xunion fileid   *
Xgetfileid (node, s)
Xstruct vnode   *node;
Xchar           *s;
X{
X    struct vnode v;
X    static union xnode
X    {
X	struct inode    i;
X	struct rnode    r;
X    }               x;
X
X    union fileid    fid;
X
X    if (node == NULL)
X	return (NULL);
X
X    eseek (kmem, (long) node, 0, "vnode");
X    eread (kmem, (char *) &v, sizeof (v), "vnode");
X
X    if (vspecial (v.v_type))
X    {
X	fid.special.dev = v.v_rdev;
X	fid.special.type = v.v_type;
X
X	if (debug > 20)
X	    printf (" %s %s device %d/%d\n",
X		    s, vtype (v.v_type), major (v.v_rdev), minor (v.v_rdev));
X	return (&fid);
X    }
X
X    if (debug > 20)
X	printf (" %s %s", s, vtype (v.v_type));
X
X    eseek (kmem, (long) v.v_data, 0, "inode/rnode");
X    eread (kmem, (char *) &x, sizeof (x), "inode/rnode");
X
X    if (x.r.r_nfsattr.na_type == v.v_type)
X    {					/* best test I could find for nfs */
X	struct vfs vf;
X	struct mntinfo mi;
X
X	eseek (kmem, (long) v.v_vfsp, 0, "vfs");
X	eread (kmem, (char *) &vf, sizeof (vf), "vfs");
X
X	eseek (kmem, (long) vf.vfs_data, 0, "mntinfo");
X	eread (kmem, (char *) &mi, sizeof (mi), "mntinfo");
X
X	fid.file.fsid = makedev (0xff, mi.mi_mntno);
X	fid.file.nodeid = x.r.r_nfsattr.na_nodeid;
X
X	if (debug > 20)
X	    printf (" inode %d on nfs fs %x (%s)\n",
X		    x.r.r_nfsattr.na_nodeid, x.r.r_nfsattr.na_fsid,
X		    rtype (x.r.r_nfsattr.na_type));
X    }
X    else
X    {
X	fid.file.fsid = x.i.i_dev;
X	fid.file.nodeid = x.i.i_number;
X
X	if (debug > 20)
X	    printf (" inode %d on device %x (%s)\n",
X		    x.i.i_number, x.i.i_dev, itype (x.i.i_mode));
X    }
X
X    return (&fid);
X}
X
X
Xchar           *
Xvtype (type)
Xenum vtype      type;
X{
X    switch (type)
X    {
X      case VNON:
X	return ("none");
X      case VREG:
X	return ("file");
X      case VDIR:
X	return ("directory");
X      case VBLK:
X	return ("block special");
X      case VCHR:
X	return ("character special");
X      case VLNK:
X	return ("symbolic link");
X      case VSOCK:
X	return ("socket");
X      case VBAD:
X	return ("bad type");
X#ifdef S_IFIFO
X      case VFIFO:
X	return ("fifo");
X#endif
X      default:
X	return ("unknown vnode type");
X    }
X}
X
Xchar           *
Xrtype (type)
Xenum nfsftype   type;
X{
X    switch (type)
X    {
X      case NFNON:
X	return ("none");
X      case NFREG:
X	return ("file");
X      case NFDIR:
X	return ("directory");
X      case NFBLK:
X	return ("block special");
X      case NFCHR:
X	return ("character special");
X      case NFLNK:
X	return ("symbolic link");
X      default:
X	return ("unknown");
X    }
X}
X
Xchar           *
Xitype (mode)
Xunsigned        mode;
X{
X    switch (mode & S_IFMT)
X    {
X      case S_IFREG:
X	return ("file");
X      case S_IFDIR:
X	return ("directory");
X      case S_IFBLK:
X	return ("block special");
X      case S_IFCHR:
X	return ("character special");
X      case S_IFLNK:
X	return ("symbolic link");
X      case S_IFSOCK:
X	return ("socket");
X#ifdef S_IFIFO
X      case S_IFIFO:
X	return ("fifo");
X#endif
X      default:
X	return ("unknown inode type");
X    }
X}
X
X/*
X * get user page for proc "p" from core or swap return pointer to user struct 
X */
Xstruct user    *
Xgetuser (p)
Xstruct proc    *p;
X{
X    struct pte     *ptep;
X    struct pte      mypgtbl[UPAGES];
X    int             n,
X                    nbytes;
X    char           *up;
X    static struct user user;
X
X    /* easy way */
X    if ((p->p_flag & SLOAD) == 0)
X    {
X	eseek (swap, (long) dtob (p->p_swaddr), 0, "user");
X	if (read (swap, (char *) &user, sizeof (struct user)) <= 0)
X	{
X	    if (debug)
X		fprintf (stderr, "error: can't get swapped user page pid %d\n",
X			 p->p_pid);
X	    return (struct user *) NULL;
X	}
X	if (debug > 50)
X	    printf ("read swap\n");
X    }
X    else
X    {					/* boo */
X	/* now get user page tbl */
X#ifdef sequent
X	eseek (mem, p->p_upte, 0L, "user page table");
X	if (read (mem, mypgtbl, sizeof (mypgtbl)) != sizeof (mypgtbl))
X	{
X#else
X	eseek (kmem, p->p_addr, 0L, "user page table");
X	if (read (kmem, mypgtbl, sizeof (mypgtbl)) != sizeof (mypgtbl))
X	{
X#endif
X	    if (debug)
X		fprintf (stderr, "error: can't get mypgtbl pid %d\n",
X			 p->p_pid);
X	    return (struct user *) NULL;
X	}
X	/* now collect pages of u area */
X	up = (char *) &user;
X	ptep = mypgtbl;
X	for (nbytes = sizeof (struct user); nbytes > 0; nbytes -= NBPG)
X	{
X	    eseek (mem, ptep++->pg_pfnum * NBPG, 0L, "page table entry");
X	    n = MIN (nbytes, NBPG);
X	    if (read (mem, up, n) != n)
X	    {
X		if (debug)
X		    fprintf (stderr, "cant get user tbl pid %d\n", p->p_pid);
X		return (struct user *) NULL;
X	    }
X	    up += n;
X	}
X    }
X    return &user;
X}
X
X
X/*
X * Get symbols from the kernel. 
X */
X
Xgetsyms ()
X{
X    register        i;
X
X    if (nlist (UNIX, nl))
X	perror (UNIX), exit (1);
X
X    for (i = 0; i < (sizeof (nl) / sizeof (nl[0])) - 1; i++)
X	if (nl[i].n_value == 0)
X	{
X	    fprintf (stderr, "%s: can't nlist for %s.\n",
X		     progname, nl[i].n_name);
X	    exit (1);
X	}
X
X    eseek (kmem, (long) nl[X_PROC].n_value, 0, "procbase");
X    eread (kmem, &procbase, (unsigned) sizeof (procbase), "procbase");
X
X    eseek (kmem, (long) nl[X_NPROC].n_value, 0, "nproc");
X    eread (kmem, &nproc, sizeof (nproc), "nproc");
X
X    /* variables used by <vmmac.h> */
X
X    Usrptma = (struct pte *) nl[X_USRPTMA].n_value;
X    usrpt = (struct pte *) nl[X_USRPT].n_value;
X}
X
X
X/*
X * Read proc table entry "n" into buffer "p" . 
X */
Xprocslot (n, p)
Xint             n;
Xstruct proc    *p;
X{
X    eseek (kmem, procbase + (long) (n * sizeof (struct proc)), 0, "proc");
X    eread (kmem, (char *) p, sizeof (struct proc), "proc");
X}
X
X/*
X * Read with error checking 
X */
Xeread (fd, p, size, s)
Xint             fd;
Xchar           *p;
Xint             size;
Xchar           *s;
X{
X    int             n;
X    char            buf[100];
X    if ((n = read (fd, p, size)) != size)
X    {
X	sprintf (buf, "read error for %s. ", s);
X	error (buf);
X    }
X    return n;
X}
X
X/*
X * Seek with error checking 
X */
X
Xlong
Xeseek (fd, off, whence, s)
Xint             fd;
Xlong            off;
Xint             whence;
Xchar           *s;
X{
X    long            lseek ();
X    long            ret;
X    char            buf[100];
X
X    if ((ret = lseek (fd, off, whence)) != off)
X    {
X	sprintf (buf, "seek for %s failed, wanted %o, got %o. ",
X		 s, off, ret);
X	error (buf);
X    }
X    return ret;
X}
//go.sysin dd *
exit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads