1/*
2 * proc.c - common process and file structure functions for lsof
3 */
4
5
6/*
7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907.  All rights reserved.
9 *
10 * Written by Victor A. Abell
11 *
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
14 *
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
18 *
19 * 1. Neither the authors nor Purdue University are responsible for any
20 *    consequences of the use of this software.
21 *
22 * 2. The origin of this software must not be misrepresented, either by
23 *    explicit claim or by omission.  Credit to the authors and Purdue
24 *    University must appear in documentation and sources.
25 *
26 * 3. Altered versions must be plainly marked as such, and must not be
27 *    misrepresented as being the original software.
28 *
29 * 4. This notice may not be removed or altered.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35static char *rcsid = "$Id: proc.c,v 1.47 2013/01/02 17:14:59 abe Exp $";
36#endif
37
38
39#include "lsof.h"
40
41
42/*
43 * Local function prototypes
44 */
45
46_PROTOTYPE(static int is_file_sel,(struct lproc *lp, struct lfile *lf));
47
48
49/*
50 * add_nma() - add to NAME column addition
51 */
52
53void
54add_nma(cp, len)
55	char *cp;			/* string to add */
56	int len;			/* string length */
57{
58	int nl;
59
60	if (!cp || !len)
61	    return;
62	if (Lf->nma) {
63	    nl = (int)strlen(Lf->nma);
64	    Lf->nma = (char *)realloc((MALLOC_P *)Lf->nma,
65				      (MALLOC_S)(len + nl + 2));
66	} else {
67	    nl = 0;
68	    Lf->nma = (char *)malloc((MALLOC_S)(len + 1));
69	}
70	if (!Lf->nma) {
71	    (void) fprintf(stderr, "%s: no name addition space: PID %ld, FD %s",
72		Pn, (long)Lp->pid, Lf->fd);
73	    Exit(1);
74	}
75	if (nl) {
76	    Lf->nma[nl] = ' ';
77	    (void) strncpy(&Lf->nma[nl + 1], cp, len);
78	    Lf->nma[nl + 1 + len] = '\0';
79	} else {
80	    (void) strncpy(Lf->nma, cp, len);
81	    Lf->nma[len] = '\0';
82	}
83}
84
85
86#if	defined(HASFSTRUCT)
87_PROTOTYPE(static char *alloc_fflbuf,(char **bp, int *al, int lr));
88
89
90/*
91 * alloc_fflbuf() - allocate file flags print buffer
92 */
93
94static char *
95alloc_fflbuf(bp, al, lr)
96	char **bp;			/* current buffer pointer */
97	int *al;			/* current allocated length */
98	int lr;				/* length required */
99{
100	int sz;
101
102	sz = (int)(lr + 1);		/* allocate '\0' space */
103	if (*bp && (sz <= *al))
104	    return(*bp);
105	if (*bp)
106	    *bp = (char *)realloc((MALLOC_P *)*bp, (MALLOC_S)sz);
107	else
108	    *bp = (char *)malloc((MALLOC_S)sz);
109	if (!*bp) {
110	    (void) fprintf(stderr, "%s: no space (%d) for print flags\n",
111		Pn, sz);
112	    Exit(1);
113	}
114	*al = sz;
115	return(*bp);
116}
117#endif	/* defined(HASFSTRUCT) */
118
119
120/*
121 * alloc_lfile() - allocate local file structure space
122 */
123
124void
125alloc_lfile(nm, num)
126	char *nm;			/* file descriptor name (may be NULL) */
127	int num;			/* file descriptor number -- -1 if
128					 * none */
129{
130	int fds;
131
132	if (Lf) {
133/*
134 * If reusing a previously allocated structure, release any allocated
135 * space it was using.
136 */
137	    if (Lf->dev_ch)
138		(void) free((FREE_P *)Lf->dev_ch);
139	    if (Lf->nm)
140		(void) free((FREE_P *)Lf->nm);
141	    if (Lf->nma)
142		(void) free((FREE_P *)Lf->nma);
143
144#if	defined(HASLFILEADD) && defined(CLRLFILEADD)
145	    CLRLFILEADD(Lf)
146#endif	/* defined(HASLFILEADD) && defined(CLRLFILEADD) */
147
148/*
149 * Othwerise, allocate a new structure.
150 */
151	} else if (!(Lf = (struct lfile *)malloc(sizeof(struct lfile)))) {
152	    (void) fprintf(stderr, "%s: no local file space at PID %d\n",
153		Pn, Lp->pid);
154	    Exit(1);
155	}
156/*
157 * Initialize the structure.
158 */
159	Lf->access = Lf->lock = ' ';
160	Lf->dev_def = Lf->inp_ty = Lf->is_com = Lf->is_nfs = Lf->is_stream
161		    = Lf->lmi_srch = Lf->nlink_def = Lf->off_def = Lf->sz_def
162		    = Lf->rdev_def
163		    = (unsigned char)0;
164	Lf->li[0].af = Lf->li[1].af = 0;
165	Lf->lts.type = -1;
166	Lf->nlink = 0l;
167
168#if	defined(HASMNTSTAT)
169	Lf->mnt_stat = (unsigned char)0;
170#endif	/* defined(HASMNTSTAT) */
171
172#if	defined(HASSOOPT)
173	Lf->lts.kai = Lf->lts.ltm = 0;
174	Lf->lts.opt = Lf->lts.qlen = Lf->lts.qlim = Lf->lts.pqlen
175		    = (unsigned int)0;
176	Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0;
177	Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs
178		      = Lf->lts.sbszs = (unsigned char)0;
179#endif	/* defined(HASSOOPT) */
180
181#if	defined(HASSOSTATE)
182	Lf->lts.ss = 0;
183#endif	/* defined(HASSOSTATE) */
184
185#if	defined(HASTCPOPT)
186	Lf->lts.mss = (unsigned long)0;
187	Lf->lts.msss = (unsigned char)0;
188	Lf->lts.topt = (unsigned int)0;
189#endif	/* defined(HASTCPOPT) */
190
191#if	defined(HASTCPTPIQ)
192	Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0;
193#endif	/* defined(HASTCPTPIQ) */
194
195#if	defined(HASTCPTPIW)
196	Lf->lts.rws = Lf->lts.wws = (unsigned char)0;
197#endif	/* defined(HASTCPTPIW) */
198
199#if	defined(HASFSINO)
200	Lf->fs_ino = 0;
201#endif	/* defined(HASFSINO) */
202
203#if	defined(HASVXFS) && defined(HASVXFSDNLC)
204	Lf->is_vxfs = 0;
205#endif	/* defined(HASVXFS) && defined(HASVXFSDNLC) */
206
207	Lf->inode = (INODETYPE)0;
208	Lf->off = (SZOFFTYPE)0;
209	if (Lp->pss & PS_PRI)
210	    Lf->sf = Lp->sf;
211	else
212	    Lf->sf = 0;
213	Lf->iproto[0] = Lf->type[0] = '\0';
214	if (nm) {
215	    (void) strncpy(Lf->fd, nm, FDLEN - 1);
216	    Lf->fd[FDLEN - 1] = '\0';
217	} else if (num >= 0) {
218	    if (num < 10000)
219		(void) snpf(Lf->fd, sizeof(Lf->fd), "%4d", num);
220	    else
221		(void) snpf(Lf->fd, sizeof(Lf->fd), "*%03d", num % 1000);
222	} else
223	    Lf->fd[0] = '\0';
224	Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL;
225	Lf->ch = -1;
226
227#if	defined(HASNCACHE) && HASNCACHE<2
228	Lf->na = (KA_T)NULL;
229#endif	/* defined(HASNCACHE) && HASNCACHE<2 */
230
231	Lf->next = (struct lfile *)NULL;
232	Lf->ntype = Ntype = N_REGLR;
233	Namech[0] = '\0';
234
235#if	defined(HASFSTRUCT)
236	Lf->fct = Lf->ffg = Lf->pof = (long)0;
237	Lf->fna = (KA_T)NULL;
238	Lf->fsv = (unsigned char)0;
239#endif	/* defined(HASFSTRUCT) */
240
241#if	defined(HASLFILEADD) && defined(SETLFILEADD)
242/*
243 * Do local initializations.
244 */
245	SETLFILEADD
246#endif	/* defined(HASLFILEADD) && defined(SETLFILEADD) */
247
248/*
249 * See if the file descriptor has been selected.
250 */
251	if (!Fdl || (!nm && num < 0))
252	    return;
253	fds = ck_fd_status(nm, num);
254	switch (FdlTy) {
255	case 0:			/* inclusion list */
256	    if (fds == 2)
257		Lf->sf |= SELFD;
258	    break;
259	case 1:			/* exclusion list */
260	    if (fds != 1)
261		Lf->sf |= SELFD;
262	}
263}
264
265
266/*
267 * alloc_lproc() - allocate local proc structure space
268 */
269
270void
271alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf)
272	int pid;			/* Process ID */
273	int pgid;			/* process group ID */
274	int ppid;			/* parent process ID */
275	UID_ARG uid;			/* User ID */
276	char *cmd;			/* command */
277	int pss;			/* process select state */
278	int sf;				/* process select flags */
279{
280	static int sz = 0;
281
282	if (!Lproc) {
283	    if (!(Lproc = (struct lproc *)malloc(
284			  (MALLOC_S)(LPROCINCR * sizeof(struct lproc)))))
285	    {
286		(void) fprintf(stderr,
287		    "%s: no malloc space for %d local proc structures\n",
288		    Pn, LPROCINCR);
289		Exit(1);
290	    }
291	    sz = LPROCINCR;
292	} else if ((Nlproc + 1) > sz) {
293	    sz += LPROCINCR;
294	    if (!(Lproc = (struct lproc *)realloc((MALLOC_P *)Lproc,
295			  (MALLOC_S)(sz * sizeof(struct lproc)))))
296	    {
297		(void) fprintf(stderr,
298		    "%s: no realloc space for %d local proc structures\n",
299		    Pn, sz);
300		Exit(1);
301	    }
302	}
303	Lp = &Lproc[Nlproc++];
304	Lp->pid = pid;
305
306#if	defined(HASTASKS)
307	Lp->tid = 0;
308#endif	/* defined(HASTASKS) */
309
310	Lp->pgid = pgid;
311	Lp->ppid = ppid;
312	Lp->file = (struct lfile *)NULL;
313	Lp->sf = (short)sf;
314	Lp->pss = (short)pss;
315	Lp->uid = (uid_t)uid;
316/*
317 * Allocate space for the full command name and copy it there.
318 */
319	if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) {
320	    (void) fprintf(stderr, "%s: PID %d, no space for command name: ",
321		Pn, pid);
322	    safestrprt(cmd, stderr, 1);
323	    Exit(1);
324	}
325
326#if	defined(HASZONES)
327/*
328 * Clear the zone name pointer.  The dialect's own code will set it.
329 */
330	Lp->zn = (char *)NULL;
331#endif	/* defined(HASZONES) */
332
333#if	defined(HASSELINUX)
334/*
335 * Clear the security context pointer.  The dialect's own code will
336 * set it.
337 */
338	Lp->cntx = (char *)NULL;
339#endif	/* defined(HASSELINUX) */
340
341}
342
343
344/*
345 * ck_fd_status() - check FD status
346 *
347 * return: 0 == FD is neither included nor excluded
348 *	   1 == FD is excluded
349 *	   2 == FD is included
350 */
351
352extern int
353ck_fd_status(nm, num)
354	char *nm;			/* file descriptor name (may be NULL) */
355	int num;			/* file descriptor number -- -1 if
356					 * none */
357{
358	char *cp;
359	struct fd_lst *fp;
360
361	if (!(fp = Fdl) || (!nm && num < 0))
362	    return(0);
363	if ((cp = nm)) {
364	    while (*cp && *cp == ' ')
365		cp++;
366	}
367/*
368 * Check for an exclusion match.
369 */
370	if (FdlTy == 1) {
371	    for (; fp; fp = fp->next) {
372		if (cp) {
373		    if (fp->nm && strcmp(fp->nm, cp) == 0)
374			return(1);
375		    continue;
376		}
377		if (num >= fp->lo && num <= fp->hi)
378		    return(1);
379	    }
380	    return(0);
381	}
382/*
383 * If Fdl isn't an exclusion list, check for an inclusion match.
384 */
385	for (; fp; fp = fp->next) {
386	    if (cp) {
387		if (fp->nm && strcmp(fp->nm, cp) == 0)
388		    return(2);
389		continue;
390	    }
391	    if (num >= fp->lo && num <= fp->hi)
392		return(2);
393	}
394	return(0);
395}
396
397
398/*
399 * comppid() - compare PIDs
400 */
401
402int
403comppid(a1, a2)
404	COMP_P *a1, *a2;
405{
406	struct lproc **p1 = (struct lproc **)a1;
407	struct lproc **p2 = (struct lproc **)a2;
408
409	if ((*p1)->pid < (*p2)->pid)
410	    return(-1);
411	if ((*p1)->pid > (*p2)->pid)
412	    return(1);
413
414#if	defined(HASTASKS)
415	if ((*p1)->tid < (*p2)->tid)
416	    return(-1);
417	if ((*p1)->tid > (*p2)->tid)
418	    return(1);
419#endif	/* defined(HASTASKS) */
420
421	return(0);
422}
423
424
425/*
426 * ent_inaddr() - enter Internet addresses
427 */
428
429void
430ent_inaddr(la, lp, fa, fp, af)
431	unsigned char *la;		/* local Internet address */
432	int lp;				/* local port */
433	unsigned char *fa;		/* foreign Internet address -- may
434					 * be NULL to indicate no foreign
435					 * address is known */
436	int fp;				/* foreign port */
437	int af;				/* address family -- e.g, AF_INET,
438					 * AF_INET */
439{
440	int m;
441
442	if (la) {
443	    Lf->li[0].af = af;
444
445#if	defined(HASIPv6)
446	    if (af == AF_INET6)
447		Lf->li[0].ia.a6 = *(struct in6_addr *)la;
448	    else
449#endif	/* defined(HASIPv6) */
450
451		Lf->li[0].ia.a4 = *(struct in_addr *)la;
452	    Lf->li[0].p = lp;
453	} else
454	    Lf->li[0].af = 0;
455	if (fa) {
456	    Lf->li[1].af = af;
457
458#if	defined(HASIPv6)
459	    if (af == AF_INET6)
460		Lf->li[1].ia.a6 = *(struct in6_addr *)fa;
461	    else
462#endif	/* defined(HASIPv6) */
463
464		Lf->li[1].ia.a4 = *(struct in_addr *)fa;
465	    Lf->li[1].p = fp;
466	} else
467	    Lf->li[1].af = 0;
468/*
469 * If network address matching has been selected, check both addresses.
470 */
471	if ((Selflags & SELNA) && Nwad) {
472	    m = (fa && is_nw_addr(fa, fp, af)) ? 1 : 0;
473	    m |= (la && is_nw_addr(la, lp, af)) ? 1 : 0;
474	    if (m)
475		Lf->sf |= SELNA;
476	}
477}
478
479
480/*
481 * examine_lproc() - examine local process
482 *
483 * return: 1 = last process
484 */
485
486int
487examine_lproc()
488{
489	int sbp = 0;
490
491	if (RptTm)
492	    return(0);
493/*
494 * List the process if the process is selected and:
495 *
496 *	o  listing is limited to a single PID selection -- this one;
497 *
498 *	o  listing is selected by an ANDed option set (not all options)
499 *	   that includes a single PID selection -- this one.
500 */
501	if ((Lp->sf & SELPID) && !Selall) {
502	    if ((Selflags == SELPID)
503	    ||  (Fand && (Selflags & SELPID))) {
504		sbp = 1;
505		Npuns--;
506	    }
507	}
508	if (Lp->pss && Npid == 1 && sbp) {
509	    print_init();
510	    (void) print_proc();
511	    PrPass++;
512	    if (PrPass < 2)
513		(void) print_proc();
514	    Lp->pss = 0;
515	}
516/*
517 * Deprecate an unselected (or listed) process.
518 */
519	if ( ! Lp->pss) {
520	    (void) free_lproc(Lp);
521	    Nlproc--;
522	}
523/*
524 * Indicate last-process if listing is limited to PID selections,
525 * and all selected processes have been listed.
526 */
527	return((sbp && Npuns == 0) ? 1 : 0);
528}
529
530
531/*
532 * free_lproc() - free lproc entry and its associated malloc'd space
533 */
534
535void
536free_lproc(lp)
537	struct lproc *lp;
538{
539	struct lfile *lf, *nf;
540
541	for (lf = lp->file; lf; lf = nf) {
542	    if (lf->dev_ch) {
543		(void) free((FREE_P *)lf->dev_ch);
544		lf->dev_ch = (char *)NULL;
545	    }
546	    if (lf->nm) {
547		(void) free((FREE_P *)lf->nm);
548		lf->nm = (char *)NULL;
549	    }
550	    if (lf->nma) {
551		(void) free((FREE_P *)lf->nma);
552		lf->nma = (char *)NULL;
553	    }
554
555#if	defined(HASLFILEADD) && defined(CLRLFILEADD)
556	    CLRLFILEADD(lf)
557#endif	/* defined(HASLFILEADD) && defined(CLRLFILEADD) */
558
559	    nf = lf->next;
560	    (void) free((FREE_P *)lf);
561	}
562	lp->file = (struct lfile *)NULL;
563	if (lp->cmd) {
564	    (void) free((FREE_P *)lp->cmd);
565	    lp->cmd = (char *)NULL;
566	}
567}
568
569
570/*
571 * is_cmd_excl() - is command excluded?
572 */
573
574int
575is_cmd_excl(cmd, pss, sf)
576	char *cmd;			/* command name */
577	short *pss;			/* process state */
578	short *sf;			/* process select flags */
579{
580	int i;
581	struct str_lst *sp;
582/*
583 * See if the command is excluded by a "-c^<command>" option.
584 */
585	if (Cmdl && Cmdnx) {
586	    for (sp = Cmdl; sp; sp = sp->next) {
587		if (sp->x && !strncmp(sp->str, cmd, sp->len))
588		    return(1);
589	    }
590	}
591/*
592 * The command is not excluded if no command selection was requested,
593 * or if its name matches any -c <command> specification.
594 *
595 */
596	if ((Selflags & SELCMD) == 0)
597	    return(0);
598	for (sp = Cmdl; sp; sp = sp->next) {
599	    if (!sp->x && !strncmp(sp->str, cmd, sp->len)) {
600		sp->f = 1;
601		*pss |= PS_PRI;
602		*sf |= SELCMD;
603		return(0);
604	    }
605	}
606/*
607 * The command name doesn't match any -c <command> specification.  See if it
608 * matches a -c /RE/[bix] specification.
609 */
610	for (i = 0; i < NCmdRxU; i++) {
611	    if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) {
612		CmdRx[i].mc = 1;
613		*pss |= PS_PRI;
614		*sf |= SELCMD;
615		return(0);
616	    }
617	}
618/*
619 * The command name matches no -c specification.
620 *
621 * It's excluded if the only selection condition is command name,
622 * or if command name selection is part of an ANDed set.
623 */
624	if (Selflags == SELCMD)
625	    return(1);
626	return (Fand ? 1 : 0);
627}
628
629
630/*
631 * is_file_sel() - is file selected?
632 */
633
634static int
635is_file_sel(lp, lf)
636	struct lproc *lp;		/* lproc structure pointer */
637	struct lfile *lf;		/* lfile structure pointer */
638{
639	if (!lf || !lf->sf)
640	    return(0);
641	if (Lf->sf & SELEXCLF)
642	    return(0);
643
644#if	defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
645	if (Myuid && (Myuid != lp->uid)) {
646	    if (!(lf->sf & (SELNA | SELNET)))
647		return(0);
648	}
649#endif	/* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
650
651	if (Selall)
652	    return(1);
653	if (Fand && ((lf->sf & Selflags) != Selflags))
654	    return(0);
655	return(1);
656}
657
658
659/*
660 * is_proc_excl() - is process excluded?
661 */
662
663int
664
665#if	defined(HASTASKS)
666is_proc_excl(pid, pgid, uid, pss, sf, tid)
667#else	/* !defined(HASTASKS) */
668is_proc_excl(pid, pgid, uid, pss, sf)
669#endif	/* defined(HASTASKS) */
670
671	int pid;			/* Process ID */
672	int pgid;			/* process group ID */
673	UID_ARG uid;			/* User ID */
674	short *pss;			/* process select state for lproc */
675	short *sf;			/* select flags for lproc */
676
677#if	defined(HASTASKS)
678	int tid;			/* task ID (not a task if zero) */
679#endif	/* defined(HASTASKS) */
680
681{
682	int i, j;
683
684	*pss = *sf = 0;
685
686#if	defined(HASSECURITY)
687/*
688 * The process is excluded by virtue of the security option if it
689 * isn't owned by the owner of this lsof process, unless the
690 * HASNOSOCKSECURITY option is also specified.  In that case the
691 * selected socket files of any process may be listed.
692 */
693# if	!defined(HASNOSOCKSECURITY)
694	if (Myuid && Myuid != (uid_t)uid)
695	    return(1);
696# endif	/* !defined(HASNOSOCKSECURITY) */
697#endif	/* defined(HASSECURITY) */
698
699/*
700 * If the excluding of process listing by UID has been specified, see if the
701 * owner of this process is excluded.
702 */
703	if (Nuidexcl) {
704	    for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) {
705		if (!Suid[i].excl)
706		    continue;
707		if (Suid[i].uid == (uid_t)uid)
708		    return(1);
709		j++;
710	    }
711	}
712/*
713 * If the excluding of process listing by PGID has been specified, see if this
714 * PGID is excluded.
715 */
716	if (Npgidx) {
717	    for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) {
718		if (!Spgid[i].x)
719		    continue;
720		if (Spgid[i].i == pgid)
721		    return(1);
722		j++;
723	    }
724	}
725/*
726 * If the excluding of process listing by PID has been specified, see if this
727 * PID is excluded.
728 */
729	if (Npidx) {
730	    for (i = j = 0; (i < Npid) && (j < Npidx); i++) {
731		if (!Spid[i].x)
732		    continue;
733		if (Spid[i].i == pid)
734		    return(1);
735		j++;
736	    }
737	}
738/*
739 * If the listing of all processes is selected, then this one is not excluded.
740 *
741 * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude
742 * network selections from the file flags, so that the tests in is_file_sel()
743 * work as expected.
744 */
745	if (Selall) {
746	    *pss = PS_PRI;
747
748#if	defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
749	    *sf = SELALL & ~(SELNA | SELNET);
750#else	/* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */
751	    *sf = SELALL;
752#endif	/* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
753
754	    return(0);
755	}
756/*
757 * If the listing of processes has been specified by process group ID, see
758 * if this one is included or excluded.
759 */
760	if (Npgidi && (Selflags & SELPGID)) {
761	    for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) {
762		if (Spgid[i].x)
763		    continue;
764		if (Spgid[i].i == pgid) {
765		    Spgid[i].f = 1;
766		    *pss = PS_PRI;
767		    *sf = SELPGID;
768		    if (Selflags == SELPGID)
769			return(0);
770		    break;
771		}
772		j++;
773	    }
774	    if ((Selflags == SELPGID) && !*sf)
775		return(1);
776	}
777/*
778 * If the listing of processes has been specified by PID, see if this one is
779 * included or excluded.
780 */
781	if (Npidi && (Selflags & SELPID)) {
782	    for (i = j = 0; (i < Npid) && (j < Npidi); i++) {
783		if (Spid[i].x)
784		    continue;
785		if (Spid[i].i == pid) {
786		    Spid[i].f = 1;
787		    *pss = PS_PRI;
788		    *sf |= SELPID;
789		    if (Selflags == SELPID)
790			return(0);
791		    break;
792		}
793		j++;
794	    }
795	    if ((Selflags == SELPID) && !*sf)
796		return(1);
797	}
798/*
799 * If the listing of processes has been specified by UID, see if the owner of
800 * this process has been included.
801 */
802	if (Nuidincl && (Selflags & SELUID)) {
803	    for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) {
804		if (Suid[i].excl)
805		    continue;
806		if (Suid[i].uid == (uid_t)uid) {
807		    Suid[i].f = 1;
808		    *pss = PS_PRI;
809		    *sf |= SELUID;
810		    if (Selflags == SELUID)
811			return(0);
812		    break;
813		}
814		j++;
815	    }
816	    if (Selflags == SELUID && (*sf & SELUID) == 0)
817		return(1);
818	}
819
820#if	defined(HASTASKS)
821	if ((Selflags & SELTASK) && tid) {
822
823	/*
824	 * This is a task and tasks are selected.
825	 */
826	    *pss = PS_PRI;
827	    *sf |= SELTASK;
828	    if ((Selflags == SELTASK)
829	    ||  (Fand && ((*sf & Selflags) == Selflags)))
830		return(0);
831	}
832#endif	/* defined(HASTASKS) */
833
834/*
835 * When neither the process group ID, nor the PID, nor the task, nor the UID
836 * is selected:
837 *
838 *	If list option ANDing of process group IDs, PIDs, UIDs or tasks is
839 *	specified, the process is excluded;
840 *
841 *	Otherwise, it's not excluded by the tests of this function.
842 */
843	if ( ! *sf)
844	    return((Fand && (Selflags & (SELPGID|SELPID|SELUID|SELTASK)))
845		   ? 1 : 0);
846/*
847 * When the process group ID, PID, task or UID is selected and the process
848 * group ID, PID, task or UID list option has been specified:
849 *
850 *	If list option ANDing has been specified, and the correct
851 *	combination of selections are in place, reply that the process is no
852 *	excluded;
853 * or
854 *	If list option ANDing has not been specified, reply that the
855 *	process is not excluded by the tests of this function.
856 */
857	if (Selflags & (SELPGID|SELPID|SELUID|SELTASK)) {
858	    if (Fand)
859		return(((Selflags & (SELPGID|SELPID|SELUID|SELTASK)) != *sf)
860			? 1 : 0);
861	    return(0);
862	}
863/*
864 * Finally, when neither the process group ID, nor the PID, nor the UID, nor
865 * the task is selected, and no applicable list option has been specified:
866 *
867 *	If list option ANDing has been specified, this process is
868 *	excluded;
869 *
870 *	Otherwise, it isn't excluded by the tests of this function.
871 */
872	return(Fand ? 1 : 0);
873}
874
875
876/*
877 * link_lfile() - link local file structures
878 */
879
880void
881link_lfile()
882{
883	if (Lf->sf & SELEXCLF)
884	    return;
885	Lp->pss |= PS_SEC;
886	if (Plf)
887	    Plf->next = Lf;
888	else
889	    Lp->file = Lf;
890	Plf = Lf;
891	if (Fnet && (Lf->sf & SELNET))
892	    Fnet = 2;
893	if (Fnfs && (Lf->sf & SELNFS))
894	    Fnfs = 2;
895	if (Ftask && (Lf->sf & SELTASK))
896	    Ftask = 2;
897	Lf = (struct lfile *)NULL;
898}
899
900
901#if	defined(HASFSTRUCT)
902/*
903 * print_fflags() - print interpreted f_flag[s]
904 */
905
906char *
907print_fflags(ffg, pof)
908	long ffg;		/* file structure's flags value */
909	long pof;		/* process open files flags value */
910{
911	int al, ct, fx;
912	static int bl = 0;
913	static char *bp = (char *)NULL;
914	char *sep;
915	int sepl;
916	struct pff_tab *tp;
917	long wf;
918	char xbuf[64];
919/*
920 * Reduce the supplied flags according to the definitions in Pff_tab[] and
921 * Pof_tab[].
922 */
923	for (ct = fx = 0; fx < 2; fx++) {
924	    if (fx == 0) {
925		sep = "";
926		sepl = 0;
927		tp = Pff_tab;
928		wf = ffg;
929	    } else {
930		sep = ";";
931		sepl = 1;
932		tp = Pof_tab;
933		wf = pof;
934	    }
935	    for (; wf && !FsvFlagX; ct += al ) {
936		while (tp->nm) {
937		    if (wf & tp->val)
938			break;
939		    tp++;
940		}
941		if (!tp->nm)
942		    break;
943		al = (int)strlen(tp->nm) + sepl;
944		bp = alloc_fflbuf(&bp, &bl, al + ct);
945		(void) snpf(bp + ct, al + 1, "%s%s", sep, tp->nm);
946		sep = ",";
947		sepl = 1;
948		wf &= ~(tp->val);
949	    }
950	/*
951	 * If flag bits remain, print them in hex.  If hex output was
952	 * specified with +fG, print all flag values, including zero,
953	 * in hex.
954	 */
955	    if (wf || FsvFlagX) {
956		(void) snpf(xbuf, sizeof(xbuf), "0x%lx", wf);
957		al = (int)strlen(xbuf) + sepl;
958		bp = alloc_fflbuf(&bp, &bl, al + ct);
959		(void) snpf(bp + ct, al + 1, "%s%s", sep, xbuf);
960		ct += al;
961	    }
962	}
963/*
964 * Make sure there is at least a NUL terminated reply.
965 */
966	if (!bp) {
967	    bp = alloc_fflbuf(&bp, &bl, 0);
968	    *bp = '\0';
969	}
970	return(bp);
971}
972#endif	/* defined(HASFSTRUCT) */
973
974
975/*
976 * print_proc() - print process
977 */
978
979int
980print_proc()
981{
982	char buf[128], *cp;
983	int lc, len, st, ty;
984	int rv = 0;
985	unsigned long ul;
986/*
987 * If nothing in the process has been selected, skip it.
988 */
989	if (!Lp->pss)
990	    return(0);
991	if (Fterse) {
992	    if (Lp->pid == LastPid)		/* eliminate duplicates */
993		return(0);
994	    LastPid = Lp->pid;
995	/*
996	 * The mode is terse and something in the process appears to have
997	 * been selected.  Make sure of that by looking for a selected file,
998	 * so that the HASSECURITY and HASNOSOCKSECURITY option combination
999	 * won't produce a false positive result.
1000	 */
1001	    for (Lf = Lp->file; Lf; Lf = Lf->next) {
1002		if (is_file_sel(Lp, Lf)) {
1003		    (void) printf("%d\n", Lp->pid);
1004		    return(1);
1005		}
1006	    }
1007	    return(0);
1008	}
1009/*
1010 * If fields have been selected, output the process-only ones, provided
1011 * that some file has also been selected.
1012 */
1013	if (Ffield) {
1014	    for (Lf = Lp->file; Lf; Lf = Lf->next) {
1015		if (is_file_sel(Lp, Lf))
1016		    break;
1017	    }
1018	    if (!Lf)
1019		return(rv);
1020	    rv = 1;
1021	    (void) printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator);
1022
1023#if	defined(HASTASKS)
1024	    if (FieldSel[LSOF_FIX_TID].st && Lp->tid)
1025		(void) printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator);
1026#endif	/* defined(HASTASKS) */
1027
1028#if	defined(HASZONES)
1029	    if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn)
1030		(void) printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator);
1031#endif	/* defined(HASZONES) */
1032
1033#if	defined(HASSELINUX)
1034	    if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus)
1035		(void) printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator);
1036#endif	/* defined(HASSELINUX) */
1037
1038	    if (FieldSel[LSOF_FIX_PGID].st && Fpgid)
1039		(void) printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator);
1040
1041#if	defined(HASPPID)
1042	    if (FieldSel[LSOF_FIX_PPID].st && Fppid)
1043		(void) printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator);
1044#endif	/* defined(HASPPID) */
1045
1046	    if (FieldSel[LSOF_FIX_CMD].st) {
1047		putchar(LSOF_FID_CMD);
1048		safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0);
1049		putchar(Terminator);
1050	    }
1051	    if (FieldSel[LSOF_FIX_UID].st)
1052		(void) printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator);
1053	    if (FieldSel[LSOF_FIX_LOGIN].st) {
1054		cp = printuid((UID_ARG)Lp->uid, &ty);
1055		if (ty == 0)
1056		    (void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
1057	    }
1058	    if (Terminator == '\0')
1059	    putchar('\n');
1060	}
1061/*
1062 * Print files.
1063 */
1064	for (Lf = Lp->file; Lf; Lf = Lf->next) {
1065	    if (!is_file_sel(Lp, Lf))
1066		continue;
1067	    rv = 1;
1068	/*
1069	 * If no field output selected, print dialects-specific formatted
1070	 * output.
1071	 */
1072	    if (!Ffield) {
1073		print_file();
1074		continue;
1075	    }
1076	/*
1077	 * Print selected fields.
1078	 */
1079	    lc = st = 0;
1080	    if (FieldSel[LSOF_FIX_FD].st) {
1081		for (cp = Lf->fd; *cp == ' '; cp++)
1082		    ;
1083		if (*cp) {
1084		    (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator);
1085		    lc++;
1086		}
1087	    }
1088	    if (FieldSel[LSOF_FIX_ACCESS].st) {
1089		(void) printf("%c%c%c",
1090		    LSOF_FID_ACCESS, Lf->access, Terminator);
1091		lc++;
1092	    }
1093	    if (FieldSel[LSOF_FIX_LOCK].st) {
1094		(void) printf("%c%c%c", LSOF_FID_LOCK, Lf->lock, Terminator);
1095		lc++;
1096	    }
1097	    if (FieldSel[LSOF_FIX_TYPE].st) {
1098		for (cp = Lf->type; *cp == ' '; cp++)
1099		    ;
1100		if (*cp) {
1101		    (void) printf("%c%s%c", LSOF_FID_TYPE, cp, Terminator);
1102		    lc++;
1103		}
1104	    }
1105
1106#if	defined(HASFSTRUCT)
1107	    if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA)
1108	    &&  (Lf->fsv & FSV_FA)) {
1109		(void) printf("%c%s%c", LSOF_FID_FA,
1110		    print_kptr(Lf->fsa, (char *)NULL, 0), Terminator);
1111		lc++;
1112	    }
1113	    if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT)
1114	    &&  (Lf->fsv & FSV_CT)) {
1115		(void) printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator);
1116		lc++;
1117	    }
1118	    if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG)
1119	    &&  (Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof)) {
1120		(void) printf("%c%s%c", LSOF_FID_FG,
1121		    print_fflags(Lf->ffg, Lf->pof), Terminator);
1122		lc++;
1123	    }
1124	    if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI)
1125	    &&  (Lf->fsv & FSV_NI)) {
1126		(void) printf("%c%s%c", LSOF_FID_NI,
1127		    print_kptr(Lf->fna, (char *)NULL, 0), Terminator);
1128		lc++;
1129	    }
1130#endif	/* defined(HASFSTRUCT) */
1131
1132	    if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) {
1133		for (cp = Lf->dev_ch; *cp == ' '; cp++)
1134		    ;
1135		if (*cp) {
1136		    (void) printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator);
1137		    lc++;
1138		}
1139	    }
1140	    if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) {
1141		if (sizeof(unsigned long) > sizeof(dev_t))
1142		    ul = (unsigned long)((unsigned int)Lf->dev);
1143		else
1144		    ul = (unsigned long)Lf->dev;
1145		(void) printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator);
1146		lc++;
1147	    }
1148	    if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) {
1149		if (sizeof(unsigned long) > sizeof(dev_t))
1150		    ul = (unsigned long)((unsigned int)Lf->rdev);
1151		else
1152		    ul = (unsigned long)Lf->rdev;
1153		(void) printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator);
1154		lc++;
1155	    }
1156	    if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) {
1157		putchar(LSOF_FID_SIZE);
1158
1159#if	defined(HASPRINTSZ)
1160		cp = HASPRINTSZ(Lf);
1161#else	/* !defined(HASPRINTSZ) */
1162		(void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
1163		cp = buf;
1164#endif	/* defined(HASPRINTSZ) */
1165
1166		(void) printf("%s", cp);
1167		putchar(Terminator);
1168		lc++;
1169	    }
1170	    if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) {
1171		putchar(LSOF_FID_OFFSET);
1172
1173#if	defined(HASPRINTOFF)
1174		cp = HASPRINTOFF(Lf, 0);
1175#else	/* !defined(HASPRINTOFF) */
1176		(void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
1177		cp = buf;
1178#endif	/* defined(HASPRINTOFF) */
1179
1180		len = strlen(cp);
1181		if (OffDecDig && len > (OffDecDig + 2)) {
1182
1183#if	defined(HASPRINTOFF)
1184		    cp = HASPRINTOFF(Lf, 1);
1185#else	/* !defined(HASPRINTOFF) */
1186		    (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
1187		    cp = buf;
1188#endif	/* defined(HASPRINTOFF) */
1189
1190		}
1191		(void) printf("%s", cp);
1192		putchar(Terminator);
1193		lc++;
1194	    }
1195	    if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) {
1196		putchar(LSOF_FID_INODE);
1197		(void) printf(InodeFmt_d, Lf->inode);
1198		putchar(Terminator);
1199		lc++;
1200	    }
1201	    if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) {
1202		(void) printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator);
1203		lc++;
1204	    }
1205	    if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) {
1206		for (cp = Lf->iproto; *cp == ' '; cp++)
1207		    ;
1208		if (*cp) {
1209		    (void) printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator);
1210		    lc++;
1211		}
1212	    }
1213	    if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) {
1214		if (strncmp(Lf->nm, "STR:", 4) == 0
1215		||  strcmp(Lf->iproto, "STR") == 0) {
1216		    putchar(LSOF_FID_STREAM);
1217		    printname(0);
1218		    putchar(Terminator);
1219		    lc++;
1220		    st++;
1221		}
1222	    }
1223	    if (st == 0 && FieldSel[LSOF_FIX_NAME].st) {
1224		putchar(LSOF_FID_NAME);
1225		printname(0);
1226		putchar(Terminator);
1227		lc++;
1228	    }
1229	    if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) {
1230		print_tcptpi(0);
1231		lc++;
1232	    }
1233	    if (Terminator == '\0' && lc)
1234		putchar('\n');
1235	}
1236	return(rv);
1237}
1238