/* * 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.46 2010/07/29 15:59:28 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^" 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 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 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 defined(HASTASKS) /* * If this is a task of a process, skip it. */ if (Lp->tid) return(0); #endif /* defined(HASTASKS) */ /* * 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); }