ofiles: list processes that have files open (ported from BSD)
Lenny Tropiano
lenny at icus.islp.ny.us
Wed Mar 29 14:54:48 AEST 1989
Mike -=]Ford[=- Ditto sent this to me a while back, I figured it was
something that would be useful to the UNIX PC community. It basically
is an enchanced "fuser-type" program that will list the processes that
have a particular file open. The program (using the "make install") will
be installed setuid "root" into /usr/lbin, if you don't want this, please
modify the Makefile, or install by hand.
This was ported from the BSD ofiles, that was recently posted to
comp.sources.unix.
$ ofiles /dev/kmem
/dev/kmem
User PID Type Command
root 192 f ttydaemon
root 193 f loadavgd
root 277 f sysinfo
root 546 f ofiles
$ ofiles /u/lenny/Filecabinet
/u/lenny/Filecabinet
User PID Type Command
lenny 252 p ksh
lenny 521 p postnews
lenny 522 p vi
root 550 p ofiles
$ ofiles /dev/fp011
/dev/fp011
User PID Type Command
lenny 252 f ksh
lenny 522 f vi
root 558 f ofiles
Enjoy,
Lenny
-- cut here -- -- cut here -- -- cut here -- -- cut here -- -- cut here --
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: Makefile README ofiles.c
# Wrapped by lenny at icus on Tue Mar 28 23:48:17 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(736 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile to compile ofiles.c (Open Files)
X# Port from BSD ofiles done by Mike -=]Ford[=- Ditto
X# Makefile contributed by Lenny Tropiano
X#
X# NOTE: If you don't want this program installed setuid, so anyone can use it,
X# modify the "make install" dependency with the permission you want to
X# grant.
X#
XCFLAGS=-v -O
XLDFLAGS=-s
XLIBS=/lib/crt0s.o /lib/shlib.ifile
XDEST=/usr/lbin/
XCC=cc
XLD=ld
X#
Xofiles: ofiles.o
X @echo "Loading ..."
X $(LD) $(LDFLAGS) -o ofiles ofiles.o $(LIBS)
X#
X# You need to be super-user to do this.
X#
X$(DEST):
X mkdir $(DEST)
X chown bin $(DEST)
X chgrp bin $(DEST)
X chmod 755 $(DEST)
X#
Xinstall: ofiles $(DEST)
X cp ofiles $(DEST)
X chown root $(DEST)/ofiles
X chgrp sys $(DEST)/ofiles
X chmod 4755 $(DEST)/ofiles
END_OF_Makefile
if test 736 -ne `wc -c <Makefile`; then
echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(750 characters\)
sed "s/^X//" >README <<'END_OF_README'
X[.. in reply to a letter to Mike about "ofiles" ..]
X
XWell, I recently ran across a posting of something called "ofiles" for
XBSD, and remembering your message, I decided to see if it ported
Xeasily to the Unix PC. It did, and here it is, although it doesn't
Xseem to exactly fit your description. It seems to be just a "fuser"
Xprogram with slightly fancier output.
X
XHere's the BSD version and the Unix PC version. If you can track down
Xthe program you were talking about, I'd like to see it.
X
X -=] Ford [=-
X
X"The number of Unix installations (In Real Life: Mike Ditto)
Xhas grown to 10, with more expected." ford at kenobi.cts.com
X- The Unix Programmer's Manual, ...!sdcsvax!crash!elgar!ford
X 2nd Edition, June, 1972. ditto at cbmvax.commodore.com
X
END_OF_README
if test 750 -ne `wc -c <README`; then
echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ofiles.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"ofiles.c\"
else
echo shar: Extracting \"ofiles.c\" \(6440 characters\)
sed "s/^X//" >ofiles.c <<'END_OF_ofiles.c'
X/*
X * UNIX PC Port programmed by Mike -=]Ford[=- Ditto (ditto at cbmvax.commodore.com)
X */
X
X#ifndef lint
Xstatic char rcsid[]="$Header: ofiles.c,v 1.1 85/05/03 06:49:19 cspencer Exp $";
X#endif lint
X#include <sys/param.h>
X#include <sys/dir.h>
X#define KERNEL
X#include <sys/file.h>
X#undef KERNEL
X#include <sys/inode.h>
X#include <sys/user.h>
X#include <sys/pte.h>
X#include <sys/proc.h>
X#include <nlist.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include <sys/vmmac.h>
X#include <sys/var.h>
X#include <stdio.h>
X
X
X#define CDIR 01
X#define OFILE 02
X#define RDIR 04
X
X
Xlong eseek();
X
X#undef NOFILE
Xint NOFILE;
Xint nproc; /* number of entries in proc table */
Xint mem; /* fd for /dev/mem */
Xint kmem;
Xint swap; /* fd for /dev/swap */
Xlong procbase;
X
Xint pids_only = 0; /* if non-zero, only output process ids */
X
Xchar *progname;
Xstruct nlist unix_nl[] = {
X#define X_PROC 0
X {"proc"},
X#define X_VAR 1
X {"v"},
X#define X_NOFILE 2
X {"nofile"},
X {0}
X};
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X struct inode *i,*getinode();
X struct stat s;
X struct user *u, *getuser();
X struct proc p;
X register int filen, flags, procn;
X register char *filename, *fsname;
X
X progname = argv[0];
X
X if(argc == 1) {
X fprintf(stderr,"usage: %s [-p] files\n", progname);
X exit(1);
X }
X
X /* check for -p flag */
X if(strcmp(argv[1],"-p") == 0) {
X pids_only++;
X --argc;
X ++argv;
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/swap", 0)) < 0)
X error("can't open /dev/swap. ");
X getsyms();
X
X while(--argc) {
X filename = *++argv;
X fsname = "";
X
X if(stat(filename, &s)) {
X fprintf(stderr,"can't stat %s. ",filename);
X perror("");
X continue;
X }
X if(! pids_only) {
X printf("%s\t%s\n", filename,fsname);
X printf("%-8.8s\tPID\tType\tCommand\n", "User");
X }
X for(procn = 0; procn < nproc; procn++){
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 i = getinode(u->u_rdir, "rdir");
X if(check(&s,i))
X flags |= RDIR;
X
X i = getinode(u->u_cdir, "cdir");
X if(check(&s,i))
X flags |= CDIR;
X
X for(filen = 0; filen < NOFILE; filen++) {
X struct file f;
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 i = getinode((char *)f.f_inode, "file");
X if(check(&s,i))
X flags |= OFILE;
X }
X }
X if(flags) gotone(u,&p,flags);
X }
X if(! pids_only)
X printf("\n");
X }
X}
X
X/*
X * print the name of the user owning process "p" and the pid of that process
X */
Xgotone(u,p,f)
Xstruct user *u;
Xstruct proc *p;
Xint f;
X{
X register struct passwd *pw;
X struct passwd *getpwuid();
X
X /* only print pids and return */
X if(pids_only) {
X printf("%d ",p->p_pid);
X fflush(stdout);
X return;
X }
X pw = getpwuid(u->u_uid);
X if(pw)
X printf("%-8.8s\t", pw->pw_name );
X else
X printf("(%d)\t", u->u_uid);
X printf("%d\t", p->p_pid);
X if(f & OFILE) putchar('f'); /* proc has a file */
X if(f & CDIR) putchar('p'); /* proc's current dir is on device */
X if(f & RDIR) putchar('r'); /* proc's root dir is on device */
X printf("\t");
X printf("%-14.14s", u->u_comm);
X printf("\n");
X}
X
X/*
X * is inode "i" on device "s"? returns TRUE or FALSE
X */
Xcheck(s, i)
Xstruct stat *s;
Xstruct inode *i;
X{
X if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == brdev(i->i_dev))
X return 1;
X else if((s->st_dev == brdev(i->i_dev)) && (s->st_ino == i->i_number))
X return 1;
X else return 0;
X}
X
X
X/*
X * getinode - read an inode from from mem at address "addr"
X * return pointer to inode struct.
X */
Xstruct inode *getinode(ip,s)
Xstruct inode *ip;
Xchar *s;
X{
X static struct inode i;
X
X eseek(kmem, (long)ip, 0, "inode");
X eread(kmem, (char *)&i, sizeof(i), "inode");
X return &i;
X}
X
X
X
X/*
X * get user page for proc "p" from core or swap
X * return pointer to user struct
X */
Xstruct user *getuser(p)
Xstruct proc *p;
X{
X char buf[NBPC];
X long upage;
X#define up ((struct user *)(buf + U_OFFSET))
X
X if (!p->p_stat ||
X p->p_stat == SIDL ||
X p->p_stat == SZOMB)
X return 0;
X
X if (p->p_flag & SLOAD)
X {
X lseek(mem, (long)ctob(p->p_addr[0]), 0);
X read(mem, buf, sizeof buf);
X }
X else
X {
X lseek(swap, (long)dbtob((long)p->p_swaddr), 0);
X read(swap, buf, sizeof buf);
X }
X
X if (/* (up->u_procp != ((struct proc *)procbase)+procidx) || */
X (up->u_ruid != p->p_uid) ||
X ((long)(up->u_ofile) < (long)VPG_BASE) ||
X ((long)(up->u_ofile) >=
X (long)VPG_BASE+sizeof (buf)-(sizeof (struct file *) * NOFILE)))
X {
X#ifdef DEBUG
X fprintf(stderr, "Warning: got bogus user area; skipping.\n");
X#endif DEBUG
X p->p_stat = 0;
X return 0;
X }
X
X /* Adjust the ofile pointer */
X up->u_ofile = (struct file **)
X ((char *)up->u_ofile + ((long)buf-VPG_BASE));
X
X return up;
X#undef up
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 sprintf(buf, "read error for %s. ", s);
X error(buf);
X }
X return n;
X}
X
X/*
X * seek with error checking
X */
Xlong eseek(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 sprintf(buf, "seek for %s failed, wanted %o, got %o. ",
X s, off, ret);
X error(buf);
X }
X return ret;
X}
X
X/*
X * print mesg "s" followed by system erro msg. exit.
X */
Xerror(s)
Xchar *s;
X{
X if (s)
X fprintf(stderr,s);
X perror("");
X exit(1);
X}
X
X/*
X * get some symbols form the kernel
X */
Xgetsyms()
X{
X register i;
X struct var v;
X
X nlist("/unix", unix_nl);
X
X for(i = 0; i < (sizeof(unix_nl)/sizeof(unix_nl[0]))-1; i++)
X if(unix_nl[i].n_value == 0) {
X fprintf(stderr,"%s: can't nlist for %s.\n",
X progname, unix_nl[i].n_name);
X exit(1);
X }
X eseek(kmem, (long)unix_nl[X_NOFILE].n_value, 0);
X eread(kmem, &NOFILE, sizeof(NOFILE), "NOFILE");
X eseek(kmem, (long)unix_nl[X_PROC].n_value, 0);
X eread(kmem, &procbase, sizeof(procbase), "procbase 1");
X eseek(kmem, (long)unix_nl[X_VAR].n_value, 0);
X eread(kmem, &v, sizeof(v), "var");
X nproc = v.v_proc;
X return;
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);
X eread(kmem, (char *)p, sizeof(struct proc), "proc");
X return;
X}
END_OF_ofiles.c
if test 6440 -ne `wc -c <ofiles.c`; then
echo shar: \"ofiles.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
--
Lenny Tropiano ICUS Software Systems [w] +1 (516) 582-5525
lenny at icus.islp.ny.us Telex; 154232428 ICUS [h] +1 (516) 968-8576
{talcott,decuac,boulder,hombre,pacbell,sbcs}!icus!lenny attmail!icus!lenny
ICUS Software Systems -- PO Box 1; Islip Terrace, NY 11752
More information about the Unix-pc.sources
mailing list