diff options
Diffstat (limited to 'proc.c')
-rw-r--r-- | proc.c | 1237 |
1 files changed, 1237 insertions, 0 deletions
@@ -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); +} |