Imported Upstream version 4.88
[platform/upstream/lsof.git] / proc.c
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
33 static char copyright[] =
34 "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35 static char *rcsid = "$Id: proc.c,v 1.48 2014/10/13 22:36:20 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
53 void
54 add_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
94 static char *
95 alloc_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
124 void
125 alloc_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(HASEPTOPTS)
173         Lf->pipend = 0;
174 #endif  /* defined(HASEPTOPTS) */
175
176 #if     defined(HASSOOPT)
177         Lf->lts.kai = Lf->lts.ltm = 0;
178         Lf->lts.opt = Lf->lts.qlen = Lf->lts.qlim = Lf->lts.pqlen
179                     = (unsigned int)0;
180         Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0;
181         Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs
182                       = Lf->lts.sbszs = (unsigned char)0;
183 #endif  /* defined(HASSOOPT) */
184
185 #if     defined(HASSOSTATE)
186         Lf->lts.ss = 0;
187 #endif  /* defined(HASSOSTATE) */
188
189 #if     defined(HASTCPOPT)
190         Lf->lts.mss = (unsigned long)0;
191         Lf->lts.msss = (unsigned char)0;
192         Lf->lts.topt = (unsigned int)0;
193 #endif  /* defined(HASTCPOPT) */
194
195 #if     defined(HASTCPTPIQ)
196         Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0;
197 #endif  /* defined(HASTCPTPIQ) */
198
199 #if     defined(HASTCPTPIW)
200         Lf->lts.rws = Lf->lts.wws = (unsigned char)0;
201 #endif  /* defined(HASTCPTPIW) */
202
203 #if     defined(HASFSINO)
204         Lf->fs_ino = 0;
205 #endif  /* defined(HASFSINO) */
206
207 #if     defined(HASVXFS) && defined(HASVXFSDNLC)
208         Lf->is_vxfs = 0;
209 #endif  /* defined(HASVXFS) && defined(HASVXFSDNLC) */
210
211         Lf->inode = (INODETYPE)0;
212         Lf->off = (SZOFFTYPE)0;
213         if (Lp->pss & PS_PRI)
214             Lf->sf = Lp->sf;
215         else
216             Lf->sf = 0;
217         Lf->iproto[0] = Lf->type[0] = '\0';
218         if (nm) {
219             (void) strncpy(Lf->fd, nm, FDLEN - 1);
220             Lf->fd[FDLEN - 1] = '\0';
221         } else if (num >= 0) {
222             if (num < 10000)
223                 (void) snpf(Lf->fd, sizeof(Lf->fd), "%4d", num);
224             else
225                 (void) snpf(Lf->fd, sizeof(Lf->fd), "*%03d", num % 1000);
226         } else
227             Lf->fd[0] = '\0';
228         Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL;
229         Lf->ch = -1;
230
231 #if     defined(HASNCACHE) && HASNCACHE<2
232         Lf->na = (KA_T)NULL;
233 #endif  /* defined(HASNCACHE) && HASNCACHE<2 */
234
235         Lf->next = (struct lfile *)NULL;
236         Lf->ntype = Ntype = N_REGLR;
237         Namech[0] = '\0';
238
239 #if     defined(HASFSTRUCT)
240         Lf->fct = Lf->ffg = Lf->pof = (long)0;
241         Lf->fna = (KA_T)NULL;
242         Lf->fsv = (unsigned char)0;
243 #endif  /* defined(HASFSTRUCT) */
244
245 #if     defined(HASLFILEADD) && defined(SETLFILEADD)
246 /*
247  * Do local initializations.
248  */
249         SETLFILEADD
250 #endif  /* defined(HASLFILEADD) && defined(SETLFILEADD) */
251
252 /*
253  * See if the file descriptor has been selected.
254  */
255         if (!Fdl || (!nm && num < 0))
256             return;
257         fds = ck_fd_status(nm, num);
258         switch (FdlTy) {
259         case 0:                 /* inclusion list */
260             if (fds == 2)
261                 Lf->sf |= SELFD;
262             break;
263         case 1:                 /* exclusion list */
264             if (fds != 1)
265                 Lf->sf |= SELFD;
266         }
267 }
268
269
270 /*
271  * alloc_lproc() - allocate local proc structure space
272  */
273
274 void
275 alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf)
276         int pid;                        /* Process ID */
277         int pgid;                       /* process group ID */
278         int ppid;                       /* parent process ID */
279         UID_ARG uid;                    /* User ID */
280         char *cmd;                      /* command */
281         int pss;                        /* process select state */
282         int sf;                         /* process select flags */
283 {
284         static int sz = 0;
285
286         if (!Lproc) {
287             if (!(Lproc = (struct lproc *)malloc(
288                           (MALLOC_S)(LPROCINCR * sizeof(struct lproc)))))
289             {
290                 (void) fprintf(stderr,
291                     "%s: no malloc space for %d local proc structures\n",
292                     Pn, LPROCINCR);
293                 Exit(1);
294             }
295             sz = LPROCINCR;
296         } else if ((Nlproc + 1) > sz) {
297             sz += LPROCINCR;
298             if (!(Lproc = (struct lproc *)realloc((MALLOC_P *)Lproc,
299                           (MALLOC_S)(sz * sizeof(struct lproc)))))
300             {
301                 (void) fprintf(stderr,
302                     "%s: no realloc space for %d local proc structures\n",
303                     Pn, sz);
304                 Exit(1);
305             }
306         }
307         Lp = &Lproc[Nlproc++];
308         Lp->pid = pid;
309
310 #if     defined(HASEPTOPTS)
311         Lp->pipe = 0;
312 #endif  /* defined(HASEPTOPTS) */
313
314 #if     defined(HASTASKS)
315         Lp->tid = 0;
316 #endif  /* defined(HASTASKS) */
317
318         Lp->pgid = pgid;
319         Lp->ppid = ppid;
320         Lp->file = (struct lfile *)NULL;
321         Lp->sf = (short)sf;
322         Lp->pss = (short)pss;
323         Lp->uid = (uid_t)uid;
324 /*
325  * Allocate space for the full command name and copy it there.
326  */
327         if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) {
328             (void) fprintf(stderr, "%s: PID %d, no space for command name: ",
329                 Pn, pid);
330             safestrprt(cmd, stderr, 1);
331             Exit(1);
332         }
333
334 #if     defined(HASZONES)
335 /*
336  * Clear the zone name pointer.  The dialect's own code will set it.
337  */
338         Lp->zn = (char *)NULL;
339 #endif  /* defined(HASZONES) */
340  
341 #if     defined(HASSELINUX)
342 /*
343  * Clear the security context pointer.  The dialect's own code will
344  * set it.
345  */
346         Lp->cntx = (char *)NULL;
347 #endif  /* defined(HASSELINUX) */
348
349 }
350
351
352 /*
353  * ck_fd_status() - check FD status
354  *
355  * return: 0 == FD is neither included nor excluded
356  *         1 == FD is excluded
357  *         2 == FD is included
358  */
359
360 extern int
361 ck_fd_status(nm, num)
362         char *nm;                       /* file descriptor name (may be NULL) */
363         int num;                        /* file descriptor number -- -1 if
364                                          * none */
365 {
366         char *cp;
367         struct fd_lst *fp;
368
369         if (!(fp = Fdl) || (!nm && num < 0))
370             return(0);
371         if ((cp = nm)) {
372             while (*cp && *cp == ' ')
373                 cp++;
374         }
375 /*
376  * Check for an exclusion match.
377  */
378         if (FdlTy == 1) {
379             for (; fp; fp = fp->next) {
380                 if (cp) {
381                     if (fp->nm && strcmp(fp->nm, cp) == 0)
382                         return(1);
383                     continue;
384                 }
385                 if (num >= fp->lo && num <= fp->hi)
386                     return(1);
387             }
388             return(0);
389         }
390 /*
391  * If Fdl isn't an exclusion list, check for an inclusion match.
392  */
393         for (; fp; fp = fp->next) {
394             if (cp) {
395                 if (fp->nm && strcmp(fp->nm, cp) == 0)
396                     return(2);
397                 continue;
398             }
399             if (num >= fp->lo && num <= fp->hi)
400                 return(2);
401         }
402         return(0);
403 }
404
405
406 /*
407  * comppid() - compare PIDs
408  */
409
410 int
411 comppid(a1, a2)
412         COMP_P *a1, *a2;
413 {
414         struct lproc **p1 = (struct lproc **)a1;
415         struct lproc **p2 = (struct lproc **)a2;
416
417         if ((*p1)->pid < (*p2)->pid)
418             return(-1);
419         if ((*p1)->pid > (*p2)->pid)
420             return(1);
421
422 #if     defined(HASTASKS)
423         if ((*p1)->tid < (*p2)->tid)
424             return(-1);
425         if ((*p1)->tid > (*p2)->tid)
426             return(1);
427 #endif  /* defined(HASTASKS) */
428
429         return(0);
430 }
431
432
433 /*
434  * ent_inaddr() - enter Internet addresses
435  */
436
437 void
438 ent_inaddr(la, lp, fa, fp, af)
439         unsigned char *la;              /* local Internet address */
440         int lp;                         /* local port */
441         unsigned char *fa;              /* foreign Internet address -- may
442                                          * be NULL to indicate no foreign
443                                          * address is known */
444         int fp;                         /* foreign port */
445         int af;                         /* address family -- e.g, AF_INET,
446                                          * AF_INET */
447 {
448         int m;
449
450         if (la) {
451             Lf->li[0].af = af;
452
453 #if     defined(HASIPv6)
454             if (af == AF_INET6)
455                 Lf->li[0].ia.a6 = *(struct in6_addr *)la;
456             else
457 #endif  /* defined(HASIPv6) */
458
459                 Lf->li[0].ia.a4 = *(struct in_addr *)la;
460             Lf->li[0].p = lp;
461         } else
462             Lf->li[0].af = 0;
463         if (fa) {
464             Lf->li[1].af = af;
465
466 #if     defined(HASIPv6)
467             if (af == AF_INET6)
468                 Lf->li[1].ia.a6 = *(struct in6_addr *)fa;
469             else
470 #endif  /* defined(HASIPv6) */
471
472                 Lf->li[1].ia.a4 = *(struct in_addr *)fa;
473             Lf->li[1].p = fp;
474         } else
475             Lf->li[1].af = 0;
476 /*
477  * If network address matching has been selected, check both addresses.
478  */
479         if ((Selflags & SELNA) && Nwad) {
480             m = (fa && is_nw_addr(fa, fp, af)) ? 1 : 0;
481             m |= (la && is_nw_addr(la, lp, af)) ? 1 : 0;
482             if (m)
483                 Lf->sf |= SELNA;
484         }
485 }
486
487
488 /*
489  * examine_lproc() - examine local process
490  *
491  * return: 1 = last process
492  */
493
494 int
495 examine_lproc()
496 {
497         int sbp = 0;
498
499         if (RptTm)
500             return(0);
501 /*
502  * List the process if the process is selected and:
503  *
504  *      o  listing is limited to a single PID selection -- this one;
505  *
506  *      o  listing is selected by an ANDed option set (not all options)
507  *         that includes a single PID selection -- this one.
508  */
509         if ((Lp->sf & SELPID) && !Selall) {
510             if ((Selflags == SELPID)
511             ||  (Fand && (Selflags & SELPID))) {
512                 sbp = 1;
513                 Npuns--;
514             }
515         }
516         if (Lp->pss && Npid == 1 && sbp) {
517             print_init();
518             (void) print_proc();
519             PrPass++;
520             if (PrPass < 2)
521                 (void) print_proc();
522             Lp->pss = 0;
523         }
524 /*
525  * Deprecate an unselected (or listed) process.
526  */
527         if ( ! Lp->pss) {
528             (void) free_lproc(Lp);
529             Nlproc--;
530         }
531 /*
532  * Indicate last-process if listing is limited to PID selections,
533  * and all selected processes have been listed.
534  */
535         return((sbp && Npuns == 0) ? 1 : 0);
536 }
537
538
539 /*
540  * free_lproc() - free lproc entry and its associated malloc'd space
541  */
542
543 void
544 free_lproc(lp)
545         struct lproc *lp;
546 {
547         struct lfile *lf, *nf;
548
549         for (lf = lp->file; lf; lf = nf) {
550             if (lf->dev_ch) {
551                 (void) free((FREE_P *)lf->dev_ch);
552                 lf->dev_ch = (char *)NULL;
553             }
554             if (lf->nm) {
555                 (void) free((FREE_P *)lf->nm);
556                 lf->nm = (char *)NULL;
557             }
558             if (lf->nma) {
559                 (void) free((FREE_P *)lf->nma);
560                 lf->nma = (char *)NULL;
561             }
562
563 #if     defined(HASLFILEADD) && defined(CLRLFILEADD)
564             CLRLFILEADD(lf)
565 #endif  /* defined(HASLFILEADD) && defined(CLRLFILEADD) */
566
567             nf = lf->next;
568             (void) free((FREE_P *)lf);
569         }
570         lp->file = (struct lfile *)NULL;
571         if (lp->cmd) {
572             (void) free((FREE_P *)lp->cmd);
573             lp->cmd = (char *)NULL;
574         }
575 }
576
577
578 /*
579  * is_cmd_excl() - is command excluded?
580  */
581
582 int
583 is_cmd_excl(cmd, pss, sf)
584         char *cmd;                      /* command name */
585         short *pss;                     /* process state */
586         short *sf;                      /* process select flags */
587 {
588         int i;
589         struct str_lst *sp;
590 /*
591  * See if the command is excluded by a "-c^<command>" option.
592  */
593         if (Cmdl && Cmdnx) {
594             for (sp = Cmdl; sp; sp = sp->next) {
595                 if (sp->x && !strncmp(sp->str, cmd, sp->len))
596                     return(1);
597             }
598         }
599 /*
600  * The command is not excluded if no command selection was requested,
601  * or if its name matches any -c <command> specification.
602  * 
603  */
604         if ((Selflags & SELCMD) == 0)
605             return(0);
606         for (sp = Cmdl; sp; sp = sp->next) {
607             if (!sp->x && !strncmp(sp->str, cmd, sp->len)) {
608                 sp->f = 1;
609                 *pss |= PS_PRI;
610                 *sf |= SELCMD;
611                 return(0);
612             }
613         }
614 /*
615  * The command name doesn't match any -c <command> specification.  See if it
616  * matches a -c /RE/[bix] specification.
617  */
618         for (i = 0; i < NCmdRxU; i++) {
619             if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) {
620                 CmdRx[i].mc = 1;
621                 *pss |= PS_PRI;
622                 *sf |= SELCMD;
623                 return(0);
624             }
625         }
626 /*
627  * The command name matches no -c specification.
628  *
629  * It's excluded if the only selection condition is command name,
630  * or if command name selection is part of an ANDed set.
631  */
632         if (Selflags == SELCMD)
633             return(1);
634         return (Fand ? 1 : 0);
635 }
636
637
638 /*
639  * is_file_sel() - is file selected?
640  */
641
642 static int
643 is_file_sel(lp, lf)
644         struct lproc *lp;               /* lproc structure pointer */
645         struct lfile *lf;               /* lfile structure pointer */
646 {
647         if (!lf || !lf->sf)
648             return(0);
649         if (Lf->sf & SELEXCLF)
650             return(0);
651
652 #if     defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
653         if (Myuid && (Myuid != lp->uid)) {
654             if (!(lf->sf & (SELNA | SELNET)))
655                 return(0);
656         }
657 #endif  /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
658
659         if (Selall)
660             return(1);
661         if (Fand && ((lf->sf & Selflags) != Selflags))
662             return(0);
663         return(1);
664 }
665
666
667 /*
668  * is_proc_excl() - is process excluded?
669  */
670
671 int
672
673 #if     defined(HASTASKS)
674 is_proc_excl(pid, pgid, uid, pss, sf, tid)
675 #else   /* !defined(HASTASKS) */
676 is_proc_excl(pid, pgid, uid, pss, sf)
677 #endif  /* defined(HASTASKS) */
678
679         int pid;                        /* Process ID */
680         int pgid;                       /* process group ID */
681         UID_ARG uid;                    /* User ID */
682         short *pss;                     /* process select state for lproc */
683         short *sf;                      /* select flags for lproc */
684
685 #if     defined(HASTASKS)
686         int tid;                        /* task ID (not a task if zero) */
687 #endif  /* defined(HASTASKS) */
688
689 {
690         int i, j;
691
692         *pss = *sf = 0;
693
694 #if     defined(HASSECURITY)
695 /*
696  * The process is excluded by virtue of the security option if it
697  * isn't owned by the owner of this lsof process, unless the
698  * HASNOSOCKSECURITY option is also specified.  In that case the
699  * selected socket files of any process may be listed.
700  */
701 # if    !defined(HASNOSOCKSECURITY)
702         if (Myuid && Myuid != (uid_t)uid)
703             return(1);
704 # endif /* !defined(HASNOSOCKSECURITY) */
705 #endif  /* defined(HASSECURITY) */
706
707 /*
708  * If the excluding of process listing by UID has been specified, see if the
709  * owner of this process is excluded.
710  */
711         if (Nuidexcl) {
712             for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) {
713                 if (!Suid[i].excl)
714                     continue;
715                 if (Suid[i].uid == (uid_t)uid)
716                     return(1);
717                 j++;
718             }
719         }
720 /*
721  * If the excluding of process listing by PGID has been specified, see if this
722  * PGID is excluded.
723  */
724         if (Npgidx) {
725             for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) {
726                 if (!Spgid[i].x)
727                     continue;
728                 if (Spgid[i].i == pgid)
729                     return(1);
730                 j++;
731             }
732         }
733 /*
734  * If the excluding of process listing by PID has been specified, see if this
735  * PID is excluded.
736  */
737         if (Npidx) {
738             for (i = j = 0; (i < Npid) && (j < Npidx); i++) {
739                 if (!Spid[i].x)
740                     continue;
741                 if (Spid[i].i == pid)
742                     return(1);
743                 j++;
744             }
745         }
746 /*
747  * If the listing of all processes is selected, then this one is not excluded.
748  *
749  * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude
750  * network selections from the file flags, so that the tests in is_file_sel()
751  * work as expected.
752  */
753         if (Selall) {
754             *pss = PS_PRI;
755
756 #if     defined(HASSECURITY) && defined(HASNOSOCKSECURITY)
757             *sf = SELALL & ~(SELNA | SELNET);
758 #else   /* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */
759             *sf = SELALL;
760 #endif  /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */
761
762             return(0);
763         }
764 /*
765  * If the listing of processes has been specified by process group ID, see
766  * if this one is included or excluded.
767  */
768         if (Npgidi && (Selflags & SELPGID)) {
769             for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) {
770                 if (Spgid[i].x)
771                     continue;
772                 if (Spgid[i].i == pgid) {
773                     Spgid[i].f = 1;
774                     *pss = PS_PRI;
775                     *sf = SELPGID;
776                     if (Selflags == SELPGID)
777                         return(0);
778                     break;
779                 }
780                 j++;
781             }
782             if ((Selflags == SELPGID) && !*sf)
783                 return(1);
784         }
785 /*
786  * If the listing of processes has been specified by PID, see if this one is
787  * included or excluded.
788  */
789         if (Npidi && (Selflags & SELPID)) {
790             for (i = j = 0; (i < Npid) && (j < Npidi); i++) {
791                 if (Spid[i].x)
792                     continue;
793                 if (Spid[i].i == pid) {
794                     Spid[i].f = 1;
795                     *pss = PS_PRI;
796                     *sf |= SELPID;
797                     if (Selflags == SELPID)
798                         return(0);
799                     break;
800                 }
801                 j++;
802             }
803             if ((Selflags == SELPID) && !*sf)
804                 return(1);
805         }
806 /*
807  * If the listing of processes has been specified by UID, see if the owner of
808  * this process has been included.
809  */
810         if (Nuidincl && (Selflags & SELUID)) {
811             for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) {
812                 if (Suid[i].excl)
813                     continue;
814                 if (Suid[i].uid == (uid_t)uid) {
815                     Suid[i].f = 1;
816                     *pss = PS_PRI;
817                     *sf |= SELUID;
818                     if (Selflags == SELUID)
819                         return(0);
820                     break;
821                 }
822                 j++;
823             }
824             if (Selflags == SELUID && (*sf & SELUID) == 0)
825                 return(1);
826         }
827
828 #if     defined(HASTASKS)
829         if ((Selflags & SELTASK) && tid) {
830
831         /*
832          * This is a task and tasks are selected.
833          */
834             *pss = PS_PRI;
835             *sf |= SELTASK;
836             if ((Selflags == SELTASK)
837             ||  (Fand && ((*sf & Selflags) == Selflags)))
838                 return(0);
839         }
840 #endif  /* defined(HASTASKS) */
841
842 /*
843  * When neither the process group ID, nor the PID, nor the task, nor the UID
844  * is selected:
845  *
846  *      If list option ANDing of process group IDs, PIDs, UIDs or tasks is
847  *      specified, the process is excluded;
848  *
849  *      Otherwise, it's not excluded by the tests of this function.
850  */
851         if ( ! *sf)
852             return((Fand && (Selflags & (SELPGID|SELPID|SELUID|SELTASK)))
853                    ? 1 : 0);
854 /*
855  * When the process group ID, PID, task or UID is selected and the process
856  * group ID, PID, task or UID list option has been specified:
857  *
858  *      If list option ANDing has been specified, and the correct
859  *      combination of selections are in place, reply that the process is no
860  *      excluded;
861  * or
862  *      If list option ANDing has not been specified, reply that the
863  *      process is not excluded by the tests of this function.
864  */
865         if (Selflags & (SELPGID|SELPID|SELUID|SELTASK)) {
866             if (Fand)
867                 return(((Selflags & (SELPGID|SELPID|SELUID|SELTASK)) != *sf)
868                         ? 1 : 0);
869             return(0);
870         }
871 /*
872  * Finally, when neither the process group ID, nor the PID, nor the UID, nor
873  * the task is selected, and no applicable list option has been specified:
874  *
875  *      If list option ANDing has been specified, this process is
876  *      excluded;
877  *
878  *      Otherwise, it isn't excluded by the tests of this function.
879  */
880         return(Fand ? 1 : 0);
881 }
882
883
884 /*
885  * link_lfile() - link local file structures
886  */
887
888 void
889 link_lfile()
890 {
891         if (Lf->sf & SELEXCLF)
892             return;
893
894 #if     defined(HASEPTOPTS)
895 /*
896  * If endpoint info has been requested, clear the SELPINFO flag from the local
897  * file structure, since it was set only to insure this file would be linked.
898  * While this might leave no file selection flags set, a later call to the
899  * process_pinfo() function might set some. Also set the PS_PIPE flag for
900  * the process.
901  *
902  * Also set the SELPINFO flag for the process.
903  */
904         if (FpipeE) {
905             Lf->sf &= ~SELPINFO;
906             Lp->pipe |= PS_PIPE;
907         }
908 #endif  /* defined(HASEPTOPTS) */
909
910         Lp->pss |= PS_SEC;
911         if (Plf)
912             Plf->next = Lf;
913         else
914             Lp->file = Lf;
915         Plf = Lf;
916         if (Fnet && (Lf->sf & SELNET))
917             Fnet = 2;
918         if (Fnfs && (Lf->sf & SELNFS))
919             Fnfs = 2;
920         if (Ftask && (Lf->sf & SELTASK))
921             Ftask = 2;
922         Lf = (struct lfile *)NULL;
923 }
924
925
926 #if     defined(HASEPTOPTS)
927 /*
928  * process_pinfo() -- process pipe info, adding it to selected files and
929  *                    selecting pipe end files (if requested)
930  */
931
932 void
933 process_pinfo(f)
934         int f;                          /* function:
935                                          *     0 == process selected pipe
936                                          *     1 == process end point
937                                          */
938 {
939         struct lproc *ep;               /* pipe endpoint process */
940         struct lfile *ef;               /* pipe endpoint file */
941         int i;                          /* temporary index */
942         char nma[1024];                 /* name addition buffer */
943         pinfo_t *pp;                    /* previous pipe info */
944         
945         if (!FpipeE)
946             return;
947         for (Lf = Lp->file; Lf; Lf = Lf->next) {
948             if ((Lf->ntype != N_FIFO) || (Lf->inp_ty != 1))
949                 continue;
950             pp = (pinfo_t *)NULL;
951             switch(f) {
952             case 0:
953
954             /*
955              * Process already selected pipe file.
956              */
957                 if (is_file_sel(Lp, Lf)) {
958
959                 /*
960                  * This file has been selected by some criterion other than its
961                  * being a pipe.  Look up the pipe's endpoints.
962                  */
963                     do {
964                         if ((pp = find_pendinfo(Lf, pp))) {
965
966                         /*
967                          * This pipe endpoint is linked to the selected pipe
968                          * file.  Add its PID and FD to the name column
969                          * addition.
970                          */
971                             ep = &Lproc[pp->lpx];
972                             ef = pp->lf;
973                             for (i = 0; i < (FDLEN - 1); i++) {
974                                 if (ef->fd[i] != ' ')
975                                     break;
976                             }
977                             (void) snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c",
978                                 ep->pid, CmdLim, ep->cmd,&ef->fd[i],
979                                 ef->access);
980                             (void) add_nma(nma, strlen(nma));
981                             if (FpipeE == 2) {
982
983                             /*
984                              * Endpoint files have been selected, so mark this
985                              * one for selection later.
986                              */
987                                 ef->pipend = 1;
988                                 ep->pipe |= PS_PIPE_END;
989                             }
990                             pp = pp->next;
991                         }
992                     } while (pp);
993                 }
994                 break;
995             case 1:
996                 if (!is_file_sel(Lp, Lf) && Lf->pipend) {
997
998                 /*
999                  * This is an unselected end point file.  Select it and add
1000                  * its end point information to its name column addition.
1001                  */
1002                     Lf->sf = Selflags;
1003                     Lp->pss |= PS_SEC;
1004                     do {
1005                         if ((pp = find_pendinfo(Lf, pp))) {
1006                             ep = &Lproc[pp->lpx];
1007                             ef = pp->lf;
1008                             for (i = 0; i < (FDLEN - 1); i++) {
1009                                 if (ef->fd[i] != ' ')
1010                                     break;
1011                             }
1012                             (void) snpf(nma, sizeof(nma) - 1, "%d,%.*s,%s%c",
1013                                 ep->pid, CmdLim, ep->cmd, &ef->fd[i],
1014                                 ef->access);
1015                             (void) add_nma(nma, strlen(nma));
1016                             pp = pp->next;
1017                         }
1018                     } while (pp);
1019                 }
1020                 break;
1021             }
1022         }
1023 }
1024 #endif  /* defined(HASEPTOPTS) */
1025
1026
1027 #if     defined(HASFSTRUCT)
1028 /*
1029  * print_fflags() - print interpreted f_flag[s]
1030  */
1031
1032 char *
1033 print_fflags(ffg, pof)
1034         long ffg;               /* file structure's flags value */
1035         long pof;               /* process open files flags value */
1036 {
1037         int al, ct, fx;
1038         static int bl = 0;
1039         static char *bp = (char *)NULL;
1040         char *sep;
1041         int sepl;
1042         struct pff_tab *tp;
1043         long wf;
1044         char xbuf[64];
1045 /*
1046  * Reduce the supplied flags according to the definitions in Pff_tab[] and
1047  * Pof_tab[].
1048  */
1049         for (ct = fx = 0; fx < 2; fx++) {
1050             if (fx == 0) {
1051                 sep = "";
1052                 sepl = 0;
1053                 tp = Pff_tab;
1054                 wf = ffg;
1055             } else {
1056                 sep = ";";
1057                 sepl = 1;
1058                 tp = Pof_tab;
1059                 wf = pof;
1060             }
1061             for (; wf && !FsvFlagX; ct += al ) {
1062                 while (tp->nm) {
1063                     if (wf & tp->val)
1064                         break;
1065                     tp++;
1066                 }
1067                 if (!tp->nm)
1068                     break;
1069                 al = (int)strlen(tp->nm) + sepl;
1070                 bp = alloc_fflbuf(&bp, &bl, al + ct);
1071                 (void) snpf(bp + ct, al + 1, "%s%s", sep, tp->nm);
1072                 sep = ",";
1073                 sepl = 1;
1074                 wf &= ~(tp->val);
1075             }
1076         /*
1077          * If flag bits remain, print them in hex.  If hex output was
1078          * specified with +fG, print all flag values, including zero,
1079          * in hex.
1080          */
1081             if (wf || FsvFlagX) {
1082                 (void) snpf(xbuf, sizeof(xbuf), "0x%lx", wf);
1083                 al = (int)strlen(xbuf) + sepl;
1084                 bp = alloc_fflbuf(&bp, &bl, al + ct);
1085                 (void) snpf(bp + ct, al + 1, "%s%s", sep, xbuf);
1086                 ct += al;
1087             }
1088         }
1089 /*
1090  * Make sure there is at least a NUL terminated reply.
1091  */
1092         if (!bp) {
1093             bp = alloc_fflbuf(&bp, &bl, 0);
1094             *bp = '\0';
1095         }
1096         return(bp);
1097 }
1098 #endif  /* defined(HASFSTRUCT) */
1099
1100
1101 /*
1102  * print_proc() - print process
1103  */
1104
1105 int
1106 print_proc()
1107 {
1108         char buf[128], *cp;
1109         int lc, len, st, ty;
1110         int rv = 0;
1111         unsigned long ul;
1112 /*
1113  * If nothing in the process has been selected, skip it.
1114  */
1115         if (!Lp->pss)
1116             return(0);
1117         if (Fterse) {
1118             if (Lp->pid == LastPid)             /* eliminate duplicates */
1119                 return(0);
1120             LastPid = Lp->pid;
1121         /*
1122          * The mode is terse and something in the process appears to have
1123          * been selected.  Make sure of that by looking for a selected file,
1124          * so that the HASSECURITY and HASNOSOCKSECURITY option combination
1125          * won't produce a false positive result.
1126          */
1127             for (Lf = Lp->file; Lf; Lf = Lf->next) {
1128                 if (is_file_sel(Lp, Lf)) {
1129                     (void) printf("%d\n", Lp->pid);
1130                     return(1);
1131                 }
1132             }
1133             return(0);
1134         }
1135 /*
1136  * If fields have been selected, output the process-only ones, provided
1137  * that some file has also been selected.
1138  */
1139         if (Ffield) {
1140             for (Lf = Lp->file; Lf; Lf = Lf->next) {
1141                 if (is_file_sel(Lp, Lf))
1142                     break;
1143             }
1144             if (!Lf)
1145                 return(rv);
1146             rv = 1;
1147             (void) printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator);
1148
1149 #if     defined(HASTASKS)
1150             if (FieldSel[LSOF_FIX_TID].st && Lp->tid)
1151                 (void) printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator);
1152 #endif  /* defined(HASTASKS) */
1153
1154 #if     defined(HASZONES)
1155             if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn)
1156                 (void) printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator);
1157 #endif  /* defined(HASZONES) */
1158  
1159 #if     defined(HASSELINUX)
1160             if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus)
1161                 (void) printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator);
1162 #endif  /* defined(HASSELINUX) */
1163
1164             if (FieldSel[LSOF_FIX_PGID].st && Fpgid)
1165                 (void) printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator);
1166
1167 #if     defined(HASPPID)
1168             if (FieldSel[LSOF_FIX_PPID].st && Fppid)
1169                 (void) printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator);
1170 #endif  /* defined(HASPPID) */
1171
1172             if (FieldSel[LSOF_FIX_CMD].st) {
1173                 putchar(LSOF_FID_CMD);
1174                 safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0);
1175                 putchar(Terminator);
1176             }
1177             if (FieldSel[LSOF_FIX_UID].st)
1178                 (void) printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator);
1179             if (FieldSel[LSOF_FIX_LOGIN].st) {
1180                 cp = printuid((UID_ARG)Lp->uid, &ty);
1181                 if (ty == 0)
1182                     (void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator);
1183             }
1184             if (Terminator == '\0')
1185                 putchar('\n');
1186         }
1187 /*
1188  * Print files.
1189  */
1190         for (Lf = Lp->file; Lf; Lf = Lf->next) {
1191             if (!is_file_sel(Lp, Lf))
1192                 continue;
1193             rv = 1;
1194         /*
1195          * If no field output selected, print dialect-specific formatted
1196          * output.
1197          */
1198             if (!Ffield) {
1199                 print_file();
1200                 continue;
1201             }
1202             lc = st = 0;
1203             if (FieldSel[LSOF_FIX_FD].st) {
1204
1205             /*
1206              * Skip leading spaces in the file descriptor.  Print the field
1207              * identifier even if there are no characters after leading
1208              * spaces.
1209              */
1210                 for (cp = Lf->fd; *cp == ' '; cp++)
1211                     ;
1212                 (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator);
1213                 lc++;
1214             }
1215         /*
1216          * Print selected fields.
1217          */
1218             if (FieldSel[LSOF_FIX_ACCESS].st) {
1219                 (void) printf("%c%c%c",
1220                     LSOF_FID_ACCESS, Lf->access, Terminator);
1221                 lc++;
1222             }
1223             if (FieldSel[LSOF_FIX_LOCK].st) {
1224                 (void) printf("%c%c%c", LSOF_FID_LOCK, Lf->lock, Terminator);
1225                 lc++;
1226             }
1227             if (FieldSel[LSOF_FIX_TYPE].st) {
1228                 for (cp = Lf->type; *cp == ' '; cp++)
1229                     ;
1230                 if (*cp) {
1231                     (void) printf("%c%s%c", LSOF_FID_TYPE, cp, Terminator);
1232                     lc++;
1233                 }
1234             }
1235
1236 #if     defined(HASFSTRUCT)
1237             if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA)
1238             &&  (Lf->fsv & FSV_FA)) {
1239                 (void) printf("%c%s%c", LSOF_FID_FA,
1240                     print_kptr(Lf->fsa, (char *)NULL, 0), Terminator);
1241                 lc++;
1242             }
1243             if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT)
1244             &&  (Lf->fsv & FSV_CT)) {
1245                 (void) printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator);
1246                 lc++;
1247             }
1248             if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG)
1249             &&  (Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof)) {
1250                 (void) printf("%c%s%c", LSOF_FID_FG,
1251                     print_fflags(Lf->ffg, Lf->pof), Terminator);
1252                 lc++;
1253             }
1254             if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI)
1255             &&  (Lf->fsv & FSV_NI)) {
1256                 (void) printf("%c%s%c", LSOF_FID_NI,
1257                     print_kptr(Lf->fna, (char *)NULL, 0), Terminator);
1258                 lc++;
1259             }
1260 #endif  /* defined(HASFSTRUCT) */
1261
1262             if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) {
1263                 for (cp = Lf->dev_ch; *cp == ' '; cp++)
1264                     ;
1265                 if (*cp) {
1266                     (void) printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator);
1267                     lc++;
1268                 }
1269             }
1270             if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) {
1271                 if (sizeof(unsigned long) > sizeof(dev_t))
1272                     ul = (unsigned long)((unsigned int)Lf->dev);
1273                 else
1274                     ul = (unsigned long)Lf->dev;
1275                 (void) printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator);
1276                 lc++;
1277             }
1278             if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) {
1279                 if (sizeof(unsigned long) > sizeof(dev_t))
1280                     ul = (unsigned long)((unsigned int)Lf->rdev);
1281                 else
1282                     ul = (unsigned long)Lf->rdev;
1283                 (void) printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator);
1284                 lc++;
1285             }
1286             if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) {
1287                 putchar(LSOF_FID_SIZE);
1288
1289 #if     defined(HASPRINTSZ)
1290                 cp = HASPRINTSZ(Lf);
1291 #else   /* !defined(HASPRINTSZ) */
1292                 (void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz);
1293                 cp = buf;
1294 #endif  /* defined(HASPRINTSZ) */
1295
1296                 (void) printf("%s", cp);
1297                 putchar(Terminator);
1298                 lc++;
1299             }
1300             if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) {
1301                 putchar(LSOF_FID_OFFSET);
1302
1303 #if     defined(HASPRINTOFF)
1304                 cp = HASPRINTOFF(Lf, 0);
1305 #else   /* !defined(HASPRINTOFF) */
1306                 (void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off);
1307                 cp = buf;
1308 #endif  /* defined(HASPRINTOFF) */
1309
1310                 len = strlen(cp);
1311                 if (OffDecDig && len > (OffDecDig + 2)) {
1312
1313 #if     defined(HASPRINTOFF)
1314                     cp = HASPRINTOFF(Lf, 1);
1315 #else   /* !defined(HASPRINTOFF) */
1316                     (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off);
1317                     cp = buf;
1318 #endif  /* defined(HASPRINTOFF) */
1319
1320                 }
1321                 (void) printf("%s", cp);
1322                 putchar(Terminator);
1323                 lc++;
1324             }
1325             if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) {
1326                 putchar(LSOF_FID_INODE);
1327                 (void) printf(InodeFmt_d, Lf->inode);
1328                 putchar(Terminator);
1329                 lc++;
1330             }
1331             if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) {
1332                 (void) printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator);
1333                 lc++;
1334             }
1335             if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) {
1336                 for (cp = Lf->iproto; *cp == ' '; cp++)
1337                     ;
1338                 if (*cp) {
1339                     (void) printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator);
1340                     lc++;
1341                 }
1342             }
1343             if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) {
1344                 if (strncmp(Lf->nm, "STR:", 4) == 0
1345                 ||  strcmp(Lf->iproto, "STR") == 0) {
1346                     putchar(LSOF_FID_STREAM);
1347                     printname(0);
1348                     putchar(Terminator);
1349                     lc++;
1350                     st++;
1351                 }
1352             }
1353             if (st == 0 && FieldSel[LSOF_FIX_NAME].st) {
1354                 putchar(LSOF_FID_NAME);
1355                 printname(0);
1356                 putchar(Terminator);
1357                 lc++;
1358             }
1359             if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) {
1360                 print_tcptpi(0);
1361                 lc++;
1362             }
1363             if (Terminator == '\0' && lc)
1364                 putchar('\n');
1365         }
1366         return(rv);
1367 }