home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
fstat2
< prev
next >
Wrap
Text File
|
1989-04-19
|
34KB
|
1,367 lines
Subject: v18i107: Show all open files status
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: abe@mace.cc.purdue.edu (Vic Abell)
Posting-number: Volume 18, Issue 107
Archive-name: fstat2
As promised, here is fstat from the 4.3BSD Tahoe release, ported to DYNIX
3.0.1[24] for Sequent Symmetry and Balance, SunOS 4.0 and ULTRIX 2.2.
Fstat is similar to the ofiles program which I recently submitted. Like
ofiles, fstat identifies open files. It's orientation differs slightly
from that of ofiles: ofiles starts with a file name and paws through the
proc and user structures to identify the file; fstat reads all the proc
and user structures, displaying information in all files, optionally
applying a few filters to the output (including a single file name filter.)
In combination with netstat -aA and grep, fstat will identify the process
associated with a network connection, just as will ofiles.
Vic Abell
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# README
# Makefile
# fstat.c
# fstat.8
# By: Vic Abell (Purdue University)
echo shar: extracting README '(1773 characters)'
sed 's/^XX//' << \SHAR_EOF > README
XXFstat comes from the 4.3BSD Tahoe distribution. It may be used to identify
XXopen files. Coupled with netstat(8) and grep(1), it can be used to discover
XXthe process that has an open socket for a network connection.
XX
XXI have converted fstat to run under 4.3BSD, DYNIX 3.0.1[24], SunOS 4.0 and
XXULTRIX 2.2. It is free of lint on all those systems, according to the lint
XXlibraries available to me.
XX
XXSpecial notes:
XX
XX 1. The included Makefile is a generic one, which you may have to
XX customize to your environment (see notes 3 and 5.) I have
XX removed the depend rule, since it relies on a local "maketd"
XX program.
XX
XX 2. Fstat needs permission to access /dev/drum, /dev/kmem and
XX /dev/mem. The Makefile of this distribution assumes that those
XX devices belong to the kmem group, and gives the fstat object a
XX setgid(kmem) mode.
XX
XX 3. SunOS 4.0 users should make sure that -lkvm appears at the
XX end of the ${CC} of the fstat rule - e. g., change
XX
XX fstat: ${OBJ}
XX ${CC} -o $@ ${CFLAGS} ${OBJ}
XX to
XX fstat: ${OBJ}
XX ${CC} -o $@ ${CFLAGS} ${OBJ} -lkvm
XX
XX 4. Some SunOS users may not have the files for making kernels -
XX specifically, "/usr/share/sys/specfs/snode.h". If you do
XX not have this header file, replace its include with the
XX following structure definition:
XX
XX struct snode {
XX struct snode *s_next;
XX struct vnode s_vnode;
XX struct vnode *s_realvp;
XX struct vnode *s_bdevvp;
XX };
XX
XX 5. Sequent users should make sure that the DYNIX symbol is defined.
XX We define it in <sys/param.h>. It may also be defined in the
XX Makefile using "-DDYNIX", e. g.,
XX
XX CDEFS= -DDYNIX
XX
XXI have added to and updated the 4.3BSD Tahoe manual page.
XX
XXVic Abell, abe@mace.cc.purdue.edu
XXPurdue University Computing Center
XXMarch 28, 1989
SHAR_EOF
if test 1773 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 1773 characters)'
fi
echo shar: extracting Makefile '(648 characters)'
sed 's/^XX//' << \SHAR_EOF > Makefile
XX# Makefile for fstat
XX
XXBIN= ${DESTDIR}/etc
XX
XXI=/usr/include
XXS=/usr/include/sys
XX
XXINCLUDE=
XXDEBUG= -O
XXCDEFS=
XXCFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
XX
XXSRC= fstat.c
XXOBJ= fstat.o
XXSOURCE= Makefile ${HDR} ${SRC}
XX
XXall: fstat
XX
XX# SunOS 4.0 requires -lkvm
XX
XXfstat: ${OBJ}
XX ${CC} -o $@ ${CFLAGS} ${OBJ}
XX
XXclean: FRC
XX rm -f Makefile.bak fstat *.o a.out core errs tags
XX
XXinstall: all FRC
XX install -c -s -m 2755 -g kmem fstat ${BIN}
XX
XXlint: ${SRC} ${HDR} FRC
XX lint ${CDEFS} ${INCLUDE} ${SRC}
XX
XXprint: source FRC
XX lpr -J'fstat source' ${SOURCE}
XX
XXsource: ${SOURCE}
XX
XXspotless: clean
XX rcsclean ${SOURCE}
XX
XXtags: ${SRC} ${HDR}
XX ctags -t ${SRC} ${HDR}
XX
XX${SOURCE}:
XX co $@
XX
XXFRC:
SHAR_EOF
if test 648 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 648 characters)'
fi
echo shar: extracting fstat.c '(20280 characters)'
sed 's/^XX//' << \SHAR_EOF > fstat.c
XX/*
XX * Copyright (c) 1987 Regents of the University of California.
XX * All rights reserved.
XX *
XX * Redistribution and use in source and binary forms are permitted
XX * provided that the above copyright notice and this paragraph are
XX * duplicated in all such forms and that any documentation,
XX * advertising materials, and other materials related to such
XX * distribution and use acknowledge that the software was developed
XX * by the University of California, Berkeley. The name of the
XX * University may not be used to endorse or promote products derived
XX * from this software without specific prior written permission.
XX * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
XX * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
XX * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
XX */
XX
XX#ifndef lint
XXchar copyright[] =
XX"@(#) Copyright (c) 1987 Regents of the University of California.\n\
XX All rights reserved.\n";
XX#endif /* not lint */
XX
XX#ifndef lint
XXstatic char sccsid[] = "@(#)fstat.c 5.13 (Berkeley) 6/18/88";
XX#endif /* not lint */
XX
XX/*
XX * fstat
XX */
XX#include <machine/pte.h>
XX
XX#include <sys/param.h>
XX#include <sys/dir.h>
XX#include <sys/user.h>
XX#include <sys/proc.h>
XX#ifndef sun
XX#include <sys/text.h>
XX#endif
XX#include <sys/stat.h>
XX#ifdef DYNIX
XX#define KERNEL
XX#include <sys/vnode.h>
XX#endif
XX#ifndef sun
XX#include <sys/inode.h>
XX#endif
XX#ifdef DYNIX
XX#undef KERNEL
XX#endif
XX#include <sys/socket.h>
XX#include <sys/socketvar.h>
XX#include <sys/domain.h>
XX#include <sys/protosw.h>
XX#include <sys/unpcb.h>
XX#include <sys/vmmac.h>
XX#define KERNEL
XX#include <sys/file.h>
XX#undef KERNEL
XX#include <net/route.h>
XX#include <netinet/in.h>
XX#include <netinet/in_pcb.h>
XX#include <stdio.h>
XX#include <ctype.h>
XX#include <nlist.h>
XX#include <pwd.h>
XX
XX#ifdef sun
XX#include <sys/vnode.h>
XX#include <ufs/inode.h>
XX#include "/usr/share/sys/specfs/snode.h"
XX#include <kvm.h>
XXkvm_t *kd;
XXstruct user *kvm_getu();
XX#endif
XX
XX#ifdef ULTRIX
XX /* UFS -> GFS */
XX# define inode gnode
XX# define x_iptr x_gptr
XX# define i_dev g_dev
XX# define i_number g_number
XX# define i_mode g_mode
XX# define i_size g_size
XXvoid exit(), nlist(), perror();
XX#endif
XX
XX#ifdef ULTRIX
XX#define ls_t long
XX#else
XX#define ls_t off_t
XX#endif
XX
XX#if defined(DYNIX) || defined(sun)
XX#define DTYPE_INODE DTYPE_VNODE
XX#endif
XX
XX#define N_KMEM "/dev/kmem"
XX#define N_MEM "/dev/mem"
XX#define N_SWAP "/dev/drum"
XX#ifdef DYNIX
XX#define N_UNIX "/dynix"
XX#else
XX#define N_UNIX "/vmunix"
XX#endif
XX
XX#define TEXT -2
XX#define WD -1
XX
XXtypedef struct devs {
XX struct devs *next;
XX dev_t dev;
XX int inum;
XX char *name;
XX} DEVS;
XXDEVS *devs;
XX
XXstatic struct nlist nl[] = {
XX { "_proc" },
XX#define X_PROC 0
XX { "_nproc" },
XX#define X_NPROC 1
XX { "_Sysmap"},
XX#define X_SYSMAP 2
XX#ifdef sun
XX { "_inode"},
XX#define X_INODE 3
XX { "_ninode"},
XX#define X_NINODE 4
XX#else
XX { "_Usrptmap" },
XX#define X_USRPTMA 3
XX { "_usrpt" },
XX#define X_USRPT 4
XX#endif
XX { "" },
XX};
XX
XXstruct proc *mproc;
XX#if !defined(DYNIX) && !defined(sun)
XXstruct pte *Usrptma, *usrpt;
XX#endif
XX
XX#ifdef sun
XXstruct inode *inodef = NULL;
XXstruct inode *inodel;
XXint ninode = 0;
XX#endif
XX
XX#ifndef DYNIX
XXunion {
XX struct user user;
XX char upages[UPAGES][NBPG];
XX} user;
XX#endif
XXstruct user *u;
XX
XXextern int errno;
XXextern char *sys_errlist[];
XXstatic int fflg, vflg;
XXstatic int kmem, mem, nproc, swap;
XXstatic char *pname, *uname;
XX
XXls_t lseek();
XX#ifdef DYNIX
XXls_t vtophys();
XX#endif
XX
XXmain(argc, argv)
XX int argc;
XX char **argv;
XX{
XX extern char *optarg;
XX extern int optind;
XX register struct passwd *passwd;
XX register int pflg, pid, uflg, uid;
XX int ch, size;
XX struct passwd *getpwnam(), *getpwuid();
XX long lgetw();
XX char *malloc(), *rindex(), *valloc();
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(DYNIX) && !defined(ULTRIX)
XX struct file *lintfp;
XX
XX file = fileNFILE = NULL;
XX lintfp = file;
XX lintfp = fileNFILE;
XX file = lintfp;
XX nfile = 0;
XX size = nfile;
XX#endif
XX#ifdef DYNIX
XX char *optarg = NULL; /* DYNIX lint misses the extern */
XX int optind = 0; /* DYNIX lint misses the extern */
XX#endif
XX#ifdef ULTRIX
XX struct file *lintfp;
XX struct nch *lintnch;
XX
XX file = fileNFILE = NULL;
XX lintfp = file;
XX lintfp = fileNFILE;
XX file = lintfp;
XX nfile = 0;
XX size = nfile;
XX nch = NULL;
XX lintnch = nch;
XX nch = lintnch;
XX nchsize = 0;
XX size = nchsize;
XX#endif
XX#endif /* lint */
XX
XX if ((pname = rindex(argv[0], '/')) != NULL)
XX pname++;
XX else
XX pname = argv[0];
XX pflg = uflg = 0;
XX while ((ch = getopt(argc, argv, "p:u:v")) != EOF)
XX switch((char)ch) {
XX case 'p':
XX if (pflg++)
XX (void) usage();
XX if (!isdigit(*optarg)) {
XX (void) fprintf(stderr,
XX "%s: -p option requires a process id.\n",
XX pname);
XX (void) usage();
XX }
XX pid = atoi(optarg);
XX break;
XX case 'u':
XX if (uflg++)
XX (void) usage();
XX if (!(passwd = getpwnam(optarg))) {
XX (void) fprintf(stderr,
XX "%s: %s is unknown uid\n",
XX pname, optarg);
XX exit(1);
XX }
XX uid = passwd->pw_uid;
XX uname = passwd->pw_name;
XX break;
XX case 'v': /* undocumented: print read error messages */
XX vflg++;
XX break;
XX case '?':
XX default:
XX (void) usage();
XX }
XX
XX if (*(argv += optind)) {
XX for (; *argv; ++argv) {
XX if (getfname(*argv))
XX fflg = 1;
XX }
XX if (!fflg) /* file(s) specified, but none accessible */
XX exit(1);
XX }
XX
XX#ifdef DYNIX
XX if ((u = (struct user *) valloc(ctob(UPAGES))) == NULL) {
XX (void) fprintf(stderr,
XX "%s: can't allocate space for user structure\n",
XX pname);
XX exit(1);
XX }
XX#else
XX u = &user.user;
XX#endif
XX openfiles();
XX
XX#ifdef ULTRIX
XX (void) nlist(N_UNIX, nl);
XX if (!nl[0].n_type)
XX#else
XX if (nlist(N_UNIX, nl) == -1 || !nl[0].n_type)
XX#endif
XX {
XX (void) fprintf(stderr, "%s: %s has no namelist\n",
XX pname, N_UNIX);
XX exit(1);
XX }
XX#ifdef sun
XX if (nl[X_INODE].n_value == (u_long)0) {
XX (void) fprintf(stderr, "%s: can't read inode pointer)\n",
XX pname);
XX exit(1);
XX }
XX inodef = (struct inode *)lgetw((ls_t)nl[X_INODE].n_value);
XX ninode = (int)lgetw((ls_t)nl[X_NINODE].n_value);
XX if (!inodef || !ninode) {
XX (void) fprintf(stderr,
XX "%s: no inodes (Is this a diskless Sun client?)\n",
XX pname);
XX exit(1);
XX }
XX inodel = inodef + (ninode - 1);
XX#endif
XX#if !defined(DYNIX) && !defined(sun)
XX Usrptma = (struct pte *)nl[X_USRPTMA].n_value;
XX usrpt = (struct pte *) nl[X_USRPT].n_value;
XX#endif
XX nproc = (int)lgetw((ls_t)nl[X_NPROC].n_value);
XX
XX size = nproc * sizeof(struct proc);
XX if ((mproc = (struct proc *)malloc((u_int)size)) == NULL) {
XX (void) fprintf(stderr, "%s: out of space\n", pname);
XX exit(1);
XX }
XX if (kread((ls_t)lgetw((ls_t)nl[X_PROC].n_value), (char *)mproc, size)
XX != size)
XX rerr1("proc table", N_KMEM);
XX
XX (void) printf("%-8.8s %-10.10s %5s %4s %-6.6s %6s %7s %-5.5s %s\n",
XX "USER", "CMD", "PID", "FD", "DEVICE", "INODE", "SIZE", "TYPE",
XX fflg ? "NAME" : "");
XX for (; nproc--; ++mproc) {
XX if (mproc->p_stat == 0)
XX continue;
XX if (pflg && mproc->p_pid != pid)
XX continue;
XX if (uflg) {
XX if (mproc->p_uid != uid)
XX continue;
XX }
XX else
XX uname = (passwd = getpwuid((int)mproc->p_uid)) ?
XX passwd->pw_name : "unknown";
XX if (mproc->p_stat == SZOMB)
XX continue;
XX#ifdef sun
XX if ((u = kvm_getu(kd, mproc)) == NULL)
XX#else
XX if (getu() == 0)
XX#endif
XX continue;
XX dotext();
XX readf();
XX }
XX exit(0);
XX}
XX
XX#ifndef sun
XX#ifdef DYNIX
XXgetu()
XX{
XX int btr;
XX
XX if ((mproc->p_flag & SLOAD) == 0) {
XX if (swap < 0)
XX return(0);
XX (void) lseek(swap, (ls_t)dtob(mproc->p_swaddr), L_SET);
XX btr = ctob(UPAGES);
XX if (read(swap, (char *)u, btr) != btr)
XX return(0);
XX } else {
XX (void) lseek(kmem, (ls_t)mproc->p_uarea, L_SET);
XX if (read(kmem, (char *)u, sizeof(struct user))
XX != sizeof(struct user))
XX return(0);
XX }
XX return(1);
XX}
XX#else /* DYNIX */
XXstatic
XXgetu()
XX{
XX struct pte *pteaddr, apte;
XX struct pte arguutl[UPAGES+CLSIZE];
XX register int i;
XX int ncl;
XX
XX if ((mproc->p_flag & SLOAD) == 0) {
XX if (swap < 0)
XX return(0);
XX (void)lseek(swap, (ls_t)dtob(mproc->p_swaddr), L_SET);
XX if (read(swap, (char *)u, sizeof(struct user))
XX != sizeof(struct user)) {
XX (void) fprintf(stderr,
XX "%s: can't read u for pid %d from %s\n",
XX pname, mproc->p_pid, N_SWAP);
XX return(0);
XX }
XX return(1);
XX }
XX pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1];
XX (void)lseek(kmem, (ls_t)pteaddr, L_SET);
XX if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) {
XX (void) printf(
XX "%s: can't read indir pte to get u for pid %d from %s\n",
XX pname, mproc->p_pid, N_SWAP);
XX return(0);
XX }
XX (void)lseek(mem, (ls_t)(ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE)
XX * sizeof(struct pte)), L_SET);
XX if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) {
XX (void) printf(
XX "%s: can't read page table for u of pid %d from %s\n",
XX pname, mproc->p_pid, N_KMEM);
XX return(0);
XX }
XX ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE);
XX while (--ncl >= 0) {
XX i = ncl * CLSIZE;
XX (void)lseek(mem, (ls_t)ctob(arguutl[CLSIZE+i].pg_pfnum), L_SET);
XX if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) {
XX (void) printf(
XX "%s: can't read page %u of u of pid %d from %s\n",
XX pname,
XX arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, N_MEM);
XX return(0);
XX }
XX }
XX return(1);
XX}
XX#endif /* DYNIX */
XX#endif /* not sun */
XX
XXstatic
XXdotext()
XX{
XX#if !defined(DYNIX) && !defined(sun)
XX struct text text;
XX
XX (void)lseek(kmem, (ls_t)mproc->p_textp, L_SET);
XX if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) {
XX rerr1("text table", N_KMEM);
XX return;
XX }
XX if (text.x_flag)
XX itrans(DTYPE_INODE, (char *)text.x_iptr, TEXT);
XX#endif
XX}
XX
XXstatic
XXitrans(ftype, g, fno)
XX int ftype, fno;
XX char *g; /* if ftype is inode/vnode */
XX{
XX struct inode inode;
XX dev_t idev;
XX char *comm, *itype();
XX char *name = (char *)NULL; /* set by devmatch() on a match */
XX int noinode = 0;
XX#if defined(DYNIX) || defined(sun)
XX struct vnode v;
XX#ifdef sun
XX struct snode s;
XX char *vntype();
XX#endif
XX#endif
XX
XX if ((g && (ftype & DTYPE_INODE)) || fflg) {
XX#if defined(DYNIX) || defined(sun)
XX/*
XX * The file structure points to:
XX *
XX * DYNIX vnode, and the vnode points to the inode
XX * BSD inode
XX * SunOS vnode, and the vode points to an snode if the vnode type
XX * is VBLK, VCHR or VFIFO; and to an inode otherwise; the
XX * snode may point to the real vnode or to a stream
XX *
XX * ULTRIX gnode
XX */
XX if (kread((ls_t)g, (char *)&v, sizeof(v)) != sizeof(v)) {
XX rerr2(errno, (int)g, "vnode");
XX return;
XX }
XX#ifdef sun
XX if (v.v_type == VCHR || v.v_type == VBLK || v.v_type == VFIFO) {
XX if (kread((ls_t)v.v_data, (char *)&s, sizeof(s))
XX != sizeof(s)) {
XX rerr2(errno, (int)v.v_data, "snode");
XX return;
XX }
XX if (s.s_realvp || s.s_bdevvp) {
XX if (kread( s.s_realvp ? (ls_t)s.s_realvp
XX : (ls_t)s.s_bdevvp,
XX (char *)&v, sizeof(v))
XX != sizeof(v)) {
XX rerr2(errno, (int)s.s_realvp,
XX "read vnode");
XX return;
XX }
XX }
XX }
XX /*
XX * The following test weeds out Sun streams that are
XX * represented by "clone" snodes whose s_realvp pointer
XX * has not been properly NULLed in the kernel.
XX */
XX if ((struct inode *)v.v_data < inodef
XX || (struct inode *)v.v_data > inodel)
XX noinode = 1;
XX else
XX if (kread((ls_t)v.v_data, (char *)&inode, sizeof(inode))
XX#else /* DYNIX && not sun */
XX if (kread((ls_t)v.v_data, (char *)&inode, sizeof(inode))
XX#endif /* sun */
XX#else /* not DYNIX && not sun */
XX if (kread((ls_t)g, (char *)&inode, sizeof(inode))
XX#endif /* DYNIX || sun */
XX != sizeof(inode)) {
XX rerr2(errno, (int)g, "inode");
XX return;
XX }
XX idev = inode.i_dev;
XX if (fflg && (noinode || !devmatch(idev, inode.i_number, &name)))
XX return;
XX }
XX if (mproc->p_pid == 0)
XX comm = "swapper";
XX else if (mproc->p_pid == 2)
XX comm = "pagedaemon";
XX else
XX comm = u->u_comm;
XX (void) printf("%-8.8s %-10.10s %5d ", uname, comm, mproc->p_pid);
XX
XX switch(fno) {
XX case WD:
XX (void) printf(" wd");
XX break;
XX case TEXT:
XX (void) printf("text");
XX break;
XX default:
XX (void) printf("%4d", fno);
XX }
XX
XX if (g == NULL) {
XX (void) printf("* (deallocated)\n");
XX return;
XX }
XX
XX switch(ftype) {
XX case DTYPE_INODE:
XX#ifndef sun
XX (void) printf(" %2d, %2d %6lu %7ld %-5.5s %s\n",
XX major(inode.i_dev), minor(inode.i_dev),
XX inode.i_number,
XX inode.i_mode == IFSOCK ? 0 : inode.i_size,
XX itype(inode.i_mode),
XX name ? name : "");
XX#else
XX if (noinode)
XX (void) printf(" %2d, %2d %6s %7s %-5.5s %s\n",
XX major(v.v_rdev), minor(v.v_rdev),
XX "none", "", vntype(v.v_type),
XX name ? name: "");
XX else
XX (void) printf(" %2d, %2d %6lu %7ld %-5.5s %s\n",
XX major(inode.i_dev), minor(inode.i_dev),
XX inode.i_number,
XX inode.i_mode == IFSOCK ? 0 : inode.i_size,
XX itype(inode.i_mode), name ? name : "");
XX#endif
XX break;
XX case DTYPE_SOCKET:
XX socktrans((struct socket *)g);
XX break;
XX#ifdef DTYPE_PORT
XX case DTYPE_PORT:
XX (void) printf("* (fifo / named pipe)\n");
XX break;
XX#endif
XX default:
XX (void) printf("* (unknown file type)\n");
XX }
XX}
XX
XXstatic char *
XXitype(mode)
XX u_short mode;
XX{
XX switch(mode & IFMT) {
XX#ifdef IFIFO
XX case IFIFO:
XX return("fifo");
XX#endif
XX case IFCHR:
XX return("chr");
XX case IFDIR:
XX return("dir");
XX case IFBLK:
XX return("blk");
XX case IFREG:
XX return("reg");
XX case IFLNK:
XX return("link");
XX case IFSOCK:
XX return("sock");
XX default:
XX return("unk");
XX }
XX /*NOTREACHED*/
XX}
XX
XX#ifdef sun
XXstatic char *
XXvntype(v)
XX enum vtype v;
XX{
XX switch (v) {
XX case VNON:
XX return("vnon");
XX case VREG:
XX return("vreg");
XX case VDIR:
XX return("vdir");
XX case VBLK:
XX return("vblk");
XX case VCHR:
XX return("vchr");
XX case VLNK:
XX return("vlnk");
XX case VSOCK:
XX return("vsock");
XX case VBAD:
XX return("vbad");
XX case VFIFO:
XX return("vfifo");
XX default:
XX return("vunk");
XX }
XX /* NOTREACHED */
XX}
XX#endif
XX
XXstatic
XXsocktrans(sock)
XX struct socket *sock;
XX{
XX static char *stypename[] = {
XX "unused", /* 0 */
XX "stream", /* 1 */
XX "dgram", /* 2 */
XX "raw", /* 3 */
XX "rdm", /* 4 */
XX "seqpak" /* 5 */
XX };
XX#define STYPEMAX 5
XX struct socket so;
XX struct protosw proto;
XX struct domain dom;
XX struct inpcb inpcb;
XX struct unpcb unpcb;
XX int len;
XX char dname[32], *strcpy();
XX
XX /* fill in socket */
XX if (kread((ls_t)sock, (char *)&so, sizeof(so)) != sizeof(so)) {
XX rerr2(errno, (int)sock, "socket");
XX return;
XX }
XX
XX /* fill in protosw entry */
XX if (kread((ls_t)so.so_proto, (char *)&proto, sizeof(proto))
XX != sizeof(proto)) {
XX rerr2(errno, (int)so.so_proto, "protosw");
XX return;
XX }
XX
XX /* fill in domain */
XX if (kread((ls_t)proto.pr_domain, (char *)&dom, sizeof(dom))
XX != sizeof(dom)) {
XX rerr2(errno, (int)proto.pr_domain, "domain");
XX return;
XX }
XX
XX /*
XX * grab domain name
XX * kludge "internet" --> "inet" for brevity
XX */
XX if (dom.dom_family == AF_INET)
XX (void)strcpy(dname, "inet");
XX else {
XX if ((len = kread((ls_t)dom.dom_name, dname, sizeof(dname) -1))
XX < 0) {
XX rerr2(errno, (int)dom.dom_name, "char");
XX dname[0] = '\0';
XX }
XX else
XX dname[len] = '\0';
XX }
XX
XX if ((u_short)so.so_type > STYPEMAX)
XX (void) printf("* (%s unk%d %x", dname, so.so_type, so.so_state);
XX else
XX (void) printf("* (%s %s %x", dname, stypename[so.so_type],
XX so.so_state);
XX
XX /*
XX * protocol specific formatting
XX *
XX * Try to find interesting things to print. For tcp, the interesting
XX * thing is the address of the tcpcb, for udp and others, just the
XX * inpcb (socket pcb). For unix domain, its the address of the socket
XX * pcb and the address of the connected pcb (if connected). Otherwise
XX * just print the protocol number and address of the socket itself.
XX * The idea is not to duplicate netstat, but to make available enough
XX * information for further analysis.
XX */
XX switch(dom.dom_family) {
XX case AF_INET:
XX getinetproto(proto.pr_protocol);
XX if (proto.pr_protocol == IPPROTO_TCP ) {
XX if (so.so_pcb) {
XX if (kread((ls_t)so.so_pcb, (char *)&inpcb,
XX sizeof(inpcb))
XX != sizeof(inpcb)) {
XX rerr2(errno, (int)so.so_pcb, "inpcb");
XX return;
XX }
XX (void) printf(" %x", (int)inpcb.inp_ppcb);
XX }
XX }
XX else if (so.so_pcb)
XX (void) printf(" %x", (int)so.so_pcb);
XX break;
XX case AF_UNIX:
XX /* print address of pcb and connected pcb */
XX if (so.so_pcb) {
XX (void) printf(" %x", (int)so.so_pcb);
XX if (kread((ls_t)so.so_pcb, (char *)&unpcb,
XX sizeof(unpcb))
XX != sizeof(struct unpcb)) {
XX rerr2(errno, (int)so.so_pcb, "unpcb");
XX return;
XX }
XX if (unpcb.unp_conn) {
XX char shoconn[4], *cp;
XX
XX cp = shoconn;
XX if (!(so.so_state & SS_CANTRCVMORE))
XX *cp++ = '<';
XX *cp++ = '-';
XX if (!(so.so_state & SS_CANTSENDMORE))
XX *cp++ = '>';
XX *cp = '\0';
XX (void) printf(" %s %x", shoconn,
XX (int)unpcb.unp_conn);
XX }
XX }
XX break;
XX default:
XX /* print protocol number and socket address */
XX (void) printf(" %d %x", proto.pr_protocol, (int)sock);
XX }
XX (void) printf(")\n");
XX}
XX
XX/*
XX * getinetproto --
XX * print name of protocol number
XX */
XXstatic
XXgetinetproto(number)
XX int number;
XX{
XX char *cp;
XX
XX switch(number) {
XX case IPPROTO_IP:
XX cp = "ip";
XX break;
XX case IPPROTO_ICMP:
XX cp ="icmp";
XX break;
XX case IPPROTO_GGP:
XX cp ="ggp";
XX break;
XX case IPPROTO_TCP:
XX cp ="tcp";
XX break;
XX case IPPROTO_EGP:
XX cp ="egp";
XX break;
XX case IPPROTO_PUP:
XX cp ="pup";
XX break;
XX case IPPROTO_UDP:
XX cp ="udp";
XX break;
XX#ifdef IPPROTO_IDP
XX case IPPROTO_IDP:
XX cp ="idp";
XX break;
XX#endif
XX case IPPROTO_RAW:
XX cp ="raw";
XX break;
XX default:
XX (void) printf(" %d", number);
XX return;
XX }
XX (void) printf(" %s", cp);
XX}
XX
XXstatic
XXreadf()
XX{
XX struct file lfile;
XX int i;
XX
XX itrans(DTYPE_INODE, (char *)u->u_cdir, WD);
XX for (i = 0; i < NOFILE; i++) {
XX#ifdef DYNIX
XX if (u->u_lofile[i].of_file == NULL)
XX continue;
XX if (kread((ls_t)vtophys((ls_t)u->u_lofile[i].of_file),
XX#else
XX if (u->u_ofile[i] == 0)
XX continue;
XX if (kread((ls_t)u->u_ofile[i],
XX#endif
XX (char *)&lfile, sizeof(lfile)) != sizeof(lfile))
XX {
XX rerr1("file", N_KMEM);
XX continue;
XX }
XX itrans(lfile.f_type, (char *)lfile.f_data, i);
XX }
XX}
XX
XXstatic
XXdevmatch(idev, inum, name)
XX dev_t idev;
XX ino_t inum;
XX char **name;
XX{
XX register DEVS *d;
XX
XX for (d = devs; d; d = d->next)
XX if (d->dev == idev && (d->inum == 0 || d->inum == inum)) {
XX *name = d->name;
XX return(1);
XX }
XX return(0);
XX}
XX
XXstatic
XXgetfname(filename)
XX char *filename;
XX{
XX struct stat statbuf;
XX DEVS *cur;
XX char *malloc();
XX
XX if (stat(filename, &statbuf)) {
XX perror(filename);
XX return(0);
XX }
XX if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) {
XX (void) fprintf(stderr, "%s: out of space\n", pname);
XX exit(1);
XX }
XX cur->next = devs;
XX devs = cur;
XX
XX /* if file is block special, look for open files on it */
XX if ((statbuf.st_mode & S_IFMT) != S_IFBLK) {
XX cur->inum = statbuf.st_ino;
XX cur->dev = statbuf.st_dev;
XX }
XX else {
XX cur->inum = 0;
XX cur->dev = statbuf.st_rdev;
XX }
XX cur->name = filename;
XX return(1);
XX}
XX
XXstatic
XXopenfiles()
XX{
XX#ifdef sun
XX if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY)) == 0) {
XX perror ("kvm");
XX exit(1);
XX }
XX#endif
XX if ((kmem = open(N_KMEM, O_RDONLY, 0)) < 0) {
XX perror(N_KMEM);
XX exit(1);
XX }
XX if ((mem = open(N_MEM, O_RDONLY, 0)) < 0) {
XX perror(N_MEM);
XX exit(1);
XX }
XX if ((swap = open(N_SWAP, O_RDONLY, 0)) < 0) {
XX perror(N_SWAP);
XX exit(1);
XX }
XX}
XX
XXstatic
XXkread(addr, buf, len)
XX ls_t addr;
XX char *buf;
XX int len;
XX{
XX#ifdef sun
XX return(kvm_read(kd, (u_long)addr, buf, len));
XX#else
XX (void) lseek(kmem, addr, L_SET);
XX return(read(kmem, buf, len));
XX#endif
XX}
XX
XXstatic
XXrerr1(what, fromwhat)
XX char *what, *fromwhat;
XX{
XX if (vflg)
XX (void) printf("%s: error reading %s from %s",
XX pname, what, fromwhat);
XX}
XX
XXstatic
XXrerr2(err, address, what)
XX int err, address;
XX char *what;
XX{
XX if (vflg)
XX (void) printf("%s: error reading %s at %x from kmem: %s\n",
XX pname, what, address, sys_errlist[err]);
XX}
XX
XXstatic long
XXlgetw(loc)
XX ls_t loc;
XX{
XX long word;
XX
XX if (kread((ls_t)loc, (char *)&word, sizeof(word)) != sizeof(word))
XX rerr2(errno, (int)loc, "word");
XX return(word);
XX}
XX
XXstatic
XXusage()
XX{
XX (void) fprintf(stderr,
XX "usage: %s [-v] [-u user] [-p pid] [filename ...]\n", pname);
XX exit(1);
XX}
XX
XX#ifdef DYNIX
XXstatic ls_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#endif /* DYNIX */
SHAR_EOF
if test 20280 -ne "`wc -c fstat.c`"
then
echo shar: error transmitting fstat.c '(should have been 20280 characters)'
fi
echo shar: extracting fstat.8 '(6096 characters)'
sed 's/^XX//' << \SHAR_EOF > fstat.8
XX.\" Copyright (c) 1987 Regents of the University of California.
XX.\" All rights reserved.
XX.\"
XX.\" Redistribution and use in source and binary forms are permitted
XX.\" provided that the above copyright notice and this paragraph are
XX.\" duplicated in all such forms and that any documentation,
XX.\" advertising materials, and other materials related to such
XX.\" distribution and use acknowledge that the software was developed
XX.\" by the University of California, Berkeley. The name of the
XX.\" University may not be used to endorse or promote products derived
XX.\" from this software without specific prior written permission.
XX.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
XX.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
XX.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
XX.\"
XX.\" @(#)fstat.8 5.4 (Berkeley) 7/9/88
XX.\"
XX.TH FSTAT 8 "July 9, 1988"
XX.UC 4
XX.SH NAME
XXfstat \- identify open files
XX.SH SYNOPSIS
XX.B fstat
XX[
XX.B \-u
XXuser ] [
XX.B \-p
XXpid ] [
XX.B filename...
XX]
XX.SH DESCRIPTION
XX.I Fstat
XXidentifies open files.
XXA file is considered open if a process has it open,
XXif it is the working directory for a process,
XXor if it is an active pure text file.
XXIf no options are specified,
XX.I fstat
XXreports on all open files.
XX.SH OPTIONS
XX.TP \w`filename...`u+4
XX.B \-u
XXrequests a report of all files open by a specified user.
XX.TP
XX.B \-p
XXrequests a report of all files open by a specified process id.
XX.TP
XX.B filename...
XXrestricts the reports to the specified files.
XXIf a file is a block special file,
XX.I fstat
XXadditionally reports on any open files on that device,
XXtreating it as a mounted file system.
XX.SH OUTPUT
XXThe following fields are printed
XX.TP \w'sockets'u+4
XX.B USER
XXis the user name of the owner of the process.
XX.TP
XX.B CMD
XXis the command name of the process.
XX.TP
XX.B PID
XXis the process id.
XX.TP
XX.B FD
XXis the file descriptor number in the per\-process open file table.
XXThere are two special file descriptors:
XX.RS
XX.TP \w'text'u+4
XX.B text
XXmeans that the file is the pure text inode (gnode under ULTRIX)
XXof the process.
XXPure text inodes do not exist on DYNIX and Sun hosts.
XX.TP
XX.B wd
XXsignifies the working directory of the process.
XX.RE
XX.IP
XXIf the file number is followed by an asterisk (*), then the file is not an
XXinode (gnode under ULTRIX), but either a socket, FIFO, or has an error of
XXsome kind.
XXThe format of the rest of the entry is variable, doesn't correspond
XXto the headings, and is enclosed in parenthesis.
XXThe
XX.B SOCKET
XXsection describes the variable format for sockets.
XX.TP
XX.B DEVICE
XXis a display of the major and minor numbers of the device where this
XXfile's inode (gnode under ULTRIX) resides.
XX.IP
XXIf the file lacks an inode \- e. g., a Sun, stream, clone file \- the
XXdevice information is taken from the vnode, and represents the file's
XXmajor and minor device numbers.
XX.TP
XX.B INODE
XXis the inode (gnode under ULTRIX) number of the file.
XXIt will be ``none'' on Sun hosts where the file is a cloned stream.
XX.TP
XX.B SIZE
XXis the size in bytes of the file, where applicable.
XX.TP
XX.B TYPE
XXis the type of the file, as found in
XX.I /usr/include/sys/file.h
XX(or
XX.I /usr/include/sys/vnode.h
XXon Sun hosts.)
XX.I
XX.TP
XX.B NAME
XXare the specified file names, if any.
XX.TP
XX.B SOCKET
XXThe information displayed for an open socket depends on its protocol domain.
XXThe first three fields are always the same:
XXfield one is the domain name;
XXfield two is the socket type (stream, dgram, etc);
XXand field three is the socket flags field in hex (see
XX.IR /usr/include/sys/socketvar.h .)
XX.IP
XXThe remaining fields are protocol dependent.
XXThere is a final field for TCP sockets: the address of the TCPCB;
XXfor UDP, the INPCB (socket PCB).
XXFor \s-2UNIX\s0 domain sockets, the remaining two fields display the address
XXof the socket PCB and the address of the connected PCB.
XXOtherwise, the protocol number and address of the socket itself are printed
XXas the final field.
XX.IP
XXThe intent is to supplement
XX.IR netstat (8).
XXFor example, the addresses mentioned above are the addresses that
XXthe ``netstat -A'' command would print for TCP, UDP, and \s-2UNIX\s0
XXdomain.
XX.IP
XXNote that, since
XX.IR pipe (2)
XXis implemented with sockets, a pipe appears as
XXa connected \s-2UNIX\s0 domain stream socket.
XXA unidirectional \s-2UNIX\s0
XXdomain socket indicates the direction of
XXflow with an arrow (``<-'' or ``->''), and a full duplex socket shows
XXa double arrow (``<->'').
XX.SH EXAMPLES
XXThis example shows the use of
XX.I fstat
XXto display information on the file
XX.IR /usr/spool/lpd/lock .
XX.PP
XX.nf
XX% fstat /usr/spool/lpd/lock
XX.br
XXUSER CMD PID FD DEVICE INODE SIZE TYPE NAME
XXroot lpd 113 3 9, 35 26683 6 reg /usr/spool/lpd/lock
XX.fi
XX.PP
XXThis example shows the use of
XX.I fstat
XXto display all the files of a process that has
XX.I /usr/spool/lpd/lock
XXopen.
XX.PP
XX.nf
XX% fstat -p 113
XXUSER CMD PID FD DEVICE INODE SIZE TYPE
XXroot lpd 113 text 9, 35 18949 74752 reg
XXroot lpd 113 wd 9, 35 26624 512 dir
XXroot lpd 113 0 9, 0 4103 0 chr
XXroot lpd 113 1 9, 0 4103 0 chr
XXroot lpd 113 2 9, 35 26634 37 reg
XXroot lpd 113 3 9, 35 26683 6 reg
XXroot lpd 113 4* (inet stream 80 tcp 80f6770c)
XX.fi
XX.PP
XXThis example shows the use of
XX.IR netstat (8),
XX.IR grep (1)
XXand
XX.I fstat
XXto locate the process that has a socket open on the ``smtp''
XXnetwork port.
XXThe
XX.B \-aA
XXarguments direct
XX.I netstat
XXto display all protocol control block (PCB) addresses,
XXand the
XX.I fstat
XXcommand displays all files, filtering the output through
XX.I grep
XXto locate the specific PCB.
XX.PP
XX.nf
XX% netstat -aA | grep smtp
XX80f67a8c tcp 0 0 *.smtp *.* LISTEN
XX% fstat | grep 80f67a8c
XXroot sendmail 108 5* (inet stream 80 tcp 80f67a8c)
XX.fi
XX.SH BUGS
XXSocket information clutters the output.
XX.PP
XXSince \fIfstat\fP takes a snapshot of the system, it is only correct for
XXa very short period of time.
XX.PP
XX.I Fstat
XXdoes not work on diskless Sun clients, because there are no inodes.
XX.SH AUTHORS
XX.I Fstat
XXcomes from the 4.3BSD Tahoe distribution.
XX.PP
XXVic Abell of the Purdue University Computing Center ported it to
XXDYNIX 3.0.1[24] for the Sequent Balance and Symmetry machines,
XXSunOS 4.0 and ULTRIX 2.2.
XX.SH SEE ALSO
XXps(1),
XXpstat(8),
XXofiles(8L).
SHAR_EOF
if test 6096 -ne "`wc -c fstat.8`"
then
echo shar: error transmitting fstat.8 '(should have been 6096 characters)'
fi
# End of shell archive
exit 0