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.