/* * dnode.c - SCO UnixWare node functions for lsof */ /* * Copyright 1996 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 1996 Purdue Research Foundation.\nAll rights reserved.\n"; static char *rcsid = "$Id: dnode.c,v 1.28 2006/03/28 21:57:57 abe Exp $"; #endif #include "lsof.h" #include #if UNIXWAREV>=70000 #undef IREAD #undef IWRITE #undef IEXEC #endif /* UNIXWAREV>=70000 */ #if defined(HAS_UW_CFS) #include #endif /* defined(HAS_UW_CFS) */ #include #if defined(HASXNAMNODE) #include #endif /* defined(HASXNAMNODE) */ _PROTOTYPE(static void ent_fa,(KA_T *a1, KA_T *a2, char *d)); _PROTOTYPE(static int get_vty,(struct vnode *v, KA_T va, struct vfs *kv, int *fx)); #if UNIXWAREV<70103 _PROTOTYPE(static int examine_stream,(KA_T vs, struct queue *q, char *mn, char *sn, KA_T *sqp)); #else /* UNIXWAREV>=70103 */ _PROTOTYPE(static int examine_stream,(KA_T vs, struct queue *q, char **mch, char **mn, char *sn, KA_T *sqp)); _PROTOTYPE(static struct l_dev * findspdev,(dev_t *dev, dev_t *rdev)); _PROTOTYPE(static void getspdev,(void)); _PROTOTYPE(static int get_vty,(struct vnode *v, KA_T va, struct vfs *kv, int *fx)); _PROTOTYPE(static struct l_dev * ismouse,(struct vnode *va, struct l_ino *i, int fx, struct vfs *kv)); #endif /* UNIXWAREV<70103 */ _PROTOTYPE(static struct l_dev * findstrdev,(dev_t *dev, dev_t *rdev)); _PROTOTYPE(static char isvlocked,(struct vnode *va)); _PROTOTYPE(static int readlino,(int fx, struct vnode *v, struct l_ino *i)); /* * Local variables and definitions */ static struct protos { char *module; /* stream module name */ char *proto; /* TCP/IP protocol name */ } Protos[] = { { "tcpu", "TCP" }, { "udpu", "UDP" }, { "tcpl", "TCP" }, { "tcp", "TCP" }, { "udpl", "UDP" }, { "udp", "UDP" }, #if UNIXWAREV<70103 { "icmp", "ICMP" }, { "ipu", "IP" }, { "ipl", "IP" }, { "ip", "IP" }, #endif /* UNIXWAREV<70103 */ }; #define NPROTOS (sizeof(Protos)/sizeof(struct protos)) #if UNIXWAREV>=70103 static struct specdev { char *name; struct l_dev *dp; } SpDev[] = { { "/dev/log", (struct l_dev *)NULL }, { "/dev/mouse", (struct l_dev *)NULL }, }; #define SPDEV_CT (sizeof(SpDev) / sizeof(struct specdev)) static int SpDevX = -1; /* SpDev[] maximum index */ #endif /* UNIXWAREV>=70103 */ /* * ent_fa() - enter fattach addresses in NAME column addition */ static void ent_fa(a1, a2, d) KA_T *a1; /* first fattach address (NULL OK) */ KA_T *a2; /* second fattach address */ char *d; /* direction ("->" or "<-") */ { char buf[64], *cp, tbuf[32]; MALLOC_S len; if (Lf->nma) return; if (!a1) (void) snpf(buf, sizeof(buf), "(FA:%s%s)", d, print_kptr(*a2, (char *)NULL, 0)); else (void) snpf(buf, sizeof(buf), " (FA:%s%s%s)", print_kptr(*a1, tbuf, sizeof(tbuf)), d, print_kptr(*a2, (char *)NULL, 0)); len = strlen(buf) + 1; if ((cp = (char *)malloc(len)) == NULL) { (void) fprintf(stderr, "%s: no space for fattach addresses at PID %d, FD %s\n", Pn, Lp->pid, Lf->fd); Exit(1); } (void) snpf(cp, len, "%s", buf); Lf->nma = cp; } /* * examine_stream() - examine stream */ static int #if UNIXWAREV<70103 examine_stream(vs, q, mn, sn, sqp) #else /* UNIXWAREV>=70103 */ examine_stream(vs, q, mch, mn, sn, sqp) #endif /* UNIXWAREV<70103 */ KA_T vs; /* stream head's stdata kernel * address */ struct queue *q; /* queue structure buffer */ #if UNIXWAREV>=70103 char **mch; /* important stream module name chain, * module names separated by "->" */ char **mn; /* pointer to module name receiver */ #else /* UNIXWAREV<70103 */ char *mn; /* module name receiver */ #endif /* UNIXWAREV>=70103 */ char *sn; /* special module name */ KA_T *sqp; /* special module's q_ptr */ { struct module_info mi; KA_T qp; struct qinit qi; struct stdata sd; char tbuf[32]; #if UNIXWAREV>=70103 static char *ab = (char *)NULL; static MALLOC_S aba = (size_t)0; MALLOC_S al, len, naba, tlen; char *ap; char tmnb[STRNML+1]; #endif /* UNIXWAREV>=70103 */ /* * Read stream's head. */ if (!vs || readstdata(vs, &sd)) { (void) snpf(Namech, Namechl, "can't read stream head from %s", print_kptr(vs, (char *)NULL, 0)); enter_nm(Namech); return(1); } if (!sd.sd_wrq) { enter_nm("no stream write queue"); return(1); } /* * Examine the write queue. */ #if UNIXWAREV<70103 for (qp = (KA_T)sd.sd_wrq, *mn = '\0'; qp; qp = (KA_T)q->q_next) #else /* UNIXWAREV>=70103 */ for (qp = (KA_T)sd.sd_wrq, al = (MALLOC_S)0, ap = ab, *mn = (char *)NULL, tmnb[sizeof(tmnb) - 1] = '\0'; qp; qp = (KA_T)q->q_next) #endif /* UNIXWAREV<70103 */ { /* * Read stream queue entry. */ if (kread(qp, (char *)q, sizeof(struct queue))) { (void) snpf(Namech, Namechl, "can't read stream queue from %s", print_kptr(qp, (char *)NULL, 0)); enter_nm(Namech); return(1); } /* * Read queue's information structure. */ if (!q->q_qinfo || readstqinit((KA_T)q->q_qinfo, &qi)) { (void) snpf(Namech, Namechl, "can't read qinit for %s from %s", print_kptr(qp, tbuf, sizeof(tbuf)), print_kptr((KA_T)q->q_qinfo, (char *)NULL, 0)); enter_nm(Namech); return(1); } /* * Read module information structure. */ if (!qi.qi_minfo || readstmin((KA_T)qi.qi_minfo, &mi)) { (void) snpf(Namech, Namechl, "can't read module info for %s from %s", print_kptr((KA_T)q->q_qinfo, tbuf, sizeof(tbuf)), print_kptr((KA_T)qi.qi_minfo, (char *)NULL, 0)); enter_nm(Namech); return(1); } /* * Read module name. */ #if UNIXWAREV<70103 if (!mi.mi_idname || kread((KA_T)mi.mi_idname, mn, STRNML-1)) #else /* UNIXWAREV>=70103 */ if (!mi.mi_idname || kread((KA_T)mi.mi_idname, tmnb, STRNML)) #endif /* UNIXWAREV<70103 */ { (void) snpf(Namech, Namechl, "can't read module name for %s from %s", print_kptr((KA_T)qi.qi_minfo, tbuf, sizeof(tbuf)), print_kptr((KA_T)mi.mi_idname, (char *)NULL, 0)); enter_nm(Namech); return(1); } #if UNIXWAREV<70103 *(mn + STRNML - 1) = '\0'; #endif /* UNIXWAREV<70103 */ /* * Save the q_ptr of the first special module. */ #if UNIXWAREV<70103 if (!sn || *sqp || !q->q_ptr) continue; if (strcmp(mn, sn) == 0) *sqp = (KA_T)q->q_ptr; #else /* UNIXWAREV>=70103 */ if (sn && !*sqp && q->q_ptr) { if (strcmp(tmnb, sn) == 0) *sqp = (KA_T)q->q_ptr; } /* * Assemble the module name chain. Allocate space as required. * Skip null module names and some "uninteresting" ones. */ len = strlen(tmnb); if (len && strcmp(tmnb, "strrhead") && strcmp(tmnb, "strwhead") ) { tlen = len + 1 + (al ? 2 : 0); if ((tlen + al) > aba) { aba = tlen + al + 64; /* allocate some extra */ if (!ab) { ab = ap = (char *)malloc(aba); } else { ab = (char *)realloc((MALLOC_P *)ab, aba); if (al) ap = ab + (al - 1); else ap = ab; } if (!ab) { (void) fprintf(stderr, "%s: no space for stream chain", Pn); Exit(1); } } (void) snpf(ap, aba - (al - 1), "%s%s", (ap == ab) ? "" : "->", tmnb); *mn = ap + ((ap == ab) ? 0 : 2); al += tlen; ap += (tlen - 1); } #endif /* UNIXWAREV<70103 */ } #if UNIXWAREV>=70103 *mch = ab; if (!*mn) *mn = ""; #endif /* UNIXWAREV>=70103 */ return(0); } #if UNIXWAREV>=70103 /* * findspdev() - find special device by raw major device number */ static struct l_dev * findspdev(dev, rdev) dev_t *dev; /* containing device */ dev_t *rdev; /* raw device */ { int i; struct l_dev *dp; if (*dev != DevDev) return((struct l_dev *)NULL); if (SpDevX < 0) (void) getspdev(); for (i = 0; i < SpDevX; i++) { if (!(dp = SpDev[i].dp)) continue; if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(dp->rdev)) return(dp); } return((struct l_dev *)NULL); } #endif /* UNIXWAREV>=70103 */ /* * findstrdev() - look up stream device by device number */ static struct l_dev * findstrdev(dev, rdev) dev_t *dev; /* device */ dev_t *rdev; /* raw device */ { struct clone *c; struct l_dev *dp; /* * Search device table for match. */ #if HASDCACHE findstrdev_again: #endif /* HASDCACHE */ if ((dp = lkupdev(dev, rdev, 0, 0))) return(dp); /* * Search for clone. */ if (Clone) { for (c = Clone; c; c = c->next) { if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(Devtp[c->dx].rdev)) { #if HASDCACHE if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx])) goto findstrdev_again; #endif /* HASDCACHE */ return(&Devtp[c->dx]); } } } #if UNIXWAREV<70103 return((struct l_dev *)NULL); #else /* UNIXWAREV>=70103 */ /* * Search for non-clone clone. */ return(findspdev(dev, rdev)); #endif /* UNIXWAREV<70103 */ } #if UNIXWAREV>=70103 /* * getspecdev() -- get Devtp[] pointers for "special" devices */ static void getspdev() { struct l_dev *dp; int i, j, n; if (SpDevX >= 0) return; /* * Scan Devtp[] for the devices named in SpDev[]. */ for (i = n = 0; (i < Ndev) && (n < SPDEV_CT); i++) { dp = Sdev[i]; for (j = 0; j < SPDEV_CT; j++) { if (SpDev[j].dp) continue; if (strcmp(SpDev[j].name, dp->name) == 0) { SpDev[j].dp = dp; n++; SpDevX = j + 1; break; } } } if (SpDevX < 0) SpDevX = 0; } #endif /* UNIXWAREV>=70103 */ /* * get_vty() - get vnode type * * return: vnode type as an N_* symbol value * N_REGLR if no special file system type applies * -1 if the vnode type is VUNNAMED * -2 if the vfs structure has an illegal type index * -3 if the vfs structure can't be read */ static int get_vty(v, va, kv, fx) struct vnode *v; /* vnode to test */ KA_T va; /* vnode's kernel address */ struct vfs *kv; /* copy of vnode's kernel vfs struct */ int *fx; /* file system type index */ { int fxt; int nty = N_REGLR; char tbuf[32]; if (v->v_type == VUNNAMED) { *fx = 0; return(-1); } if (!v->v_vfsp) { *fx = 0; if ((v->v_type == VFIFO) || v->v_stream) return(N_STREAM); return(N_REGLR); } if (!kread((KA_T)v->v_vfsp, (char *)kv, sizeof(struct vfs))) { /* * Check the file system type. */ fxt = kv->vfs_fstype; if (fxt > 0 && fxt <= Fsinfomax) { if (!strcmp(Fsinfo[fxt-1], "fifofs")) nty = N_FIFO; else if (!strcmp(Fsinfo[fxt-1], "nfs")) nty = N_NFS; else if (!strcmp(Fsinfo[fxt-1], "namefs")) nty = N_NM; else if (!strcmp(Fsinfo[fxt-1], "nsc_cfs")) nty = N_CFS; #if defined(HASPROCFS) else if (!strcmp(Fsinfo[fxt-1], "proc")) nty = N_PROC; #endif /* defined(HASPROCFS) */ } else { (void) snpf(Namech, Namechl, "vnode@%s: bad file system index (%d)", print_kptr(va, (char *)NULL, 0), fxt); enter_nm(Namech); return(-2); } } else { (void) snpf(Namech, Namechl, "vnode@%s: bad vfs pointer (%s)", print_kptr(va, tbuf, sizeof(tbuf)), print_kptr((KA_T)v->v_vfsp, (char *)NULL, 0)); enter_nm(Namech); return(-3); } if (nty == N_REGLR) { if (v->v_type == VFIFO) nty = N_FIFO; else if (v->v_stream) nty = N_STREAM; } *fx = fxt; return(nty); } #if UNIXWAREV>=70103 /* * ismouse() - is vnode attached to /dev/mouse */ static struct l_dev * ismouse(va, i, fx, kv) struct vnode *va; /* local vnode address */ struct l_ino *i; /* local inode structure */ int fx; /* file system index */ struct vfs *kv; /* copy of kernel VFS structure */ { struct l_dev *dp; int j; if ((fx < 1) || (fx > Fsinfomax)) return((struct l_dev *)NULL); if ((dp = findspdev(&kv->vfs_dev, &va->v_rdev))) { i->dev = kv->vfs_dev; i->dev_def = 1; i->nlink = (long)0; i->nlink_def = 0; i->nm = (char *)NULL; i->number = dp->inode; i->number_def = 1; i->rdev = va->v_rdev; i->rdev_def = 0; i->size = (SZOFFTYPE)0; i->size_def = 0; Ntype = N_REGLR; } return(dp); } #endif /* UNIXWAREV>=70103 */ /* * isvlocked() - is a vnode locked */ static char isvlocked(va) struct vnode *va; /* local vnode address */ { struct filock f; KA_T flf, flp; int i, l; if (!(flf = (KA_T)va->v_filocks)) return(' '); flp = flf; i = 0; do { if (i++ > 1000) break; if (kread(flp, (char *)&f, sizeof(f))) break; if (f.set.l_sysid || f.set.l_pid != (pid_t)Lp->pid) continue; if (!f.set.l_whence && !f.set.l_start #if UNIXWAREV>=70101 # if UNIXWAREV<70103 && (f.set.l_len == 0x7fffffffffffffff) # else /* UNIXWAREV>=70103 */ && (f.set.l_len == 0x7fffffffffffffffLL) # endif /* UNIXWAREV<70103 */ #else /* UNIXWAREV<70101 */ && ((f.set.l_len == 0) || (f.set.l_len == 0x7fffffff)) #endif /* UNIXWAREV>=70101*/ ) l = 1; else l = 0; switch (f.set.l_type & (F_RDLCK | F_WRLCK)) { case F_RDLCK: return((l) ? 'R' : 'r'); case F_WRLCK: return((l) ? 'W' : 'w'); case (F_RDLCK + F_WRLCK): return('u'); default: return(' '); } } while (flp != (KA_T)f.next && (flp = (KA_T)f.next) && flp != flf); return(' '); } /* * process_node() - process node */ void process_node(na) KA_T na; /* vnode kernel space address */ { char *cp, *ep; dev_t dev, rdev; unsigned char devs = 0; unsigned char rdevs = 0; unsigned char ni = 0; struct l_dev *dp; struct fifonode f; int fx, rfx; struct l_ino i; int is = 1; int j, k; KA_T ka; struct vfs kv, rkv; #if UNIXWAREV<70103 struct module_info mi; char mn[STRNML]; #else /* UNIXWAREV>=70103 */ char *mch, *mn; #endif /* UNIXWAREV<70103 */ struct mnode mno; MALLOC_S msz; struct namenode nn; int px; struct queue q; struct rnode r; struct vnode rv, v; struct snode s; unsigned char sd = 1; struct so_so so; KA_T sqp = (KA_T)NULL; size_t sz; char tbuf[32], *ty; enum vtype type; struct sockaddr_un ua; #if defined(HASPROCFS) struct as as; struct proc p; KA_T pa; struct procfsid *pfi; long pid; struct prnode pr; # if UNIXWAREV<20102 struct pid pids; # else /* UNIXWAREV>=20102 */ struct prcommon prc; # endif /* UNIXWAREV>=20102 */ #endif /* defined(HASPROCFS) */ /* * Read the vnode. */ if (!na) { enter_nm("no vnode address"); return; } if (readvnode((KA_T)na, &v)) { enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = na; #endif /* defined(HASNCACHE) */ #if defined(HASFSTRUCT) Lf->fna = na; Lf->fsv |= FSV_NI; #endif /* defined(HASFSTRUCT) */ /* * Determine the vnode type. */ if ((Ntype = get_vty(&v, na, &kv, &fx)) < 0) { if (Ntype == -1) Lf->sf = 0; return; } /* * Determine the lock state. */ get_lock_state: Lf->lock = isvlocked(&v); /* * Read the fifonode, inode, namenode, prnode, rnode, snode, ... */ switch (Ntype) { case N_FIFO: if (!v.v_data || readfifonode((KA_T)v.v_data, &f)) { (void) snpf(Namech, Namechl, "vnode@%s: can't read fifonode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (f.fn_realvp) { if (readvnode((KA_T)f.fn_realvp, &rv)) { (void) snpf(Namech, Namechl, "fifonode@%s: can't read real vnode (%s)", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)f.fn_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } #if defined(HASNCACHE) Lf->na = (KA_T)f.fn_realvp; #endif /* defined(HASNCACHE) */ if (!rv.v_data || (is = readlino(fx, &rv, &i))) { (void) snpf(Namech, Namechl, "fifonode@%s: can't read inode (%s)", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } } else ni = 1; break; case N_NFS: if (!v.v_data || readrnode((KA_T)v.v_data, &r)) { (void) snpf(Namech, Namechl, "vnode@%s: can't read rnode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } break; case N_NM: if (!v.v_data || kread((KA_T)v.v_data, (char *)&nn, sizeof(nn))) { (void) snpf(Namech, Namechl, "vnode@%s: no namenode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } i.dev = nn.nm_vattr.va_fsid; i.rdev = nn.nm_vattr.va_rdev; i.number = (INODETYPE)nn.nm_vattr.va_nodeid; i.size = nn.nm_vattr.va_size; if (!nn.nm_mountpt) break; /* * The name node is mounted over/to another vnode. Process that node. */ (void) ent_fa(&na, (KA_T *)&nn.nm_mountpt, "->"); if (kread((KA_T)nn.nm_mountpt, (char *)&rv, sizeof(rv))) { (void) snpf(Namech, Namechl, "vnode@%s: can't read namenode's mounted vnode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)nn.nm_mountpt, (char *)NULL, 0)); return; } if ((Ntype = get_vty(&rv, (KA_T)nn.nm_mountpt, &rkv, &rfx)) < 0) { if (Ntype == -1) Lf->sf = 0; return; } /* * Unless the mounted-over/to node is another "namefs" node, promote * it to the vnode of interest. */ if (Ntype == N_NM) break; fx = rfx; kv = rkv; v = rv; goto get_lock_state; #if defined(HASPROCFS) case N_PROC: ni = 1; if (!v.v_data || kread((KA_T)v.v_data, (char *)&pr, sizeof(pr))) { (void) snpf(Namech, Namechl, "vnode@%s: can't read prnode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } # if UNIXWAREV>=20102 i.number = (INODETYPE)pr.pr_ino; sd = 0; if (pr.pr_common && !kread((KA_T)pr.pr_common, (char *)&prc, sizeof(prc))) { pid = (long)prc.prc_pid; switch(pr.pr_type) { case PR_PIDDIR: (void) snpf(Namech, Namechl, "/%s/%ld", HASPROCFS, pid); break; case PR_AS: (void) snpf(Namech, Namechl, "/%s/%ld/as", HASPROCFS, pid); break; case PR_CTL: (void) snpf(Namech, Namechl, "/%s/%ld/ctl", HASPROCFS, pid); break; case PR_STATUS: (void) snpf(Namech, Namechl, "/%s/%ld/status", HASPROCFS, pid); break; case PR_MAP: (void) snpf(Namech, Namechl, "/%s/%ld/map", HASPROCFS, pid); break; case PR_CRED: (void) snpf(Namech, Namechl, "/%s/%ld/cred", HASPROCFS, pid); break; case PR_SIGACT: (void) snpf(Namech, Namechl, "/%s/%ld/sigact", HASPROCFS, pid); break; case PR_OBJECTDIR: (void) snpf(Namech, Namechl, "/%s/%ld/object", HASPROCFS, pid); break; case PR_LWPDIR: (void) snpf(Namech, Namechl, "/%s/%ld/lwp", HASPROCFS, pid); break; case PR_LWPIDDIR: (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d", HASPROCFS, pid, prc.prc_lwpid); break; case PR_LWPCTL: (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpctl", HASPROCFS, pid, prc.prc_lwpid); break; case PR_LWPSTATUS: (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpstatus", HASPROCFS, pid, prc.prc_lwpid); break; case PR_LWPSINFO: (void) snpf(Namech, Namechl, "/%s/%ld/lwp/%d/lwpsinfo", HASPROCFS, pid, prc.prc_lwpid); break; } } else pid = 0l; break; # else /* UNIXWAREV<20102 */ if (!pr.pr_proc) { sd = 0; pid = 0l; if (v.v_type == VDIR) i.number = (INODETYPE)PR_ROOTINO; else i.number = (INODETYPE)0; break; } if (kread((KA_T)pr.pr_proc, (char *)&p, sizeof(p))) { (void) snpf(Namech, Namechl, "prnode@%s: can't read proc (%s)", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)pr.pr_proc, (char *)NULL, 0)); enter_nm(Namech); return; } if (!p.p_pidp || kread((KA_T)p.p_pidp, (char *)&pids, sizeof(pids))) { (void) snpf(Namech, Namechl, "proc struct at %s: can't read pid (%s)", print_kptr((KA_T)pr.pr_proc, tbuf, sizeof(tbuf)), print_kptr((KA_T)p.p_pidp, (char *)NULL, 0)); enter_nm(Namech); return; } pid = (long)pids.pid_id; (void) snpf(Namech, Namechl, "/%s/%ld", HASPROCFS, pid); i.number = (INODETYPE)(pid + PR_INOBIAS); if (!p.p_as || kread((KA_T)p.p_as, (char *)&as, sizeof(as))) sd = 0; else i.size = as.a_size; break; # endif /* UNIXWAREV>=20102 */ #endif /* defined(HASPROCFS) */ case N_STREAM: if (v.v_stream) { Lf->is_stream = ni = 1; #if UNIXWAREV>=70101 if (process_unix_sockstr(&v, na)) { /* * The stream is a UNIX socket stream. No more need be done; * process_unix_stream() has done it all. */ return; } #endif /* UNIXWAREV>=70101 */ /* * Get the queue pointer and module name at the end of the stream. * The module name identifies socket streams. */ if (examine_stream((KA_T)v.v_stream, &q, #if UNIXWAREV>=70103 &mch, &mn, #else /* UNIXWAREV<70103 */ mn, #endif /* UNIXWAREV>=70103 */ "sockmod", &sqp)) return; for (px = 0; px < NPROTOS; px++) { if (strcmp(mn, Protos[px].module) == 0) { process_socket(Protos[px].proto, &q); return; } } /* * If this stream has a "sockmod" module with a non-NULL q_ptr, * try to use it to read an so_so structure. */ if (sqp && kread(sqp, (char *)&so, sizeof(so)) == 0) break; sqp = (KA_T)NULL; (void) snpf(Namech, Namechl, "STR"); j = strlen(Namech); if (v.v_type == VCHR) { /* * If this is a VCHR stream, look up the device name and record it. */ if ((dp = findstrdev(&DevDev, (dev_t *)&v.v_rdev))) { Lf->inode = dp->inode; Lf->inp_ty = 1; Namech[j++] = ':'; k = strlen(dp->name); if ((j + k) <= (Namechl - 1)) { (void) snpf(&Namech[j], Namechl - j, "%s", dp->name); j += k; if ((cp = strrchr(Namech, '/')) && *(cp + 1) == '\0') { *cp = '\0'; j--; } } } } /* * Follow the "STR" and possibly the device name with "->" and * the module name or the stream's significant module names. */ if ((j + 2) <= (Namechl - 1)) { (void) snpf(&Namech[j], Namechl - j, "->"); j += 2; } #if UNIXWAREV<70103 if (mn[0]) { if ((j + strlen(mn)) <= (Namechl - 1)) (void) snpf(&Namech[j], Namechl - j, mn); #else /* UNIXWAREV>=70103 */ if (*mch) { if ((j + strlen(mch)) <= (Namechl - 1)) (void) snpf(&Namech[j], Namechl - j, mch); #endif /* UNIXWAREV<70103 */ } else { if ((j + strlen("none")) <= (Namechl - 1)) (void) snpf(&Namech[j], Namechl - j, "none"); } } break; case N_REGLR: default: /* * Follow a VBLK or VCHR vnode to its snode, then to its real vnode, * finally to its inode. */ if ((v.v_type == VBLK) || (v.v_type == VCHR)) { if (!v.v_data || readsnode((KA_T)v.v_data, &s)) { (void) snpf(Namech, Namechl, "vnode@%s: can't read snode (%s)", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); enter_nm(Namech); return; } if (s.s_realvp) { if (readvnode((KA_T)s.s_realvp, &rv)) { (void) snpf(Namech, Namechl, "snode@%s: can't read real vnode (%s)", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); enter_nm(Namech); return; } if (!rv.v_data || (is = readlino(fx, &rv, &i))) { (void) snpf(Namech, Namechl, "snode@%s: unknown inode@%s; fx=", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); ep = endnm(&sz); if (fx < 1 || fx > Fsinfomax) (void) snpf(ep, sz, "%d", fx); else (void) snpf(ep, sz, "%s", Fsinfo[fx - 1]); enter_nm(Namech); return; } } /* * If there's no real vnode, look for a common vnode and a * common snode. */ else if ((ka = (KA_T)s.s_commonvp)) { if (readvnode(ka, &rv)) { (void) snpf(Namech, Namechl, "snode@%s: can't read common vnode (%s)", print_kptr((KA_T)v.v_data, tbuf, sizeof(tbuf)), print_kptr((KA_T)ka, (char *)NULL, 0)); enter_nm(Namech); return; } #if UNIXWAREV>=70103 if (!rv.v_vfsp) { if ((dp = ismouse(&rv, &i, fx, &kv))) { (void) snpf(Namech, Namechl, "STR:%s", dp->name); break; } } #endif /* UNIXWAREV>=70103 */ if (get_vty(&rv, ka, &rkv, &rfx) < 0) Lf->is_com = ni = 1; else { if ((is = readlino(rfx, &rv, &i))) { (void) snpf(Namech, Namechl, "vnode@%s: unknown successor@%s; fx=", print_kptr((KA_T)ka, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); ep = endnm(&sz); if (rfx < 1 || rfx > Fsinfomax) (void) snpf(ep, sz, "%d", rfx); else (void) snpf(ep, sz, "%s", Fsinfo[rfx - 1]); enter_nm(Namech); return; } } } else ni = 1; break; } #if UNIXWAREV>=70103 else if (v.v_type == VNON) { ni = 1; break; } #endif /* UNIXWAREV>=70103 */ if (v.v_data == NULL) { (void) snpf(Namech, Namechl, "vnode@%s: no further information", print_kptr(na, (char *)NULL, 0)); enter_nm(Namech); return; } /* * Read inode information. */ if ((is = readlino(fx, &v, &i))) { (void) snpf(Namech, Namechl, "vnode@%s: unknown successor@%s; fx=", print_kptr(na, tbuf, sizeof(tbuf)), print_kptr((KA_T)v.v_data, (char *)NULL, 0)); ep = endnm(&sz); if (fx < 1 || fx > Fsinfomax) (void) snpf(ep, sz, "%d", fx); else (void) snpf(ep, sz, "%s", Fsinfo[fx - 1]); enter_nm(Namech); return; } } /* * Get device and type for printing. */ switch (Ntype) { case N_NFS: dev = r.r_attr.va_fsid; devs = 1; break; #if defined(HASPROCFS) case N_PROC: dev = kv.vfs_dev; devs = 1; break; #endif /* defined(HASPROCFS) */ case N_STREAM: if (sqp) { if (so.lux_dev.size >= 8) { dev = DevDev; rdev = so.lux_dev.addr.tu_addr.dev; devs = rdevs = 1; } else enter_dev_ch(print_kptr(sqp, (char *)NULL, 0)); break; } if (v.v_type == VFIFO) { KA_T ta; if ((ta = (KA_T)(v.v_data ? v.v_data : v.v_stream))) enter_dev_ch(print_kptr(ta, (char *)NULL, 0)); break; } /* fall through */ default: if (!ni) { dev = i.dev; devs = (Ntype == N_CFS) ? i.dev_def : 1; } else if ((Ntype == N_STREAM) && ((v.v_type == VCHR) || (v.v_type == VBLK))) { dev = DevDev; devs = 1; } if ((v.v_type == VCHR) || (v.v_type == VBLK)) { rdev = v.v_rdev; rdevs = (Ntype == N_CFS) ? i.rdev_def : 1; } } type = v.v_type; /* * Obtain the inode number. */ switch (Ntype) { case N_NFS: Lf->inode = (INODETYPE)r.r_attr.va_nodeid; Lf->inp_ty = 1; break; #if defined(HASPROCFS) case N_PROC: Lf->inode = i.number; Lf->inp_ty = 1; break; #endif /* defined(HASPROCFS) */ case N_FIFO: if (!f.fn_realvp) { enter_dev_ch(print_kptr((KA_T)v.v_data, (char *)NULL, 0)); Lf->inode = (INODETYPE)f.fn_ino; Lf->inp_ty = 1; if (f.fn_flag & ISPIPE) (void) snpf(Namech, Namechl, "PIPE"); if (f.fn_mate) { ep = endnm(&sz); (void) snpf(ep, sz, "->%s", print_kptr((KA_T)f.fn_mate, (char *)NULL, 0)); } break; } /* fall through */ case N_CFS: case N_REGLR: if (!ni) { Lf->inode = i.number; Lf->inp_ty = (Ntype == N_CFS) ? i.number_def : 1; } break; case N_STREAM: if (sqp && so.lux_dev.size >= 8) { Lf->inode = (INODETYPE)so.lux_dev.addr.tu_addr.ino; Lf->inp_ty = 1; } } /* * Obtain the file size. */ if (Foffset) Lf->off_def = 1; else { switch (Ntype) { case N_FIFO: case N_STREAM: if (!Fsize) Lf->off_def = 1; break; case N_NFS: Lf->sz = (SZOFFTYPE)r.r_attr.va_size; Lf->sz_def = sd; break; #if defined(HASPROCFS) case N_PROC: #if UNIXWAREV<70103 Lf->sz = (SZOFFTYPE)i.size; Lf->sz_def = sd; #else /* UNIXWAREV>=70103 */ Lf->sz = (SZOFFTYPE)0; Lf->sz_def = 0; #endif /* UNIXWAREV<70103 */ break; #endif /* defined(HASPROCFS) */ case N_CFS: case N_REGLR: if ((type == VREG) || (type == VDIR)) { if (!ni) { Lf->sz = (SZOFFTYPE)i.size; Lf->sz_def = (Ntype == N_CFS) ? i.size_def : sd; } } else if (((type == VBLK) || (type == VCHR)) && !Fsize) Lf->off_def = 1; break; } } /* * Record link count. */ if (Fnlink) { switch(Ntype) { case N_FIFO: Lf->nlink = (long)f.fn_open; Lf->nlink_def = 1; break; case N_NFS: Lf->nlink = (long)r.r_attr.va_nlink; Lf->nlink_def = 1; break; #if defined(HASPROCFS) case N_PROC: #endif /* defined(HASPROCFS) */ case N_CFS: case N_REGLR: if (!ni) { Lf->nlink = (long)i.nlink; Lf->nlink_def = i.nlink_def; } break; } if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) Lf->sf |= SELNLINK; } /* * Record an NFS file selection. */ if (Ntype == N_NFS && Fnfs) Lf->sf |= SELNFS; /* * Defer file system info lookup until printname(). */ Lf->lmi_srch = 1; /* * Save the device numbers and their states. * * Format the vnode type, and possibly the device name. */ if (type != VFIFO) { Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; } switch (type) { case VNON: ty ="VNON"; break; case VREG: ty = "VREG"; break; case VDIR: ty = "VDIR"; break; case VBLK: ty = "VBLK"; Ntype = N_BLK; break; case VCHR: ty = "VCHR"; if (Lf->is_stream == 0) Ntype = N_CHR; break; case VLNK: ty = "VLNK"; break; #if defined(VSOCK) case VSOCK: ty = "SOCK"; break; #endif /* VSOCK */ case VBAD: ty = "VBAD"; break; case VFIFO: if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') { Lf->dev = dev; Lf->dev_def = devs; Lf->rdev = rdev; Lf->rdev_def = rdevs; } ty = "FIFO"; break; case VUNNAMED: ty = "UNNM"; break; default: (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); ty = NULL; } if (ty) (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); Lf->ntype = Ntype; /* * If this is a VBLK file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (Lf->ntype == N_BLK)) find_bl_ino(); /* * If this is a VCHR file and it's missing an inode number, try to * supply one. */ if ((Lf->inp_ty == 0) && (type == VCHR)) find_ch_ino(); /* * If this is a stream with a "sockmod" module whose q_ptr leads to an * so_so structure, assume it's a UNIX domain socket and try to get * the path. Clear the is_stream status. */ if (Ntype == N_STREAM && sqp) { if (Funix) Lf->sf |= SELUNX; (void) snpf(Lf->type, sizeof(Lf->type), "unix"); if (!Namech[0] && so.laddr.buf && so.laddr.len == sizeof(ua) && !kread((KA_T)so.laddr.buf, (char *)&ua, sizeof(ua))) { ua.sun_path[sizeof(ua.sun_path) - 1] = '\0'; (void) snpf(Namech, Namechl, "%s", ua.sun_path); if (Sfile && is_file_named(Namech, 0)) Lf->sf = SELNM; if (so.lux_dev.size >= 8) { Lf->inode = (INODETYPE)so.lux_dev.addr.tu_addr.ino; Lf->inp_ty = 1; } } if (so.so_conn) { ep = endnm(&sz); (void) snpf(ep, sz, "->%s", print_kptr((KA_T)so.so_conn, (char *)NULL, 0)); } Lf->is_stream = 0; } /* * Test for specified file. */ #if defined(HASPROCFS) if (Ntype == N_PROC) { if (Procsrch) { Procfind = 1; Lf->sf |= SELNM; } else { for (pfi = Procfsid; pfi; pfi = pfi->next) { if ((pfi->pid && pid && pfi->pid == (pid_t)pid) # if defined(HASPINODEN) || ((Lf->inp_ty == 1) && (Lf->inode == pfi->inode)) # endif /* defined(HASPINODEN) */ ) { pfi->f = 1; Lf->sf |= SELNM; if (!Namech[0] && pfi->nm) { (void) strncpy(Namech, pfi->nm, Namechl - 1); Namech[Namechl-1] = '\0'; } break; } } } } else #endif /* defined(HASPROCFS) */ { if (Sfile && is_file_named((char *)NULL, ((type == VCHR) || (type == VBLK)) ? 1 : 0)) Lf->sf |= SELNM; } /* * Enter name characters. If there's an l_ino structure with a file name * pointer, and no name column addition exists, make what the l_ino file * name pointer addresses a name column addition. */ if (!Lf->nma && !is && i.nm) { if ((msz = (MALLOC_S)strlen(i.nm))) { if (!(cp = (char *)malloc(msz + 1))) { (void) fprintf(stderr, "%s: can't allocate %d bytes for l_ino name addition\n", msz, Pn); Exit(1); } (void) snpf(cp, msz + 1, "%s", i.nm); Lf->nma = cp; } } if (Namech[0]) enter_nm(Namech); } /* * readlino() - read local inode information */ static int readlino(fx, v, i) int fx; /* file system index */ struct vnode *v; /* vnode pointing to inode */ struct l_ino *i; /* local inode */ { #if defined(HAS_UW_CFS) cnode_t cn; #endif /* defined(HAS_UW_CFS) */ struct vnode fa; struct mnode mn; struct inode sn; #if defined(HASXNAMNODE) struct xnamnode xn; #endif /* defined(HASXNAMNODE) */ i->nlink_def = 0; if (fx < 1 || fx > Fsinfomax || !v->v_data) return(1); if (!strcmp(Fsinfo[fx-1], "fifofs") || !strcmp(Fsinfo[fx-1], "sfs") || !strcmp(Fsinfo[fx-1], "ufs")) { if (kread((KA_T)v->v_data, (char *)&sn, sizeof(sn))) return(1); i->dev = sn.i_dev; i->dev_def = 1; i->rdev = v->v_rdev; i->rdev_def = 1; i->nlink = (long)sn.i_nlink; i->nlink_def = 1; i->nm = (char *)NULL; i->number = (INODETYPE)sn.i_number; i->size = (SZOFFTYPE)sn.i_size; i->size_def = 1; return(0); } #if defined(HAS_UW_CFS) else if (!strcmp(Fsinfo[fx-1], "nsc_cfs")) { if (kread((KA_T)v->v_data, (char *)&cn, sizeof(cn))) return(1); if (cn.c_attr.va_mask & AT_FSID) { i->dev = cn.c_attr.va_fsid; i->dev_def = 1; } else i->dev_def = 0; i->rdev = v->v_rdev; i->rdev_def = 1; if (cn.c_attr.va_mask & AT_NLINK) { i->nlink = cn.c_attr.va_nlink; i->nlink_def = 1; } else i->nlink_def = 0; i->nm = (char *)NULL; if (cn.c_attr.va_mask & AT_NODEID) { i->number = (INODETYPE)cn.c_attr.va_nodeid; i->number_def = 1; } else i->number_def = 0; if (cn.c_attr.va_mask & AT_SIZE) { i->size = cn.c_attr.va_size; i->size_def = 1; } else i->size_def = 0; return(0); } #endif /* defined(HAS_UW_CFS) */ else if (!strcmp(Fsinfo[fx-1], "s5")) return(reads5lino(v, i)); else if (!strcmp(Fsinfo[fx-1], "vxfs")) return(readvxfslino(v, i)); else if (!strcmp(Fsinfo[fx-1], "bfs")) return(readbfslino(v, i)); #if defined(HASXNAMNODE) else if (!strcmp(Fsinfo[fx-1], "xnamfs") || !strcmp(Fsinfo[fx-1], "XENIX")) { if (kread((KA_T)v->v_data, (char *)&xn, sizeof(xn))) return(1); i->dev = xn.x_dev; i->nlink = (long)xn.x_count; i->nlink_def = 1; i->nm = (char *)NULL; i->rdev = xn.x_fsid; i->size = xn.x_size; return(0); } #endif /* defined(HASXNAMNODE) */ else if (!strcmp(Fsinfo[fx-1], "memfs")) { if (kread((KA_T)v->v_data, (char *)&mn, sizeof(mn))) return(1); i->dev = mn.mno_fsid; i->dev_def = 1; i->nlink = (long)mn.mno_nlink; i->nlink_def = 1; i->nm = (char *)NULL; i->number = (INODETYPE)mn.mno_nodeid; i->number_def = 1; i->rdev = mn.mno_rdev; i->rdev = mn.mno_rdev; i->size = (SZOFFTYPE)mn.mno_size; i->size_def = 1; return(0); } #if UNIXWAREV>=70000 else if (!strcmp(Fsinfo[fx-1], "cdfs")) return readcdfslino(v, i); else if (!strcmp(Fsinfo[fx-1], "dosfs")) return readdosfslino(v, i); #endif /* UNIXWAREV>=70000 */ return(1); }