diff options
Diffstat (limited to 'dialects/osr/dnode.c')
-rw-r--r-- | dialects/osr/dnode.c | 739 |
1 files changed, 739 insertions, 0 deletions
diff --git a/dialects/osr/dnode.c b/dialects/osr/dnode.c new file mode 100644 index 0000000..755c82f --- /dev/null +++ b/dialects/osr/dnode.c @@ -0,0 +1,739 @@ +/* + * dnode.c - SCO OpenServer node functions for lsof + */ + + +/* + * Copyright 1995 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 1995 Purdue Research Foundation.\nAll rights reserved.\n"; +static char *rcsid = "$Id: dnode.c,v 1.21 2006/03/28 22:09:23 abe Exp $"; +#endif + + +#include "lsof.h" + + +_PROTOTYPE(static struct l_dev * finddev,(dev_t *dev, dev_t *rdev, int stream)); + + +/* + * finddev() - look up device by device number + */ + +static struct l_dev * +finddev(dev, rdev, stream) + dev_t *dev; /* device */ + dev_t *rdev; /* raw device */ + int stream; /* stream if 1 */ +{ + struct clone *c; + struct l_dev *dp; +/* + * Search device table for match. + */ + +#if defined(HASDCACHE) + +finddev_again: + +#endif /* defined(HASDCACHE) */ + + if ((dp = lkupdev(dev, rdev, 0, 0))) + return(dp); +/* + * Search for clone. + */ + if (stream && Clone) { + for (c = Clone; c; c = c->next) { + if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(Devtp[c->dx].rdev)) { + +#if defined(HASDCACHE) + if (DCunsafe && !Devtp[c->dx].v && !vfy_dev(&Devtp[c->dx])) + goto finddev_again; +#endif /* defined(HASDCACHE) */ + + return(&Devtp[c->dx]); + } + } + } + return((struct l_dev *)NULL); +} + + +/* + * process_node() - process node + */ + +void +process_node(na) + KA_T na; /* inode kernel space address */ +{ + char *cp, tbuf[32]; + short dl; + struct l_dev *dp; + unsigned char *fa = (unsigned char *)NULL; + struct filock fl; + KA_T flf, flp; + int fp, lp; + struct inode i; + short ity, udpsf, udpsl; + int j, k, l; + KA_T ka, qp; + unsigned char *la = (unsigned char *)NULL; + struct mounts *lm; + struct module_info mi; + unsigned short *n; + KA_T p; + struct inpcb pcb; + int port; + int pt = -1; + struct queue q; + struct qinit qi; + struct stdata sd; + char *tn; + int type; + struct udpdev udp; + short udptm = 0; + +#if defined(HAS_NFS) + struct rnode r; +#endif /* defined(HAS_NFS) */ + +#if OSRV>=500 + short hpps = 0; + unsigned short *n1; + struct pipeinode pi; +#endif /* OSRV>=500 */ + +/* + * Read the inode. + */ + if ( ! na) { + enter_nm("no inode address"); + return; + } + if (readinode(na, &i)) { + 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) */ + +/* + * Identify the node type. + */ + if (HaveSockdev && (i.i_ftype & IFMT) == IFCHR + && GET_MAJ_DEV(i.i_rdev) == Sockdev) + { + + /* + * Process a socket. + */ + process_socket(&i); + return; + } + if (Selinet) + return; + ity = i.i_fstyp; + type = i.i_ftype & IFMT; + if (ity < 1 || ity > Fsinfomax || !Fsinfo[ity-1]) { + +#if OSRV>=500 + if (ity) { +#endif /* OSRV>=500 */ + + (void) snpf(Namech,Namechl,"unknown fstyp (%d) in inode",ity); + enter_nm(Namech); + return; + +#if OSRV>=500 + } +#endif /* OSRV>=500 */ + + } + if (ity && strcasecmp(Fsinfo[ity-1], "HS") == 0) + Ntype = N_HSFS; + +#if defined(HAS_NFS) + else if (ity && strcasecmp(Fsinfo[ity-1], "NFS") == 0) { + + /* + * Get information on NFS file. + */ + Ntype = N_NFS; + Lf->is_nfs = 1; + if (Fnfs) + Lf->sf |= SELNFS; + if (!i.i_fsptr || readrnode((KA_T)i.i_fsptr, &r)) { + (void) snpf(Namech, Namechl, "can't read rnode (%s)", + print_kptr((KA_T)i.i_fsptr, (char *)NULL, 0)); + enter_nm(Namech); + return; + } + +# if defined(HASNCACHE) + Lf->na = (KA_T)i.i_fsptr; +# endif /* defined(HASNCACHE) */ + + } +#endif /* defined(HAS_NFS) */ + + else { + + /* + * Determine the node type from the inode file type. + */ + switch (type) { + case IFBLK: + Ntype = N_BLK; + break; + case IFCHR: + Ntype = N_CHR; + break; + case IFIFO: + Ntype = N_FIFO; + break; + case IFMPB: + case IFMPC: + Ntype = N_MPC; + break; + case IFNAM: + Ntype = N_NM; + break; + } + } +/* + * Obtain lock information. + */ + if ((flf = (KA_T)i.i_filocks)) { + flp = flf; + do { + if ((kread(flp, (char *)&fl, sizeof(fl)))) + break; + if (fl.set.l_pid != (pid_t)Lp->pid) + continue; + if (fl.set.l_whence == (short)0 && fl.set.l_start == (off_t)0 + && fl.set.l_len == 0x7fffffff) + l = 1; + else + l = 0; + +#if OSRV<500 + if (i.i_flag & IXLOCKED) +#else /* OSRV>=500 */ + if (fl.flags & F_XOUT) +#endif /* OSRV<500 */ + + Lf->lock = l ? 'X' : 'x'; + else if (fl.set.l_type == F_RDLCK) + Lf->lock = l ? 'R' : 'r'; + else if (fl.set.l_type == F_WRLCK) + Lf->lock = l ? 'W' : 'w'; + else if (fl.set.l_type == (F_RDLCK | F_WRLCK)) + Lf->lock = 'u'; + break; + } while ((flp = (KA_T)fl.next) && flp != flf); + } + +#if OSRV>=500 +/* + * See if a FIFO node is an HPPS node -- 3.2v5.0.0 and higher. + */ + if (Ntype == N_FIFO && ity && strcasecmp(Fsinfo[ity-1], "HPPS") == 0) + { + hpps = 1; + if (i.i_fsptr) { + enter_dev_ch(print_kptr((KA_T)i.i_fsptr, (char )NULL, 0)); + if (kread((KA_T)i.i_fsptr, (char *)&pi, sizeof(pi)) == 0) + hpps = 2; + } + } +#endif /* OSRV>=500 */ + +/* + * Determine the device. + */ + switch (Ntype) { + case N_BLK: + Lf->dev = i.i_dev; + Lf->rdev = i.i_rdev; + Lf->dev_def = Lf->rdev_def = 1; + break; + case N_FIFO: + case N_HSFS: + case N_NM: + case N_REGLR: + +#if OSRV>=500 + if (hpps) + break; +#endif /* OSRV>=500 */ + + Lf->dev = i.i_dev; + Lf->dev_def = 1; + break; + case N_CHR: + Lf->dev = i.i_dev; + Lf->rdev = i.i_rdev; + Lf->dev_def = Lf->rdev_def = 1; + if (i.i_sptr) { + + /* + * Namech may be: + * /dev/* name if it exists for i.i_rdev; + * cdevsw[].d_name if it exists for GET_MAJ_DEV(i.i_rdev); + * "STR:" otherwise. + */ + (void) snpf(Namech, Namechl, "STR:"); + Lf->is_stream = 1; + k = strlen(Namech); + cp = (char *)NULL; + if ((dp = finddev(&Lf->dev, &Lf->rdev, 1))) { + (void) snpf(&Namech[k], Namechl - k, dp->name); + k += strlen(dp->name); + if ((cp = strrchr(dp->name, '/'))) + cp++; + } else if ((j = GET_MAJ_DEV(i.i_rdev)) + < Cdevcnt && (cp = Cdevsw[j])) + { + (void) snpf(Namech, Namechl, "%s", cp); + k += strlen(cp); + } + /* + * Get the module names of all queue elements of the stream's + * sd_wrq queue. Skip module names that end in "head", + * match the last component of the /dev name, or match the + * cdevsw[].d_name. + */ + p = (KA_T)NULL; + if (!kread((KA_T)i.i_sptr, (char *)&sd, sizeof(sd))) { + dl = sizeof(tbuf) - 1; + tbuf[dl] = '\0'; + qp = (KA_T)sd.sd_wrq; + for (j = 0; qp && j < 20; j++, qp = (KA_T)q.q_next) { + if (kread(qp, (char *)&q, sizeof(q))) + break; + if (!(ka = (KA_T)q.q_qinfo) + || kread(ka, (char *)&qi, sizeof(qi))) + continue; + if (!(ka = (KA_T)qi.qi_minfo) + || kread(ka, (char *)&mi, sizeof(mi))) + continue; + if (!(ka = (KA_T)mi.mi_idname) + || kread(ka, tbuf, dl)) + continue; + if ((l = strlen(tbuf)) < 1) + continue; + if (l >= 4 && strcmp(&tbuf[l - 4], "head") == 0) + continue; + if (cp && strcmp(cp, tbuf) == 0) { + if (q.q_ptr && pt < 0) { + + /* + * If this is a TCP or UDP module and the + * queue structure has a private pointer in + * q_ptr, save it as a PCB address. + */ + if (strcasecmp(cp, "tcp") == 0) { + pt = 0; + (void) snpf(Lf->iproto, + sizeof(Lf->iproto), "TCP"); + } else if (strcasecmp(cp, "udp") == 0) { + pt = 1; + (void) snpf(Lf->iproto, + sizeof(Lf->iproto), "UDP"); + } + if (pt >= 0) + p = (KA_T)q.q_ptr; + else + pt = -1; + } + continue; + } + if (k) { + if ((k + 2) > (Namechl - 1)) + break; + (void) snpf(&Namech[k], Namechl - k, "->"); + k += 2; + } + if ((k + l) > (Namechl - 1)) + break; + (void) snpf(&Namech[k], Namechl - k, tbuf); + k += l; + } + } + if (p && pt >= 0) { + + /* + * If the stream has a TCP or UDP module with a PCB pointer, + * print any associated local and foreign Internet addresses. + */ + if (kread(p, (char *)&pcb, sizeof(pcb))) + break; + if (Fnet) + Lf->sf |= SELNET; + if ((k + 1) > (Namechl - 1)) + break; + if (pt == 1 && pcb.inp_ppcb) { + + /* + * If this is a UDP stream, get the udpdev structure at the + * PCB's per-protocol address. It may contain addresses. + */ + if (kread((KA_T)pcb.inp_ppcb, (char *)&udp, sizeof(udp)) + == 0) { + +#if OSRV>=500 + if (udp.ud_lsin.sin_addr.s_addr != INADDR_ANY + || udp.ud_lsin.sin_port != 0) + udpsl = 1; + else + udpsl = 0; +#endif /* OSRV>=500 */ + + if (udp.ud_fsin.sin_addr.s_addr != INADDR_ANY + || udp.ud_fsin.sin_port != 0) + udpsf = 1; + else + udpsf = 0; + } + } else + udpsf = udpsl = 0; + /* + * Enter the local address from the PCB. If there is none, + * and if this is a 5.0.0 or greater UDP stream, and if it + * has a local address set, use it. + */ + la = (unsigned char *)&pcb.inp_laddr; + lp = (int)ntohs(pcb.inp_lport); + +#if OSRV>=500 + if (((struct in_addr *)la)->s_addr == INADDR_ANY + && lp == 0 && udpsl) { + la = (unsigned char *)&udp.ud_lsin.sin_addr; + lp = (int)ntohs(udp.ud_lsin.sin_port); + } + +#endif /* OSRV>=500 */ + + /* + * Enter the foreign address from the PCB. If there is + * none, and if this is a 5.0.0 or greater UDP stream, and + * if it has a local address set, use it. + */ + if (pcb.inp_faddr.s_addr!=INADDR_ANY || pcb.inp_fport!=0) { + fa = (unsigned char *)&pcb.inp_faddr; + fp = (int)ntohs(pcb.inp_fport); + } else if (udpsf) { + fa = (unsigned char *)&udp.ud_fsin.sin_addr; + fp = (int)ntohs(udp.ud_fsin.sin_port); + udptm = 1; + } + if (fa || la) { + (void) ent_inaddr(la, lp, fa, fp, AF_INET); + if (udptm && !Lf->nma) + (void) udp_tm(udp.ud_ftime); + } + if (!i.i_number) + Lf->inp_ty = 2; + } + } else { + if (ity) { + if (strcasecmp(Fsinfo[ity-1], "COM") == 0) + Ntype = N_COM; + else + Ntype = N_CHR; + } else { + Ntype = N_CHR; + if (!finddev(&i.i_dev, &i.i_rdev, 0) + && HaveEventMajor + && GET_MAJ_DEV(i.i_rdev) == EventMajor) + (void) snpf(Namech, Namechl, + "clone %d:/dev/event", GET_MIN_DEV(i.i_rdev)); + } + } + break; + +#if defined(HAS_NFS) + case N_NFS: + +#if OSRV<500 + Lf->dev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_dev), + GET_MIN_DEV(i.i_dev)); + Lf->rdev = (dev_t)_makedev(~GET_MAJ_DEV(i.i_rdev), + GET_MIN_DEV(i.i_rdev)); +#else /* OSRV>=500 */ + Lf->dev = i.i_dev; + Lf->rdev = i.i_rdev; +#endif /* OSRV<500 */ + + Lf->dev_def = Lf->rdev_def = 1; + break; +#endif /* defined(HAS_NFS) */ + + } +/* + * Determine the inode number. + */ + switch (Ntype) { + case N_HSFS: + +#if OSRV<500 + /* + * High Sierra inode numbers for versions below 5.0.0, as reported + * by "ls -i" and stat(2), are the lower 16 bits of i_number. + */ + if ((Lf->inode = (unsigned long)(i.i_number & 0xffff))) +#else /* OSRV>=500 */ + if ((Lf->inode = (unsigned long)i.i_number)) +#endif /* OSRV<500 */ + + Lf->inp_ty = 1; + break; + +#if defined(HAS_NFS) + case N_NFS: + +#if OSRV<500 + n = (unsigned short *)&r.r_fh.fh_pad[14]; + if ((Lf->inode = (unsigned long)ntohs(*n))) + Lf->inp_ty = 1; + else if ((Lf->inode = (unsigned long)r.r_fh.fh_u.fh_fgen_u)) +#else /* OSRV>=500 */ + n = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[4]; + n1 = (unsigned short *)&r.r_fh.fh_u.fh_fid_u[2]; + if ((Lf->inode = (unsigned long)*n)) + Lf->inp_ty = 1; + else if ((Lf->inode = (unsigned long)*n1)) +#endif /* OSRV<500 */ + + Lf->inp_ty = 1; + break; +#endif /* defined(HAS_NFS) */ + + case N_BLK: + case N_CHR: + case N_COM: + case N_FIFO: + case N_NM: + case N_REGLR: + +#if OSRV>=500 + /* + * Inodes for some 5.0.x HPPS FIFOs have an i_number that is the same + * as i_fsptr. If it is, ignore it, because i_fsptr has already been + * recorded for the DEVICE column. + */ + if (hpps && i.i_fsptr && i.i_number + && (unsigned long)i.i_fsptr == (unsigned long)i.i_number) + break; +#endif /* OSRV>=500 */ + + if (i.i_number) { + Lf->inode = (unsigned long)i.i_number; + Lf->inp_ty = 1; + } + break; + } +/* + * Determine the file size. + */ + if (Foffset) + Lf->off_def = 1; + else { + switch (Ntype) { + case N_BLK: + if (!Fsize) + Lf->off_def = 1; + break; + case N_CHR: + case N_COM: + if (!Fsize) + Lf->off_def = 1; + break; + case N_FIFO: + +#if OSRV>=500 + if (hpps == 2) { + Lf->sz = (SZOFFTYPE)pi.count; + Lf->sz_def = 1; + break; + } +#endif /* OSRV>=500 */ + + if (!Fsize) + Lf->off_def = 1; + break; + case N_HSFS: + +#if defined(HAS_NFS) + case N_NFS: + Lf->sz = (SZOFFTYPE)i.i_size; + Lf->sz_def = 1; + break; +#endif /* defined(HAS_NFS) */ + + case N_REGLR: + if (type == IFREG || type == IFDIR) { + Lf->sz = (SZOFFTYPE)i.i_size; + Lf->sz_def = 1; + } + break; + } + } +/* + * Record link count. + */ + if (Fnlink) { + Lf->nlink = (long)i.i_nlink; + Lf->nlink_def = 1; + if (Nlink && (Lf->nlink < Nlink)) + Lf->sf |= SELNLINK; + } +/* + * Format the type name. + */ + switch (type) { + case IFDIR: + tn = "DIR"; + break; + case IFBLK: + tn = "BLK"; + break; + case IFCHR: + tn = "CHR"; + break; + case IFREG: + tn = "REG"; + break; + case IFMPC: + tn = "MPC"; + break; + case IFMPB: + tn = "MPB"; + break; + case IFNAM: + if (i.i_rdev == S_INSEM) + tn = "XSEM"; + else if (i.i_rdev == S_INSHD) + tn = "XSD"; + else { + tn = "XNAM"; + (void) snpf(Namech, Namechl, + "unknown Xenix special file type: %x", i.i_rdev); + } + break; + case IFIFO: + tn = "FIFO"; + break; + +#if defined(IFLNK) + case IFLNK: + tn = "LINK"; + break; +#endif /* defined(IFLNK) */ + + default: + (void) snpf(Lf->type, sizeof(Lf->type), "%04o", + ((type >> 12) & 0xfff)); + tn = NULL; + } + if (tn) + (void) snpf(Lf->type, sizeof(Lf->type), "%s", tn); +/* + * Save the file system names. + */ + switch (Ntype) { + case N_BLK: + case N_CHR: + case N_FIFO: + case N_HSFS: + +#if defined(HAS_NFS) + case N_NFS: +#endif /* defined(HAS_NFS) */ + + case N_NM: + case N_REGLR: + if (Lf->dev_def) { + + /* + * Defer the local mount info table search until printname(). + */ + Lf->lmi_srch = 1; + } + break; + } + Lf->ntype = Ntype; + +#if defined(HASBLKDEV) +/* + * If this is a IFBLK file and it's missing an inode number, try to + * supply one. + */ + if ((Lf->inp_ty == 0) && (type == IFBLK)) + find_bl_ino(); +#endif /* defined(HASBLKDEV) */ + +/* + * If this is a IFCHR file and it's missing an inode number, try to + * supply one. + */ + if ((Lf->inp_ty == 0) && (type == IFCHR)) + find_ch_ino(); +/* + * Test for specified file. + */ + if (Sfile && is_file_named((char *)NULL, + ((type == IFCHR) || (type == IFBLK) || (type == IFNAM)) ? 1 + : 0)) + Lf->sf |= SELNM; + +#if OSRV>=500 +/* + * If this is an HPPS node and no other name characters have been + * entered, enter HPPS as the name. + */ + if (hpps && Namech[0] == '\0') + (void) snpf(Namech, Namechl, "HPPS"); +#endif /* OSRV>=500 */ + +/* + * Enter name characters. + */ + if (Namech[0]) + enter_nm(Namech); +} |