Bump to lsof 4.91
[platform/upstream/lsof.git] / main.c
1 /*
2  * main.c - common main function for lsof
3  *
4  * V. Abell, Purdue University
5  */
6
7
8 /*
9  * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
10  * 47907.  All rights reserved.
11  *
12  * Written by Victor A. Abell
13  *
14  * This software is not subject to any license of the American Telephone
15  * and Telegraph Company or the Regents of the University of California.
16  *
17  * Permission is granted to anyone to use this software for any purpose on
18  * any computer system, and to alter it and redistribute it freely, subject
19  * to the following restrictions:
20  *
21  * 1. Neither the authors nor Purdue University are responsible for any
22  *    consequences of the use of this software.
23  *
24  * 2. The origin of this software must not be misrepresented, either by
25  *    explicit claim or by omission.  Credit to the authors and Purdue
26  *    University must appear in documentation and sources.
27  *
28  * 3. Altered versions must be plainly marked as such, and must not be
29  *    misrepresented as being the original software.
30  *
31  * 4. This notice may not be removed or altered.
32  */
33
34 #ifndef lint
35 static char copyright[] =
36 "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
37 static char *rcsid = "$Id: main.c,v 1.59 2018/03/26 21:50:45 abe Exp $";
38 #endif
39
40
41 #include "lsof.h"
42
43
44 /*
45  * Local definitions
46  */
47
48 static int GObk[] = { 1, 1 };           /* option backspace values */
49 static char GOp;                        /* option prefix -- '+' or '-' */
50 static char *GOv = (char *)NULL;        /* option `:' value pointer */
51 static int GOx1 = 1;                    /* first opt[][] index */
52 static int GOx2 = 0;                    /* second opt[][] index */
53
54
55 _PROTOTYPE(static int GetOpt,(int ct, char *opt[], char *rules, int *err));
56 _PROTOTYPE(static char *sv_fmt_str,(char *f));
57
58
59 /*
60  * main() - main function for lsof
61  */
62
63 int
64 main(argc, argv)
65         int argc;
66         char *argv[];
67 {
68         int ad, c, i, n, rv, se1, se2, ss;
69         char *cp;
70         int err = 0;
71         int ev = 0;
72         int fh = 0;
73         char *fmtr = (char *)NULL;
74         long l;
75         MALLOC_S len;
76         struct lfile *lf;
77         struct nwad *np, *npn;
78         char options[128];
79         int rc = 0;
80         struct stat sb;
81         struct sfile *sfp;
82         struct lproc **slp = (struct lproc **)NULL;
83         int sp = 0;
84         struct str_lst *str, *strt;
85         int version = 0;
86         int xover = 0;
87
88 #if     defined(HAS_STRFTIME)
89         char *fmt = (char *)NULL;
90         size_t fmtl = (size_t)0;
91 #endif  /* defined(HAS_STRFTIME) */
92
93 #if     defined(HASZONES)
94         znhash_t *zp;
95 #endif  /* defined(HASZONES) */
96
97 #if     defined(HASSELINUX)
98 /*
99  * This stanza must be immediately before the "Save progam name." code, since
100  * it contains code itself.
101  */
102         cntxlist_t *cntxp;
103
104         CntxStatus = is_selinux_enabled() ? 1 : 0;
105 #endif  /* defined(HASSELINUX) */
106
107 /*
108  * Save program name.
109  */
110         if ((Pn = strrchr(argv[0], '/')))
111             Pn++;
112         else
113             Pn = argv[0];
114 /*
115  * Close enough file descriptors above 2 that library functions will have
116  * open descriptors.
117  *
118  * Make sure stderr, stdout, and stdin are open descriptors.  Open /dev/null
119  * for ones that aren't.  Be terse.
120  *
121  * Make sure umask allows lsof to define its own file permissions.
122  */
123
124         if ((MaxFd = (int) GET_MAX_FD()) < 53)
125             MaxFd = 53;
126
127 #if     defined(HAS_CLOSEFROM)
128         (void) closefrom(3);
129 #else   /* !defined(HAS_CLOSEFROM) */
130         for (i = 3; i < MaxFd; i++)
131             (void) close(i);
132 #endif  /* !defined(HAS_CLOSEFROM) */
133
134         while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2))
135             ;
136         if (i < 0)
137             Exit(1);
138         if (i > 2)
139             (void) close(i);
140         (void) umask(0);
141
142 #if     defined(HASSETLOCALE)
143 /*
144  * Set locale to environment's definition.
145  */
146         (void) setlocale(LC_CTYPE, "");
147 #endif  /* defined(HASSETLOCALE) */
148
149 /*
150  * Common initialization.
151  */
152         Mypid = getpid();
153         if ((Mygid = (gid_t)getgid()) != getegid())
154             Setgid = 1;
155         Euid = geteuid();
156         if ((Myuid = (uid_t)getuid()) && !Euid)
157             Setuidroot = 1;
158         if (!(Namech = (char *)malloc(MAXPATHLEN + 1))) {
159             (void) fprintf(stderr, "%s: no space for name buffer\n", Pn);
160             Exit(1);
161         }
162         Namechl = (size_t)(MAXPATHLEN + 1);
163 /*
164  * Create option mask.
165  */
166         (void) snpf(options, sizeof(options),
167             "?a%sbc:%sD:d:%s%sf:F:g:hi:%s%slL:%s%snNo:Op:Pr:%ss:S:tT:u:UvVwx:%s%s%s",
168
169 #if     defined(HAS_AFS) && defined(HASAOPT)
170             "A:",
171 #else   /* !defined(HAS_AFS) || !defined(HASAOPT) */
172             "",
173 #endif  /* defined(HAS_AFS) && defined(HASAOPT) */
174
175 #if     defined(HASNCACHE)
176             "C",
177 #else   /* !defined(HASNCACHE) */
178             "",
179 #endif  /* defined(HASNCACHE) */
180
181 #if     defined(HASEOPT)
182             "e:",
183 #else   /* !defined(HASEOPT) */
184             "",
185 #endif  /* defined(HASEOPT) */
186
187 #if     defined(HASEPTOPTS)
188             "E",
189 #else   /* !defined(HASEPTOPTS) */
190             "",
191 #endif  /* defined(HASEPTOPTS) */
192
193 #if     defined(HASKOPT)
194             "k:",
195 #else   /* !defined(HASKOPT) */
196             "",
197 #endif  /* defined(HASKOPT) */
198
199 #if     defined(HASTASKS)
200             "K:",
201 #else   /* !defined(HASTASKS) */
202             "",
203 #endif  /* defined(HASTASKS) */
204
205 #if     defined(HASMOPT) || defined(HASMNTSUP)
206             "m:",
207 #else   /* !defined(HASMOPT) && !defined(HASMNTSUP) */
208             "",
209 #endif  /* defined(HASMOPT) || defined(HASMNTSUP) */
210
211 #if     defined(HASNORPC_H)
212             "",
213 #else   /* !defined(HASNORPC_H) */
214             "M",
215 #endif  /* defined(HASNORPC_H) */
216
217 #if     defined(HASPPID)
218             "R",
219 #else   /* !defined(HASPPID) */
220             "",
221 #endif  /* defined(HASPPID) */
222
223 #if     defined(HASXOPT)
224 # if    defined(HASXOPT_ROOT)
225             (Myuid == 0) ? "X" : "",
226 # else  /* !defined(HASXOPT_ROOT) */
227             "X",
228 # endif /* defined(HASXOPT_ROOT) */
229 #else   /* !defined(HASXOPT) */
230             "",
231 #endif  /* defined(HASXOPT) */
232
233 #if     defined(HASZONES)
234             "z:",
235 #else   /* !defined(HASZONES) */
236             "",
237 #endif  /* defined(HASZONES) */
238  
239 #if     defined(HASSELINUX)
240             "Z:"
241 #else   /* !defined(HASSELINUX) */
242             ""
243 #endif  /* defined(HASSELINUX) */
244
245             );
246 /*
247  * Loop through options.
248  */
249         while ((c = GetOpt(argc, argv, options, &rv)) != EOF) {
250             if (rv) {
251                 err = 1;
252                 continue;
253             }
254             switch (c) {
255             case 'a':
256                 Fand = 1;
257                 break;
258
259 #if     defined(HAS_AFS) && defined(HASAOPT)
260             case 'A':
261                 if (!GOv || *GOv == '-' || *GOv == '+') {
262                     (void) fprintf(stderr, "%s: -A not followed by path\n", Pn);
263                     err = 1;
264                     if (GOv) {
265                         GOx1 = GObk[0];
266                         GOx2 = GObk[1];
267                     }
268                 } else
269                     AFSApath = GOv;
270                 break;
271 #endif  /* defined(HAS_AFS) && defined(HASAOPT) */
272
273             case 'b':
274                 Fblock = 1;
275                 break;
276             case 'c':
277                 if (GOp == '+') {
278                     if (!GOv || (*GOv == '-') || (*GOv == '+')
279                     ||  !isdigit((int)*GOv))
280                     {
281                         (void) fprintf(stderr,
282                             "%s: +c not followed by width number\n", Pn);
283                         err = 1;
284                         if (GOv) {
285                             GOx1 = GObk[0];
286                             GOx2 = GObk[1];
287                         }
288                     } else {
289                         CmdLim = TaskCmdLim = atoi(GOv);
290
291 #if     defined(MAXSYSCMDL)
292                         if (CmdLim > MAXSYSCMDL) {
293                             (void) fprintf(stderr,
294                                 "%s: +c %d > what system provides (%d)\n",
295                                 Pn, CmdLim, MAXSYSCMDL);
296                             err = 1;
297                         }
298 #endif  /* defined(MAXSYSCMDL) */
299
300                     }
301                     break;
302                 }
303                 if (GOv && (*GOv == '/')) {
304                     if (enter_cmd_rx(GOv))
305                         err = 1;
306                 } else {
307                     if (enter_str_lst("-c", GOv, &Cmdl, &Cmdni, &Cmdnx))
308                         err = 1;
309
310 #if     defined(MAXSYSCMDL)
311                     else if (Cmdl->len > MAXSYSCMDL) {
312                         (void) fprintf(stderr, "%s: \"-c ", Pn);
313                         (void) safestrprt(Cmdl->str, stderr, 2);
314                         (void) fprintf(stderr, "\" length (%d) > what system",
315                             Cmdl->len);
316                         (void) fprintf(stderr, " provides (%d)\n",
317                             MAXSYSCMDL);
318                         Cmdl->len = 0;  /* (to avoid later error report) */
319                         err = 1;
320                     }
321 #endif  /* defined(MAXSYSCMDL) */
322
323                 }
324                 break;
325
326 #if     defined(HASNCACHE)
327             case 'C':
328                 Fncache = (GOp == '-') ? 0 : 1;
329                 break;
330
331 #endif  /* defined(HASNCACHE) */
332             case 'd':
333                 if (GOp == '+') {
334                     if (enter_dir(GOv, 0))
335                         err = 1;
336                     else {
337                         Selflags |= SELNM;
338                         xover = 1;
339                     }
340                 } else {
341                     if (enter_fd(GOv))
342                         err = 1;
343                 }
344                 break;
345             case 'D':
346                 if (GOp == '+') {
347                     if (enter_dir(GOv, 1))
348                         err = 1;
349                     else {
350                         Selflags |= SELNM;
351                         xover = 1;
352                     }
353                 } else {
354
355 #if     defined(HASDCACHE)
356                     if (ctrl_dcache(GOv))
357                         err = 1;
358 #else   /* !defined(HASDCACHE) */
359                     (void) fprintf(stderr, "%s: unsupported option: -D\n", Pn);
360                     err = 1;
361 #endif  /* defined(HASDCACHE) */
362
363                 }
364                 break;
365
366 #if     defined(HASEOPT)
367             case 'e':
368                 if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0)))
369                     err = 1;
370                 break;
371 #endif  /* defined(HASEOPT) */
372
373 #if     defined(HASEPTOPTS)
374             case 'E':
375                 FeptE = (GOp == '+') ? 2 : 1;
376                 break;
377 #endif  /* defined(HASEPTOPTS) */
378
379             case 'f':
380                 if (!GOv || *GOv == '-' || *GOv == '+') {
381                     Ffilesys = (GOp == '+') ? 2 : 1;
382                     if (GOv) {
383                         GOx1 = GObk[0];
384                         GOx2 = GObk[1];
385                     }
386                     break;
387                 }
388
389 #if     defined(HASFSTRUCT)
390                 for (; *GOv; GOv++) {
391                     switch (*GOv) {
392
393 # if    !defined(HASNOFSCOUNT)
394                     case 'c':
395                     case 'C':
396                         if (GOp == '+') {
397                             Fsv |= FSV_CT;
398                             FsvByf = 1;
399                         } else
400                             Fsv &= (unsigned char)~FSV_CT;
401                         break;
402 # endif /* !defined(HASNOFSCOUNT) */
403
404 # if    !defined(HASNOFSADDR)
405                     case 'f':
406                     case 'F':
407                         if (GOp == '+') {
408                             Fsv |= FSV_FA;
409                             FsvByf = 1;
410                         } else
411                             Fsv &= (unsigned char)~FSV_FA;
412                         break;
413 # endif /* !defined(HASNOFSADDR) */
414
415 # if    !defined(HASNOFSFLAGS)
416                     case 'g':
417                     case 'G':
418                         if (GOp == '+') {
419                             Fsv |= FSV_FG;
420                             FsvByf = 1;
421                         } else
422                             Fsv &= (unsigned char)~FSV_FG;
423                         FsvFlagX = (*GOv == 'G') ? 1 : 0;
424                         break;
425 # endif /* !defined(HASNOFSFLAGS) */
426
427 # if    !defined(HASNOFSNADDR)
428                     case 'n':
429                     case 'N':
430                         if (GOp == '+') {
431                             Fsv |= FSV_NI;
432                             FsvByf = 1;
433                         } else
434                             Fsv &= (unsigned char)~FSV_NI;
435                         break;
436 # endif /* !defined(HASNOFSNADDR */
437
438                     default:
439                         (void) fprintf(stderr,
440                             "%s: unknown file struct option: %c\n", Pn, *GOv);
441                         err++;
442                     }
443                 }
444 #else   /* !defined(HASFSTRUCT) */
445                 (void) fprintf(stderr,
446                     "%s: unknown string for %cf: %s\n", Pn, GOp, GOv);
447                 err++;
448 #endif  /* defined(HASFSTRUCT) */
449
450                 break;
451             case 'F':
452                 if (!GOv || *GOv == '-' || *GOv == '+'
453                 ||  strcmp(GOv, "0") == 0) {
454                     if (GOv) {
455                         if (*GOv == '-' || *GOv == '+') {
456                             GOx1 = GObk[0];
457                             GOx2 = GObk[1];
458                         } else if (*GOv == '0')
459                             Terminator = '\0';
460                     }
461                     for (i = 0; FieldSel[i].nm; i++) {
462
463 #if     !defined(HASPPID)
464                         if (FieldSel[i].id == LSOF_FID_PPID)
465                             continue;
466 #endif  /* !defined(HASPPID) */
467
468 #if     !defined(HASTASKS)
469                         if (FieldSel[i].id == LSOF_FID_TCMD)
470                             continue;
471 #endif  /* !defined(HASTASKS) */
472
473 #if     !defined(HASFSTRUCT)
474                         if (FieldSel[i].id == LSOF_FID_CT
475                         ||  FieldSel[i].id == LSOF_FID_FA
476                         ||  FieldSel[i].id == LSOF_FID_FG
477                         ||  FieldSel[i].id == LSOF_FID_NI)
478                             continue;
479 #endif  /* !defined(HASFSTRUCT) */
480  
481 #if     defined(HASSELINUX)
482                         if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus)
483                             continue;
484 #else   /* !defined(HASSELINUX) */
485                         if (FieldSel[i].id == LSOF_FID_CNTX)
486                             continue;
487 #endif  /* !defined(HASSELINUX) */
488
489                         if (FieldSel[i].id == LSOF_FID_RDEV)
490                             continue;   /* for compatibility */
491
492 #if     !defined(HASTASKS)
493                         if (FieldSel[i].id == LSOF_FID_TID)
494                             continue;
495 #endif  /* !defined(HASTASKS) */
496
497 #if     !defined(HASZONES)
498                         if (FieldSel[i].id == LSOF_FID_ZONE)
499                             continue;
500 #endif  /* !defined(HASZONES) */
501
502                         FieldSel[i].st = 1;
503                         if (FieldSel[i].opt && FieldSel[i].ov)
504                             *(FieldSel[i].opt) |= FieldSel[i].ov;
505                     }
506
507 #if     defined(HASFSTRUCT)
508                     Ffield = FsvFlagX = 1;
509 #else   /* !defined(HASFSTRUCT) */
510                     Ffield = 1;
511 #endif  /* defined(HASFSTRUCT) */
512
513                     break;
514                 }
515                 if (strcmp(GOv, "?") == 0) {
516                     fh = 1;
517                     break;
518                 }
519                 for (; *GOv; GOv++) {
520                     for (i = 0; FieldSel[i].nm; i++) {
521
522 #if     !defined(HASPPID)
523                         if (FieldSel[i].id == LSOF_FID_PPID)
524                             continue;
525 #endif  /* !defined(HASPPID) */
526
527 #if     !defined(HASTASKS)
528                         if (FieldSel[i].id == LSOF_FID_TCMD)
529                             continue;
530 #endif  /* !defined(HASTASKS) */
531
532 #if     !defined(HASFSTRUCT)
533                         if (FieldSel[i].id == LSOF_FID_CT
534                         ||  FieldSel[i].id == LSOF_FID_FA
535                         ||  FieldSel[i].id == LSOF_FID_FG
536                         ||  FieldSel[i].id == LSOF_FID_NI)
537                             continue;
538 #endif  /* !defined(HASFSTRUCT) */
539
540 #if     !defined(HASTASKS)
541                         if (FieldSel[i].id == LSOF_FID_TID)
542                             continue;
543 #endif  /* !defined(HASTASKS) */
544
545                         if (FieldSel[i].id == *GOv) {
546                             FieldSel[i].st = 1;
547                             if (FieldSel[i].opt && FieldSel[i].ov)
548                                 *(FieldSel[i].opt) |= FieldSel[i].ov;
549
550 #if     defined(HASFSTRUCT)
551                             if (i == LSOF_FIX_FG)
552                                 FsvFlagX = 1;
553 #endif  /* defined(HASFSTRUCT) */
554
555                             if (i == LSOF_FIX_TERM)
556                                 Terminator = '\0';
557                             break;
558                         }
559                     }
560                     if ( ! FieldSel[i].nm) {
561                         (void) fprintf(stderr,
562                             "%s: unknown field: %c\n", Pn, *GOv);
563                         err++;
564                     }
565                 }
566                 Ffield = 1;
567                 break;
568             case 'g':
569                 if (GOv) {
570                     if (*GOv == '-' || *GOv == '+') {
571                         GOx1 = GObk[0];
572                         GOx2 = GObk[1];
573                     } else if (enter_id(PGID, GOv))
574                         err = 1;
575                 }
576                 Fpgid = 1;
577                 break;
578             case 'h':
579             case '?':
580                 Fhelp = 1;
581                 break;
582             case 'i':
583                 if (!GOv || *GOv == '-' || *GOv == '+') {
584                     Fnet = 1;
585                     FnetTy = 0;
586                     if (GOv) {
587                         GOx1 = GObk[0];
588                         GOx2 = GObk[1];
589                     }
590                     break;
591                 }
592                 if (enter_network_address(GOv))
593                     err = 1;
594                 break;
595
596 #if     defined(HASKOPT)
597             case 'k':
598                 if (!GOv || *GOv == '-' || *GOv == '+') {
599                     (void) fprintf(stderr, "%s: -k not followed by path\n", Pn);
600                     err = 1;
601                     if (GOv) {
602                         GOx1 = GObk[0];
603                         GOx2 = GObk[1];
604                     }
605                 } else
606                     Nmlst = GOv;
607                 break;
608 #endif  /* defined(HASKOPT) */
609
610 #if     defined(HASTASKS)
611             case 'K':
612                 if (!GOv || *GOv == '-' || *GOv == '+') {
613                     Ftask = 1;
614                     IgnTasks = 0;
615                     Selflags |= SELTASK;
616                     if (GOv) {
617                         GOx1 = GObk[0];
618                         GOx2 = GObk[1];
619                     }
620                 } else {
621                     if (!strcasecmp(GOv, "i")) {
622                         Ftask = 0;
623                         IgnTasks = 1;
624                         Selflags &= ~SELTASK;
625                    } else {
626                         (void) fprintf(stderr,
627                             "%s: -K not followed by i (but by %s)\n", Pn, GOv);
628                         err = 1;
629                    }
630                 }
631                 break;
632 #endif  /* defined(HASTASKS) */
633
634             case 'l':
635                 Futol = 0;
636                 break;
637             case 'L':
638                 Fnlink = (GOp == '+') ? 1 : 0;
639                 if (!GOv || *GOv == '-' || *GOv == '+') {
640                     Nlink = 0l;
641                     if (GOv) {
642                         GOx1 = GObk[0];
643                         GOx2 = GObk[1];
644                     }
645                     break;
646                 }
647                 for (cp = GOv, l = 0l, n = 0; *cp; cp++) {
648                     if (!isdigit((unsigned char)*cp))
649                         break;
650                     l = (l * 10l) + ((long)*cp - (long)'0');
651                     n++;
652                 }
653                 if (n) {
654                     if (GOp != '+') {
655                         (void) fprintf(stderr,
656                             "%s: no number may follow -L\n", Pn);
657                         err = 1;
658                     } else {
659                         Nlink = l;
660                         Selflags |= SELNLINK;
661                     }
662                 } else
663                     Nlink = 0l;
664                 if (*cp) {
665                     GOx1 = GObk[0];
666                     GOx2 = GObk[1] + n;
667                 }
668                 break;
669
670 #if     defined(HASMOPT) || defined(HASMNTSUP)
671             case 'm':
672                 if (GOp == '-') {
673
674 # if    defined(HASMOPT)
675                     if (!GOv || *GOv == '-' || *GOv == '+') {
676                         (void) fprintf(stderr,
677                             "%s: -m not followed by path\n", Pn);
678                         err = 1;
679                         if (GOv) {
680                             GOx1 = GObk[0];
681                             GOx2 = GObk[1];
682                         }
683                     } else
684                         Memory = GOv;
685 # else  /* !defined(HASMOPT) */
686                     (void) fprintf(stderr, "%s: -m not supported\n", Pn);
687                     err = 1;
688 # endif /* defined(HASMOPT) */
689
690                 } else if (GOp == '+') {
691
692 # if    defined(HASMNTSUP)
693                     if (!GOv || *GOv == '-' || *GOv == '+') {
694                         MntSup = 1;
695                         if (GOv) {
696                             GOx1 = GObk[0];
697                             GOx2 = GObk[1];
698                         }
699                     } else {
700                         MntSup = 2;
701                         MntSupP = GOv;
702                     }
703 # else  /* !defined(HASMNTSUP) */
704                     (void) fprintf(stderr, "%s: +m not supported\n", Pn);
705                     err = 1;
706 # endif /* defined(HASMNTSUP) */
707
708                 } else {
709                     (void) fprintf(stderr, "%s: %cm not supported\n", Pn, GOp);
710                     err = 1;
711                 }
712                 break;
713 #endif  /* defined(HASMOPT) || defined(HASMNTSUP) */
714
715 #if     !defined(HASNORPC_H)
716             case 'M':
717                 FportMap = (GOp == '+') ? 1 : 0;
718                 break;
719 #endif  /* !defined(HASNORPC_H) */
720
721             case 'n':
722                 Fhost = (GOp == '-') ? 0 : 1;
723                 break;
724             case 'N':
725                 Fnfs = 1;
726                 break;
727             case 'o':
728                 if (!GOv || *GOv == '-' || *GOv == '+') {
729                     Foffset = 1;
730                     if (GOv) {
731                         GOx1 = GObk[0];
732                         GOx2 = GObk[1];
733                     }
734                     break;
735                 }
736                 for (cp = GOv, i = n = 0; *cp; cp++) {
737                     if (!isdigit((unsigned char)*cp))
738                         break;
739                     i = (i * 10) + ((int)*cp - '0');
740                     n++;
741                 }
742                 if (n)
743                     OffDecDig = i;
744                 else
745                     Foffset = 1;
746                 if (*cp) {
747                     GOx1 = GObk[0];
748                     GOx2 = GObk[1] + n;
749                 }
750                 break;
751             case 'O':
752                 Fovhd = (GOp == '-') ? 1 : 0;
753                 break;
754             case 'p':
755                 if (enter_id(PID, GOv))
756                     err = 1;
757                 break;
758             case 'P':
759                 Fport = (GOp == '-') ? 0 : 1;
760                 break;
761             case 'r':
762                 if (GOp == '+')
763                     ev = rc = 1;
764                 if (!GOv || *GOv == '-' || *GOv == '+') {
765                     RptTm = RPTTM;
766                     if (GOv) {
767                         GOx1 = GObk[0];
768                         GOx2 = GObk[1];
769                     }
770                     break;
771                 }
772                 for (cp = GOv, i = n = 0; *cp; cp++) {
773                     if (!isdigit((unsigned char)*cp))
774                         break;
775                     i = (i * 10) + ((int)*cp - '0');
776                     n++;
777                 }
778                 if (n)
779                     RptTm = i;
780                 else
781                     RptTm = RPTTM;
782                 if (!*cp)
783                      break;
784                 while(*cp && (*cp == ' '))
785                     cp++;
786                 if (*cp != LSOF_FID_MARK) {
787                     GOx1 = GObk[0];
788                     GOx2 = GObk[1] + n;
789                     break;
790                 }
791
792 #if     defined(HAS_STRFTIME)
793
794             /*
795              * Collect the strftime(3) format and test it.
796              */
797                 cp++;
798                 if ((fmtl = strlen(cp) + 1) < 1) {
799                     (void) fprintf(stderr, "%s: <fmt> too short: \"%s\"\n",
800                         Pn, cp);
801                     err = 1;
802                 } else {
803                     fmt = cp;
804                     fmtl = (fmtl * 8) + 1;
805                     if (!(fmtr = (char *)malloc((MALLOC_S)fmtl))) {
806                         (void) fprintf(stderr,
807                             "%s: no space (%d) for <fmt> result: \"%s\"\n",
808                             Pn, (int)fmtl, cp);
809                             Exit(1);
810                     }
811                     if (util_strftime(fmtr, fmtl - 1, fmt) < 1) {
812                         (void) fprintf(stderr, "%s: illegal <fmt>: \"%s\"\n",
813                             Pn, fmt);
814                         err = 1;
815                     }
816                 }
817
818 #else   /* !defined(HAS_STRFTIME) */
819                 (void) fprintf(stderr, "%s: m<fmt> not supported: \"%s\"\n",
820                     Pn, cp);
821                 err = 1;
822 #endif  /* defined(HAS_STRFTIME) */
823
824                 break;
825
826 #if     defined(HASPPID)
827             case 'R':
828                 Fppid = 1;
829                 break;
830 #endif  /* defined(HASPPID) */
831
832             case 's':
833
834 #if     defined(HASTCPUDPSTATE)
835                 if (!GOv || *GOv == '-' || *GOv == '+') {
836                     Fsize = 1;
837                     if (GOv) {
838                         GOx1 = GObk[0];
839                         GOx2 = GObk[1];
840                     }
841                 } else {
842                     if (enter_state_spec(GOv))
843                         err = 1;
844                 }
845 #else   /* !defined(HASTCPUDPSTATE) */
846                 Fsize = 1;
847 #endif  /* defined(HASTCPUDPSTATE) */
848
849                 break;
850             case 'S':
851                 if (!GOv || *GOv == '-' || *GOv == '+') {
852                     TmLimit = TMLIMIT;
853                     if (GOv) {
854                         GOx1 = GObk[0];
855                         GOx2 = GObk[1];
856                     }
857                     break;
858                 }
859                 for (cp = GOv, i = n = 0; *cp; cp++) {
860                     if (!isdigit((unsigned char)*cp))
861                         break;
862                     i = (i * 10) + ((int)*cp - '0');
863                     n++;
864                 }
865                 if (n)
866                     TmLimit = i;
867                 else
868                     TmLimit = TMLIMIT;
869                 if (*cp) {
870                     GOx1 = GObk[0];
871                     GOx2 = GObk[1] + n;
872                 }
873                 if (TmLimit < TMLIMMIN) {
874                     (void) fprintf(stderr,
875                         "%s: WARNING: -S time (%d) changed to %d\n",
876                         Pn, TmLimit, TMLIMMIN);
877                     TmLimit = TMLIMMIN;
878                 }
879                 break;
880             case 't':
881                 Fterse = Fwarn = 1;
882                 break;
883             case 'T':
884                 if (!GOv || *GOv == '-' || *GOv == '+') {
885                     Ftcptpi = (GOp == '-') ? 0 : TCPTPI_STATE;
886                     if (GOv) {
887                         GOx1 = GObk[0];
888                         GOx2 = GObk[1];
889                     }
890                     break;
891                 }
892                 for (Ftcptpi = 0; *GOv; GOv++) {
893                     switch (*GOv) {
894
895 #if     defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT)
896                     case 'f':
897                         Ftcptpi |= TCPTPI_FLAGS;
898                         break;
899 #endif  /* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT) */
900
901 #if     defined(HASTCPTPIQ)
902                     case 'q':
903                         Ftcptpi |= TCPTPI_QUEUES;
904                         break;
905 #endif  /* defined(HASTCPTPIQ) */
906
907                     case 's':
908                         Ftcptpi |= TCPTPI_STATE;
909                         break;
910
911 #if     defined(HASTCPTPIW)
912                     case 'w':
913                         Ftcptpi |= TCPTPI_WINDOWS;
914                         break;
915 #endif  /* defined(HASTCPTPIW) */
916
917                     default:
918                         (void) fprintf(stderr,
919                         "%s: unsupported TCP/TPI info selection: %c\n",
920                             Pn, *GOv);
921                         err = 1;
922                     }
923                 }
924                 break;
925             case 'u':
926                 if (enter_uid(GOv))
927                     err = 1;
928                 break;
929             case 'U':
930                 Funix = 1;
931                 break;
932             case 'v':
933                 version = 1;
934                 break;
935             case 'V':
936                 Fverbose = 1;
937                 break;
938             case 'w':
939                 Fwarn = (GOp == '+') ? 0 : 1;
940                 break;
941             case 'x':
942                 if (!GOv || *GOv == '-' || *GOv == '+') {
943                     Fxover = XO_ALL;
944                     if (GOv) {
945                         GOx1 = GObk[0];
946                         GOx2 = GObk[1];
947                     }
948                     break;
949                 } else {
950                     for (; *GOv; GOv++) {
951                         switch (*GOv) {
952                         case 'f':
953                             Fxover |= XO_FILESYS;
954                             break;
955                         case 'l':
956                             Fxover |= XO_SYMLINK;
957                             break;
958                         default:
959                             (void) fprintf(stderr,
960                                 "%s: unknown cross-over option: %c\n",
961                                 Pn, *GOv);
962                             err++;
963                         }
964                     }
965                 }
966                 break;
967
968 #if     defined(HASXOPT)
969             case 'X':
970                 Fxopt = Fxopt ? 0 : 1;
971                 break;
972 #endif  /* defined(HASXOPT) */
973
974 #if     defined(HASZONES)
975             case 'z':
976                 Fzone = 1;
977                 if (GOv && (*GOv != '-') && (*GOv != '+')) {
978
979                 /*
980                  * Add to the zone name argument hash.
981                  */
982                     if (enter_zone_arg(GOv))
983                         err = 1;
984                 } else if (GOv) {
985                     GOx1 = GObk[0];
986                     GOx2 = GObk[1];
987                 }
988                 break;
989 #endif  /* defined(HASZONES) */
990  
991 #if     defined(HASSELINUX)
992             case 'Z':
993                 if (!CntxStatus) {
994                    (void) fprintf(stderr, "%s: -Z limited to SELinux\n", Pn);
995                     err = 1;
996                 } else {
997                     Fcntx = 1;
998                     if (GOv && (*GOv != '-') && (*GOv != '+')) {
999
1000                     /*
1001                      * Add to the context name argument hash.
1002                      */
1003                         if (enter_cntx_arg(GOv))
1004                             err = 1;
1005                     } else if (GOv) {
1006                         GOx1 = GObk[0];
1007                         GOx2 = GObk[1];
1008                     }
1009                 }
1010                 break;
1011 #endif  /* defined(HASSELINUX) */
1012
1013             default:
1014                 (void) fprintf(stderr, "%s: unknown option (%c)\n", Pn, c);
1015                 err = 1;
1016             }
1017         }
1018 /*
1019  * If IgnTasks is set, remove SELTASK from SelAll and SelProc.
1020  */
1021         SelAll = IgnTasks ? (SELALL & ~SELTASK) : SELALL;
1022         SelProc = IgnTasks ? (SELPROC & ~SELTASK) : SELPROC;
1023 /*
1024  * Check for argument consistency.
1025  */
1026         if (Cmdnx && Cmdni) {
1027
1028         /*
1029          * Check for command inclusion/exclusion conflicts.
1030          */
1031             for (str = Cmdl; str; str = str->next) {
1032                 if (str->x) {
1033                     for (strt = Cmdl; strt; strt = strt->next) {
1034                         if (!strt->x) {
1035                             if (!strcmp(str->str, strt->str)) {
1036                                 (void) fprintf(stderr,
1037                                     "%s: -c^%s and -c%s conflict.\n",
1038                                     Pn, str->str, strt->str);
1039                                 err++;
1040                             }
1041                         }
1042                     }
1043                 }
1044             }
1045         }
1046
1047 #if     defined(HASTCPUDPSTATE)
1048         if (TcpStXn && TcpStIn) {
1049
1050         /*
1051          * Check for excluded and included TCP states.
1052          */
1053             for (i = 0; i < TcpNstates; i++) {
1054                 if (TcpStX[i] && TcpStI[i]) {
1055                     (void) fprintf(stderr,
1056                         "%s: can't include and exclude TCP state: %s\n",
1057                         Pn, TcpSt[i]);
1058                     err = 1;
1059                 }
1060             }
1061         }
1062         if (UdpStXn && UdpStIn) {
1063
1064         /*
1065          * Check for excluded and included UDP states.
1066          */
1067             for (i = 0; i < UdpNstates; i++) {
1068                 if (UdpStX[i] && UdpStI[i]) {
1069                     (void) fprintf(stderr,
1070                         "%s: can't include and exclude UDP state: %s\n",
1071                         Pn, UdpSt[i]);
1072                     err = 1;
1073                 }
1074             }
1075         }
1076 #endif  /* defined(HASTCPUDPSTATE) */
1077
1078         if (Fsize && Foffset) {
1079             (void) fprintf(stderr, "%s: -o and -s are mutually exclusive\n",
1080                 Pn);
1081             err++;
1082         }
1083         if (Ffield) {
1084             if (Fterse) {
1085                 (void) fprintf(stderr,
1086                     "%s: -F and -t are mutually exclusive\n", Pn);
1087                 err++;
1088             }
1089             FieldSel[LSOF_FIX_PID].st = 1;
1090
1091 #if     defined(HAS_STRFTIME)
1092             if (fmtr) {
1093
1094             /*
1095              * The field output marker format can't contain "%n" new line
1096              * requests.
1097              */
1098                 for (cp = strchr(fmt, '%'); cp; cp = strchr(cp, '%')) {
1099                     if (*++cp  == 'n') {
1100                         (void) fprintf(stderr,
1101                             "%s: %%n illegal in -r m<fmt> when -F has", Pn);
1102                         (void) fprintf(stderr,
1103                             " been specified: \"%s\"\n", fmt);
1104                         err++;
1105                         break;
1106                     } else if (*cp == '%')
1107                         cp++;
1108                 }
1109             }
1110 #endif  /* defined(HAS_STRFTIME) */
1111
1112         }
1113         if (Fxover && !xover) {
1114             (void) fprintf(stderr, "%s: -x must accompany +d or +D\n", Pn);
1115             err++;
1116         }
1117
1118 #if     defined(HASEOPT)
1119         if (Efsysl) {
1120
1121         /*
1122          * If there are file systems specified by -e options, check them.
1123          */
1124             efsys_list_t *ep;           /* Efsysl pointer */
1125             struct mounts *mp, *mpw;    /* local mount table pointers */
1126
1127             if ((mp = readmnt())) {
1128                 for (ep = Efsysl; ep; ep = ep->next) {
1129                     for (mpw = mp; mpw; mpw = mpw->next) {
1130                         if (!strcmp(mpw->dir, ep->path)) {
1131                             ep->mp = mpw;
1132                             break;
1133                         }
1134                     }
1135                     if (!ep->mp) {
1136                         (void) fprintf(stderr,
1137                             "%s: \"-e %s\" is not a mounted file system.\n",
1138                             Pn, ep->path);
1139                         err++;
1140                     }
1141                 }
1142             }
1143         }
1144 #endif  /* defined(HASEOPT) */
1145
1146         if (DChelp || err || Fhelp || fh || version)
1147             usage(err ? 1 : 0, fh, version);
1148 /*
1149  * Reduce the size of Suid[], if necessary.
1150  */
1151         if (Suid && Nuid && Nuid < Mxuid) {
1152             if (!(Suid = (struct seluid *)realloc((MALLOC_P *)Suid,
1153                          (MALLOC_S)(sizeof(struct seluid) * Nuid))))
1154             {
1155                 (void) fprintf(stderr, "%s: can't realloc UID table\n", Pn);
1156                 Exit(1);
1157             }
1158             Mxuid = Nuid;
1159         }
1160 /*
1161  * Compute the selection flags.
1162  */
1163         if ((Cmdl && Cmdni) || CmdRx)
1164             Selflags |= SELCMD;
1165  
1166 #if     defined(HASSELINUX)
1167         if (CntxArg)
1168             Selflags |= SELCNTX;
1169 #endif  /* defined(HASSELINUX) */
1170
1171         if (Fdl)
1172             Selflags |= SELFD;
1173         if (Fnet)
1174             Selflags |= SELNET;
1175         if (Fnfs)
1176             Selflags |= SELNFS;
1177         if (Funix)
1178             Selflags |= SELUNX;
1179         if (Npgid && Npgidi)
1180             Selflags |= SELPGID;
1181         if (Npid && Npidi)
1182             Selflags |= SELPID;
1183         if (Nuid && Nuidincl)
1184             Selflags |= SELUID;
1185         if (Nwad)
1186             Selflags |= SELNA;
1187
1188 #if     defined(HASZONES)
1189         if (ZoneArg)
1190             Selflags |= SELZONE;
1191 #endif  /* defined(HASZONES) */
1192
1193         if (GOx1 < argc)
1194             Selflags |= SELNM;
1195         if (Selflags == 0) {
1196             if (Fand) {
1197                 (void) fprintf(stderr,
1198                     "%s: no select options to AND via -a\n", Pn);
1199                 usage(1, 0, 0);
1200             }
1201             Selflags = SelAll;
1202         } else {
1203             if (GOx1 >= argc && (Selflags & (SELNA|SELNET)) != 0
1204             &&  (Selflags & ~(SELNA|SELNET)) == 0)
1205                 Selinet = 1;
1206             AllProc = 0;
1207         }
1208 /*
1209  * Get the device for DEVDEV_PATH.
1210  */
1211         if (stat(DEVDEV_PATH, &sb)) {
1212             se1 = errno;
1213             if ((ad = strcmp(DEVDEV_PATH, "/dev"))) {
1214                 if ((ss = stat("/dev", &sb)))
1215                     se2 = errno;
1216                 else
1217                     se2 = 0;
1218             } else {
1219                 se2 = 0;
1220                 ss = 1;
1221             }
1222             if (ss) {
1223                 (void) fprintf(stderr, "%s: can't stat(%s): %s\n", Pn,
1224                     DEVDEV_PATH, strerror(se1));
1225                 if (ad) {
1226                     (void) fprintf(stderr, "%s: can't stat(/dev): %s\n", Pn,
1227                     strerror(se2));
1228                 }
1229                 Exit(1);
1230             }
1231         }
1232         DevDev = sb.st_dev;
1233 /*
1234  * Process the file arguments.
1235  */
1236         if (GOx1 < argc) {
1237             if (ck_file_arg(GOx1, argc, argv, Ffilesys, 0, (struct stat *)NULL))
1238                 usage(1, 0, 0);
1239         }
1240 /*
1241  * Do dialect-specific initialization.
1242  */
1243         initialize();
1244         if (Sfile)
1245             (void) hashSfile();
1246
1247 #if     defined(WILLDROPGID)
1248 /*
1249  * If this process isn't setuid(root), but it is setgid(not_real_gid),
1250  * relinquish the setgid power.  (If it hasn't already been done.)
1251  */
1252         (void) dropgid();
1253 #endif  /* defined(WILLDROPGID) */
1254
1255
1256 #if     defined(HASDCACHE)
1257 /*
1258  * If there is a device cache, prepare the device table.
1259  */
1260         if (DCstate)
1261             readdev(0);
1262 #endif  /* defined(HASDCACHE) */
1263
1264 /*
1265  * Define the size and offset print formats.
1266  */
1267         (void) snpf(options, sizeof(options), "%%%su", INODEPSPEC);
1268         InodeFmt_d = sv_fmt_str(options);
1269         (void) snpf(options, sizeof(options), "%%#%sx", INODEPSPEC);
1270         InodeFmt_x = sv_fmt_str(options);
1271         (void) snpf(options, sizeof(options), "0t%%%su", SZOFFPSPEC);
1272         SzOffFmt_0t = sv_fmt_str(options);
1273         (void) snpf(options, sizeof(options), "%%%su", SZOFFPSPEC);
1274         SzOffFmt_d = sv_fmt_str(options);
1275         (void) snpf(options, sizeof(options), "%%*%su", SZOFFPSPEC);
1276         SzOffFmt_dv = sv_fmt_str(options);
1277         (void) snpf(options, sizeof(options), "%%#%sx", SZOFFPSPEC);
1278         SzOffFmt_x = sv_fmt_str(options);
1279
1280 #if     defined(HASMNTSUP)
1281 /*
1282  * Report mount supplement information, as requested.
1283  */
1284         if (MntSup == 1) {
1285             (void) readmnt();
1286             Exit(0);
1287         }
1288 #endif  /* defined(HASMNTSUP) */
1289
1290 /*
1291  * Gather and report process information every RptTm seconds.
1292  */
1293         if (RptTm)
1294             CkPasswd = 1;
1295         do {
1296
1297         /*
1298          * Gather information about processes.
1299          */
1300             gather_proc_info();
1301         /*
1302          * If the local process table has more than one entry, sort it by PID.
1303          */
1304             if (Nlproc > 1) {
1305                 if (Nlproc > sp) {
1306                     len = (MALLOC_S)(Nlproc * sizeof(struct lproc *));
1307                     sp = Nlproc;
1308                     if (!slp)
1309                         slp = (struct lproc **)malloc(len);
1310                     else
1311                         slp = (struct lproc **)realloc((MALLOC_P *)slp, len);
1312                     if (!slp) {
1313                         (void) fprintf(stderr,
1314                             "%s: no space for %d sort pointers\n", Pn, Nlproc);
1315                         Exit(1);
1316                     }
1317                 }
1318                 for (i = 0; i < Nlproc; i++) {
1319                     slp[i] = &Lproc[i];
1320                 }
1321                 (void) qsort((QSORT_P *)slp, (size_t)Nlproc,
1322                              (size_t)sizeof(struct lproc *), comppid);
1323             }
1324             if ((n = Nlproc)) {
1325
1326 #if     defined(HASNCACHE)
1327             /*
1328              * If using the kernel name cache, force its reloading.
1329              */
1330                 NcacheReload = 1;
1331 #endif  /* defined(HASNCACHE) */
1332
1333 #if     defined(HASEPTOPTS)
1334             /*
1335              * If endpoint info has been requested, make sure it is coded for
1336              * printing.
1337              *
1338              * Lf contents must be preserved, since they may point to a
1339              * malloc()'d area, and since Lf is used throughout the printing
1340              * of the selected processes.
1341              */
1342                 if (FeptE) {
1343                     lf = Lf;
1344                 /*
1345                  * Scan all selected processes.
1346                  */
1347                     for (i = 0; i < Nlproc; i++) {
1348                         Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
1349
1350                         /*
1351                          * For processes that have been selected for printing
1352                          * and have files that are the end point(s) of pipe(s),
1353                          * process the file endpoints.
1354                          */
1355                             if (Lp->pss && (Lp->ept & EPT_PIPE))
1356                                 (void) process_pinfo(0);
1357
1358 # if    defined(HASUXSOCKEPT)
1359                         /*
1360                          * For processes that have been selected for printing
1361                          * and have files that are the end point(s) of UNIX
1362                          * socket(s), process the file endpoints.
1363                          */
1364                             if (Lp->pss && (Lp->ept & EPT_UXS))
1365                                 (void) process_uxsinfo(0);
1366 # endif /* defined(HASUXSOCKEPT) */
1367
1368 # if    defined(HASPTYEPT)
1369                         /*
1370                          * For processes that have been selected for printing
1371                          * and have files that are the end point(s) of pseudo-
1372                          * terminal files(s), process the file endpoints.
1373                          */
1374                             if (Lp->pss && (Lp->ept & EPT_PTY))
1375                                 (void) process_ptyinfo(0);
1376 # endif /* defined(HASPTYEPT) */
1377
1378                     }
1379                 /*
1380                  * In a second pass, look for unselected endpoint files,
1381                  * possibly selecting them for printing.
1382                  */
1383                     for (i = 0; i < Nlproc; i++) {
1384                         Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
1385
1386                         /*
1387                          * Process pipe endpoints.
1388                          */
1389                             if (Lp->ept & EPT_PIPE_END)
1390                                 (void) process_pinfo(1);
1391
1392 # if    defined(HASUXSOCKEPT)
1393                         /*
1394                          * Process UNIX socket endpoints.
1395                          */
1396                             if (Lp->ept & EPT_UXS_END)
1397                                 (void) process_uxsinfo(1);
1398 # endif /* defined(HASUXSOCKEPT) */
1399
1400 # if    defined(HASPTYEPT)
1401                         /*
1402                          * Process pseudo-terminal endpoints.
1403                          */
1404                             if (Lp->ept & EPT_PTY_END)
1405                                 (void) process_ptyinfo(1);
1406 # endif /* defined(HASPTYEPT) */
1407
1408                     }
1409                     Lf = lf;
1410                 }
1411 #endif  /* defined(HASEPTOPTS) */
1412
1413             /*
1414              * Print the selected processes and count them.
1415              *
1416              * Lf contents must be preserved, since they may point to a
1417              * malloc()'d area, and since Lf is used throughout the print
1418              * process.
1419              */
1420                 for (lf = Lf, print_init(); PrPass < 2; PrPass++) {
1421                     for (i = n = 0; i < Nlproc; i++) {
1422                         Lp = (Nlproc > 1) ? slp[i] : &Lproc[i];
1423                         if (Lp->pss) {
1424                             if (print_proc())
1425                                 n++;
1426                         }
1427                         if (RptTm && PrPass)
1428                             (void) free_lproc(Lp);
1429                     }
1430                 }
1431                 Lf = lf;
1432             }
1433         /*
1434          * If a repeat time is set, sleep for the specified time.
1435          *
1436          * If conditional repeat mode is in effect, see if it's time to exit.
1437          */
1438             if (RptTm) {
1439
1440 #if     defined(HASEPTOPTS)
1441                 (void) clear_pinfo();
1442
1443 # if    defined(HASUXSOCKEPT)
1444                 (void) clear_uxsinfo();
1445 # endif /* defined(HASUXSOCKEPT) */
1446
1447 # if    defined(HASPTYEPT)
1448                 (void) clear_ptyinfo();
1449 # endif /* defined(HASPTYEPT) */
1450 #endif  /* defined(HASEPTOPTS) */
1451
1452                 if (rc) {
1453                     if (!n)
1454                         break;
1455                     else
1456                         ev = 0;
1457                 }
1458
1459 #if     defined(HAS_STRFTIME)
1460                 if (fmt && fmtr) {
1461
1462                 /*
1463                  * Format the marker line.
1464                  */
1465                     (void) util_strftime(fmtr, fmtl - 1, fmt);
1466                     fmtr[fmtl - 1] = '\0';
1467                 }
1468 #endif  /* defined(HAS_STRFTIME) */
1469
1470                 if (Ffield) {
1471                     putchar(LSOF_FID_MARK);
1472
1473 #if     defined(HAS_STRFTIME)
1474                     if (fmtr)
1475                         (void) printf("%s", fmtr);
1476 #endif  /* defined(HAS_STRFTIME) */
1477
1478                     putchar(Terminator);
1479                     if (Terminator != '\n')
1480                         putchar('\n');
1481                 } else {
1482
1483 #if     defined(HAS_STRFTIME)
1484                     if (fmtr)
1485                         cp = fmtr;
1486                     else
1487 #endif  /* defined(HAS_STRFTIME) */
1488
1489                         cp = "=======";
1490                     puts(cp);
1491                 }
1492                 (void) fflush(stdout);
1493                 (void) childx();
1494                 (void) sleep(RptTm);
1495                 Hdr = Nlproc = 0;
1496                 CkPasswd = 1;
1497             }
1498         } while (RptTm);
1499 /*
1500  * See if all requested information was displayed.  Return zero if it
1501  * was; one, if not.  If -V was specified, report what was not displayed.
1502  */
1503         (void) childx();
1504         rv = 0;
1505         for (str = Cmdl; str; str = str->next) {
1506
1507         /*
1508          * Check command specifications.
1509          */
1510             if (str->f)
1511                 continue;
1512             rv = 1;
1513             if (Fverbose) {
1514                 (void) printf("%s: command not located: ", Pn);
1515                 safestrprt(str->str, stdout, 1);
1516             }
1517         }
1518         for (i = 0; i < NCmdRxU; i++) {
1519         
1520         /*
1521          * Check command regular expressions.
1522          */
1523             if (CmdRx[i].mc)
1524                 continue;
1525             rv = 1;
1526             if (Fverbose) {
1527                 (void) printf("%s: no command found for regex: ", Pn);
1528                 safestrprt(CmdRx[i].exp, stdout, 1);
1529             }
1530         }
1531         for (sfp = Sfile; sfp; sfp = sfp->next) {
1532
1533         /*
1534          * Check file specifications.
1535          */
1536             if (sfp->f)
1537                 continue;
1538             rv = 1;
1539             if (Fverbose) {
1540                 (void) printf("%s: no file%s use located: ", Pn,
1541                     sfp->type ? "" : " system");
1542                 safestrprt(sfp->aname, stdout, 1);
1543             }
1544         }
1545
1546 #if     defined(HASPROCFS)
1547         /*
1548          * Report on proc file system search results.
1549          */
1550             if (Procsrch && !Procfind) {
1551                 rv = 1;
1552                 if (Fverbose) {
1553                     (void) printf("%s: no file system use located: ", Pn);
1554                     safestrprt(Mtprocfs ? Mtprocfs->dir : HASPROCFS, stdout, 1);
1555                 }
1556             }
1557             {
1558                 struct procfsid *pfi;
1559
1560                 for (pfi = Procfsid; pfi; pfi = pfi->next) {
1561                     if (!pfi->f) {
1562                         rv = 1;
1563                         if (Fverbose) {
1564                             (void) printf("%s: no file use located: ", Pn);
1565                             safestrprt(pfi->nm, stdout, 1);
1566                         }
1567                     }
1568                 }
1569             }
1570 #endif  /* defined(HASPROCFS) */
1571
1572         if ((np = Nwad)) {
1573
1574         /*
1575          * Check Internet address specifications.
1576          *
1577          * If any Internet address derived from the same argument was found,
1578          * consider all derivations found.  If no derivation from the same
1579          * argument was found, report only the first failure.
1580          *
1581          */
1582             for (; np; np = np->next) {
1583                 if (!(cp = np->arg))
1584                     continue;
1585                 for (npn = np->next; npn; npn = npn->next) {
1586                     if (!npn->arg)
1587                         continue;
1588                     if (!strcmp(cp, npn->arg)) {
1589
1590                     /*
1591                      * If either of the duplicate specifications was found,
1592                      * mark them both found.  If neither was found, mark all
1593                      * but the first one found.
1594                      */
1595                         if (np->f)
1596                             npn->f = np->f;
1597                         else if (npn->f)
1598                             np->f = npn->f;
1599                         else
1600                             npn->f = 1;
1601                     }
1602                 }
1603             }
1604             for (np = Nwad; np; np = np->next) {
1605                 if (!np->f && (cp = np->arg)) {
1606                     rv = 1;
1607                     if (Fverbose) {
1608                         (void) printf("%s: Internet address not located: ", Pn);
1609                         safestrprt(cp ? cp : "(unknown)", stdout, 1);
1610                     }
1611                 }
1612             }
1613         }
1614         if (Fnet && Fnet < 2) {
1615
1616         /*
1617          * Report no Internet files located.
1618          */
1619             rv = 1;
1620             if (Fverbose)
1621                 (void) printf("%s: no Internet files located\n", Pn);
1622         }
1623
1624 #if     defined(HASTCPUDPSTATE)
1625         if (TcpStIn) {
1626
1627         /*
1628          * Check for included TCP states not located.
1629          */
1630             for (i = 0; i < TcpNstates; i++) {
1631                 if (TcpStI[i] == 1) {
1632                     rv = 1;
1633                     if (Fverbose)
1634                         (void) printf("%s: TCP state not located: %s\n",
1635                             Pn, TcpSt[i]);
1636                 }
1637             }
1638         }
1639         if (UdpStIn) {
1640
1641         /*
1642          * Check for included UDP states not located.
1643          */
1644             for (i = 0; i < UdpNstates; i++) {
1645                 if (UdpStI[i] == 1) {
1646                     rv = 1;
1647                     if (Fverbose)
1648                         (void) printf("%s: UDP state not located: %s\n",
1649                             Pn, UdpSt[i]);
1650                 }
1651             }
1652         }
1653 #endif  /* defined(HASTCPUDPSTATE) */
1654
1655         if (Fnfs && Fnfs < 2) {
1656
1657         /*
1658          * Report no NFS files located.
1659          */
1660             rv = 1;
1661             if (Fverbose)
1662                 (void) printf("%s: no NFS files located\n", Pn);
1663         }
1664         for (i = 0; i < Npid; i++) {
1665
1666         /*
1667          * Check inclusionary process ID specifications.
1668          */
1669             if (Spid[i].f || Spid[i].x)
1670                 continue;
1671             rv = 1;
1672             if (Fverbose)
1673                 (void) printf("%s: process ID not located: %d\n",
1674                     Pn, Spid[i].i);
1675         }
1676
1677 #if     defined(HASTASKS)
1678         if (Ftask && Ftask < 2) {
1679
1680         /*
1681          * Report no tasks located.
1682          */
1683             rv = 1;
1684             if (Fverbose)
1685                 (void) printf("%s: no tasks located\n", Pn);
1686         }
1687 #endif  /* defined(HASTASKS) */
1688
1689 #if     defined(HASZONES)
1690         if (ZoneArg) {
1691
1692         /*
1693          * Check zone argument results.
1694          */
1695             for (i = 0; i < HASHZONE; i++) {
1696                 for (zp = ZoneArg[i]; zp; zp = zp->next) {
1697                     if (!zp->f) {
1698                         rv = 1;
1699                         if (Fverbose) {
1700                             (void) printf("%s: zone not located: ", Pn);
1701                             safestrprt(zp->zn, stdout, 1);
1702                         }
1703                     }
1704                 }
1705             }
1706         }
1707 #endif  /* defined(HASZONES) */
1708  
1709 #if     defined(HASSELINUX)
1710         if (CntxArg) {
1711
1712         /*
1713          * Check context argument results.
1714          */
1715             for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) {
1716                 if (!cntxp->f) {
1717                     rv = 1;
1718                     if (Fverbose) {
1719                         (void) printf("%s: context not located: ", Pn);
1720                         safestrprt(cntxp->cntx, stdout, 1);
1721                     }
1722                 }
1723             }
1724         }
1725 #endif  /* defined(HASSELINUX) */
1726
1727         for (i = 0; i < Npgid; i++) {
1728
1729         /*
1730          * Check inclusionary process group ID specifications.
1731          */
1732             if (Spgid[i].f || Spgid[i].x)
1733                 continue;
1734             rv = 1;
1735             if (Fverbose)
1736                 (void) printf("%s: process group ID not located: %d\n",
1737                     Pn, Spgid[i].i);
1738         }
1739         for (i = 0; i < Nuid; i++) {
1740
1741         /*
1742          * Check inclusionary user ID specifications.
1743          */
1744             if (Suid[i].excl || Suid[i].f)
1745                 continue;
1746             rv = 1;
1747             if (Fverbose) {
1748                 if (Suid[i].lnm) {
1749                     (void) printf("%s: login name (UID %lu) not located: ",
1750                         Pn, (unsigned long)Suid[i].uid);
1751                     safestrprt(Suid[i].lnm, stdout, 1);
1752                 } else
1753                     (void) printf("%s: user ID not located: %lu\n", Pn,
1754                         (unsigned long)Suid[i].uid);
1755             }
1756         }
1757         if (!rv && rc)
1758             rv = ev;
1759         if (!rv && ErrStat)
1760             rv = 1;
1761         Exit(rv);
1762         return(rv);             /* to make code analyzers happy */
1763 }
1764
1765
1766 /*
1767  * GetOpt() -- Local get option
1768  *
1769  * Liberally adapted from the public domain AT&T getopt() source,
1770  * distributed at the 1985 UNIFORM conference in Dallas
1771  *
1772  * The modifications allow `?' to be an option character and allow
1773  * the caller to decide that an option that may be followed by a
1774  * value doesn't have one -- e.g., has a default instead.
1775  */
1776
1777 static int
1778 GetOpt(ct, opt, rules, err)
1779         int ct;                         /* option count */
1780         char *opt[];                    /* options */
1781         char *rules;                    /* option rules */
1782         int *err;                       /* error return */
1783 {
1784         register int c;
1785         register char *cp = (char *)NULL;
1786
1787         if (GOx2 == 0) {
1788
1789         /*
1790          * Move to a new entry of the option array.
1791          *
1792          * EOF if:
1793          *
1794          *      Option list has been exhausted;
1795          *      Next option doesn't start with `-' or `+';
1796          *      Next option has nothing but `-' or `+';
1797          *      Next option is ``--'' or ``++''.
1798          */
1799             if (GOx1 >= ct
1800             ||  (opt[GOx1][0] != '-' && opt[GOx1][0] != '+')
1801             ||  !opt[GOx1][1])
1802                  return(EOF);
1803             if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) {
1804                 GOx1++;
1805                 return(EOF);
1806             }
1807             GOp = opt[GOx1][0];
1808             GOx2 = 1;
1809         }
1810 /*
1811  * Flag `:' option character as an error.
1812  *
1813  * Check for a rule on this option character.
1814  */
1815         *err = 0;
1816         if ((c = opt[GOx1][GOx2]) == ':') {
1817             (void) fprintf(stderr,
1818                 "%s: colon is an illegal option character.\n", Pn);
1819             *err = 1;
1820         } else if (!(cp = strchr(rules, c))) {
1821             (void) fprintf(stderr, "%s: illegal option character: %c\n", Pn, c);
1822             *err = 2;
1823         }
1824         if (*err) {
1825
1826         /*
1827          * An error was detected.
1828          *
1829          * Advance to the next option character.
1830          *
1831          * Return the character causing the error.
1832          */
1833             if (opt[GOx1][++GOx2] == '\0') {
1834                 GOx1++;
1835                 GOx2 = 0;
1836             }
1837             return(c);
1838         }
1839         if (*(cp + 1) == ':') {
1840
1841         /*
1842          * The option may have a following value.  The caller decides
1843          * if it does.
1844          *
1845          * Save the position of the possible value in case the caller
1846          * decides it does not belong to the option and wants it
1847          * reconsidered as an option character.  The caller does that
1848          * with:
1849          *              GOx1 = GObk[0]; GOx2 = GObk[1];
1850          *
1851          * Don't indicate that an option of ``--'' is a possible value.
1852          *
1853          * Finally, on the assumption that the caller will decide that
1854          * the possible value belongs to the option, position to the
1855          * option following the possible value, so that the next call
1856          * to GetOpt() will find it.
1857          */
1858             if(opt[GOx1][GOx2 + 1] != '\0') {
1859                 GObk[0] = GOx1;
1860                 GObk[1] = ++GOx2;
1861                 GOv = &opt[GOx1++][GOx2];
1862             } else if (++GOx1 >= ct)
1863                 GOv = (char *)NULL;
1864             else {
1865                 GObk[0] = GOx1;
1866                 GObk[1] = 0;
1867                 GOv = opt[GOx1];
1868                 if (strcmp(GOv, "--") == 0)
1869                     GOv = (char *)NULL;
1870                 else
1871                     GOx1++;
1872             }
1873             GOx2 = 0;
1874         } else {
1875
1876         /*
1877          * The option character stands alone with no following value.
1878          *
1879          * Advance to the next option character.
1880          */
1881             if (opt[GOx1][++GOx2] == '\0') {
1882                 GOx2 = 0;
1883                 GOx1++;
1884             }
1885             GOv = (char *)NULL;
1886         }
1887 /*
1888  * Return the option character.
1889  */
1890         return(c);
1891 }
1892
1893
1894 /*
1895  * sv_fmt_str() - save format string
1896  */
1897
1898 static char *
1899 sv_fmt_str(f)
1900         char *f;                        /* format string */
1901 {
1902         char *cp;
1903         MALLOC_S l;
1904
1905         l = (MALLOC_S)(strlen(f) + 1);
1906         if (!(cp = (char *)malloc(l))) {
1907             (void) fprintf(stderr,
1908                 "%s: can't allocate %d bytes for format: %s\n", Pn, (int)l, f);
1909             Exit(1);
1910         }
1911         (void) snpf(cp, l, "%s", f);
1912         return(cp);
1913 }