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