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
35static char copyright[] =
36"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
37static 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
48static int GObk[] = { 1, 1 };		/* option backspace values */
49static char GOp;			/* option prefix -- '+' or '-' */
50static char *GOv = (char *)NULL;	/* option `:' value pointer */
51static int GOx1 = 1;			/* first opt[][] index */
52static 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
63int
64main(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
1629static int
1630GetOpt(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
1750static char *
1751sv_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}
1766