summaryrefslogtreecommitdiff
path: root/dialects/osr/dnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'dialects/osr/dnode.c')
-rw-r--r--dialects/osr/dnode.c739
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);
+}