1/*
2 * arg.c - common argument processing support functions for lsof
3 */
4
5
6/*
7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907.  All rights reserved.
9 *
10 * Written by Victor A. Abell
11 *
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
14 *
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
18 *
19 * 1. Neither the authors nor Purdue University are responsible for any
20 *    consequences of the use of this software.
21 *
22 * 2. The origin of this software must not be misrepresented, either by
23 *    explicit claim or by omission.  Credit to the authors and Purdue
24 *    University must appear in documentation and sources.
25 *
26 * 3. Altered versions must be plainly marked as such, and must not be
27 *    misrepresented as being the original software.
28 *
29 * 4. This notice may not be removed or altered.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35static char *rcsid = "$Id: arg.c,v 1.51 2012/04/10 16:30:06 abe Exp $";
36#endif
37
38
39#include "lsof.h"
40
41
42/*
43 * Local definitions
44 */
45
46#define	CMDRXINCR	32		/* CmdRx[] allocation increment */
47
48
49/*
50 * Local static variables
51 */
52
53static int NCmdRxA = 0;			/* space allocated to CmdRx[] */
54
55
56/*
57 * Local function prototypes
58 */
59
60_PROTOTYPE(static int ckfd_range,(char *first, char *dash, char *last, int *lo, int *hi));
61_PROTOTYPE(static int enter_fd_lst,(char *nm, int lo, int hi, int excl));
62_PROTOTYPE(static int enter_nwad,(struct nwad *n, int sp, int ep, char *s, struct hostent *he));
63_PROTOTYPE(static struct hostent *lkup_hostnm,(char *hn, struct nwad *n));
64_PROTOTYPE(static char *isIPv4addr,(char *hn, unsigned char *a, int al));
65
66
67/*
68 * ckfd_range() - check fd range
69 */
70
71static int
72ckfd_range(first, dash, last, lo, hi)
73	char *first;			/* starting character */
74	char *dash;			/* '-' location */
75	char *last;			/* '\0' location */
76	int *lo;			/* returned low value */
77	int *hi;			/* returned high value */
78{
79	char *cp;
80/*
81 * See if the range character pointers make sense.
82 */
83	if (first >= dash || dash >= last) {
84	    (void) fprintf(stderr, "%s: illegal FD range for -d: ", Pn);
85	    safestrprt(first, stderr, 1);
86	    return(1);
87	}
88/*
89 * Assemble and check the high and low values.
90 */
91	for (cp = first, *lo = 0; *cp && cp < dash; cp++) {
92	    if (!isdigit((unsigned char)*cp)) {
93
94FD_range_nondigit:
95
96		(void) fprintf(stderr, "%s: non-digit in -d FD range: ", Pn);
97		safestrprt(first, stderr, 1);
98		return(1);
99	    }
100	    *lo = (*lo * 10) + (int)(*cp - '0');
101	}
102	for (cp = dash+1, *hi = 0; *cp && cp < last; cp++) {
103	    if (!isdigit((unsigned char)*cp))
104		goto FD_range_nondigit;
105	    *hi = (*hi * 10) + (int)(*cp - '0');
106	}
107	if (*lo >= *hi) {
108	    (void) fprintf(stderr, "%s: -d FD range's low >= its high: ", Pn);
109	    safestrprt(first, stderr, 1);
110	    return(1);
111	}
112	return(0);
113}
114
115
116/*
117 * ck_file_arg() - check file arguments
118 */
119
120int
121ck_file_arg(i, ac, av, fv, rs, sbp)
122	int i;			/* first file argument index */
123	int ac;			/* argument count */
124	char *av[];		/* argument vector */
125	int fv;			/* Ffilesys value (real or temporary) */
126	int rs;			/* Readlink() status if argument count == 1:
127				 *	0 = undone; 1 = done */
128	struct stat *sbp;	/* if non-NULL, pointer to stat(2) buffer
129				 * when argument count == 1 */
130{
131	char *ap, *fnm, *fsnm, *path;
132	short err = 0;
133	int fsm, ftype, j, k;
134	MALLOC_S l;
135	struct mounts *mp;
136	static struct mounts **mmp = (struct mounts **)NULL;
137	int mx, nm;
138	static int nma = 0;
139	struct stat sb;
140	struct sfile *sfp;
141	short ss = 0;
142
143#if	defined(CKFA_EXPDEV)
144	dev_t dev, rdev;
145#endif	/* defined(CKFA_EXPDEV) */
146
147#if	defined(HASPROCFS)
148	unsigned char ad, an;
149	int pfsnl = -1;
150	pid_t pid;
151	struct procfsid *pfi;
152#endif	/* defined(HASPROCFS) */
153
154/*
155 * Loop through arguments.
156 */
157	for (; i < ac; i++) {
158	    if (rs && (ac == 1) && (i == 0))
159		path = av[i];
160	    else {
161		if (!(path = Readlink(av[i]))) {
162		    ErrStat = 1;
163		    continue;
164		}
165	    }
166	/*
167	 * Remove terminating `/' characters from paths longer than one.
168	 */
169	    j = k = strlen(path);
170	    while ((k > 1) && (path[k-1] == '/')) {
171		k--;
172	    }
173	    if (k < j) {
174		if (path != av[i])
175		    path[k] = '\0';
176		else {
177		    if (!(ap = (char *)malloc((MALLOC_S)(k + 1)))) {
178			(void) fprintf(stderr, "%s: no space for copy of %s\n",
179			    Pn, path);
180			Exit(1);
181		    }
182		    (void) strncpy(ap, path, k);
183		    ap[k] = '\0';
184		    path = ap;
185		}
186	    }
187	/*
188	 * Check for file system argument.
189	 */
190	    for (ftype = 1, mp = readmnt(), nm = 0;
191		 (fv != 1) && mp;
192		 mp = mp->next)
193	    {
194		fsm = 0;
195		if (strcmp(mp->dir, path) == 0)
196		    fsm++;
197		else if (fv == 2 || (mp->fs_mode & S_IFMT) == S_IFBLK) {
198		    if (mp->fsnmres && strcmp(mp->fsnmres, path) == 0)
199			fsm++;
200		}
201		if (!fsm)
202		    continue;
203		ftype = 0;
204	    /*
205	     * Skip duplicates.
206	     */
207		for (mx = 0; mx < nm; mx++) {
208		    if (strcmp(mp->dir, mmp[mx]->dir) == 0
209		    &&  mp->dev == mmp[mx]->dev
210		    &&  mp->rdev == mmp[mx]->rdev
211		    &&  mp->inode == mmp[mx]->inode)
212			break;
213		}
214		if (mx < nm)
215		    continue;
216	    /*
217	     * Allocate space for and save another mount point match and
218	     * the type of match -- directory name (mounted) or file system
219	     * name (mounted-on).
220	     */
221		if (nm >= nma) {
222		    nma += 5;
223		    l = (MALLOC_S)(nma * sizeof(struct mounts *));
224		    if (mmp)
225			mmp = (struct mounts **)realloc((MALLOC_P *)mmp, l);
226		    else
227			mmp = (struct mounts **)malloc(l);
228		    if (!mmp) {
229			(void) fprintf(stderr,
230			    "%s: no space for mount pointers\n", Pn);
231			Exit(1);
232		    }
233		}
234		mmp[nm++] = mp;
235	    }
236	    if (fv == 2 && nm == 0) {
237		(void) fprintf(stderr, "%s: not a file system: ", Pn);
238		safestrprt(av[i], stderr, 1);
239		ErrStat = 1;
240		continue;
241	    }
242	/*
243	 * Loop through the file system matches.  If there were none, make one
244	 * pass through the loop, using simply the path name.
245	 */
246	    mx = 0;
247	    do {
248
249	    /*
250	     * Allocate an sfile structure and fill in the type and link.
251	     */
252		if (!(sfp = (struct sfile *)malloc(sizeof(struct sfile)))) {
253		    (void) fprintf(stderr, "%s: no space for files\n", Pn);
254		    Exit(1);
255		}
256		sfp->next = Sfile;
257		Sfile = sfp;
258		sfp->f = 0;
259		if ((sfp->type = ftype)) {
260
261		/*
262		 * For a non-file system path, use the path as the file name
263		 * and set a NULL file system name.
264		 */
265		    fnm = path;
266		    fsnm = (char *)NULL;
267		/*
268		 * Stat the path to obtain its characteristics.
269		 */
270		    if (sbp && (ac == 1))
271			sb = *sbp;
272		    else {
273			if (statsafely(fnm, &sb) != 0) {
274			    int en = errno;
275
276			    (void) fprintf(stderr, "%s: status error on ", Pn);
277			    safestrprt(fnm, stderr, 0);
278			    (void) fprintf(stderr, ": %s\n", strerror(en));
279			    Sfile = sfp->next;
280			    (void) free((FREE_P *)sfp);
281			    ErrStat = 1;
282			    continue;
283			}
284
285#if	defined(HASSPECDEVD)
286			(void) HASSPECDEVD(fnm, &sb);
287#endif	/* defined(HASSPECDEVD) */
288
289		    }
290		    sfp->i = (INODETYPE)sb.st_ino;
291		    sfp->mode = sb.st_mode & S_IFMT;
292
293#if	defined(CKFA_EXPDEV)
294		/*
295		 * Expand device numbers before saving, so that they match the
296		 * already-expanded local mount info table device numbers.
297		 * (This is an EP/IX 2.1.1 and above artifact.)
298		 */
299		    sfp->dev = expdev(sb.st_dev);
300		    sfp->rdev = expdev(sb.st_rdev);
301#else	/* !defined(CKFA_EXPDEV) */
302		    sfp->dev = sb.st_dev;
303		    sfp->rdev = sb.st_rdev;
304#endif	/* defined(CKFA_EXPDEV) */
305
306#if	defined(CKFA_MPXCHAN)
307		/*
308		 * Save a (possible) multiplexed channel number.  (This is an
309		 * AIX artifact.)
310		 */
311		    sfp->ch = getchan(path);
312#endif	/* defined(CKFA_MPXCHAN) */
313
314		} else {
315
316#if	defined(SAVE_MP_IN_SFILE)
317		    sfp->mp = mp = mmp[mx++];
318#else	/* !defined(SAVE_MP_IN_SFILE) */
319		    mp = mmp[mx++];
320#endif	/* defined(SAVE_MP_IN_SFILE) */
321
322		    ss++;
323
324#if	defined(HASPROCFS)
325		/*
326		 * If this is a /proc file system, set the search flag and
327		 * abandon the sfile entry.
328		 */
329		    if (mp == Mtprocfs) {
330			Sfile = sfp->next;
331			(void) free((FREE_P *)sfp);
332			Procsrch = 1;
333			continue;
334		    }
335#endif	/* defined(HASPROCFS) */
336
337		/*
338		 * Derive file name and file system name for a mount point.
339		 *
340		 * Save the device numbers, inode number, and modes.
341		 */
342		    fnm = mp->dir;
343		    fsnm = mp->fsname;
344		    sfp->dev = mp->dev;
345		    sfp->rdev = mp->rdev;
346		    sfp->i = mp->inode;
347		    sfp->mode = mp->mode & S_IFMT;
348		}
349		ss = 1;		/* indicate a "safe" stat() */
350	    /*
351	     * Store the file name and file system name pointers in the sfile
352	     * structure, allocating space as necessary.
353	     */
354		if (!fnm || fnm == path) {
355		    sfp->name = fnm;
356
357#if	defined(HASPROCFS)
358		    an = 0;
359#endif	/* defined(HASPROCFS) */
360
361		} else {
362		    if (!(sfp->name = mkstrcpy(fnm, (MALLOC_S *)NULL))) {
363			(void) fprintf(stderr,
364			    "%s: no space for file name: ", Pn);
365			safestrprt(fnm, stderr, 1);
366			Exit(1);
367		    }
368
369#if	defined(HASPROCFS)
370		    an = 1;
371#endif	/* defined(HASPROCFS) */
372
373		}
374		if (!fsnm || fsnm == path) {
375		    sfp->devnm = fsnm;
376
377#if	defined(HASPROCFS)
378		    ad = 0;
379#endif	/* defined(HASPROCFS) */
380
381		} else {
382		    if (!(sfp->devnm = mkstrcpy(fsnm, (MALLOC_S *)NULL))) {
383			(void) fprintf(stderr,
384			    "%s: no space for file system name: ", Pn);
385			safestrprt(fsnm, stderr, 1);
386			Exit(1);
387		    }
388
389#if	defined(HASPROCFS)
390		    ad = 1;
391#endif	/* defined(HASPROCFS) */
392
393		}
394		if (!(sfp->aname = mkstrcpy(av[i], (MALLOC_S *)NULL))) {
395		    (void) fprintf(stderr,
396			"%s: no space for argument file name: ", Pn);
397			safestrprt(av[i], stderr, 1);
398		    Exit(1);
399		}
400
401#if	defined(HASPROCFS)
402	    /*
403	     * See if this is an individual member of a proc file system.
404	     */
405		if (!Mtprocfs || Procsrch)
406		    continue;
407
408# if	defined(HASFSTYPE) && HASFSTYPE==1
409		if (strcmp(sb.st_fstype, HASPROCFS) != 0)
410		    continue;
411# endif	/* defined(HASFSTYPE) && HASFSTYPE==1 */
412
413		if (pfsnl == -1)
414		    pfsnl = strlen(Mtprocfs->dir);
415		if (!pfsnl)
416		    continue;
417		if (strncmp(Mtprocfs->dir, path, pfsnl) != 0)
418		    continue;
419		if (path[pfsnl] != '/')
420
421# if	defined(HASPINODEN)
422		    pid = 0;
423# else	/* !defined(HASPINODEN) */
424		    continue;
425# endif	/* defined(HASPINODEN) */
426
427		else {
428		    for (j = pfsnl+1; path[j]; j++) {
429			if (!isdigit((unsigned char)path[j]))
430			    break;
431		    }
432		    if (path[j] || (j - pfsnl - 1) < 1
433		    ||  (sfp->mode & S_IFMT) != S_IFREG)
434
435# if	defined(HASPINODEN)
436			pid = 0;
437# else	/* !defined(HASPINODEN) */
438			continue;
439# endif	/* defined(HASPINODEN) */
440
441		    else
442			pid = atoi(&path[pfsnl+1]);
443		}
444		if (!(pfi = (struct procfsid *)malloc((MALLOC_S)
445			     sizeof(struct procfsid))))
446		{
447		    (void) fprintf(stderr, "%s: no space for %s ID: ",
448			Pn, Mtprocfs->dir);
449		    safestrprt(path, stderr, 1);
450		    Exit(1);
451		}
452		pfi->pid = pid;
453		pfi->f = 0;
454		pfi->nm = sfp->aname;
455		pfi->next = Procfsid;
456		Procfsid = pfi;
457
458# if	defined(HASPINODEN)
459		pfi->inode = (INODETYPE)sfp->i;
460# endif	/* defined(HASPINODEN) */
461
462	    /*
463	     * Abandon the Sfile entry, lest it be used in is_file_named().
464	     */
465		Sfile = sfp->next;
466		if (ad)
467		    (void) free((FREE_P *)sfp->devnm);
468		if (an)
469		    (void) free((FREE_P *)sfp->name);
470		(void) free((FREE_P *)sfp);
471#endif	/* defined(HASPROCFS) */
472
473	    } while (mx < nm);
474	}
475	if (!ss)
476	    err = 1;
477	return((int)err);
478}
479
480
481#if	defined(HASDCACHE)
482/*
483 * ctrl_dcache() - enter device cache control
484 */
485
486int
487ctrl_dcache(c)
488	char *c;			/* control string */
489{
490	int rc = 0;
491
492	if (!c) {
493	    (void) fprintf(stderr,
494		"%s: no device cache option control string\n", Pn);
495	    return(1);
496	}
497/*
498 * Decode argument function character.
499 */
500	switch (*c) {
501	case '?':
502	    if (*(c+1) != '\0') {
503		(void) fprintf(stderr, "%s: nothing should follow -D?\n", Pn);
504		return(1);
505	    }
506	    DChelp = 1;
507	    return(0);
508	case 'b':
509	case 'B':
510	    if (Setuidroot
511
512#if	!defined(WILLDROPGID)
513	    ||  Myuid
514#endif	/* !defined(WILLDROPGID) */
515
516	    )
517		rc = 1;
518	    else
519		DCstate = 1;
520	    break;
521	case 'r':
522	case 'R':
523	    if (Setuidroot && *(c+1))
524		rc = 1;
525	    else
526		DCstate = 2;
527	    break;
528	case 'u':
529	case 'U':
530	    if (Setuidroot
531
532#if	!defined(WILLDROPGID)
533	    ||  Myuid
534#endif	/* !defined(WILLDROPGID) */
535
536	    )
537		rc = 1;
538	    else
539		DCstate = 3;
540	    break;
541	case 'i':
542	case 'I':
543	    if (*(c+1) == '\0') {
544		DCstate = 0;
545		return(0);
546	    }
547	    /* fall through */
548	default:
549	    (void) fprintf(stderr, "%s: unknown -D option: ", Pn);
550	    safestrprt(c, stderr, 1);
551	    return(1);
552	}
553	if (rc) {
554	    (void) fprintf(stderr, "%s: -D option restricted to root: ", Pn);
555	    safestrprt(c, stderr, 1);
556	    return(1);
557	}
558/*
559 * Skip to optional path name and save it.
560 */
561	for (c++; *c && (*c == ' ' || *c == '\t'); c++)
562	    ;
563	if (strlen(c)) {
564	    if (!(DCpathArg = mkstrcpy(c, (MALLOC_S *)NULL))) {
565		(void) fprintf(stderr, "%s: no space for -D path: ", Pn);
566		safestrprt(c, stderr, 1);
567		Exit(1);
568	    }
569	}
570	return(0);
571}
572#endif	/* defined(HASDCACHE) */
573
574
575/*
576 * enter_cmd_rx() - enter command regular expression
577 */
578
579int
580enter_cmd_rx(x)
581	char *x;			/* regular expression */
582{
583	int bmod = 0;
584	int bxmod = 0;
585	int i, re;
586	int imod = 0;
587	int xmod = 0;
588	int co = REG_NOSUB|REG_EXTENDED;
589	char reb[256], *xb, *xe, *xm;
590	MALLOC_S xl;
591	char *xp = (char *)NULL;
592/*
593 * Make sure the supplied string starts a regular expression.
594 */
595	if (!*x || (*x != '/')) {
596	    (void) fprintf(stderr, "%s: regexp doesn't begin with '/': ", Pn);
597	    if (x)
598		safestrprt(x, stderr, 1);
599	    return(1);
600	}
601/*
602 * Skip to the end ('/') of the regular expression.
603 */
604	xb = x + 1;
605	for (xe = xb; *xe; xe++) {
606	    if (*xe == '/')
607		break;
608	}
609	if (*xe != '/') {
610	    (void) fprintf(stderr, "%s: regexp doesn't end with '/': ", Pn);
611	    safestrprt(x, stderr, 1);
612	    return(1);
613	}
614/*
615 * Decode any regular expression modifiers.
616 */
617	for (i = 0, xm = xe + 1; *xm; xm++) {
618	    switch(*xm) {
619	    case 'b':			/* This is a basic expression. */
620		if (++bmod > 1) {
621		    if (bmod == 2) {
622			(void) fprintf(stderr,
623			    "%s: b regexp modifier already used: ", Pn);
624			safestrprt(x, stderr, 1);
625		    }
626		    i = 1;
627		} else if (xmod) {
628		    if (++bxmod == 1) {
629			(void) fprintf(stderr,
630			    "%s: b and x regexp modifiers conflict: ", Pn);
631			safestrprt(x, stderr, 1);
632		    }
633		    i = 1;
634		} else
635		    co &= ~REG_EXTENDED;
636		break;
637	    case 'i':			/* Ignore case. */
638		if (++imod > 1) {
639		    if (imod == 2) {
640			(void) fprintf(stderr,
641			    "%s: i regexp modifier already used: ", Pn);
642			safestrprt(x, stderr, 1);
643		    }
644		    i = 1;
645		} else
646		    co |= REG_ICASE;
647		break;
648	    case 'x':			/* This is an extended expression. */
649		if (++xmod > 1) {
650		    if (xmod == 2) {
651			(void) fprintf(stderr,
652			    "%s: x regexp modifier already used: ", Pn);
653			safestrprt(x, stderr, 1);
654		    }
655		    i = 1;
656		} else if (bmod) {
657		    if (++bxmod == 1) {
658			(void) fprintf(stderr,
659			    "%s: b and x regexp modifiers conflict: ", Pn);
660			safestrprt(x, stderr, 1);
661		    }
662		    i = 1;
663		} else
664		    co |= REG_EXTENDED;
665		break;
666	    default:
667		(void) fprintf(stderr, "%s: invalid regexp modifier: %c\n",
668		Pn, (int)*xm);
669		i = 1;
670	    }
671	}
672	if (i)
673	    return(1);
674/*
675 * Allocate space to hold expression and copy it there.
676 */
677	xl = (MALLOC_S)(xe - xb);
678	if (!(xp = (char *)malloc(xl + 1))) {
679	    (void) fprintf(stderr, "%s: no regexp space for: ", Pn);
680	    safestrprt(x, stderr, 1);
681	    Exit(1);
682	}
683	(void) strncpy(xp, xb, xl);
684	xp[(int)xl] = '\0';
685/*
686 * Assign a new CmdRx[] slot for this expression.
687 */
688	if (NCmdRxA >= NCmdRxU) {
689
690	/*
691	 * More CmdRx[] space must be assigned.
692	 */
693	    NCmdRxA += CMDRXINCR;
694	    xl = (MALLOC_S)(NCmdRxA * sizeof(lsof_rx_t));
695	    if (CmdRx)
696		CmdRx = (lsof_rx_t *)realloc((MALLOC_P *)CmdRx, xl);
697	    else
698		CmdRx = (lsof_rx_t *)malloc(xl);
699	    if (!CmdRx) {
700		(void) fprintf(stderr, "%s: no space for regexp: ", Pn);
701		safestrprt(x, stderr, 1);
702		Exit(1);
703	    }
704	}
705	i = NCmdRxU;
706	CmdRx[i].exp = xp;
707/*
708 * Compile the expression.
709 */
710	if ((re = regcomp(&CmdRx[i].cx, xp, co))) {
711	    (void) fprintf(stderr, "%s: regexp error: ", Pn);
712	    safestrprt(x, stderr, 0);
713	    (void) regerror(re, &CmdRx[i].cx, &reb[0], sizeof(reb));
714	    (void) fprintf(stderr, ": %s\n", reb);
715	    if (xp) {
716		(void) free((FREE_P *)xp);
717		xp = (char *)NULL;
718	    }
719	    return(1);
720	}
721/*
722 * Complete the CmdRx[] table entry.
723 */
724	CmdRx[i].mc = 0;
725	CmdRx[i].exp = xp;
726	NCmdRxU++;
727	return(0);
728}
729
730
731#if	defined(HASEOPT)
732/*
733 * enter_efsys() -- enter path of file system whose kernel blocks are to be
734 *		    eliminated
735 */
736
737int
738enter_efsys(e, rdlnk)
739	char *e;			/* file system path */
740	int rdlnk;			/* avoid readlink(2) if non-zero */
741{
742	char *ec;			/* pointer to copy of path */
743	efsys_list_t *ep;		/* file system path list pointer */
744	int i;				/* temporary index */
745	char *path;			/* Readlink() of file system path */
746
747	if (!e || (*e != '/')) {
748	    if (!Fwarn)
749		(void) fprintf(stderr,
750		    "%s: -e not followed by a file system path: \"%s\"\n",
751		    Pn, e);
752	    return(1);
753	}
754	if (!(ec = mkstrcpy(e, (MALLOC_S *)NULL))) {
755	    (void) fprintf(stderr, "%s: no space for -e string: ", Pn);
756	    safestrprt(e, stderr, 1);
757	    Exit(1);
758	}
759	if (rdlnk)
760	    path = ec;
761	else {
762	    if (!(path = Readlink(ec)))
763		return(1);
764	}
765/*
766 * Remove terminating `/' characters from paths longer than one.
767 */
768	for (i = (int)strlen(path); (i > 1) && (path[i - 1] == '/'); i--) {
769	    path[i - 1] = '\0';
770	}
771/*
772 * Enter file system path on list, avoiding duplicates.
773 */
774	for (ep = Efsysl; ep; ep = ep->next) {
775	   if (!strcmp(ep->path, path))
776		return(0);
777	}
778	if (!(ep = (efsys_list_t *)malloc((MALLOC_S)(sizeof(efsys_list_t))))) {
779	   (void) fprintf(stderr, "%s: no space for \"-e %s\" entry\n",
780		Pn, e);
781	   Exit(1);
782	}
783	ep->path = path;
784	ep->pathl = i;
785	ep->rdlnk = rdlnk;
786	ep->mp = (struct mounts *)NULL;
787	ep->next = Efsysl;
788	Efsysl = ep;
789	return(0);
790}
791#endif	/* defined(HASEOPT) */
792
793
794/*
795 * enter_fd() - enter file descriptor list for searching
796 */
797
798int
799enter_fd(f)
800	char *f;			/* file descriptor list pointer */
801{
802	char c, *cp1, *cp2, *dash;
803	int err, excl, hi, lo;
804	char *fc;
805/*
806 *  Check for non-empty list and make a copy.
807 */
808	if (!f || (strlen(f) + 1) < 2) {
809	    (void) fprintf(stderr, "%s: no file descriptor specified\n", Pn);
810	    return(1);
811	}
812	if (!(fc = mkstrcpy(f, (MALLOC_S *)NULL))) {
813	    (void) fprintf(stderr, "%s: no space for fd string: ", Pn);
814	    safestrprt(f, stderr, 1);
815	    Exit(1);
816	}
817/*
818 * Isolate each file descriptor in the comma-separated list, then enter it
819 * in the file descriptor string list.  If a descriptor has the form:
820 *
821 *	[0-9]+-[0-9]+
822 *
823 * treat it as an ascending range of file descriptor numbers.
824 *
825 * Accept a leading '^' as an excusion on match.
826 */
827	for (cp1 = fc, err = 0; *cp1;) {
828	    if (*cp1 == '^') {
829		excl = 1;
830		cp1++;
831	    } else
832		excl = 0;
833	    for (cp2 = cp1, dash = (char *)NULL; *cp2 && *cp2 != ','; cp2++) {
834		if (*cp2 == '-')
835		    dash = cp2;
836	    }
837	    if ((c = *cp2) != '\0')
838		*cp2 = '\0';
839	    if (cp2 > cp1) {
840		if (dash) {
841		    if (ckfd_range(cp1, dash, cp2, &lo, &hi))
842			err = 1;
843		    else {
844			if (enter_fd_lst((char *)NULL, lo, hi, excl))
845			    err = 1;
846		    }
847		} else {
848		    if (enter_fd_lst(cp1, 0, 0, excl))
849			err = 1;
850		}
851	    }
852	    if (c == '\0')
853		break;
854	    cp1 = cp2 + 1;
855	}
856	(void) free((FREE_P *)fc);
857	return(err);
858}
859
860
861/*
862 * enter_fd_lst() - make an entry in the FD list, Fdl
863 */
864
865static int
866enter_fd_lst(nm, lo, hi, excl)
867	char *nm;			/* FD name (none if NULL) */
868	int lo;				/* FD low boundary (if nm NULL) */
869	int hi;				/* FD high boundary (if nm NULL) */
870	int excl;			/* exclusion on match */
871{
872	char buf[256], *cp;
873	int n;
874	struct fd_lst *f, *ft;
875/*
876 * Don't allow a mixture of exclusions and inclusions.
877 */
878	if (FdlTy >= 0) {
879	    if (FdlTy != excl) {
880		if (!Fwarn) {
881
882		/*
883		 * If warnings are enabled, report a mixture.
884		 */
885		    if (nm) {
886			(void) snpf(buf, sizeof(buf) - 1, "%s%s",
887			    excl ? "^" : "", nm);
888		    } else {
889			if (lo != hi) {
890			    (void) snpf(buf, sizeof(buf) - 1, "%s%d-%d",
891				excl ? "^" : "", lo, hi);
892			} else {
893			    (void) snpf(buf, sizeof(buf) - 1, "%s%d",
894				excl ? "^" : "", lo);
895			}
896		    }
897		    buf[sizeof(buf) - 1] = '\0';
898		    (void) fprintf(stderr,
899		        "%s: %s in an %s -d list: %s\n", Pn,
900			excl ? "exclude" : "include",
901			FdlTy ? "exclude" : "include",
902			buf);
903		}
904		return(1);
905	    }
906	}
907/*
908 * Allocate an fd_lst entry.
909 */
910	if (!(f = (struct fd_lst *)malloc((MALLOC_S)sizeof(struct fd_lst)))) {
911	   (void) fprintf(stderr, "%s: no space for FD list entry\n", Pn);
912	   Exit(1);
913	}
914	if (nm) {
915
916	/*
917	 * Process an FD name.  First see if it contains only digits; if it
918	 * does, convert them to an integer and set the low and high
919	 * boundaries to the result.
920	 *
921	 * If the name has a non-digit, store it as a string, and set the
922	 * boundaries to impossible values (i.e., low > high).
923	 */
924	    for (cp = nm, n = 0; *cp; cp++) {
925		if (!isdigit((unsigned char)*cp))
926		    break;
927		n = (n * 10) + (int)(*cp - '0');
928	    }
929	    if (*cp) {
930		if (!(f->nm = mkstrcpy(nm, (MALLOC_S *)NULL))) {
931		    (void) fprintf(stderr,
932			"%s: no space for copy of: %s\n", Pn, nm);
933		    Exit(1);
934		}
935		lo = 1;
936		hi = 0;
937	    } else {
938		f->nm = (char *)NULL;
939		lo = hi = n;
940	    }
941	} else
942	    f->nm = (char *)NULL;
943/*
944 * Skip duplicates.
945 */
946	for (ft = Fdl; ft; ft = ft->next) {
947	    if (f->nm) {
948		if (!ft->nm || strcmp(f->nm, ft->nm))
949		    continue;
950	    } else if ((lo != ft->lo) || (hi != ft->hi))
951		continue;
952	    (void) free((FREE_P *)f);
953	    return(0);
954	}
955/*
956 * Complete the fd_lst entry and link it to the head of the chain.
957 */
958	f->hi = hi;
959	f->lo = lo;
960	f->next = Fdl;
961	Fdl = f;
962	FdlTy = excl;
963	return(0);
964}
965
966
967/*
968 * enter_dir() - enter the files of a directory for searching
969 */
970
971#define	EDDEFFNL	128		/* default file name length */
972
973int
974enter_dir(d, descend)
975	char *d;			/* directory path name pointer */
976	int descend;			/* subdirectory descend flag:
977					 *	0 = don't descend
978					 *	1 = descend */
979{
980	char *av[2];
981	dev_t ddev;
982	DIR *dfp;
983	char *dn = (char *)NULL;
984	MALLOC_S dnl, dnamlen;
985	struct DIRTYPE *dp;
986	int en, sl;
987	int fct = 0;
988	char *fp = (char *)NULL;
989	MALLOC_S fpl = (MALLOC_S)0;
990	MALLOC_S fpli = (MALLOC_S)0;
991	struct stat sb;
992/*
993 * Check the directory path; reduce symbolic links; stat(2) it; make sure it's
994 * really a directory.
995 */
996	if (!d || !*d || *d == '+' || *d == '-') {
997	    if (!Fwarn)
998		(void) fprintf(stderr,
999		    "%s: +d not followed by a directory path\n", Pn);
1000	    return(1);
1001	}
1002	if (!(dn = Readlink(d)))
1003	    return(1);
1004	if (statsafely(dn, &sb)) {
1005	    if (!Fwarn) {
1006		en = errno;
1007		(void) fprintf(stderr, "%s: WARNING: can't stat(", Pn);
1008		safestrprt(dn, stderr, 0);
1009		(void) fprintf(stderr, "): %s\n", strerror(en));
1010	    }
1011	    if (dn && dn != d) {
1012		(void) free((FREE_P *)dn);
1013		dn = (char *)NULL;
1014	    }
1015	    return(1);
1016	}
1017	if ((sb.st_mode & S_IFMT) != S_IFDIR) {
1018	    if (!Fwarn) {
1019		(void) fprintf(stderr, "%s: WARNING: not a directory: ", Pn);
1020		safestrprt(dn, stderr, 1);
1021	    }
1022	    if (dn && dn != d) {
1023		(void) free((FREE_P *)dn);
1024		dn = (char *)NULL;
1025	    }
1026	    return(1);
1027	}
1028
1029#if	defined(HASSPECDEVD)
1030	(void) HASSPECDEVD(dn, &sb);
1031#endif	/* defined(HASSPECDEVD) */
1032
1033	ddev = sb.st_dev;
1034/*
1035 * Stack the directory and record it in Sfile for searching.
1036 */
1037	Dstkn = Dstkx = 0;
1038	Dstk = (char **)NULL;
1039	(void) stkdir(dn);
1040	av[0] = (dn == d) ? mkstrcpy(dn, (MALLOC_S *)NULL) : dn;
1041	av[1] = (char *)NULL;
1042	dn = (char *)NULL;
1043	if (!ck_file_arg(0, 1, av, 1, 1, &sb)) {
1044	    av[0] = (char *)NULL;
1045	    fct++;
1046	}
1047/*
1048 * Unstack the next directory and examine it.
1049 */
1050	while (--Dstkx >= 0) {
1051	    if (!(dn = Dstk[Dstkx]))
1052		continue;
1053	    Dstk[Dstkx] = (char *)NULL;
1054	/*
1055	 * Open the directory path and prepare its name for use with the
1056	 * files in the directory.
1057	 */
1058	    if (!(dfp = OpenDir(dn))) {
1059		if (!Fwarn) {
1060		    if ((en = errno) != ENOENT) {
1061			(void) fprintf(stderr,
1062			    "%s: WARNING: can't opendir(", Pn);
1063			safestrprt(dn, stderr, 0);
1064			(void) fprintf(stderr, "): %s\n", strerror(en));
1065		    }
1066	        }
1067		(void) free((FREE_P *)dn);
1068		dn = (char *)NULL;
1069		continue;
1070	    }
1071	    dnl = strlen(dn);
1072	    sl = ((dnl > 0) && (*(dn + dnl - 1) == '/')) ? 0 : 1;
1073	/*
1074	 * Define space for possible addition to the directory path.
1075	 */
1076	    fpli = (MALLOC_S)(dnl + sl + EDDEFFNL + 1);
1077	    if ((int)fpli > (int)fpl) {
1078		fpl = fpli;
1079		if (!fp)
1080		    fp = (char *)malloc(fpl);
1081		else
1082		    fp = (char *)realloc(fp, fpl);
1083		if (!fp) {
1084		    (void) fprintf(stderr,
1085			"%s: no space for path to entries in directory: %s\n",
1086			Pn, dn);
1087		    Exit(1);
1088		}
1089	    }
1090	    (void) snpf(fp, (size_t)fpl, "%s%s", dn, sl ? "/" : "");
1091	    (void) free((FREE_P *)dn);
1092	    dn = (char *)NULL;
1093	/*
1094	 * Read the contents of the directory.
1095	 */
1096	    for (dp = ReadDir(dfp); dp; dp = ReadDir(dfp)) {
1097
1098	    /*
1099	     * Skip: entries with no inode number;
1100	     *	     entries with a zero length name;
1101	     *	     ".";
1102	     *	     and "..".
1103	     */
1104		if (!dp->d_ino)
1105		    continue;
1106
1107#if     defined(HASDNAMLEN)
1108		dnamlen = (MALLOC_S)dp->d_namlen;
1109#else   /* !defined(HASDNAMLEN) */
1110		dnamlen = (MALLOC_S)strlen(dp->d_name);
1111#endif  /* defined(HASDNAMLEN) */
1112
1113		if (!dnamlen)
1114		    continue;
1115		if (dnamlen <= 2 && dp->d_name[0] == '.') {
1116		    if (dnamlen == 1)
1117			continue;
1118		    if (dp->d_name[1] == '.')
1119			continue;
1120		}
1121	    /*
1122	     * Form the entry's path name.
1123	     */
1124		fpli = (MALLOC_S)(dnamlen - (fpl - dnl - sl - 1));
1125		if ((int)fpli > 0) {
1126		    fpl += fpli;
1127		    if (!(fp = (char *)realloc(fp, fpl))) {
1128			(void) fprintf(stderr, "%s: no space for: ", Pn);
1129			safestrprt(dn, stderr, 0);
1130			putc('/', stderr);
1131			safestrprtn(dp->d_name, dnamlen, stderr, 1);
1132			Exit(1);
1133		    }
1134		}
1135		(void) strncpy(fp + dnl + sl, dp->d_name, dnamlen);
1136		fp[dnl + sl + dnamlen] = '\0';
1137	    /*
1138	     * Lstatsafely() the entry; complain if that fails.
1139	     *
1140	     * Stack entries that represent subdirectories.
1141	     */
1142		if (lstatsafely(fp, &sb)) {
1143		    if ((en = errno) != ENOENT) {
1144			if (!Fwarn) {
1145			    (void) fprintf(stderr,
1146				"%s: WARNING: can't lstat(", Pn);
1147			    safestrprt(fp, stderr, 0);
1148			    (void) fprintf(stderr, "): %s\n", strerror(en));
1149			}
1150		    }
1151		    continue;
1152		}
1153
1154#if	defined(HASSPECDEVD)
1155		(void) HASSPECDEVD(fp, &sb);
1156#endif	/* defined(HASSPECDEVD) */
1157
1158		if (!(Fxover & XO_FILESYS)) {
1159
1160		/*
1161		 * Unless "-x" or "-x f" was specified, don't cross over file
1162		 * system mount points.
1163		 */
1164		    if (sb.st_dev != ddev)
1165			continue;
1166		}
1167		if ((sb.st_mode & S_IFMT) == S_IFLNK) {
1168
1169		/*
1170		 * If this is a symbolic link and "-x_ or "-x l" was specified,
1171		 * Statsafely() the entry and process it.
1172		 *
1173		 * Otherwise skip symbolic links.
1174		 */
1175		    if (Fxover & XO_SYMLINK) {
1176			if (statsafely(fp, &sb)) {
1177			    if ((en = errno) != ENOENT) {
1178				if (!Fwarn) {
1179				    (void) fprintf(stderr,
1180					"%s: WARNING: can't stat(", Pn);
1181				    safestrprt(fp, stderr, 0);
1182				    (void) fprintf(stderr,
1183					") symbolc link: %s\n", strerror(en));
1184				}
1185			    }
1186			    continue;
1187		        }
1188		    } else
1189			continue;
1190		}
1191		if (av[0]) {
1192		    (void) free((FREE_P *)av[0]);
1193		    av[0] = (char *)NULL;
1194		}
1195		av[0] = mkstrcpy(fp, (MALLOC_S *)NULL);
1196		if ((sb.st_mode & S_IFMT) == S_IFDIR && descend)
1197
1198		/*
1199		 * Stack a subdirectory according to the descend argument.
1200		 */
1201		    stkdir(av[0]);
1202	    /*
1203	     * Use ck_file_arg() to record the entry for searching.  Force it
1204	     * to consider the entry a file, not a file system.
1205	     */
1206		if (!ck_file_arg(0, 1, av, 1, 1, &sb)) {
1207		    av[0] = (char *)NULL;
1208		    fct++;
1209		}
1210	    }
1211	    (void) CloseDir(dfp);
1212	    if (dn && dn != d) {
1213		(void) free((FREE_P *)dn);
1214		dn = (char *)NULL;
1215	    }
1216	}
1217/*
1218 * Free malloc()'d space.
1219 */
1220	if (dn && dn != d) {
1221	    (void) free((FREE_P *)dn);
1222	    dn = (char *)NULL;
1223	}
1224	if (av[0] && av[0] != fp) {
1225	    (void) free((FREE_P *)av[0]);
1226	    av[0] = (char *)NULL;
1227	}
1228	if (fp) {
1229	    (void) free((FREE_P *)fp);
1230	    fp = (char *)NULL;
1231	}
1232	if (Dstk) {
1233	    (void) free((FREE_P *)Dstk);
1234	    Dstk = (char **)NULL;
1235	}
1236	if (!fct) {
1237
1238	/*
1239	 * Warn if no files were recorded for searching.
1240	 */
1241	    if (!Fwarn) {
1242		(void) fprintf(stderr,
1243		    "%s: WARNING: no files found in directory: ", Pn);
1244		safestrprt(d, stderr, 1);
1245	    }
1246	    return(1);
1247	}
1248	return(0);
1249}
1250
1251
1252/*
1253 * enter_id() - enter PGID or PID for searching
1254 */
1255
1256int
1257enter_id(ty, p)
1258	enum IDType ty;			/* type: PGID or PID */
1259	char *p;			/* process group ID string pointer */
1260{
1261	char *cp;
1262	int err, i, id, j, mx, n, ni, nx, x;
1263	struct int_lst *s;
1264
1265	if (!p) {
1266	    (void) fprintf(stderr, "%s: no process%s ID specified\n",
1267		Pn, (ty == PGID) ? " group" : "");
1268	    return(1);
1269	}
1270/*
1271 * Set up variables for the type of ID.
1272 */
1273	switch (ty) {
1274	case PGID:
1275	    mx = Mxpgid;
1276	    n = Npgid;
1277	    ni = Npgidi;
1278	    nx = Npgidx;
1279	    s = Spgid;
1280	    break;
1281	case PID:
1282	    mx = Mxpid;
1283	    n = Npid;
1284	    ni = Npidi;
1285	    nx = Npidx;
1286	    s = Spid;
1287	    break;
1288	default:
1289	    (void) fprintf(stderr, "%s: enter_id \"", Pn);
1290	    safestrprt(p, stderr, 0);
1291	    (void) fprintf(stderr, "\", invalid type: %d\n", ty);
1292	    Exit(1);
1293	}
1294/*
1295 * Convert and store the ID.
1296 */
1297	for (cp = p, err = 0; *cp;) {
1298
1299	/*
1300	 * Assemble ID.
1301	 */
1302	    for (i = id = x = 0; *cp && *cp != ','; cp++) {
1303		if (!i) {
1304		    i = 1;
1305		    if (*cp == '^') {
1306			x = 1;
1307			continue;
1308		    }
1309		}
1310
1311#if	defined(__STDC__)
1312		if (!isdigit((unsigned char)*cp))
1313#else	/* !defined(__STDC__) */
1314		if (!isascii(*cp) || ! isdigit((unsigned char)*cp))
1315#endif	/* __STDC__ */
1316
1317		{
1318		    (void) fprintf(stderr, "%s: illegal process%s ID: ",
1319			Pn, (ty == PGID) ? " group" : "");
1320		    safestrprt(p, stderr, 1);
1321		    return(1);
1322		}
1323		id = (id * 10) + *cp - '0';
1324	    }
1325	    if (*cp)
1326		cp++;
1327	/*
1328	 * Avoid entering duplicates and conflicts.
1329	 */
1330	    for (i = j = 0; i < n; i++) {
1331		if (id == s[i].i) {
1332		    if (x == s[i].x) {
1333			j = 1;
1334			continue;
1335		    }
1336		    (void) fprintf(stderr,
1337			"%s: P%sID %d has been included and excluded.\n",
1338			Pn,
1339			(ty == PGID) ? "G" : "",
1340			id);
1341		    err = j = 1;
1342		    break;
1343		}
1344	    }
1345	    if (j)
1346		continue;
1347	/*
1348	 * Allocate table table space.
1349	 */
1350	    if (n >= mx) {
1351		mx += IDINCR;
1352		if (!s)
1353		    s = (struct int_lst *)malloc(
1354			(MALLOC_S)(sizeof(struct int_lst) * mx));
1355		else
1356		    s = (struct int_lst *)realloc((MALLOC_P *)s,
1357			(MALLOC_S)(sizeof(struct int_lst) * mx));
1358		if (!s) {
1359		    (void) fprintf(stderr, "%s: no space for %d process%s IDs",
1360			Pn, mx, (ty == PGID) ? " group" : "");
1361		    Exit(1);
1362		}
1363	    }
1364	    s[n].f = 0;
1365	    s[n].i = id;
1366	    s[n++].x = x;
1367	    if (x)
1368		nx++;
1369	    else
1370		ni++;
1371	}
1372/*
1373 * Save variables for the type of ID.
1374 */
1375	if (ty == PGID) {
1376	    Mxpgid = mx;
1377	    Npgid = n;
1378	    Npgidi = ni;
1379	    Npgidx = nx;
1380	    Spgid = s;
1381	} else {
1382	    Mxpid = mx;
1383	    Npid = Npuns = n;
1384	    Npidi = ni;
1385	    Npidx = nx;
1386	    Spid = s;
1387	}
1388	return(err);
1389}
1390
1391
1392/*
1393 * enter_network_address() - enter Internet address for searching
1394 */
1395
1396int
1397enter_network_address(na)
1398	char *na;			/* Internet address string pointer */
1399{
1400	int ae, i, pr;
1401	int ep = -1;
1402	int ft = 0;
1403	struct hostent *he = (struct hostent *)NULL;
1404	char *hn = (char *)NULL;
1405	MALLOC_S l;
1406	struct nwad n;
1407	char *p, *wa;
1408	int pt = 0;
1409	int pu = 0;
1410	struct servent *se, *se1;
1411	char *sn = (char *)NULL;
1412	int sp = -1;
1413	MALLOC_S snl = 0;
1414
1415#if	defined(HASIPv6)
1416	char *cp;
1417#endif	/* defined(HASIPv6) */
1418
1419	if (!na) {
1420	    (void) fprintf(stderr, "%s: no network address specified\n", Pn);
1421	    return(1);
1422	}
1423	zeromem((char *)&n, sizeof(n));
1424	wa = na;
1425/*
1426 * Process an IP version type specification, IPv4 or IPv6, optionally followed
1427 * by a '@' and a host name or Internet address, or a ':' and a service name or
1428 * port number.
1429 */
1430	if ((*wa == '4') || (*wa == '6')) {
1431	    if (*wa == '4')
1432		ft = 4;
1433	    else if (*wa == '6') {
1434
1435#if	defined(HASIPv6)
1436		ft = 6;
1437#else	/* !defined(HASIPv6) */
1438		(void) fprintf(stderr, "%s: IPv6 not supported: -i ", Pn);
1439		safestrprt(na, stderr, 1);
1440		goto nwad_exit;
1441#endif	/* defined(HASIPv6) */
1442
1443	    }
1444	    wa++;
1445	    if (!*wa) {
1446
1447	    /*
1448	     * If nothing follows 4 or 6, then all network files of the
1449	     * specified IP version are selected.  Sequential -i, -i4, and
1450	     * -i6 specifications interact logically -- e.g., -i[46] followed
1451	     * by -i[64] is the same as -i.
1452	     */
1453		if (!Fnet) {
1454		    Fnet = 1;
1455		    FnetTy = ft;
1456		} else {
1457		    if (FnetTy) {
1458			if (FnetTy != ft)
1459			    FnetTy = 0;
1460		    } else
1461			FnetTy = ft;
1462		}
1463		return(0);
1464	    }
1465	} else if (Fnet)
1466	    ft = FnetTy;
1467/*
1468 * If an IP version has been specified, use it to set the address family.
1469 */
1470	switch (ft) {
1471	case 4:
1472	    n.af = AF_INET;
1473	    break;
1474
1475#if	defined(HASIPv6)
1476	case 6:
1477	    n.af = AF_INET6;
1478	    break;
1479#endif	/* defined(HASIPv6) */
1480
1481	}
1482/*
1483 * Process protocol name, optionally followed by a '@' and a host name or
1484 * Internet address, or a ':' and a service name or port number.
1485 */
1486	if (*wa && *wa != '@' && *wa != ':') {
1487	    for (p = wa; *wa && *wa != '@' && *wa != ':'; wa++)
1488		;
1489	    if ((l = wa - p)) {
1490		if (!(n.proto = mkstrcat(p, l, (char *)NULL, -1, (char *)NULL,
1491			        -1, (MALLOC_S *)NULL)))
1492		{
1493		    (void) fprintf(stderr,
1494			"%s: no space for protocol name from: -i ", Pn);
1495		    safestrprt(na, stderr, 1);
1496nwad_exit:
1497		    if (n.proto)
1498			(void) free((FREE_P *)n.proto);
1499		    if (hn)
1500			(void) free((FREE_P *)hn);
1501		    if (sn)
1502			(void) free((FREE_P *)sn);
1503		    return(1);
1504		}
1505	    /*
1506	     * The protocol name should be "tcp", "udp" or "udplite".
1507	     */
1508		if ((strcasecmp(n.proto, "tcp") != 0)
1509		&&  (strcasecmp(n.proto, "udp") != 0)
1510		&&  (strcasecmp(n.proto, "udplite") != 0))
1511		{
1512		    (void) fprintf(stderr,
1513			"%s: unknown protocol name (%s) in: -i ", Pn, n.proto);
1514		    safestrprt(na, stderr, 1);
1515		    goto nwad_exit;
1516		}
1517	    /*
1518	     * Convert protocol name to lower case.
1519	     */
1520		for (p = n.proto; *p; p++) {
1521		    if (*p >= 'A' && *p <= 'Z')
1522			*p = *p - 'A' + 'a';
1523		}
1524	    }
1525	}
1526/*
1527 * Process an IPv4 address (1.2.3.4), IPv6 address ([1:2:3:4:5:6:7:8]),
1528 * or host name, preceded by a '@' and optionally followed by a colon
1529 * and a service name or port number.
1530 */
1531	if (*wa == '@') {
1532	    wa++;
1533	    if (!*wa || *wa == ':') {
1534
1535#if	defined(HASIPv6)
1536unacc_address:
1537#endif	/* defined(HASIPv6) */
1538
1539		(void) fprintf(stderr,
1540		    "%s: unacceptable Internet address in: -i ", Pn);
1541		safestrprt(na, stderr, 1);
1542		goto nwad_exit;
1543	    }
1544
1545	    if ((p = isIPv4addr(wa, n.a, sizeof(n.a)))) {
1546
1547	    /*
1548	     * Process IPv4 address.
1549	     */
1550		if (ft == 6) {
1551		    (void) fprintf(stderr,
1552			"%s: IPv4 addresses are prohibited: -i ", Pn);
1553		    safestrprt(na, stderr, 1);
1554		    goto nwad_exit;
1555		}
1556		wa = p;
1557		n.af = AF_INET;
1558	    } else if (*wa == '[') {
1559
1560#if	defined(HASIPv6)
1561	    /*
1562	     * Make sure IPv6 addresses are permitted.  If they are, assemble
1563	     * one.
1564	     */
1565		if (ft == 4) {
1566		    (void) fprintf(stderr,
1567			"%s: IPv6 addresses are prohibited: -i ", Pn);
1568		    safestrprt(na, stderr, 1);
1569		    goto nwad_exit;
1570		}
1571		if (!(cp = strrchr(++wa, ']')))
1572		    goto unacc_address;
1573		*cp = '\0';
1574		i = inet_pton(AF_INET6, wa, (void *)&n.a);
1575		*cp = ']';
1576		if (i != 1)
1577		    goto unacc_address;
1578		for (ae = i = 0; i < MAX_AF_ADDR; i++) {
1579		    if ((ae |= n.a[i]))
1580			break;
1581		}
1582		if (!ae)
1583		    goto unacc_address;
1584		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)&n.a[0])) {
1585		    if (ft == 6) {
1586			(void) fprintf(stderr,
1587			    "%s: IPv4 addresses are prohibited: -i ", Pn);
1588			safestrprt(na, stderr, 1);
1589			goto nwad_exit;
1590		    }
1591		    for (i = 0; i < 4; i++) {
1592			n.a[i] = n.a[i+12];
1593		    }
1594		    n.af = AF_INET;
1595		} else
1596		    n.af = AF_INET6;
1597		wa = cp + 1;
1598#else	/* !defined(HASIPv6) */
1599		(void) fprintf(stderr,
1600		    "%s: unsupported IPv6 address in: -i ", Pn);
1601		safestrprt(na, stderr, 1);
1602		goto nwad_exit;
1603#endif	/* defined(HASIPv6) */
1604
1605	    } else {
1606
1607	    /*
1608	     * Assemble host name.
1609	     */
1610		for (p = wa; *p && *p != ':'; p++)
1611		    ;
1612		if ((l = p - wa)) {
1613		    if (!(hn = mkstrcat(wa, l, (char *)NULL, -1, (char *)NULL,
1614			       -1, (MALLOC_S *)NULL)))
1615		    {
1616			(void) fprintf(stderr,
1617			    "%s: no space for host name: -i ", Pn);
1618			safestrprt(na, stderr, 1);
1619			goto nwad_exit;
1620		    }
1621
1622#if	defined(HASIPv6)
1623
1624		/*
1625		 * If no IP version has been specified, look up an IPv6 host
1626		 * name first.  If that fails, look up an IPv4 host name.
1627		 *
1628		 * If the IPv6 version has been specified, look up the host
1629		 * name only under its IP version specification.
1630		 */
1631		    if (!ft)
1632			n.af = AF_INET6;
1633		    if (!(he = lkup_hostnm(hn, &n)) && !ft) {
1634			n.af = AF_INET;
1635			he = lkup_hostnm(hn, &n);
1636		    }
1637#else	/* !defined(HASIPv6) */
1638		    if (!ft)
1639			n.af = AF_INET;
1640		    he = lkup_hostnm(hn, &n);
1641#endif	/* defined(HASIPv6) */
1642
1643		    if (!he) {
1644			fprintf(stderr, "%s: unknown host name (%s) in: -i ",
1645			    Pn, hn);
1646			safestrprt(na, stderr, 1);
1647			goto nwad_exit;
1648		    }
1649		}
1650		wa = p;
1651	    }
1652	}
1653/*
1654 * If there is no port number, enter the address.
1655 */
1656	if (!*wa)
1657	    goto nwad_enter;
1658/*
1659 * Process a service name or port number list, preceded by a colon.
1660 *
1661 * Entries of the list are separated with commas; elements of a numeric range
1662 * are specified with a separating minus sign (`-'); all service names must
1663 * belong to the same protocol; embedded spaces are not allowed.  An embedded
1664 * minus sign in a name is taken to be part of the name, the starting entry
1665 * of a range can't be a service name.
1666 */
1667	if (*wa != ':' || *(wa + 1) == '\0') {
1668
1669unacc_port:
1670	    (void) fprintf(stderr,
1671		"%s: unacceptable port specification in: -i ", Pn);
1672	    safestrprt(na, stderr, 1);
1673	    goto nwad_exit;
1674	}
1675	for (++wa; wa && *wa; wa++) {
1676	    for (ep = pr = sp = 0; *wa; wa++) {
1677		if (*wa < '0' || *wa > '9') {
1678
1679		/*
1680		 * Convert service name to port number, using already-specified
1681		 * protocol name.  A '-' is taken to be part of the name; hence
1682		 * the starting entry of a range can't be a service name.
1683		 */
1684		    for (p = wa; *wa && *wa != ','; wa++)
1685			;
1686		    if (!(l = wa - p)) {
1687			(void) fprintf(stderr,
1688			    "%s: invalid service name: -i ", Pn);
1689			safestrprt(na, stderr, 1);
1690			goto nwad_exit;
1691		    }
1692		    if (sn) {
1693			if (l > snl) {
1694			    sn = (char *)realloc((MALLOC_P *)sn, l + 1);
1695			    snl = l;
1696			}
1697		    } else {
1698			sn = (char *)malloc(l + 1);
1699			snl = l;
1700		    }
1701		    if (!sn) {
1702			(void) fprintf(stderr,
1703			    "%s: no space for service name: -i ", Pn);
1704			safestrprt(na, stderr, 1);
1705			goto nwad_exit;
1706		    }
1707		    (void) strncpy(sn, p, l);
1708		    *(sn + l) = '\0';
1709		    if (n.proto) {
1710
1711		    /*
1712		     * If the protocol has been specified, look up the port
1713		     * number for the service name for the specified protocol.
1714		     */
1715			if (!(se = getservbyname(sn, n.proto))) {
1716			    (void) fprintf(stderr,
1717				"%s: unknown service %s for %s in: -i ",
1718				Pn, sn, n.proto);
1719			    safestrprt(na, stderr, 1);
1720			    goto nwad_exit;
1721			}
1722			pt = (int)ntohs(se->s_port);
1723		    } else {
1724
1725		    /*
1726		     * If no protocol has been specified, look up the port
1727		     * numbers for the service name for both TCP and UDP.
1728		     */
1729			if((se = getservbyname(sn, "tcp")))
1730			    pt = (int)ntohs(se->s_port);
1731			if ((se1 = getservbyname(sn, "udp")))
1732			    pu = (int)ntohs(se1->s_port);
1733			if (!se && !se1) {
1734			    (void) fprintf(stderr,
1735				"%s: unknown service %s in: -i ", Pn, sn);
1736			    safestrprt(na, stderr, 1);
1737			    goto nwad_exit;
1738			}
1739			if (se && se1 && pt != pu) {
1740			    (void) fprintf(stderr,
1741				"%s: TCP=%d and UDP=%d %s ports conflict;\n",
1742				Pn, pt, pu, sn);
1743			    (void) fprintf(stderr,
1744				"      specify \"tcp:%s\" or \"udp:%s\": -i ",
1745				sn, sn);
1746			    safestrprt(na, stderr, 1);
1747			    goto nwad_exit;
1748			}
1749			if (!se && se1)
1750			    pt = pu;
1751		    }
1752		    if (pr)
1753			ep = pt;
1754		    else {
1755			sp = pt;
1756			if (*wa == '-')
1757			    pr++;
1758		    }
1759		} else {
1760
1761		/*
1762		 * Assemble port number.
1763		 */
1764		    for (; *wa && *wa != ','; wa++) {
1765			if (*wa == '-') {
1766			    if (pr)
1767				goto unacc_port;
1768			    pr++;
1769			    break;
1770			}
1771			if (*wa < '0' || *wa > '9')
1772			    goto unacc_port;
1773			if (pr)
1774			    ep = (ep * 10) + *wa - '0';
1775			else
1776			    sp = (sp * 10) + *wa - '0';
1777		    }
1778		}
1779		if (!*wa || *wa == ',')
1780		    break;
1781		if (pr)
1782		    continue;
1783		goto unacc_port;
1784	    }
1785	    if (!pr)
1786		ep = sp;
1787	    if (ep < sp)
1788		goto unacc_port;
1789	/*
1790	 * Enter completed port or port range specification.
1791	 */
1792
1793nwad_enter:
1794
1795	    for (i = 1; i;) {
1796		if (enter_nwad(&n, sp, ep, na, he))
1797		    goto nwad_exit;
1798
1799#if	defined(HASIPv6)
1800	    /*
1801	     * If IPv6 is enabled, a host name was specified, and the
1802	     * associated * address is for the AF_INET6 address family,
1803	     * try to get and address for the AF_INET family, too, unless
1804	     * IPv4 is prohibited.
1805	     */
1806		if (hn && (n.af == AF_INET6) && (ft != 6)) {
1807		    n.af = AF_INET;
1808		    if ((he = lkup_hostnm(hn, &n)))
1809			continue;
1810		}
1811#endif	/* defined(HASIPv6) */
1812
1813		i = 0;
1814	    }
1815	    if (!*wa)
1816		break;
1817	}
1818	if (sn)
1819	    (void) free((FREE_P *)sn);
1820	return(0);
1821}
1822
1823/*
1824 * enter_nwad() - enter nwad structure
1825 */
1826
1827static int
1828enter_nwad(n, sp, ep, s, he)
1829	struct nwad *n;			/* pointer to partially completed
1830					 * nwad (less port) */
1831	int sp;				/* starting port number */
1832	int ep;				/* ending port number */
1833	char *s;			/* string that states the address */
1834	struct hostent *he;		/* pointer to hostent struct from which
1835					 * network address came */
1836{
1837	int ac;
1838	unsigned char *ap;
1839	static int na = 0;
1840	struct nwad nc;
1841	struct nwad *np;
1842/*
1843 * Allocate space for the argument specification.
1844 */
1845	if (strlen(s)) {
1846	    if (!(n->arg = mkstrcpy(s, (MALLOC_S *)NULL))) {
1847		(void) fprintf(stderr,
1848		    "%s: no space for Internet argument: -i ", Pn);
1849		safestrprt(s, stderr, 1);
1850		Exit(1);
1851	    }
1852	} else
1853	    n->arg = (char *)NULL;
1854/*
1855 * Loop through all hostent addresses.
1856 */
1857	for (ac = 1, nc = *n;;) {
1858
1859	/*
1860	 * Test address specification -- it must contain at least one of:
1861	 * protocol, Internet address or port.  If correct, link into search
1862	 * list.
1863	 */
1864	    if (!nc.proto
1865	    &&  !nc.a[0] && !nc.a[1] && !nc.a[2] && !nc.a[3]
1866
1867#if	defined(HASIPv6)
1868	    &&  (nc.af != AF_INET6
1869	    ||   (!nc.a[4]  && !nc.a[5]  && !nc.a[6]  && !nc.a[7]
1870	    &&    !nc.a[8]  && !nc.a[9]  && !nc.a[10] && !nc.a[11]
1871	    &&    !nc.a[12] && !nc.a[13] && !nc.a[14] && !nc.a[15]))
1872#endif	/* defined(HASIPv6) */
1873
1874	    &&  sp == -1) {
1875		(void) fprintf(stderr,
1876		    "%s: incomplete Internet address specification: -i ", Pn);
1877		safestrprt(s, stderr, 1);
1878		return(1);
1879	    }
1880	/*
1881	 * Limit the network address chain length to MAXNWAD for reasons of
1882	 * search efficiency.
1883	 */
1884	    if (na >= MAXNWAD) {
1885		(void) fprintf(stderr,
1886		    "%s: network address limit (%d) exceeded: -i ",
1887		    Pn, MAXNWAD);
1888		safestrprt(s, stderr, 1);
1889		return(1);
1890	    }
1891	/*
1892	 * Allocate space for the address specification.
1893	 */
1894	    if ((np = (struct nwad *)malloc(sizeof(struct nwad))) == NULL) {
1895		(void) fprintf(stderr,
1896		    "%s: no space for network address from: -i ", Pn);
1897		safestrprt(s, stderr, 1);
1898		return(1);
1899	    }
1900	/*
1901	 * Construct and link the address specification.
1902	 */
1903	    *np = nc;
1904	    np->sport = sp;
1905	    np->eport = ep;
1906	    np->f = 0;
1907	    np->next = Nwad;
1908	    Nwad = np;
1909	    na++;
1910	/*
1911	 * If the network address came from gethostbyname(), advance to
1912	 * the next address; otherwise quit.
1913	 */
1914	    if (!he)
1915		break;
1916	    if (!(ap = (unsigned char *)he->h_addr_list[ac++]))
1917		break;
1918
1919#if	defined(HASIPv6)
1920	    {
1921		int i;
1922
1923		for (i = 0;
1924		     (i < (he->h_length - 1)) && (i < (MAX_AF_ADDR - 1));
1925		     i++)
1926		{
1927		    nc.a[i] = *ap++;
1928		}
1929		nc.a[i] = *ap;
1930	    }
1931#else	/* !defined(HASIPv6) */
1932	    nc.a[0] = *ap++;
1933	    nc.a[1] = *ap++;
1934	    nc.a[2] = *ap++;
1935	    nc.a[3] = *ap;
1936#endif	/* defined(HASIPv6) */
1937
1938	}
1939	return(0);
1940}
1941
1942
1943#if	defined(HASTCPUDPSTATE)
1944/*
1945 * enter_state_spec() -- enter TCP and UDP state specifications
1946 */
1947
1948int
1949enter_state_spec(ss)
1950	char *ss;			/* state specification string */
1951{
1952	char *cp, *ne, *ns, *pr;
1953	int err, d, f, i, tx, x;
1954	size_t len;
1955	static char *ssc = (char *)NULL;
1956	char *ty;
1957/*
1958 * Check the protocol specification.
1959 */
1960	if (!strncasecmp(ss, "tcp:", 4)) {
1961	    pr = "TCP";
1962	    tx = 0;
1963	}
1964
1965#if	!defined(USE_LIB_PRINT_TCPTPI)
1966	else if (!strncasecmp(ss, "UDP:", 4)) {
1967	    pr = "UDP";
1968	    tx = 1;
1969	}
1970
1971#endif	/* !defined(USE_LIB_PRINT_TCPTPI) */
1972
1973	else {
1974	    (void) fprintf(stderr, "%s: unknown -s protocol: \"%s\"\n",
1975		Pn, ss);
1976	    return(1);
1977	}
1978	cp = ss + 4;
1979	if (!*cp) {
1980	    (void) fprintf(stderr, "%s: no %s state names in: %s\n",
1981		Pn, pr, ss);
1982	    return(1);
1983	}
1984	(void) build_IPstates();
1985	if (!(tx ? UdpSt : TcpSt)) {
1986	    (void) fprintf(stderr, "%s: no %s state names available: %s\n",
1987		Pn, pr, ss);
1988	    return(1);
1989	}
1990/*
1991 * Allocate the inclusion and exclusion tables for the protocol.
1992 */
1993	if (tx) {
1994	    if (UdpNstates) {
1995		if (!UdpStI) {
1996		    if (!(UdpStI = (unsigned char *)calloc((MALLOC_S)UdpNstates,
1997				   sizeof(unsigned char))))
1998		    {
1999			ty = "UDP state inclusion";
2000
2001no_IorX_space:
2002
2003			(void) fprintf(stderr, "%s: no %s table space\n",
2004			    Pn, ty);
2005			Exit(1);
2006		    }
2007		}
2008		if (!UdpStX) {
2009		    if (!(UdpStX = (unsigned char *)calloc((MALLOC_S)UdpNstates,
2010				   sizeof(unsigned char))))
2011		    {
2012			ty = "UDP state exclusion";
2013			goto no_IorX_space;
2014		    }
2015		}
2016	    }
2017	} else {
2018	    if (TcpNstates) {
2019		if (!TcpStI) {
2020		    if (!(TcpStI = (unsigned char *)calloc((MALLOC_S)TcpNstates,
2021				   sizeof(unsigned char))))
2022		    {
2023			ty = "TCP state inclusion";
2024			goto no_IorX_space;
2025		    }
2026		}
2027		if (!TcpStX) {
2028		    if (!(TcpStX = (unsigned char *)calloc((MALLOC_S)TcpNstates,
2029				   sizeof(unsigned char))))
2030		    {
2031			ty = "TCP state exclusion";
2032			goto no_IorX_space;
2033		    }
2034		}
2035	    }
2036	}
2037/*
2038 * Convert the state names in the rest of the string to state indexes and
2039 * record them in the appropriate inclusion or exclusion table.
2040 */
2041	if (ssc)
2042	    (void) free((MALLOC_P *)ssc);
2043	if (!(ssc = mkstrcpy(cp, (MALLOC_S *)NULL))) {
2044	    (void) fprintf(stderr,
2045		"%s: no temporary state argument space for: %s\n", Pn, ss);
2046	    Exit(1);
2047	}
2048	cp = ssc;
2049	err = 0;
2050	while (*cp) {
2051
2052	/*
2053	 * Determine inclusion or exclusion for this state name.
2054	 */
2055	    if (*cp == '^') {
2056		x = 1;
2057		cp++;
2058	    } else
2059		x = 0;
2060	/*
2061	 * Find the end of the state name.  Make sure it is non-null in length
2062	 * and terminated with '\0'.
2063	 */
2064	    ns = cp;
2065	    while (*cp && (*cp != ',')) {
2066		cp++;
2067	    }
2068	    ne = cp;
2069	    if (*cp) {
2070		*cp = '\0';
2071		cp++;
2072	    }
2073	    if (!(len = (size_t)(ne - ns))) {
2074		(void) fprintf(stderr, "%s: NULL %s state name in: %s\n",
2075		    Pn, pr, ss);
2076		err = 1;
2077		continue;
2078	    }
2079	/*
2080	 * Find the state name in the appropriate table.
2081	 */
2082	    f = 0;
2083	    if (tx) {
2084		if (UdpSt) {
2085		    for (i = 0; i < UdpNstates; i++) {
2086			if (!strcasecmp(ns, UdpSt[i])) {
2087			    f = 1;
2088			    break;
2089			}
2090		    }
2091		}
2092	    } else {
2093		if (TcpSt) {
2094		    for (i = 0; i < TcpNstates; i++) {
2095			if (!strcasecmp(ns, TcpSt[i])) {
2096			    f = 1;
2097			    break;
2098			}
2099		    }
2100		}
2101	    }
2102	    if (!f) {
2103		(void) fprintf(stderr, "%s: unknown %s state name: %s\n",
2104		    Pn, pr, ns);
2105		err = 1;
2106		continue;
2107	    }
2108	/*
2109	 * Set the inclusion or exclusion status in the appropriate table.
2110	 */
2111	    d = 0;
2112	    if (x) {
2113		if (tx) {
2114		    if (!UdpStX[i]) {
2115			UdpStX[i] = 1;
2116			UdpStXn++;
2117		    } else
2118			d = 1;
2119		} else {
2120		    if (!TcpStX[i]) {
2121			TcpStX[i] = 1;
2122			TcpStXn++;
2123		    } else
2124			d = 1;
2125		}
2126	    } else {
2127		if (tx) {
2128		    if (!UdpStI[i]) {
2129			UdpStI[i] = 1;
2130			UdpStIn++;
2131		    } else
2132			d = 1;
2133		} else {
2134		    if (!TcpStI[i]) {
2135			TcpStI[i] = 1;
2136			TcpStIn++;
2137		    } else
2138			d = 1;
2139		}
2140	    }
2141	    if (d) {
2142
2143	    /*
2144	     * Report a duplicate.
2145	     */
2146		(void) fprintf(stderr, "%s: duplicate %s %sclusion: %s\n",
2147		    Pn, pr,
2148		    x ? "ex" : "in",
2149		    ns);
2150		err = 1;
2151	    }
2152	}
2153/*
2154 * Release any temporary space and return.
2155 */
2156	if (ssc) {
2157	    (void) free((MALLOC_P *)ssc);
2158	    ssc = (char *)NULL;
2159	}
2160	return(err);
2161}
2162#endif	/* defined(HASTCPUDPSTATE) */
2163
2164
2165/*
2166 * enter_str_lst() - enter a string on a list
2167 */
2168
2169int
2170enter_str_lst(opt, s, lp, incl, excl)
2171	char *opt;			/* option name */
2172	char *s;			/* string to enter */
2173	struct str_lst **lp;		/* string's list */
2174	int *incl;			/* included count */
2175	int *excl;			/* excluded count */
2176{
2177	char *cp;
2178	short i, x;
2179	MALLOC_S len;
2180	struct str_lst *lpt;
2181
2182	if (!s || *s == '-' || *s == '+') {
2183	    (void) fprintf(stderr, "%s: missing %s option value\n",
2184		Pn, opt);
2185	    return(1);
2186	}
2187	if (*s == '^') {
2188	    i = 0;
2189	    x = 1;
2190	    s++;
2191	} else {
2192	    i = 1;
2193	    x = 0;
2194	}
2195	if (!(cp = mkstrcpy(s, &len))) {
2196	    (void) fprintf(stderr, "%s: no string copy space: ", Pn);
2197	    safestrprt(s, stderr, 1);
2198	    return(1);
2199	}
2200	if ((lpt = (struct str_lst *)malloc(sizeof(struct str_lst))) == NULL) {
2201	    (void) fprintf(stderr, "%s: no list space: ", Pn);
2202	    safestrprt(s, stderr, 1);
2203	    (void) free((FREE_P *)cp);
2204	    return(1);
2205	}
2206	lpt->f = 0;
2207	lpt->str = cp;
2208	lpt->len = (int)len;
2209	lpt->x = x;
2210	if (i)
2211	    *incl += 1;
2212	if (x)
2213	    *excl += 1;
2214	lpt->next = *lp;
2215	*lp = lpt;
2216	return(0);
2217}
2218
2219
2220/*
2221 * enter_uid() - enter User Identifier for searching
2222 */
2223
2224int
2225enter_uid(us)
2226	char *us;			/* User IDentifier string pointer */
2227{
2228	int err, i, j, lnml, nn;
2229	unsigned char excl;
2230	MALLOC_S len;
2231	char lnm[LOGINML+1], *lp;
2232	struct passwd *pw;
2233	char *s, *st;
2234	uid_t uid;
2235
2236	if (!us) {
2237	    (void) fprintf(stderr, "%s: no UIDs specified\n", Pn);
2238	    return(1);
2239	}
2240	for (err = 0, s = us; *s;) {
2241
2242	/*
2243	 * Assemble next User IDentifier.
2244	 */
2245	    for (excl = i = j = lnml = nn = uid = 0, st = s;
2246		 *s && *s != ',';
2247		 i++, s++)
2248	    {
2249		if (lnml >= LOGINML) {
2250		    while (*s && *s != ',') {
2251			s++;
2252			lnml++;
2253		    }
2254		    (void) fprintf(stderr,
2255			"%s: -u login name > %d characters: ", Pn,
2256			    (int)LOGINML);
2257		    safestrprtn(st, lnml, stderr, 1);
2258		    err = j = 1;
2259		    break;
2260		}
2261		if (i == 0 && *s == '^') {
2262		    excl = 1;
2263		    continue;
2264		}
2265		lnm[lnml++] = *s;
2266		if (nn)
2267		    continue;
2268
2269#if	defined(__STDC__)
2270		if (isdigit((unsigned char)*s))
2271#else	/* !defined(__STDC__) */
2272		if (isascii(*s) && isdigit((unsigned char)*s))
2273#endif	/* defined(__STDC__) */
2274
2275		    uid = (uid * 10) + *s - '0';
2276		else
2277		    nn++;
2278	    }
2279	    if (*s)
2280		s++;
2281	    if (j)
2282		continue;
2283	    if (nn) {
2284	       lnm[lnml++] = '\0';
2285		if ((pw = getpwnam(lnm)) == NULL) {
2286		    (void) fprintf(stderr, "%s: can't get UID for ", Pn);
2287		    safestrprt(lnm, stderr, 1);
2288		    err = 1;
2289		    continue;
2290		} else
2291		    uid = pw->pw_uid;
2292	    }
2293
2294#if	defined(HASSECURITY) && !defined(HASNOSOCKSECURITY)
2295	/*
2296	 * If the security mode is enabled, only the root user may list files
2297	 * belonging to user IDs other than the real user ID of this lsof
2298	 * process.  If HASNOSOCKSECURITY is also defined, then anyone may
2299	 * list anyone else's socket files.
2300	 */
2301	    if (Myuid && uid != Myuid) {
2302		(void) fprintf(stderr,
2303		    "%s: ID %d request rejected because of security mode.\n",
2304		    Pn, uid);
2305		err = 1;
2306		continue;
2307	    }
2308#endif	/* defined(HASSECURITY)  && !defined(HASNOSOCKSECURITY) */
2309
2310	/*
2311	 * Avoid entering duplicates.
2312	 */
2313	    for (i = j = 0; i < Nuid; i++) {
2314		if (uid != Suid[i].uid)
2315		    continue;
2316		if (Suid[i].excl == excl) {
2317		    j = 1;
2318		    continue;
2319		}
2320		(void) fprintf(stderr,
2321		    "%s: UID %d has been included and excluded.\n",
2322			Pn, (int)uid);
2323		err = j = 1;
2324		break;
2325	    }
2326	    if (j)
2327		continue;
2328	/*
2329	 * Allocate space for User IDentifier.
2330	 */
2331	    if (Nuid >= Mxuid) {
2332		Mxuid += UIDINCR;
2333		len = (MALLOC_S)(Mxuid * sizeof(struct seluid));
2334		if (!Suid)
2335		    Suid = (struct seluid *)malloc(len);
2336		else
2337		    Suid = (struct seluid *)realloc((MALLOC_P *)Suid, len);
2338		if (!Suid) {
2339		    (void) fprintf(stderr, "%s: no space for UIDs", Pn);
2340		    Exit(1);
2341		}
2342	    }
2343	    if (nn) {
2344		if (!(lp = mkstrcpy(lnm, (MALLOC_S *)NULL))) {
2345		    (void) fprintf(stderr, "%s: no space for login: ", Pn);
2346		    safestrprt(lnm, stderr, 1);
2347		    Exit(1);
2348		}
2349		Suid[Nuid].lnm = lp;
2350	    } else
2351		Suid[Nuid].lnm = (char *)NULL;
2352	    Suid[Nuid].uid = uid;
2353	    Suid[Nuid++].excl = excl;
2354	    if (excl)
2355		Nuidexcl++;
2356	    else
2357		Nuidincl++;
2358	}
2359	return(err);
2360}
2361
2362
2363/*
2364 * isIPv4addr() - is host name an IPv4 address
2365 */
2366
2367static char *
2368isIPv4addr(hn, a, al)
2369	char *hn;			/* host name */
2370	unsigned char *a;		/* address receptor */
2371	int al;				/* address receptor length */
2372{
2373	int dc = 0;			/* dot count */
2374	int i;				/* temorary index */
2375	int ov[MIN_AF_ADDR];		/* octet values */
2376	int ovx = 0;			/* ov[] index */
2377/*
2378 * The host name must begin with a number and the return octet value
2379 * arguments must be acceptable.
2380 */
2381	if ((*hn < '0') || (*hn > '9'))
2382	    return((char *)NULL);
2383	if (!a || (al < MIN_AF_ADDR))
2384	    return((char *)NULL);
2385/*
2386 * Start the first octet assembly, then parse tge remainder of the host
2387 * name for four octets, separated by dots.
2388 */
2389	ov[0] = (int)(*hn++ - '0');
2390	while (*hn && (*hn != ':')) {
2391	    if (*hn == '.') {
2392
2393	    /*
2394	     * Count a dot.  Make sure a preceding octet value has been
2395	     * assembled.  Don't assemble more than MIN_AF_ADDR octets.
2396	     */
2397		dc++;
2398		if ((ov[ovx] < 0) || (ov[ovx] > 255))
2399		    return((char *)NULL);
2400		if (++ovx > (MIN_AF_ADDR - 1))
2401		    return((char *)NULL);
2402		ov[ovx] = -1;
2403	    } else if ((*hn >= '0') && (*hn <= '9')) {
2404
2405	    /*
2406	     * Assemble an octet.
2407	     */
2408		if (ov[ovx] < 0)
2409		    ov[ovx] = (int)(*hn - '0');
2410		else
2411		    ov[ovx] = (ov[ovx] * 10) + (int)(*hn - '0');
2412	    } else {
2413
2414	    /*
2415	     * A non-address character has been detected.
2416	     */
2417		return((char *)NULL);
2418	    }
2419	    hn++;
2420	}
2421/*
2422 * Make sure there were three dots and four non-null octets.
2423 */
2424	if ((dc != 3)
2425	||  (ovx != (MIN_AF_ADDR - 1))
2426	||  (ov[ovx] < 0) || (ov[ovx] > 255))
2427	    return((char *)NULL);
2428/*
2429 * Copy the octets as unsigned characters and return the ending host name
2430 * character position.
2431 */
2432	for (i = 0; i < MIN_AF_ADDR; i++) {
2433	     a[i] = (unsigned char)ov[i];
2434	}
2435	return(hn);
2436}
2437
2438
2439/*
2440 * lkup_hostnm() - look up host name
2441 */
2442
2443static struct hostent *
2444lkup_hostnm(hn, n)
2445	char *hn;			/* host name */
2446	struct nwad *n;			/* network address destination */
2447{
2448	unsigned char *ap;
2449	struct hostent *he;
2450	int ln;
2451/*
2452 * Get hostname structure pointer.  Return NULL if there is none.
2453 */
2454
2455#if	defined(HASIPv6)
2456	he = gethostbyname2(hn, n->af);
2457#else	/* !defined(HASIPv6) */
2458	he = gethostbyname(hn);
2459#endif	/* defined(HASIPv6) */
2460
2461	if (!he)
2462	    return(he);
2463/*
2464 * Copy first hostname structure address to destination structure.
2465 */
2466
2467#if	defined(HASIPv6)
2468	if (n->af != he->h_addrtype)
2469	    return((struct hostent *)NULL);
2470	if (n->af == AF_INET6) {
2471
2472	/*
2473	 * Copy an AF_INET6 address.
2474	 */
2475	    if (he->h_length > MAX_AF_ADDR)
2476		return((struct hostent *)NULL);
2477	    (void) memcpy((void *)&n->a[0], (void *)he->h_addr, he->h_length);
2478	    if ((ln = MAX_AF_ADDR - he->h_length) > 0)
2479		zeromem((char *)&n->a[he->h_length], ln);
2480	    return(he);
2481	}
2482#endif	/* defined(HASIPv6) */
2483
2484/*
2485 * Copy an AF_INET address.
2486 */
2487	if (he->h_length != 4)
2488	    return((struct hostent *)NULL);
2489	ap = (unsigned char *)he->h_addr;
2490	n->a[0] = *ap++;
2491	n->a[1] = *ap++;
2492	n->a[2] = *ap++;
2493	n->a[3] = *ap;
2494	if ((ln = MAX_AF_ADDR - 4) > 0)
2495	    zeromem((char *)&n->a[4], ln);
2496	return(he);
2497}
2498