This is ofiles.c in view mode; [Download] [Up]
/*
* ofiles.c - show open files
*/
/*
* Copyright 1991 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by: Victor A. Abell
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1991 Purdue Research Foundation.\nAll rights reserved.\n";
#endif
/*
* Ofiles displays files opened by processes of the NeXTStep 1.0a and
* 2.0 systems for the NeXT work station.
*/
/*
* Usage:
*
* ofiles [-h] [-n] [-N] [-p] [-P n] [-u] [-U n] [names]
*
* where:
*
* -h Display help.
*
* -n Display Internet network files.
*
* -N Display NFS files.
*
* -p Display only Process ID numbers.
* (disables header)
*
* -P n Display files for process ID number n.
*
* -u Display Unix domain sockets.
*
* -U n Display files for User ID number n.
*
* names are the names of files to locate.
*/
/*
* Compile options:
*
* NS=xx where xx is the NeXTStep version
* 10 for version 1.0a
* 20 for version 2.0
(No other NeXTStep versions have been tested.)
*
* VMUNIX is the path to the kernel name list file
*
* See the Makefile for ways to supply these options.
*
*/
#ifndef MACH
#define MACH 1 /* for proper vnode definition */
#endif
#ifndef NCPUS
#define NCPUS 1 /* number of CPU's */
#endif
#ifndef NS
#define NS 20 /* NeXTStep version */
#endif
#ifndef VMUNIX
#define VMUNIX "/mach" /* namelist file path */
#endif
#include <sys/param.h>
#include <c.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <mntent.h>
#include <string.h>
#include <nlist.h>
#if NS<20
#include <sys/queue.h>
#else /* NS>=20 */
#include <kern/queue.h>
#endif
#ifndef KERNEL
#define KERNEL
#endif
#include <sys/file.h>
#undef KERNEL
#if NS>=20
#include <sys/policy.h>
#endif
#ifndef SHOW_UTT
#define SHOW_UTT
#endif
#if NS<20
#include "NS_1.0a_user.h"
#else /* NS>=20 */
#include <sys/user.h>
#endif
#undef SHOW_UTT
#include <sys/dir.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/stat.h>
#if NS>=20
#include <sys/ucred.h>
#endif
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
#include <ufs/inode.h>
#if NS<20
#include <sys/task.h>
#else /* NS>=20 */
#include <kern/task.h>
#endif
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <nfs/nfs.h>
#include <nfs/nfs_clnt.h>
#include <nfs/rnode.h>
extern int errno;
extern char *optarg;
extern int optind;
extern char *sys_errlist[];
static struct nlist nl[] = {
{ {"_allproc"}, 0, 0, 0 },
#define X_ALLPROC 0
{ {"_nfs_vnodeops"}, 0, 0, 0},
#define X_NFS_OPS 1
{ {""}, 0, 0, 0 },
};
#define DEVINCR 1024 /* device table malloc() increment */
#define STATTMO 5 /* stat() timeout (seconds) */
char *Command; /* command name */
dev_t Dev; /* device number */
char Devch[32]; /* alternate characters for device printing */
struct dev {
int key; /* ((mode & S_IFMT) << 4) + (dev_t & 0xffff) */
char *name; /* /dev/<name> */
} *Devtp = NULL; /* device table pointer */
char Fd[4]; /* file descriptor for printing */
int Fdev = 0; /* have device number flag */
int Fhelp = 0; /* -h flag status */
int Fnet = 0; /* -n flag status */
int Fnfs = 0; /* -N flag status */
int Fprint = 0; /* print line flag */
int Fproc = 0; /* -p flag status */
int Fpid = 0; /* -P flag status */
int Fuid = 0; /* -U flag status */
int Funix = 0; /* -u flag status */
int Hdr = 0; /* header print status */
int Inode = -1; /* inode number (-1 if none) */
int Kmem = -1; /* /dev/kmem fd */
int Lock = 0; /* exclusive/shared lock count */
char Namech[1024]; /* name characters for printing */
struct mounts {
char *dir; /* directory */
char *fsname; /* file system */
struct mounts *next; /* forward link */
dev_t dev; /* device */
} *Mtab = NULL; /* mounted devices */
int Ndev = 0; /* number of device table entries */
struct dev **Sdev = NULL; /* pointer to device table pointers, sorted
* by key */
struct sfile {
char *name; /* file name */
dev_t dev; /* device */
u_short mode; /* mode */
ino_t i; /* inode number */
int f; /* file found flag */
struct sfile *next; /* link to next entry */
} *Sfile = NULL; /* chain of files to search for */
int Spid; /* Process ID to search for */
int Suid; /* User ID to search for */
int Pid; /* Process ID */
char *Pn; /* program name */
jmp_buf Tmo_jbuf; /* stattimeout jump buffer */
char Type[5]; /* type for printing */
int Uid; /* User ID */
int compdev(), printmnt();
char *endnm();
void printdevname(), printfile(), printinaddr(), printiproto(),
printline(), printrnode(), printsocket(), printvnode(),
readdev(), readmnt(), stattimeout();
main(argc, argv)
int argc;
char *argv[];
{
int c, err, i, nb, ndev;
struct file f;
#if NS>=20
struct file **ofp = NULL;
#endif
struct proc *np, p, *procp;
struct sfile *sfp;
struct stat sb;
struct task t;
struct utask ut;
/*
* Save program name for messages.
*/
if ((Pn = strrchr(argv[0], '/')) != NULL)
Pn++;
else
Pn = argv[0];
/*
* Process arguments.
*/
while ((c = getopt(argc, argv, "hnNpP:uU:")) != EOF) {
switch(c) {
case 'h':
Fhelp = 1;
break;
case 'n':
Fnet = 1;
break;
case 'N':
Fnfs = 1;
break;
case 'p':
Fproc = 1;
break;
case 'P':
Fpid = 1;
Spid = atoi(optarg);
break;
case 'u':
Funix = 1;
break;
case 'U':
Fuid = 1;
Suid = atoi(optarg);
break;
case '?':
err++;
break;
default:
(void) fprintf(stderr, "%s: unknown option (%c)\n",
Pn, c);
err++;
}
}
/*
* Process any file names.
*/
for (i = optind; i < argc; i++) {
if (stat(argv[i], &sb) != 0) {
(void) fprintf(stderr, "%s: can't find %s: %s\n",
Pn, argv[i], sys_errlist[errno]);
err++;
continue;
}
if ((sfp = (struct sfile *)malloc(sizeof(struct sfile)))
== NULL) {
(void) fprintf(stderr, "%s: no space for files\n", Pn);
exit(1);
}
sfp->next = Sfile;
Sfile = sfp;
sfp->name = argv[i];
if ((sfp->mode = (sb.st_mode & S_IFMT)) == S_IFCHR
|| sfp->mode == S_IFBLK
|| (sb.st_dev & 0x8000))
sfp->dev = sb.st_rdev;
else
sfp->dev = sb.st_dev;
sfp->i = sb.st_ino;
sfp->f = 0;
}
/*
* Display usage if error or if requested.
*/
if (err || Fhelp) {
(void) fprintf(stderr,
"%s usage: [-h] [-n] [-N] [-p] [-P n] [-u] [-U n]", Pn);
(void) fprintf(stderr,
" [names]\n");
(void) fprintf(stderr,
"\t-h display help\n");
(void) fprintf(stderr,
"\t-l n set lines per header to n (0 for no header)");
(void) fprintf(stderr,
"\t-n display Internet network files\n");
(void) fprintf(stderr,
"\t-N display NFS files\n");
(void) fprintf(stderr,
"\t-p display only Process ID numbers (disables header)\n");
(void) fprintf(stderr,
"\t-P n display files for process ID number n\n");
(void) fprintf(stderr,
"\t-u display Unix domain sockets\n");
(void) fprintf(stderr,
"\t-U n display files for User ID number n\n");
(void) fprintf(stderr,
"\tnames of files to locate\n");
if (err)
exit(1);
exit(0);
}
/*
* Open /dev/kmem and read selected names from VMUNIX.
*
* Read and build device and mount tables.
*/
if ((Kmem = open("/dev/kmem", O_RDONLY, 0)) < 0) {
(void) fprintf(stderr, "%s: can't open /dev/kmem: %s\n",
Pn, sys_errlist[errno]);
exit(1);
}
if (nlist(VMUNIX, nl) == -1) {
(void) fprintf(stderr, "%s: can't read namelist\n", Pn);
exit(1);
}
if (nl[X_ALLPROC].n_value == 0l) {
(void) fprintf(stderr, "%s: no address for %s\n",
Pn, nl[X_ALLPROC].n_un.n_name);
exit(1);
}
if (kread((off_t)nl[X_ALLPROC].n_value, (char *)&procp, sizeof(procp))
!= sizeof(procp)) {
(void) fprintf(stderr,
"%s: can't read nl[X_ALLPROC].n_un.n_name: %s\n",
Pn, sys_errlist[errno]);
exit(1);
}
(void) readdev();
(void) readmnt();
/*
* Read the processes on the "all processes" list.
*/
for(np = procp; np; np = p.p_nxt) {
if (kread((off_t) np, &p, sizeof(p)) != sizeof(p)) {
(void) fprintf(stderr,
"%s: can't read proc struct at %x\n",
Pn, np);
exit(1);
}
if (Fpid && p.p_pid != Spid)
continue;
/*
* Read the task associated with the process, and the user
* area assocated with the task.
*/
if (kread((off_t) p.task, &t, sizeof(t)) != sizeof(t))
continue;
if ((struct proc *)t.proc != np)
continue;
if (kread((off_t) t.u_address, &ut, sizeof(ut)) != sizeof(ut))
continue;
if ((struct proc *)ut.uu_procp != np)
continue;
if (Fuid && Suid != p.p_uid)
continue;
/*
* Print information on the current directory.
*/
if (ut.uu_cdir) {
Command = ut.uu_comm;
Fdev = 0;
Devch[0] = Type[0] = '\0';
(void) strcpy(Fd, "cd");
Fprint = (Fnet || Fnfs || Funix || Sfile) ? 0 : 1;
Inode = -1;
Lock = 0;
Namech[0] = '\0';
Pid = p.p_pid;
Uid = p.p_uid;
printvnode(ut.uu_cdir);
}
#if NS>=20
/*
* Get the file pointers from the user area.
*/
if (ofp != NULL)
(void) free(ofp);
nb = sizeof(struct file) * ut.uu_ofile_cnt;
if ((ofp = (struct file **)malloc((size_t)nb)) == NULL) {
(void) fprintf(stderr,
"%s: no file table space, process %d\n",
Pn, p.p_pid);
exit(1);
}
if (kread((off_t) ut.uu_ofile, ofp, nb) != nb)
continue;
#endif
/*
* Print information on all the files referenced from the user area.
*/
#if NS>=20
for (i = 0; i < ut.uu_ofile_cnt; i++) {
if (ofp[i]) {
#else /* NS<20 */
for (i = 0; i < NOFILE; i++) {
if (ut.uu_ofile[i]) {
#endif
Command = ut.uu_comm;
Fdev = 0;
Devch[0] = Type[0] = '\0';
(void) sprintf(Fd, "%2d", i);
Fprint = (Fnet || Fnfs || Funix || Sfile) ? 0
: 1;
Inode = -1;
Lock = 0;
Namech[0] = '\0';
Pid = p.p_pid;
Uid = p.p_uid;
#if NS>=20
printfile(ofp[i]);
#else /* NS<20 */
printfile(ut.uu_ofile[i]);
#endif
}
}
}
for (sfp = Sfile; sfp; sfp = sfp->next) {
if (sfp->f == 0)
exit(1);
}
exit(0);
}
/*
* compdev() - compare device numbers
*/
compdev(p1, p2)
struct dev **p1;
struct dev **p2;
{
if ((*p1)->key < (*p2)->key)
return(-1);
if ((*p1)->key == (*p2)->key)
return(0);
return(1);
}
/*
* endnm() - locate end of Namech
*/
char *
endnm()
{
char *s;
for (s = Namech; *s; s++)
;
return(s);
}
/*
* isfile() - is file selected for printing
*/
isfile(d, i)
dev_t d; /* device */
ino_t i; /* inode */
{
struct sfile *s;
for (s = Sfile; s; s = s->next) {
if (d == s->dev) {
if (s->mode == S_IFCHR || s->mode == S_IFBLK
|| i == s->i) {
(void) strcat(Namech, s->name);
s->f = 1;
return(1);
}
}
}
return(0);
}
/*
* kread() - read from kernel memory
*/
kread(addr, buf, len)
off_t addr; /* kernel memory address */
char *buf; /* buffer to receive data */
int len; /* length to read */
{
if (lseek(Kmem, addr, L_SET) < 0)
return(-1);
return(read(Kmem, buf, len));
}
/*
* printdevname() - print device name
*/
void
printdevname(mode, rdev)
u_short mode; /* S_IFMT mode */
dev_t rdev; /* device */
{
int key, low, hi, mid;
struct dev *dp;
key = (mode << 4) + (rdev & 0xffff);
low = mid = 0;
hi = Ndev;
while (low <= hi) {
mid = (low + hi) / 2;
dp = Sdev[mid];
if (key < dp->key)
hi = mid - 1;
else if (key > dp->key)
low = mid + 1;
else {
(void) sprintf(Namech, "/dev/%s", dp->name);
return;
}
}
(void) strcpy(Namech, "name unknown");
}
/*
* printfile() - print file information
*/
void
printfile(fp)
struct file *fp; /* kernel file table address */
{
struct file f;
if (kread((off_t) fp, (char *) &f, sizeof(f)) != sizeof(f)) {
(void) sprintf(Namech, "can't read file struct from %x", fp);
} else {
if (f.f_count) {
if (f.f_type == DTYPE_VNODE) {
printvnode(f.f_data);
} else {
printsocket(f.f_data);
}
}
}
return;
}
/*
* printinaddr() - print Internet address
*/
void
printinaddr(ia, p)
struct in_addr *ia; /* Internet address */
u_short p; /* port */
{
unsigned char *u;
if (ia->s_addr == INADDR_ANY) {
(void) sprintf(endnm(), "*:%d", p);
return;
}
u = (unsigned char *) ia;
(void) sprintf(endnm(), "%u.%u.%u.%u:%u", u[0], u[1], u[2], u[3], p);
}
/*
* printiproto(p) - print Internet protocol name
*/
void
printiproto(p)
int p; /* protocol number */
{
char *s;
switch(p) {
#ifdef IPPROTO_TCP
case IPPROTO_TCP:
s = "TCP";
break;
#endif
#ifdef IPPROTO_UDP
case IPPROTO_UDP:
s = "UDP";
break;
#endif
#ifdef IPPROTO_IP
case IPPROTO_IP:
s = "IP";
break;
#endif
#ifdef IPPROTO_ICMP
case IPPROTO_ICMP:
s = "ICMP";
break;
#endif
#ifdef IPPROTO_IGMP
case IPPROTO_IGMP:
s = "IGMP";
break;
#endif
#ifdef IPPROTO_GGP
case IPPROTO_GGP:
s = "GGP";
break;
#endif
#ifdef IPPROTO_EGP
case IPPROTO_EGP:
s = "EGP";
break;
#endif
#ifdef IPPROTO_PUP
case IPPROTO_PUP:
s = "PUP";
break;
#endif
#ifdef IPPROTO_IDP
case IPPROTO_IDP:
s = "IDP";
break;
#endif
#ifdef IPPROTO_ND
case IPPROTO_ND: return "nd";
s = "ND";
break;
#endif
#ifdef IPPROTO_RAW
case IPPROTO_RAW:
s = "RAW";
break;
#endif
default:
s = "unknown";
}
(void) sprintf(Devch, "%8.8s", s);
}
/*
* printmnt(dev) - print mount entry for device
*/
printmnt(rdev)
dev_t rdev; /* device */
{
struct mounts *mtp;
if (rdev & 0x8000)
rdev |= 0xff00;
for (mtp = Mtab; mtp; mtp = mtp->next) {
if (rdev == mtp->dev) {
(void) sprintf(Namech, "%s (%s)", mtp->dir,
mtp->fsname);
return(1);
}
}
return(0);
}
/*
* printrnode() - print NFS information from rnode
*/
void
printrnode(vp)
struct vnode *vp;
{
struct inode ic;
struct mntinfo m;
struct rnode r;
char *s;
struct vfs v;
struct vnode vc;
/*
* Read associated rnode, vfs structure and mntinfo structures.
*/
if (vp->v_vfsp == NULL) {
(void) sprintf(Namech, "no vfs address in %x", vp);
printline();
return;
}
if (kread((off_t) vp->v_data, &r, sizeof(r)) != sizeof(r)) {
(void) sprintf(Namech, "can't read rnode at %x", vp->v_data);
printline();
return;
}
if (kread((off_t) vp->v_vfsp, &v, sizeof(v)) != sizeof(v)) {
(void) sprintf(Namech, "can't read vfs at %x", vp->v_vfsp);
printline();
return;
}
if (v.vfs_data == NULL) {
(void) sprintf(Namech, "no mntinfo address in %x", vp->v_vfsp);
printline();
return;
}
if (kread((off_t) v.vfs_data, &m, sizeof(m)) != sizeof(m)) {
(void) sprintf(Namech, "can't read mntinfo at %x", v.vfs_data);
printline();
return;
}
if (Fnfs)
Fprint = 1;
else if (Sfile)
#if NS<20
Fprint = isfile((dev_t)(r.r_nfsattr.na_rdev & 0xffff),
(ino_t)r.r_nfsattr.na_nodeid);
#else /* NS>=20 */
Fprint = isfile(vp->v_rdev, (ino_t)r.r_attr.va_nodeid);
#endif
if (Namech[0] == '\0')
#if NS<20
(void) sprintf(Namech, "%s (%s)", v.vfs_name, m.mi_hostname);
#else /* NS>=20 */
(void) printmnt((dev_t)r.r_attr.va_fsid);
#endif
/*
* If the vfs structure covers another vnode (the mount point), and we
* don't know the file name, read the covered vnode and associated inode.
*/
if (v.vfs_vnodecovered && Namech[0] == '\0') {
if (kread((off_t) v.vfs_vnodecovered, &vc, sizeof(vc))
== sizeof(vc)) {
if (vc.v_type == VDIR && vc.v_data) {
if (kread((off_t) vc.v_data, &ic, sizeof(ic))
== sizeof(ic)) {
printdevname(S_IFBLK, ic.i_dev);
(void) sprintf(endnm(), "%s (%s)",
Namech[0] ? "" : "NFS",
m.mi_hostname);
}
}
}
}
/*
* Display the remote device, remote inode and host name.
*/
#if NS<20
Dev = (dev_t)r.r_nfsattr.na_fsid;
#else /* NS>=20 */
Dev = (dev_t)r.r_attr.va_fsid;
#endif
Fdev = 1;
#if NS<20
Inode = (ino_t)r.r_nfsattr.na_nodeid;
#else /* NS>=20 */
Inode = (ino_t)r.r_attr.va_nodeid;
#endif
if (Namech[0] == '\0')
(void) sprintf(endnm(), "NFS (%s)", m.mi_hostname);
printline();
}
/*
* printline() - print output line
*/
void
printline()
{
if (Fprint == 0)
return;
if (Fproc) {
(void) printf("%d\n", Pid);
return;
}
if (Hdr == 0) {
(void) printf("COMMAND PID UID FD TYPE DEVICE INODE");
(void) printf(" NAME/[LOCAL][REMOTE]\n");
}
Hdr++;
(void) printf("%-7.7s %5d %5d %2s%c%4.4s ",
Command,
Pid,
Uid,
Fd,
Lock ? '*' : ' ',
Type
);
if (Fdev)
(void) printf(" %3d,%3d ", (Dev >> 8) & 0xff, Dev &0xff);
else {
if (Devch[0])
(void) printf("%8.8s ", Devch);
else
(void) printf(" ");
}
if (Inode >= 0)
(void) printf("%5d ", Inode);
else
(void) printf(" ");
(void) printf("%s\n", Namech);
}
/*
* printsocket(sp) - print socket
*/
void
printsocket(sp)
caddr_t *sp; /* socket's kernel address */
{
struct domain d;
struct inode i;
struct inpcb inp;
int is = 0;
struct mbuf mb;
struct protosw p;
struct socket s;
char *sep;
struct sockaddr_un *ua;
struct unpcb uc, unp;
struct vnode v;
/*
* Read the socket, the associated protocol switch table entry, and the
* associated domain structure.
*/
(void) strcpy(Type, "sock");
if (kread((off_t) sp, (char *) &s, sizeof(s)) != sizeof(s)) {
(void) sprintf(Namech, "can't read socket struct from %x", sp);
printline();
return;
}
if (kread((off_t) s.so_proto, (char *) &p, sizeof(p)) != sizeof(p)) {
(void) sprintf(Namech, "can't read protosw struct from %x",
s.so_proto);
printline();
return;
}
if (kread((off_t) p.pr_domain, (char *) &d, sizeof(d)) != sizeof(d)) {
(void) sprintf(Namech, "can't read domain struct from %x",
p.pr_domain);
printline();
return;
}
/*
* Process socket by the associated domain family.
*/
switch (d.dom_family) {
case AF_INET:
if (Fnet)
Fprint = 1;
(void) strcpy(Type, "inet");
/*
* Read Internet protocol control block.
*/
if (kread((off_t) s.so_pcb, (char *) &inp, sizeof(inp))
!= sizeof(inp))
return;
if ((struct socket *)sp != inp.inp_socket)
return;
printiproto(p.pr_protocol);
if (inp.inp_laddr.s_addr != INADDR_ANY || inp.inp_lport != 0) {
printinaddr(&inp.inp_laddr, inp.inp_lport);
sep = "->";
} else
sep = "";
if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) {
(void) sprintf(endnm(), "%s", sep);
printinaddr(&inp.inp_faddr, inp.inp_fport);
}
break;
case AF_UNIX:
if (Funix)
Fprint = 1;
(void) strcpy(Type, "unix");
/*
* Read Unix protocol control block and the Unix address structure.
*/
(void) sprintf(Devch, "%8x", sp);
if (kread((off_t) s.so_pcb, (char *) &unp, sizeof(unp))
!= sizeof(unp)) {
(void) sprintf(Namech, "can't read unpcb at %x",
s.so_pcb);
break;
}
if ((struct socket *)sp != unp.unp_socket) {
(void) sprintf(Namech, "unp_socket (%x) mismatch",
unp.unp_socket);
break;
}
if (unp.unp_addr) {
if (kread((off_t) unp.unp_addr, (char *) &mb,
sizeof(mb))
!= sizeof(mb)) {
(void) sprintf(Namech,
"can't read unp_addr at %x",
unp.unp_addr);
break;
}
ua = (struct sockaddr_un *)(((char *)&mb) + mb.m_off);
} else {
ua = (struct sockaddr_un *)&mb;
(void) bzero((char *)ua, sizeof(struct sockaddr_un));
ua->sun_family = AF_UNSPEC;
}
/*
* Print information on Unix socket that has no address bound
* to it, although it may be connected to another Unix domain
* socket as a pipe.
*/
if (ua->sun_family != AF_UNIX) {
if (ua->sun_family == AF_UNSPEC) {
if (unp.unp_conn) {
if (kread((off_t) unp.unp_conn,
(char *) &uc, sizeof(uc))
!= sizeof(uc)) {
(void) sprintf(Namech,
"can't read unp_conn at %x",
unp.unp_conn);
} else {
(void) sprintf(Namech,
"->unix %8x", uc.unp_socket);
}
} else
(void) strcpy(Namech, "no address");
} else
(void) sprintf(Namech,
"unknown sun_family (%d)",
ua->sun_family);
break;
}
/*
* Read any associated vnode and then read its assocated inode.
*/
if (unp.unp_vnode) {
if (kread((off_t) unp.unp_vnode, &v, sizeof(v))
== sizeof(v)) {
if (v.v_type == VSOCK) {
if (kread((off_t) v.v_data, &i,
sizeof(i))
== sizeof(i))
is = 1;
}
}
}
/*
* Print Unix socket information.
*/
if (is) {
Dev = i.i_dev;
Fdev = 1;
Devch[0] = '\0';
Inode = i.i_number;
if (Sfile) {
if (isfile(i.i_dev, i.i_number))
Fprint = 1;
break;
}
}
(void) sprintf(Namech, "%.*s",
mb.m_len - sizeof(ua->sun_family),
ua->sun_path[0] ? ua->sun_path : "no address");
break;
default:
(void) strcpy(Type, "sock");
(void) strcpy(Namech, "unknown");
}
printline();
}
/*
* printvnode() - print vnode
*/
void
printvnode(p)
caddr_t p; /* vnode's kernel address */
{
struct inode i;
int j;
struct vnode v;
if (kread((off_t) p, &v, sizeof(v)) != sizeof(v)) {
(void) sprintf(Namech, "can't read vnode at %x", v);
printline();
return;
}
Lock = v.v_shlockc + v.v_exlockc;
switch (v.v_type) {
case VNON:
(void) strcpy(Type, "VNON");
break;
case VREG:
case VDIR:
(void) strcpy(Type, (v.v_type == VREG) ? "VREG" : "VDIR");
if (v.v_data == NULL) {
(void) sprintf(Namech, "no inode/rnode address in %x",
p);
break;
}
if (v.v_op == (struct vnodeops *)nl[X_NFS_OPS].n_value) {
(void) printrnode(&v);
return;
}
if (kread((off_t) v.v_data, &i, sizeof(i)) != sizeof(i)) {
(void) sprintf(Namech, "can't read inode at %x",
v.v_data);
break;
}
Dev = i.i_dev;
Fdev = 1;
Inode = i.i_number;
if (Sfile) {
if (isfile(i.i_dev, i.i_number))
Fprint = 1;
break;
}
if (printmnt(i.i_dev) == 0)
printdevname(S_IFBLK, i.i_dev);
break;
case VBLK:
(void) strcpy(Type, "VBLK");
break;
case VCHR:
Dev = v.v_rdev;
Fdev = 1;
(void) strcpy(Type, "VCHR");
if (Sfile) {
if (isfile(v.v_rdev, 0))
Fprint = 1;
break;
}
printdevname(S_IFCHR, v.v_rdev);
break;
case VLNK:
(void) strcpy(Type, "VLNK");
break;
case VSOCK:
(void) strcpy(Type, "VSOCK");
break;
case VBAD:
(void) strcpy(Type, "VBAD");
break;
case VFIFO:
(void) strcpy(Type, "VFIFO");
break;
case VSTR:
(void) strcpy(Type, "VSTR");
break;
default:
(void) sprintf(Type, "%4d", v.v_type);
(void) strcpy(Namech, "unknown type");
}
printline();
return;
}
/*
* readdev() - read names, modes and device types of everything in /dev
*/
void
readdev()
{
DIR *dfp;
struct direct *dp;
u_short mode;
int err, i;
char path[MAXNAMLEN+1];
struct stat sb;
if ((dfp = opendir("/dev")) == NULL) {
(void) fprintf(stderr, "%s: can't open /dev\n", Pn);
exit(1);
}
(void) strcpy(path, "/dev/");
for (err = i = 0, dp = readdir(dfp); dp; dp = readdir(dfp)) {
if (dp->d_fileno == 0)
continue;
if (dp->d_name[0] == '.')
continue;
(void) strcpy(&path[5], dp->d_name);
if (stat(path, &sb) != 0) {
(void) fprintf(stderr, "%s: can't stat %s: %s\n",
Pn, path, sys_errlist[errno]);
err++;
continue;
}
if ((mode = (sb.st_mode & S_IFMT)) != S_IFCHR
&& mode != S_IFBLK)
continue;
if (i >= Ndev) {
Ndev += DEVINCR;
if (Devtp == NULL)
Devtp = (struct dev *)malloc(
(size_t)((sizeof(struct dev)) * Ndev));
else
Devtp = (struct dev *)realloc((void *)Devtp,
(size_t)(sizeof(struct dev) * Ndev));
if (Devtp == NULL) {
(void) fprintf(stderr,
"%s: no space for devices\n", Pn);
exit(1);
}
}
Devtp[i].key = (mode << 4) + (sb.st_rdev & 0xffff);
if ((Devtp[i].name = (char *)malloc((unsigned)(dp->d_namlen+1)))
== NULL) {
(void) fprintf(stderr, "%s: no space for /dev/%s\n",
Pn, dp->d_name);
exit(1);
}
(void) strcpy(Devtp[i].name, dp->d_name);
i++;
}
if (Ndev > i) {
Ndev = i;
Devtp = (struct dev *)realloc((void *)Devtp,
(size_t)(sizeof(struct dev) * Ndev));
}
(void) closedir(dfp);
if (err)
exit(1);
if ((Sdev = (struct dev **)malloc((size_t)(sizeof(struct dev *)
* Ndev)))
== NULL) {
(void) fprintf(stderr, "%s: no space for device pointers\n",
Pn);
exit(1);
}
for (i = 0; i < Ndev; i++) {
Sdev[i] = &Devtp[i];
}
(void) qsort((void *)Sdev, (size_t)Ndev, (size_t)sizeof(struct dev *),
compdev);
}
/*
* readmnt() - read mount table
*/
void
readmnt()
{
int err = 0;
FILE *mfp;
struct mntent *mp;
struct mounts *mtp;
struct stat sb;
if ((mfp = setmntent(MOUNTED, "r")) == NULL) {
(void) fprintf(stderr, "%s: can't access %s\n", Pn, MOUNTED);
exit(1);
}
while ((mp = getmntent(mfp)) != NULL) {
if (statsafely(mp->mnt_dir, &sb, STATTMO))
continue;
if ((mtp = (struct mounts *)malloc(sizeof(struct mounts)))
== NULL) {
err = 1;
break;
}
if ((mtp->dir = (char *)malloc(strlen(mp->mnt_dir)+1))
== NULL) {
err = 1;
break;
}
(void) strcpy(mtp->dir, mp->mnt_dir);
if ((mtp->fsname = (char *)malloc(strlen(mp->mnt_fsname)+1))
== NULL) {
err = 1;
break;
}
(void) strcpy(mtp->fsname, mp->mnt_fsname);
mtp->dev = sb.st_dev;
mtp->next = Mtab;
Mtab = mtp;
}
(void) endmntent(mfp);
if (err) {
(void) fprintf(stderr, "%s: no space for mount at %s (%s)\n",
Pn, mp->mnt_fsname, mp->mnt_dir);
exit(1);
}
}
/*
* statsafely() - stat path safely (i. e., with timeout)
*/
statsafely(path, buf, tm)
char *path;
struct stat *buf;
int tm;
{
int err;
static int sverr;
if (tm == 0)
return(stat(path, buf));
sverr = errno;
if (setjmp(Tmo_jbuf)) {
(void) alarm(0);
(void) signal(SIGALRM, SIG_IGN);
errno = ETIMEDOUT;
return(-1);
}
(void) signal(SIGALRM, stattimeout);
(void) alarm((unsigned)tm);
err = stat(path, buf);
if (err != 0)
sverr = errno;
(void) alarm(0);
(void) signal(SIGALRM, SIG_IGN);
errno = sverr;
return(err);
}
/*
* stattimeout() - time out a stat() call
*/
void
stattimeout()
{
(void) alarm(0);
(void) signal(SIGALRM, SIG_IGN);
longjmp(Tmo_jbuf, 1);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.