summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c1237
1 files changed, 1237 insertions, 0 deletions
diff --git a/proc.c b/proc.c
new file mode 100644
index 0000000..f42d160
--- /dev/null
+++ b/proc.c
@@ -0,0 +1,1237 @@
+/*
+ * proc.c - common process and file structure functions for lsof
+ */
+
+
+/*
+ * Copyright 1994 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 1994 Purdue Research Foundation.\nAll rights reserved.\n";
+static char *rcsid = "$Id: proc.c,v 1.47 2013/01/02 17:14:59 abe Exp $";
+#endif
+
+
+#include "lsof.h"
+
+
+/*
+ * Local function prototypes
+ */
+
+_PROTOTYPE(static int is_file_sel,(struct lproc *lp, struct lfile *lf));
+
+
+/*
+ * add_nma() - add to NAME column addition
+ */
+
+void
+add_nma(cp, len)
+ char *cp; /* string to add */
+ int len; /* string length */
+{
+ int nl;
+
+ if (!cp || !len)
+ return;
+ if (Lf->nma) {
+ nl = (int)strlen(Lf->nma);
+ Lf->nma = (char *)realloc((MALLOC_P *)Lf->nma,
+ (MALLOC_S)(len + nl + 2));
+ } else {
+ nl = 0;
+ Lf->nma = (char *)malloc((MALLOC_S)(len + 1));
+ }
+ if (!Lf->nma) {
+ (void) fprintf(stderr, "%s: no name addition space: PID %ld, FD %s",
+ Pn, (long)Lp->pid, Lf->fd);
+ Exit(1);
+ }
+ if (nl) {
+ Lf->nma[nl] = ' ';
+ (void) strncpy(&Lf->nma[nl + 1], cp, len);
+ Lf->nma[nl + 1 + len] = '\0';
+ } else {
+ (void) strncpy(Lf->nma, cp, len);
+ Lf->nma[len] = '\0';
+ }
+}
+
+
+#if defined(HASFSTRUCT)
+_PROTOTYPE(static char *alloc_fflbuf,(char **bp, int *al, int lr));
+
+
+/*
+ * alloc_fflbuf() - allocate file flags print buffer
+ */
+
+static char *
+alloc_fflbuf(bp, al, lr)
+ char **bp; /* current buffer pointer */
+ int *al; /* current allocated length */
+ int lr; /* length required */
+{
+ int sz;
+
+ sz = (int)(lr + 1); /* allocate '\0' space */
+ if (*bp && (sz <= *al))
+ return(*bp);
+ if (*bp)
+ *bp = (char *)realloc((MALLOC_P *)*bp, (MALLOC_S)sz);
+ else
+ *bp = (char *)malloc((MALLOC_S)sz);
+ if (!*bp) {
+ (void) fprintf(stderr, "%s: no space (%d) for print flags\n",
+ Pn, sz);
+ Exit(1);
+ }
+ *al = sz;
+ return(*bp);
+}
+#endif /* defined(HASFSTRUCT) */
+
+
+/*
+ * alloc_lfile() - allocate local file structure space
+ */
+
+void
+alloc_lfile(nm, num)
+ char *nm; /* file descriptor name (may be NULL) */
+ int num; /* file descriptor number -- -1 if
+ * none */
+{
+ int fds;
+
+ if (Lf) {
+/*
+ * If reusing a previously allocated structure, release any allocated
+ * space it was using.
+ */
+ if (Lf->dev_ch)
+ (void) free((FREE_P *)Lf->dev_ch);
+ if (Lf->nm)
+ (void) free((FREE_P *)Lf->nm);
+ if (Lf->nma)
+ (void) free((FREE_P *)Lf->nma);
+
+#if defined(HASLFILEADD) && defined(CLRLFILEADD)
+ CLRLFILEADD(Lf)
+#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */
+
+/*
+ * Othwerise, allocate a new structure.
+ */
+ } else if (!(Lf = (struct lfile *)malloc(sizeof(struct lfile)))) {
+ (void) fprintf(stderr, "%s: no local file space at PID %d\n",
+ Pn, Lp->pid);
+ Exit(1);
+ }
+/*
+ * Initialize the structure.
+ */
+ Lf->access = Lf->lock = ' ';
+ Lf->dev_def = Lf->inp_ty = Lf->is_com = Lf->is_nfs = Lf->is_stream
+ = Lf->lmi_srch = Lf->nlink_def = Lf->off_def = Lf->sz_def
+ = Lf->rdev_def
+ = (unsigned char)0;
+ Lf->li[0].af = Lf->li[1].af = 0;
+ Lf->lts.type = -1;
+ Lf->nlink = 0l;
+
+#if defined(HASMNTSTAT)
+ Lf->mnt_stat = (unsigned char)0;
+#endif /* defined(HASMNTSTAT) */
+
+#if defined(HASSOOPT)
+ Lf->lts.kai = Lf->lts.ltm = 0;
+ Lf->lts.opt = Lf->lts.qlen = Lf->lts.qlim = Lf->lts.pqlen
+ = (unsigned int)0;
+ Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0;
+ Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs
+ = Lf->lts.sbszs = (unsigned char)0;
+#endif /* defined(HASSOOPT) */
+
+#if defined(HASSOSTATE)
+ Lf->lts.ss = 0;
+#endif /* defined(HASSOSTATE) */
+
+#if defined(HASTCPOPT)
+ Lf->lts.mss = (unsigned long)0;
+ Lf->lts.msss = (unsigned char)0;
+ Lf->lts.topt = (unsigned int)0;
+#endif /* defined(HASTCPOPT) */
+
+#if defined(HASTCPTPIQ)
+ Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0;
+#endif /* defined(HASTCPTPIQ) */
+
+#if defined(HASTCPTPIW)
+ Lf->lts.rws = Lf->lts.wws = (unsigned char)0;
+#endif /* defined(HASTCPTPIW) */
+
+#if defined(HASFSINO)
+ Lf->fs_ino = 0;
+#endif /* defined(HASFSINO) */
+
+#if defined(HASVXFS) && defined(HASVXFSDNLC)
+ Lf->is_vxfs = 0;
+#endif /* defined(HASVXFS) && defined(HASVXFSDNLC) */
+
+ Lf->inode = (INODETYPE)0;
+ Lf->off = (SZOFFTYPE)0;
+ if (Lp->pss & PS_PRI)
+ Lf->sf = Lp->sf;
+ else
+ Lf->sf = 0;
+ Lf->iproto[0] = Lf->type[0] = '\0';
+ if (nm) {
+ (void) strncpy(Lf->fd, nm, FDLEN - 1);
+ Lf->fd[FDLEN - 1] = '\0';
+ } else if (num >= 0) {
+ if (num < 10000)
+ (void) snpf(Lf->fd, sizeof(Lf->fd), "%4d", num);
+ else
+ (void) snpf(Lf->fd, sizeof(Lf->fd), "*%03d", num % 1000);
+ } else
+ Lf->fd[0] = '\0';
+ Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL;
+ Lf->ch = -1;
+
+#if defined(HASNCACHE) && HASNCACHE<2
+ Lf->na = (KA_T)NULL;
+#endif /* defined(HASNCACHE) && HASNCACHE<2 */
+
+ Lf->next = (struct lfile *)NULL;
+ Lf->ntype = Ntype = N_REGLR;
+ Namech[0] = '\0';
+
+#if defined(HASFSTRUCT)
+ Lf->fct = Lf->ffg = Lf->pof = (long)0;
+ Lf->fna = (KA_T)NULL;
+ Lf->fsv = (unsigned char)0;
+#endif /* defined(HASFSTRUCT) */
+
+#if defined(HASLFILEADD) && defined(SETLFILEADD)
+/*
+ * Do local initializations.
+ */
+ SETLFILEADD
+#endif /* defined(HASLFILEADD) && defined(SETLFILEADD) */
+
+/*
+ * See if the file descriptor has been selected.
+ */
+ if (!Fdl || (!nm && num < 0))
+ return;
+ fds = ck_fd_status(nm, num);
+ switch (FdlTy) {
+ case 0: /* inclusion list */
+ if (fds == 2)
+ Lf->sf |= SELFD;
+ break;
+ case 1: /* exclusion list */
+ if (fds != 1)
+ Lf->sf |= SELFD;
+ }
+}
+
+
+/*
+ * alloc_lproc() - allocate local proc structure space
+ */
+
+void
+alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf)
+ int pid; /* Process ID */
+ int pgid; /* process group ID */
+ int ppid; /* parent process ID */
+ UID_ARG uid; /* User ID */
+ char *cmd; /* command */
+ int pss; /* process select state */
+ int sf; /* process select flags */
+{
+ static int sz = 0;
+
+ if (!Lproc) {
+ if (!(Lproc = (struct lproc *)malloc(
+ (MALLOC_S)(LPROCINCR * sizeof(struct lproc)))))
+ {
+ (void) fprintf(stderr,
+ "%s: no malloc space for %d local proc structures\n",
+ Pn, LPROCINCR);
+ Exit(1);
+ }
+ sz = LPROCINCR;
+ } else if ((Nlproc + 1) > sz) {
+ sz += LPROCINCR;
+ if (!(Lproc = (struct lproc *)realloc((MALLOC_P *)Lproc,
+ (MALLOC_S)(sz * sizeof(struct lproc)))))
+ {
+ (void) fprintf(stderr,
+ "%s: no realloc space for %d local proc structures\n",
+ Pn, sz);
+ Exit(1);
+ }
+ }
+ Lp = &Lproc[Nlproc++];
+ Lp->pid = pid;
+
+#if defined(HASTASKS)
+ Lp->tid = 0;
+#endif /* defined(HASTASKS) */
+
+ Lp->pgid = pgid;
+ Lp->ppid = ppid;
+ Lp->file = (struct lfile *)NULL;
+ Lp->sf = (short)sf;
+ Lp->pss = (short)pss;
+ Lp->uid = (uid_t)uid;
+/*
+ * Allocate space for the full command name and copy it there.
+ */
+ if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) {
+ (void) fprintf(stderr, "%s: PID %d, no space for command name: ",
+ Pn, pid);
+ safestrprt(cmd, stderr, 1);
+ Exit(1);
+ }
+
+#if defined(HASZONES)
+/*
+ * Clear the zone name pointer. The dialect's own code will set it.
+ */
+ Lp->zn = (char *)NULL;
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+/*
+ * Clear the security context pointer. The dialect's own code will
+ * set it.
+ */
+ Lp->cntx = (char *)NULL;
+#endif /* defined(HASSELINUX) */
+
+}
+
+
+/*
+ * ck_fd_status() - check FD status
+ *
+ * return: 0 == FD is neither included nor excluded
+ * 1 == FD is excluded
+ * 2 == FD is included
+ */
+
+extern int
+ck_fd_status(nm, num)
+ char *nm; /* file descriptor name (may be NULL) */
+ int num; /* file descriptor number -- -1 if
+ * none */
+{
+ char *cp;
+ struct fd_lst *fp;
+
+ if (!(fp = Fdl) || (!nm && num < 0))
+ return(0);
+ if ((cp = nm)) {
+ while (*cp && *cp == ' ')
+ cp++;
+ }
+/*
+ * Check for an exclusion match.
+ */
+ if (FdlTy == 1) {
+ for (; fp; fp = fp->next) {
+ if (cp) {
+ if (fp->nm && strcmp(fp->nm, cp) == 0)
+ return(1);
+ continue;
+ }
+ if (num >= fp->lo && num <= fp->hi)
+ return(1);
+ }
+ return(0);
+ }
+/*
+ * If Fdl isn't an exclusion list, check for an inclusion match.
+ */
+ for (; fp; fp = fp->next) {
+ if (cp) {
+ if (fp->nm && strcmp(fp->nm, cp) == 0)
+ return(2);
+ continue;
+ }
+ if (num >= fp->lo && num <= fp->hi)
+ return(2);
+ }
+ return(0);
+}
+
+
+/*
+ * comppid() - compare PIDs
+ */
+
+int
+comppid(a1, a2)
+ COMP_P *a1, *a2;
+{
+ struct lproc **p1 = (struct lproc **)a1;
+ struct lproc **p2 = (struct lproc **)a2;
+
+ if ((*p1)->pid < (*p2)->pid)
+ return(-1);
+ if ((*p1)->pid > (*p2)->pid)
+ return(1);
+
+#if defined(HASTASKS)
+ if ((*p1)->tid < (*p2)->tid)
+ return(-1);
+ if ((*p1)->tid > (*p2)->tid)
+ return(1);
+#endif /* defined(HASTASKS) */
+
+ return(0);
+}
+
+
+/*
+ * ent_inaddr() - enter Internet addresses
+ */
+
+void
+ent_inaddr(la, lp, fa, fp, af)
+ unsigned char *la; /* local Internet address */
+ int lp; /* local port */
+ unsigned char *fa; /* foreign Internet address -- may
+ * be NULL to indicate no foreign
+ * address is known */
+ int fp; /* foreign port */
+ int af; /* address family -- e.g, AF_INET,
+ * AF_INET */
+{
+ int m;
+
+ if (la) {
+ Lf->li[0].af = af;
+
+#if defined(HASIPv6)
+ if (af == AF_INET6)
+ Lf->li[0].ia.a6 = *(struct in6_addr *)la;
+ else
+#endif /* defined(HASIPv6) */
+
+ Lf->li[0].ia.a4 = *(struct in_addr *)la;
+ Lf->li[0].p = lp;
+ } else
+ Lf->li[0].af = 0;
+ if (fa) {
+ Lf->li[1].af = af;
+
+#if defined(HASIPv6)
+ if (af == AF_INET6)
+ Lf->li[1].ia.a6 = *(struct in6_addr *)fa;
+ else
+#endif /* defined(HASIPv6) */
+
+ Lf->li[1].ia.a4 = *(struct in_addr *)fa;
+ Lf->li[1].p = fp;
+ } else
+ Lf->li[1].af = 0;
+/*
+ * If network address matching has been selected, check both addresses.
+ */
+ if ((Selflags & SELNA) && Nwad) {
+ m = (fa && is_nw_addr(fa, fp, af)) ? 1 : 0;
+ m |= (la && is_nw_addr(la, lp, af)) ? 1 : 0;
+ if (m)
+ Lf->sf |= SELNA;
+ }
+}
+
+
+/*
+ * examine_lproc() - examine local process
+ *
+ * return: 1 = last process
+ */
+
+int
+examine_lproc()
+{
+ int sbp = 0;
+
+ if (RptTm)
+ return(0);
+/*
+ * List the process if the process is selected and:
+ *
+ * o listing is limited to a single PID selection -- this one;
+ *
+ * o listing is selected by an ANDed option set (not all options)
+ * that includes a single PID selection -- this one.
+ */
+ if ((Lp->sf & SELPID) && !Selall) {
+ if ((Selflags == SELPID)
+ || (Fand && (Selflags & SELPID))) {
+ sbp = 1;
+ Npuns--;
+ }
+ }
+ if (Lp->pss && Npid == 1 && sbp) {
+ print_init();
+ (void) print_proc();
+ PrPass++;
+ if (PrPass < 2)
+ (void) print_proc();
+ Lp->pss = 0;
+ }
+/*
+ * Deprecate an unselected (or listed) process.
+ */
+ if ( ! Lp->pss) {
+ (void) free_lproc(Lp);
+ Nlproc--;
+ }
+/*
+ * Indicate last-process if listing is limited to PID selections,
+ * and all selected processes have been listed.
+ */
+ return((sbp && Npuns == 0) ? 1 : 0);
+}
+
+
+/*
+ * free_lproc() - free lproc entry and its associated malloc'd space
+ */
+
+void
+free_lproc(lp)
+ struct lproc *lp;
+{
+ struct lfile *lf, *nf;
+
+ for (lf = lp->file; lf; lf = nf) {
+ if (lf->dev_ch) {
+ (void) free((FREE_P *)lf->dev_ch);
+ lf->dev_ch = (char *)NULL;
+ }
+ if (lf->nm) {
+ (void) free((FREE_P *)lf->nm);
+ lf->nm = (char *)NULL;
+ }
+ if (lf->nma) {
+ (void) free((FREE_P *)lf->nma);
+ lf->nma = (char *)NULL;
+ }
+
+#if defined(HASLFILEADD) && defined(CLRLFILEADD)
+ CLRLFILEADD(lf)
+#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */
+
+ nf = lf->next;
+ (void) free((FREE_P *)lf);
+ }
+ lp->file = (struct lfile *)NULL;
+ if (lp->cmd) {
+ (void) free((FREE_P *)lp->cmd);
+ lp->cmd = (char *)NULL;
+ }
+}
+
+
+/*
+ * is_cmd_excl() - is command excluded?
+ */
+
+int
+is_cmd_excl(cmd, pss, sf)
+ char *cmd; /* command name */
+ short *pss; /* process state */
+ short *sf; /* process select flags */
+{
+ int i;
+ struct str_lst *sp;
+/*
+ * See if the command is excluded by a "-c^<command>" option.
+ */
+ if (Cmdl && Cmdnx) {
+ for (sp = Cmdl; sp; sp = sp->next) {
+ if (sp->x && !strncmp(sp->str, cmd, sp->len))
+ return(1);
+ }
+ }
+/*
+ * The command is not excluded if no command selection was requested,
+ * or if its name matches any -c <command> specification.
+ *
+ */
+ if ((Selflags & SELCMD) == 0)
+ return(0);
+ for (sp = Cmdl; sp; sp = sp->next) {
+ if (!sp->x && !strncmp(sp->str, cmd, sp->len)) {
+ sp->f = 1;
+ *pss |= PS_PRI;
+ *sf |= SELCMD;
+ return(0);
+ }
+ }
+/*
+ * The command name doesn't match any -c <command> specification. See if it
+ * matches a -c /RE/[bix] specification.
+ */
+ for (i = 0; i < NCmdRxU; i++) {
+ if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) {
+ CmdRx[i].mc = 1;
+ *pss |= PS_PRI;
+ *sf |= SELCMD;
+ return(0);
+ }
+ }
+/*
+ * The command name matches no -c specification.
+ *
+ * It's excluded if the only selection condition is command name,
+ * or if command name selection is part of an ANDed set.
+ */
+ if (Selflags == SELCMD)
+ return(1);
+ return (Fand ? 1 : 0);
+}
+
+
+/*
+ * is_file_sel() - is file selected?
+ */
+
+static int
+is_file_sel(lp, lf)
+ struct lproc *lp; /* lproc structure pointer */
+ struct lfile *lf; /* lfile structure pointer */
+{
+ if (!lf || !lf->sf)
+ return(0);
+ if (Lf->sf & SELEXCLF)
+ return(0);
+
+#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
+ if (Myuid && (Myuid != lp->uid)) {
+ if (!(lf->sf & (SELNA | SELNET)))
+ return(0);
+ }
+#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
+
+ if (Selall)
+ return(1);
+ if (Fand && ((lf->sf & Selflags) != Selflags))
+ return(0);
+ return(1);
+}
+
+
+/*
+ * is_proc_excl() - is process excluded?
+ */
+
+int
+
+#if defined(HASTASKS)
+is_proc_excl(pid, pgid, uid, pss, sf, tid)
+#else /* !defined(HASTASKS) */
+is_proc_excl(pid, pgid, uid, pss, sf)
+#endif /* defined(HASTASKS) */
+
+ int pid; /* Process ID */
+ int pgid; /* process group ID */
+ UID_ARG uid; /* User ID */
+ short *pss; /* process select state for lproc */
+ short *sf; /* select flags for lproc */
+
+#if defined(HASTASKS)
+ int tid; /* task ID (not a task if zero) */
+#endif /* defined(HASTASKS) */
+
+{
+ int i, j;
+
+ *pss = *sf = 0;
+
+#if defined(HASSECURITY)
+/*
+ * The process is excluded by virtue of the security option if it
+ * isn't owned by the owner of this lsof process, unless the
+ * HASNOSOCKSECURITY option is also specified. In that case the
+ * selected socket files of any process may be listed.
+ */
+# if !defined(HASNOSOCKSECURITY)
+ if (Myuid && Myuid != (uid_t)uid)
+ return(1);
+# endif /* !defined(HASNOSOCKSECURITY) */
+#endif /* defined(HASSECURITY) */
+
+/*
+ * If the excluding of process listing by UID has been specified, see if the
+ * owner of this process is excluded.
+ */
+ if (Nuidexcl) {
+ for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) {
+ if (!Suid[i].excl)
+ continue;
+ if (Suid[i].uid == (uid_t)uid)
+ return(1);
+ j++;
+ }
+ }
+/*
+ * If the excluding of process listing by PGID has been specified, see if this
+ * PGID is excluded.
+ */
+ if (Npgidx) {
+ for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) {
+ if (!Spgid[i].x)
+ continue;
+ if (Spgid[i].i == pgid)
+ return(1);
+ j++;
+ }
+ }
+/*
+ * If the excluding of process listing by PID has been specified, see if this
+ * PID is excluded.
+ */
+ if (Npidx) {
+ for (i = j = 0; (i < Npid) && (j < Npidx); i++) {
+ if (!Spid[i].x)
+ continue;
+ if (Spid[i].i == pid)
+ return(1);
+ j++;
+ }
+ }
+/*
+ * If the listing of all processes is selected, then this one is not excluded.
+ *
+ * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude
+ * network selections from the file flags, so that the tests in is_file_sel()
+ * work as expected.
+ */
+ if (Selall) {
+ *pss = PS_PRI;
+
+#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
+ *sf = SELALL & ~(SELNA | SELNET);
+#else /* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */
+ *sf = SELALL;
+#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
+
+ return(0);
+ }
+/*
+ * If the listing of processes has been specified by process group ID, see
+ * if this one is included or excluded.
+ */
+ if (Npgidi && (Selflags & SELPGID)) {
+ for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) {
+ if (Spgid[i].x)
+ continue;
+ if (Spgid[i].i == pgid) {
+ Spgid[i].f = 1;
+ *pss = PS_PRI;
+ *sf = SELPGID;
+ if (Selflags == SELPGID)
+ return(0);
+ break;
+ }
+ j++;
+ }
+ if ((Selflags == SELPGID) && !*sf)
+ return(1);
+ }
+/*
+ * If the listing of processes has been specified by PID, see if this one is
+ * included or excluded.
+ */
+ if (Npidi && (Selflags & SELPID)) {
+ for (i = j = 0; (i < Npid) && (j < Npidi); i++) {
+ if (Spid[i].x)
+ continue;
+ if (Spid[i].i == pid) {
+ Spid[i].f = 1;
+ *pss = PS_PRI;
+ *sf |= SELPID;
+ if (Selflags == SELPID)
+ return(0);
+ break;
+ }
+ j++;
+ }
+ if ((Selflags == SELPID) && !*sf)
+ return(1);
+ }
+/*
+ * If the listing of processes has been specified by UID, see if the owner of
+ * this process has been included.
+ */
+ if (Nuidincl && (Selflags & SELUID)) {
+ for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) {
+ if (Suid[i].excl)
+ continue;
+ if (Suid[i].uid == (uid_t)uid) {
+ Suid[i].f = 1;
+ *pss = PS_PRI;
+ *sf |= SELUID;
+ if (Selflags == SELUID)
+ return(0);
+ break;
+ }
+ j++;
+ }
+ if (Selflags == SELUID && (*sf & SELUID) == 0)
+ return(1);
+ }
+
+#if defined(HASTASKS)
+ if ((Selflags & SELTASK) && tid) {
+
+ /*
+ * This is a task and tasks are selected.
+ */
+ *pss = PS_PRI;
+ *sf |= SELTASK;
+ if ((Selflags == SELTASK)
+ || (Fand && ((*sf & Selflags) == Selflags)))
+ return(0);
+ }
+#endif /* defined(HASTASKS) */
+
+/*
+ * When neither the process group ID, nor the PID, nor the task, nor the UID
+ * is selected:
+ *
+ * If list option ANDing of process group IDs, PIDs, UIDs or tasks is
+ * specified, the process is excluded;
+ *
+ * Otherwise, it's not excluded by the tests of this function.
+ */
+ if ( ! *sf)
+ return((Fand && (Selflags & (SELPGID|SELPID|SELUID|SELTASK)))
+ ? 1 : 0);
+/*
+ * When the process group ID, PID, task or UID is selected and the process
+ * group ID, PID, task or UID list option has been specified:
+ *
+ * If list option ANDing has been specified, and the correct
+ * combination of selections are in place, reply that the process is no
+ * excluded;
+ * or
+ * If list option ANDing has not been specified, reply that the
+ * process is not excluded by the tests of this function.
+ */
+ if (Selflags & (SELPGID|SELPID|SELUID|SELTASK)) {
+ if (Fand)
+ return(((Selflags & (SELPGID|SELPID|SELUID|SELTASK)) != *sf)
+ ? 1 : 0);
+ return(0);
+ }
+/*
+ * Finally, when neither the process group ID, nor the PID, nor the UID, nor
+ * the task is selected, and no applicable list option has been specified:
+ *
+ * If list option ANDing has been specified, this process is
+ * excluded;
+ *
+ * Otherwise, it isn't excluded by the tests of this function.
+ */
+ return(Fand ? 1 : 0);
+}
+
+
+/*
+ * link_lfile() - link local file structures
+ */
+
+void
+link_lfile()
+{
+ if (Lf->sf & SELEXCLF)
+ return;
+ Lp->pss |= PS_SEC;
+ if (Plf)
+ Plf->next = Lf;
+ else
+ Lp->file = Lf;
+ Plf = Lf;
+ if (Fnet && (Lf->sf & SELNET))
+ Fnet = 2;
+ if (Fnfs && (Lf->sf & SELNFS))
+ Fnfs = 2;
+ if (Ftask && (Lf->sf & SELTASK))
+ Ftask = 2;
+ Lf = (struct lfile *)NULL;
+}
+
+
+#if defined(HASFSTRUCT)
+/*
+ * print_fflags() - print interpreted f_flag[s]
+ */
+
+char *
+print_fflags(ffg, pof)
+ long ffg; /* file structure's flags value */
+ long pof; /* process open files flags value */
+{
+ int al, ct, fx;
+ static int bl = 0;
+ static char *bp = (char *)NULL;
+ char *sep;
+ int sepl;
+ struct pff_tab *tp;
+ long wf;
+ char xbuf[64];
+/*
+ * Reduce the supplied flags according to the definitions in Pff_tab[] and
+ * Pof_tab[].
+ */
+ for (ct = fx = 0; fx < 2; fx++) {
+ if (fx == 0) {
+ sep = "";
+ sepl = 0;
+ tp = Pff_tab;
+ wf = ffg;
+ } else {
+ sep = ";";
+ sepl = 1;
+ tp = Pof_tab;
+ wf = pof;
+ }
+ for (; wf && !FsvFlagX; ct += al ) {
+ while (tp->nm) {
+ if (wf & tp->val)
+ break;
+ tp++;
+ }
+ if (!tp->nm)
+ break;
+ al = (int)strlen(tp->nm) + sepl;
+ bp = alloc_fflbuf(&bp, &bl, al + ct);
+ (void) snpf(bp + ct, al + 1, "%s%s", sep, tp->nm);
+ sep = ",";
+ sepl = 1;
+ wf &= ~(tp->val);
+ }
+ /*
+ * If flag bits remain, print them in hex. If hex output was
+ * specified with +fG, print all flag values, including zero,
+ * in hex.
+ */
+ if (wf || FsvFlagX) {
+ (void) snpf(xbuf, sizeof(xbuf), "0x%lx", wf);
+ al = (int)strlen(xbuf) + sepl;
+ bp = alloc_fflbuf(&bp, &bl, al + ct);
+ (void) snpf(bp + ct, al + 1, "%s%s", sep, xbuf);
+ ct += al;
+ }
+ }
+/*
+ * Make sure there is at least a NUL terminated reply.
+ */
+ if (!bp) {
+ bp = alloc_fflbuf(&bp, &bl, 0);
+ *bp = '\0';
+ }
+ return(bp);
+}
+#endif /* defined(HASFSTRUCT) */
+
+
+/*
+ * print_proc() - print process
+ */
+
+int
+print_proc()
+{
+ char buf[128], *cp;
+ int lc, len, st, ty;
+ int rv = 0;
+ unsigned long ul;
+/*
+ * If nothing in the process has been selected, skip it.
+ */
+ if (!Lp->pss)
+ return(0);
+ if (Fterse) {
+ if (Lp->pid == LastPid) /* eliminate duplicates */
+ return(0);
+ LastPid = Lp->pid;
+ /*
+ * The mode is terse and something in the process appears to have
+ * been selected. Make sure of that by looking for a selected file,
+ * so that the HASSECURITY and HASNOSOCKSECURITY option combination
+ * won't produce a false positive result.
+ */
+ for (Lf = Lp->file; Lf; Lf = Lf->next) {
+ if (is_file_sel(Lp, Lf)) {
+ (void) printf("%d\n", Lp->pid);
+ return(1);
+ }
+ }
+ return(0);
+ }
+/*
+ * If fields have been selected, output the process-only ones, provided
+ * that some file has also been selected.
+ */
+ if (Ffield) {
+ for (Lf = Lp->file; Lf; Lf = Lf->next) {
+ if (is_file_sel(Lp, Lf))
+ break;
+ }
+ if (!Lf)
+ return(rv);
+ rv = 1;
+ (void) printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator);
+
+#if defined(HASTASKS)
+ if (FieldSel[LSOF_FIX_TID].st && Lp->tid)
+ (void) printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator);
+#endif /* defined(HASTASKS) */
+
+#if defined(HASZONES)
+ if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn)
+ (void) printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator);
+#endif /* defined(HASZONES) */
+
+#if defined(HASSELINUX)
+ if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus)
+ (void) printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator);
+#endif /* defined(HASSELINUX) */
+
+ if (FieldSel[LSOF_FIX_PGID].st && Fpgid)
+ (void) printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator);
+
+#if defined(HASPPID)
+ if (FieldSel[LSOF_FIX_PPID].st && Fppid)
+ (void) printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator);
+#endif /* defined(HASPPID) */
+
+ if (FieldSel[LSOF_FIX_CMD].st) {
+ putchar(LSOF_FID_CMD);
+ safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0);
+ putchar(Terminator);
+ }
+ if (FieldSel[LSOF_FIX_UID].st)
+ (void) printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator);
+ if (FieldSel[LSOF_FIX_LOGIN].st) {
+ cp = printuid((UID_ARG)Lp->uid, &ty);
+ if (ty == 0)
+ (void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
+ }
+ if (Terminator == '\0')
+ putchar('\n');
+ }
+/*
+ * Print files.
+ */
+ for (Lf = Lp->file; Lf; Lf = Lf->next) {
+ if (!is_file_sel(Lp, Lf))
+ continue;
+ rv = 1;
+ /*
+ * If no field output selected, print dialects-specific formatted
+ * output.
+ */
+ if (!Ffield) {
+ print_file();
+ continue;
+ }
+ /*
+ * Print selected fields.
+ */
+ lc = st = 0;
+ if (FieldSel[LSOF_FIX_FD].st) {
+ for (cp = Lf->fd; *cp == ' '; cp++)
+ ;
+ if (*cp) {
+ (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator);
+ lc++;
+ }
+ }
+ if (FieldSel[LSOF_FIX_ACCESS].st) {
+ (void) printf("%c%c%c",
+ LSOF_FID_ACCESS, Lf->access, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_LOCK].st) {
+ (void) printf("%c%c%c", LSOF_FID_LOCK, Lf->lock, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_TYPE].st) {
+ for (cp = Lf->type; *cp == ' '; cp++)
+ ;
+ if (*cp) {
+ (void) printf("%c%s%c", LSOF_FID_TYPE, cp, Terminator);
+ lc++;
+ }
+ }
+
+#if defined(HASFSTRUCT)
+ if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA)
+ && (Lf->fsv & FSV_FA)) {
+ (void) printf("%c%s%c", LSOF_FID_FA,
+ print_kptr(Lf->fsa, (char *)NULL, 0), Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT)
+ && (Lf->fsv & FSV_CT)) {
+ (void) printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG)
+ && (Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof)) {
+ (void) printf("%c%s%c", LSOF_FID_FG,
+ print_fflags(Lf->ffg, Lf->pof), Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI)
+ && (Lf->fsv & FSV_NI)) {
+ (void) printf("%c%s%c", LSOF_FID_NI,
+ print_kptr(Lf->fna, (char *)NULL, 0), Terminator);
+ lc++;
+ }
+#endif /* defined(HASFSTRUCT) */
+
+ if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) {
+ for (cp = Lf->dev_ch; *cp == ' '; cp++)
+ ;
+ if (*cp) {
+ (void) printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator);
+ lc++;
+ }
+ }
+ if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) {
+ if (sizeof(unsigned long) > sizeof(dev_t))
+ ul = (unsigned long)((unsigned int)Lf->dev);
+ else
+ ul = (unsigned long)Lf->dev;
+ (void) printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) {
+ if (sizeof(unsigned long) > sizeof(dev_t))
+ ul = (unsigned long)((unsigned int)Lf->rdev);
+ else
+ ul = (unsigned long)Lf->rdev;
+ (void) printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) {
+ putchar(LSOF_FID_SIZE);
+
+#if defined(HASPRINTSZ)
+ cp = HASPRINTSZ(Lf);
+#else /* !defined(HASPRINTSZ) */
+ (void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
+ cp = buf;
+#endif /* defined(HASPRINTSZ) */
+
+ (void) printf("%s", cp);
+ putchar(Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) {
+ putchar(LSOF_FID_OFFSET);
+
+#if defined(HASPRINTOFF)
+ cp = HASPRINTOFF(Lf, 0);
+#else /* !defined(HASPRINTOFF) */
+ (void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
+ cp = buf;
+#endif /* defined(HASPRINTOFF) */
+
+ len = strlen(cp);
+ if (OffDecDig && len > (OffDecDig + 2)) {
+
+#if defined(HASPRINTOFF)
+ cp = HASPRINTOFF(Lf, 1);
+#else /* !defined(HASPRINTOFF) */
+ (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
+ cp = buf;
+#endif /* defined(HASPRINTOFF) */
+
+ }
+ (void) printf("%s", cp);
+ putchar(Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) {
+ putchar(LSOF_FID_INODE);
+ (void) printf(InodeFmt_d, Lf->inode);
+ putchar(Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) {
+ (void) printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator);
+ lc++;
+ }
+ if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) {
+ for (cp = Lf->iproto; *cp == ' '; cp++)
+ ;
+ if (*cp) {
+ (void) printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator);
+ lc++;
+ }
+ }
+ if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) {
+ if (strncmp(Lf->nm, "STR:", 4) == 0
+ || strcmp(Lf->iproto, "STR") == 0) {
+ putchar(LSOF_FID_STREAM);
+ printname(0);
+ putchar(Terminator);
+ lc++;
+ st++;
+ }
+ }
+ if (st == 0 && FieldSel[LSOF_FIX_NAME].st) {
+ putchar(LSOF_FID_NAME);
+ printname(0);
+ putchar(Terminator);
+ lc++;
+ }
+ if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) {
+ print_tcptpi(0);
+ lc++;
+ }
+ if (Terminator == '\0' && lc)
+ putchar('\n');
+ }
+ return(rv);
+}