home *** CD-ROM | disk | FTP | other *** search
- Path: wugate!wucs1!uunet!bbn.com!rsalz
- From: rsalz@bbn.com (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v18i107: Show all open files status
- Message-ID: <1681@papaya.bbn.com>
- Date: 19 Apr 89 19:06:23 GMT
- Organization: BBN Laboratories Inc., Cambridge MA
- Lines: 1363
- 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
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
-