xref: /illumos-gate/usr/src/cmd/auditreduce/option.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Command line option processing for auditreduce.
31*7c478bd9Sstevel@tonic-gate  * The entry point is process_options(), which is called by main().
32*7c478bd9Sstevel@tonic-gate  * Process_options() is the only function visible outside this module.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <locale.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/zone.h>	/* for max zonename length */
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #ifdef	TSOL
39*7c478bd9Sstevel@tonic-gate #include <tsol/label.h>
40*7c478bd9Sstevel@tonic-gate #endif	/* TSOL */
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include "auditr.h"
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * Object entry.
46*7c478bd9Sstevel@tonic-gate  * Maps object strings specified on the command line to a flag
47*7c478bd9Sstevel@tonic-gate  * used when searching by object type.
48*7c478bd9Sstevel@tonic-gate  */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate struct obj_ent {
51*7c478bd9Sstevel@tonic-gate 	char	*obj_str; /* string specified on the command line */
52*7c478bd9Sstevel@tonic-gate 	int	obj_flag; /* flag used when searching */
53*7c478bd9Sstevel@tonic-gate };
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate typedef struct obj_ent obj_ent_t;
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /*
58*7c478bd9Sstevel@tonic-gate  * Supports searches by object type.
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate static obj_ent_t obj_tbl[] = {
61*7c478bd9Sstevel@tonic-gate 			{ "file", OBJ_PATH },
62*7c478bd9Sstevel@tonic-gate 			{ "filegroup", OBJ_FGROUP },
63*7c478bd9Sstevel@tonic-gate 			{ "fileowner", OBJ_FOWNER },
64*7c478bd9Sstevel@tonic-gate 			{ "lp", OBJ_LP   },
65*7c478bd9Sstevel@tonic-gate 			{ "msgqid", OBJ_MSG  },
66*7c478bd9Sstevel@tonic-gate 			{ "msgqgroup", OBJ_MSGGROUP },
67*7c478bd9Sstevel@tonic-gate 			{ "msgqowner", OBJ_MSGOWNER },
68*7c478bd9Sstevel@tonic-gate 			{ "path", OBJ_PATH },
69*7c478bd9Sstevel@tonic-gate 			{ "pid", OBJ_PROC },
70*7c478bd9Sstevel@tonic-gate 			{ "procgroup", OBJ_PGROUP },
71*7c478bd9Sstevel@tonic-gate 			{ "procowner", OBJ_POWNER },
72*7c478bd9Sstevel@tonic-gate 			{ "semid", OBJ_SEM  },
73*7c478bd9Sstevel@tonic-gate 			{ "semgroup", OBJ_SEMGROUP  },
74*7c478bd9Sstevel@tonic-gate 			{ "semowner", OBJ_SEMOWNER  },
75*7c478bd9Sstevel@tonic-gate 			{ "shmid", OBJ_SHM  },
76*7c478bd9Sstevel@tonic-gate 			{ "shmgroup", OBJ_SHMGROUP  },
77*7c478bd9Sstevel@tonic-gate 			{ "shmowner", OBJ_SHMOWNER  },
78*7c478bd9Sstevel@tonic-gate 			{ "sock", OBJ_SOCK } };
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate extern int	derive_date(char *, struct tm *);
81*7c478bd9Sstevel@tonic-gate extern int	parse_time(char *, int);
82*7c478bd9Sstevel@tonic-gate extern char	*re_comp2(char *);
83*7c478bd9Sstevel@tonic-gate extern time_t	tm_to_secs(struct tm *);
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate static int	a_isnum(char *, int);
86*7c478bd9Sstevel@tonic-gate static int	check_file(audit_fcb_t *, int);
87*7c478bd9Sstevel@tonic-gate static int	gather_dir(char *);
88*7c478bd9Sstevel@tonic-gate static audit_pcb_t *get_next_pcb(char *);
89*7c478bd9Sstevel@tonic-gate static obj_ent_t *obj_lkup(char *);
90*7c478bd9Sstevel@tonic-gate static int	proc_class(char *);
91*7c478bd9Sstevel@tonic-gate static int	proc_date(char *, int);
92*7c478bd9Sstevel@tonic-gate static int	proc_file(char *, int);
93*7c478bd9Sstevel@tonic-gate static int	process_fileopt(int, char *argv[], int);
94*7c478bd9Sstevel@tonic-gate static int	proc_group(char *, gid_t *);
95*7c478bd9Sstevel@tonic-gate static int	proc_id(char *, int);
96*7c478bd9Sstevel@tonic-gate static int	proc_object(char *);
97*7c478bd9Sstevel@tonic-gate static void	proc_pcb(audit_pcb_t *, char *, int);
98*7c478bd9Sstevel@tonic-gate #ifdef	TSOL
99*7c478bd9Sstevel@tonic-gate static int	proc_slabel(char *);
100*7c478bd9Sstevel@tonic-gate #endif	/* TSOL */
101*7c478bd9Sstevel@tonic-gate static int	proc_subject(char *);
102*7c478bd9Sstevel@tonic-gate static int	proc_type(char *);
103*7c478bd9Sstevel@tonic-gate static int	proc_user(char *, uid_t *);
104*7c478bd9Sstevel@tonic-gate static int	proc_zonename(char *);
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate /*
107*7c478bd9Sstevel@tonic-gate  * .func	process_options - process command line options.
108*7c478bd9Sstevel@tonic-gate  * .desc	Process the user's command line options. These are of two types:
109*7c478bd9Sstevel@tonic-gate  *	single letter flags that are denoted by '-', and filenames. Some
110*7c478bd9Sstevel@tonic-gate  *	of the flags have arguments. Getopt() is used to get the flags.
111*7c478bd9Sstevel@tonic-gate  *	When this is done it calls process_fileopt() to handle any filenames
112*7c478bd9Sstevel@tonic-gate  *	that were there.
113*7c478bd9Sstevel@tonic-gate  * .call	ret = process_options(argc, argv).
114*7c478bd9Sstevel@tonic-gate  * .arg	argc	- the original value.
115*7c478bd9Sstevel@tonic-gate  * .arg	argv	- the original value.
116*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
117*7c478bd9Sstevel@tonic-gate  * .ret	-1	- command line error detected (message already printed).
118*7c478bd9Sstevel@tonic-gate  */
119*7c478bd9Sstevel@tonic-gate int
120*7c478bd9Sstevel@tonic-gate process_options(int argc, char **argv)
121*7c478bd9Sstevel@tonic-gate {
122*7c478bd9Sstevel@tonic-gate 	int	opt;
123*7c478bd9Sstevel@tonic-gate 	int	error = FALSE;
124*7c478bd9Sstevel@tonic-gate 	int	error_combo = FALSE;
125*7c478bd9Sstevel@tonic-gate 	extern int	optind;		/* in getopt() */
126*7c478bd9Sstevel@tonic-gate 	extern char	*optarg;	/* in getopt() - holds arg to flag */
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	static char	*options = "ACD:M:NQR:S:VO:a:b:c:d:e:g:j:m:o:r:s:u:z:";
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	error_str = gettext("general error");
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	zonename = NULL;
133*7c478bd9Sstevel@tonic-gate 	/*
134*7c478bd9Sstevel@tonic-gate 	 * Big switch to process the flags.
135*7c478bd9Sstevel@tonic-gate 	 * Start_over: is for handling the '-' for standard input. Getopt()
136*7c478bd9Sstevel@tonic-gate 	 * doesn't recognize it.
137*7c478bd9Sstevel@tonic-gate 	 */
138*7c478bd9Sstevel@tonic-gate start_over:
139*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, options)) != EOF) {
140*7c478bd9Sstevel@tonic-gate 		switch (opt) {
141*7c478bd9Sstevel@tonic-gate 		case 'A':		/* all records from the files */
142*7c478bd9Sstevel@tonic-gate 			f_all = TRUE;
143*7c478bd9Sstevel@tonic-gate 			break;
144*7c478bd9Sstevel@tonic-gate 		case 'C':		/* process only completed files */
145*7c478bd9Sstevel@tonic-gate 			f_complete = TRUE;
146*7c478bd9Sstevel@tonic-gate 			break;
147*7c478bd9Sstevel@tonic-gate 		case 'D':		/* delete the files when done */
148*7c478bd9Sstevel@tonic-gate 			/* force 'A' 'C' 'O' to be active */
149*7c478bd9Sstevel@tonic-gate 			f_all = f_complete = TRUE;
150*7c478bd9Sstevel@tonic-gate 			f_outfile = optarg;
151*7c478bd9Sstevel@tonic-gate 			f_delete = TRUE;
152*7c478bd9Sstevel@tonic-gate 			break;
153*7c478bd9Sstevel@tonic-gate 		case 'M':		/* only files from a certain machine */
154*7c478bd9Sstevel@tonic-gate 			f_machine = optarg;
155*7c478bd9Sstevel@tonic-gate 			break;
156*7c478bd9Sstevel@tonic-gate 		case 'N':		/* new object selection mode */
157*7c478bd9Sstevel@tonic-gate 			new_mode = TRUE;
158*7c478bd9Sstevel@tonic-gate 			break;
159*7c478bd9Sstevel@tonic-gate 		case 'Q':		/* no file error reporting */
160*7c478bd9Sstevel@tonic-gate 			f_quiet = TRUE;
161*7c478bd9Sstevel@tonic-gate 			break;
162*7c478bd9Sstevel@tonic-gate 		case 'R':		/* from specified root */
163*7c478bd9Sstevel@tonic-gate 			f_root = optarg;
164*7c478bd9Sstevel@tonic-gate 			break;
165*7c478bd9Sstevel@tonic-gate 		case 'S':		/* from specified server */
166*7c478bd9Sstevel@tonic-gate 			f_server = optarg;
167*7c478bd9Sstevel@tonic-gate 			break;
168*7c478bd9Sstevel@tonic-gate 		case 'V':		/* list all files as they are opened */
169*7c478bd9Sstevel@tonic-gate 			f_verbose = TRUE;
170*7c478bd9Sstevel@tonic-gate 			break;
171*7c478bd9Sstevel@tonic-gate 		case 'O':		/* write to outfile */
172*7c478bd9Sstevel@tonic-gate 			f_outfile = optarg;
173*7c478bd9Sstevel@tonic-gate 			break;
174*7c478bd9Sstevel@tonic-gate 		case 'a':		/* after 'date' */
175*7c478bd9Sstevel@tonic-gate 		case 'b':		/* before 'date' */
176*7c478bd9Sstevel@tonic-gate 		case 'd':		/* from 'day' */
177*7c478bd9Sstevel@tonic-gate 			if (proc_date(optarg, opt))
178*7c478bd9Sstevel@tonic-gate 				error = TRUE;
179*7c478bd9Sstevel@tonic-gate 			break;
180*7c478bd9Sstevel@tonic-gate 		case 'j':		/* subject */
181*7c478bd9Sstevel@tonic-gate 			if (proc_subject(optarg))
182*7c478bd9Sstevel@tonic-gate 				error = TRUE;
183*7c478bd9Sstevel@tonic-gate 			break;
184*7c478bd9Sstevel@tonic-gate 		case 'm':		/* message 'type' */
185*7c478bd9Sstevel@tonic-gate 			if (proc_type(optarg))
186*7c478bd9Sstevel@tonic-gate 				error = TRUE;
187*7c478bd9Sstevel@tonic-gate 			break;
188*7c478bd9Sstevel@tonic-gate 		case 'o':		/* object type */
189*7c478bd9Sstevel@tonic-gate 			if (proc_object(optarg))
190*7c478bd9Sstevel@tonic-gate 				error = TRUE;
191*7c478bd9Sstevel@tonic-gate 			break;
192*7c478bd9Sstevel@tonic-gate 		case 'c':		/* message class */
193*7c478bd9Sstevel@tonic-gate 			if (proc_class(optarg))
194*7c478bd9Sstevel@tonic-gate 				error = TRUE;
195*7c478bd9Sstevel@tonic-gate 			break;
196*7c478bd9Sstevel@tonic-gate 		case 'u':		/* form audit user */
197*7c478bd9Sstevel@tonic-gate 		case 'e':		/* form effective user */
198*7c478bd9Sstevel@tonic-gate 		case 'r':		/* form real user */
199*7c478bd9Sstevel@tonic-gate 		case 'f':		/* form effective group */
200*7c478bd9Sstevel@tonic-gate 		case 'g':		/* form real group */
201*7c478bd9Sstevel@tonic-gate 			if (proc_id(optarg, opt))
202*7c478bd9Sstevel@tonic-gate 				error = TRUE;
203*7c478bd9Sstevel@tonic-gate 			break;
204*7c478bd9Sstevel@tonic-gate #ifdef	TSOL
205*7c478bd9Sstevel@tonic-gate 		case 's':		/* sensitivity label range */
206*7c478bd9Sstevel@tonic-gate 			if (proc_slabel(optarg))
207*7c478bd9Sstevel@tonic-gate 				error = TRUE;
208*7c478bd9Sstevel@tonic-gate 			break;
209*7c478bd9Sstevel@tonic-gate #endif	/* TSOL */
210*7c478bd9Sstevel@tonic-gate 		case 'z':		/* zone name */
211*7c478bd9Sstevel@tonic-gate 			if (proc_zonename(optarg))
212*7c478bd9Sstevel@tonic-gate 				error = TRUE;
213*7c478bd9Sstevel@tonic-gate 			break;
214*7c478bd9Sstevel@tonic-gate 		default:
215*7c478bd9Sstevel@tonic-gate 			return (-1);
216*7c478bd9Sstevel@tonic-gate 		}
217*7c478bd9Sstevel@tonic-gate 		if (error) {
218*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
219*7c478bd9Sstevel@tonic-gate 				gettext("%s command line error - %s.\n"),
220*7c478bd9Sstevel@tonic-gate 				ar, error_str);
221*7c478bd9Sstevel@tonic-gate 			return (-1);
222*7c478bd9Sstevel@tonic-gate 		}
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 	/* catch '-' option for stdin processing - getopt() won't see it */
225*7c478bd9Sstevel@tonic-gate 	if (optind < argc) {
226*7c478bd9Sstevel@tonic-gate 		if (argv[optind][0] == '-' && argv[optind][1] == '\0') {
227*7c478bd9Sstevel@tonic-gate 			optind++;
228*7c478bd9Sstevel@tonic-gate 			f_stdin = TRUE;
229*7c478bd9Sstevel@tonic-gate 			goto start_over;
230*7c478bd9Sstevel@tonic-gate 		}
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 	/*
233*7c478bd9Sstevel@tonic-gate 	 * Give a default value for 'b' option if not specified.
234*7c478bd9Sstevel@tonic-gate 	 */
235*7c478bd9Sstevel@tonic-gate 	if (m_before == 0)
236*7c478bd9Sstevel@tonic-gate 		m_before = MAXLONG;	/* forever */
237*7c478bd9Sstevel@tonic-gate 	/*
238*7c478bd9Sstevel@tonic-gate 	 * Validate combinations of options.
239*7c478bd9Sstevel@tonic-gate 	 * The following are done:
240*7c478bd9Sstevel@tonic-gate 	 *	1. Can't have 'M' or 'S' or 'R' with filenames.
241*7c478bd9Sstevel@tonic-gate 	 *	2. Can't have an after ('a') time after a before ('b') time.
242*7c478bd9Sstevel@tonic-gate 	 *	3. Delete ('D') must have 'C' and 'A' and 'O' with it.
243*7c478bd9Sstevel@tonic-gate 	 *	4. Input from stdin ('-') can't have filenames too.
244*7c478bd9Sstevel@tonic-gate 	 */
245*7c478bd9Sstevel@tonic-gate 	if ((f_machine || f_server || f_root) && (argc != optind)) {
246*7c478bd9Sstevel@tonic-gate 		error_str = gettext(
247*7c478bd9Sstevel@tonic-gate 		    "no filenames allowed with 'M' or 'S' or 'R' options");
248*7c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate 	if (m_after >= m_before) {
251*7c478bd9Sstevel@tonic-gate 		error_str =
252*7c478bd9Sstevel@tonic-gate 			gettext("'a' parameter must be before 'b' parameter");
253*7c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
254*7c478bd9Sstevel@tonic-gate 	}
255*7c478bd9Sstevel@tonic-gate 	if (f_delete &&
256*7c478bd9Sstevel@tonic-gate 	    (!f_complete || !f_all || !f_outfile)) {
257*7c478bd9Sstevel@tonic-gate 		error_str = gettext(
258*7c478bd9Sstevel@tonic-gate 		    "'C', 'A', and 'O' must be specified with 'D'");
259*7c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 	if (f_stdin && (argc != optind)) {
262*7c478bd9Sstevel@tonic-gate 		error_str = gettext("no filenames allowed with '-' option");
263*7c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
264*7c478bd9Sstevel@tonic-gate 	}
265*7c478bd9Sstevel@tonic-gate 	/*
266*7c478bd9Sstevel@tonic-gate 	 * If error with option combos then print message and exit.
267*7c478bd9Sstevel@tonic-gate 	 * If there was an error with just an option then exit.
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 	if (error_combo) {
270*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
271*7c478bd9Sstevel@tonic-gate 		    gettext("%s command line error - %s.\n"), ar, error_str);
272*7c478bd9Sstevel@tonic-gate 		return (-1);
273*7c478bd9Sstevel@tonic-gate 	}
274*7c478bd9Sstevel@tonic-gate 	if (f_root == NULL)
275*7c478bd9Sstevel@tonic-gate 		f_root = "/etc/security/audit";
276*7c478bd9Sstevel@tonic-gate 	/*
277*7c478bd9Sstevel@tonic-gate 	 * Now handle any filenames included in the command line.
278*7c478bd9Sstevel@tonic-gate 	 */
279*7c478bd9Sstevel@tonic-gate 	return (process_fileopt(argc, argv, optind));
280*7c478bd9Sstevel@tonic-gate }
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate int
283*7c478bd9Sstevel@tonic-gate proc_subject(char *optarg)
284*7c478bd9Sstevel@tonic-gate {
285*7c478bd9Sstevel@tonic-gate 	if (flags & M_SUBJECT) {
286*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'j' option specified multiple times");
287*7c478bd9Sstevel@tonic-gate 		return (-1);
288*7c478bd9Sstevel@tonic-gate 	}
289*7c478bd9Sstevel@tonic-gate 	flags |= M_SUBJECT;
290*7c478bd9Sstevel@tonic-gate 	subj_id = atol(optarg);
291*7c478bd9Sstevel@tonic-gate 	return (0);
292*7c478bd9Sstevel@tonic-gate }
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate int
296*7c478bd9Sstevel@tonic-gate proc_object(char *optarg)
297*7c478bd9Sstevel@tonic-gate {
298*7c478bd9Sstevel@tonic-gate 	char	*obj_str;
299*7c478bd9Sstevel@tonic-gate 	char	*obj_val;
300*7c478bd9Sstevel@tonic-gate 	char	*obj_arg;
301*7c478bd9Sstevel@tonic-gate 	int	err;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	obj_ent_t *oep;
304*7c478bd9Sstevel@tonic-gate 	struct hostent *he;
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	if (flags & M_OBJECT) {
307*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'o' option specified multiple times");
308*7c478bd9Sstevel@tonic-gate 		return (-1);
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 	flags |= M_OBJECT;
311*7c478bd9Sstevel@tonic-gate 	if ((obj_arg = strdup(optarg)) == (char *)0)
312*7c478bd9Sstevel@tonic-gate 		return (-1);
313*7c478bd9Sstevel@tonic-gate 	if ((obj_str = strtok(optarg, "=")) == (char *)0 ||
314*7c478bd9Sstevel@tonic-gate 	    (oep = obj_lkup(obj_str)) == (obj_ent_t *)0 ||
315*7c478bd9Sstevel@tonic-gate 	    (obj_val = strtok((char *)0, "=")) == (char *)0) {
316*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid object arg (%s)"),
317*7c478bd9Sstevel@tonic-gate 		    obj_arg);
318*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
319*7c478bd9Sstevel@tonic-gate 		return (-1);
320*7c478bd9Sstevel@tonic-gate 	}
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	obj_flag = oep->obj_flag;
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 	switch (obj_flag) {
325*7c478bd9Sstevel@tonic-gate 	case OBJ_PATH:
326*7c478bd9Sstevel@tonic-gate 		if ((error_str = re_comp2(obj_val)) != (char *)NULL) {
327*7c478bd9Sstevel@tonic-gate 			return (-1);
328*7c478bd9Sstevel@tonic-gate 		}
329*7c478bd9Sstevel@tonic-gate 		return (0);
330*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
331*7c478bd9Sstevel@tonic-gate 	case OBJ_SOCK:
332*7c478bd9Sstevel@tonic-gate 		if (!a_isnum(obj_val, TRUE)) {
333*7c478bd9Sstevel@tonic-gate 			obj_id = atol(obj_val);
334*7c478bd9Sstevel@tonic-gate 			socket_flag = SOCKFLG_PORT;
335*7c478bd9Sstevel@tonic-gate 			return (0);
336*7c478bd9Sstevel@tonic-gate 		}
337*7c478bd9Sstevel@tonic-gate 		if (*obj_val == '0') {
338*7c478bd9Sstevel@tonic-gate 			(void) sscanf(obj_val, "%x", (uint_t *)&obj_id);
339*7c478bd9Sstevel@tonic-gate 			socket_flag = SOCKFLG_PORT;
340*7c478bd9Sstevel@tonic-gate 			return (0);
341*7c478bd9Sstevel@tonic-gate 		}
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 		he = getipnodebyname((const void *)obj_val, AF_INET6, 0, &err);
344*7c478bd9Sstevel@tonic-gate 		if (he == 0) {
345*7c478bd9Sstevel@tonic-gate 			he = getipnodebyname((const void *)obj_val, AF_INET,
346*7c478bd9Sstevel@tonic-gate 			    0, &err);
347*7c478bd9Sstevel@tonic-gate 			if (he == 0) {
348*7c478bd9Sstevel@tonic-gate 				(void) sprintf(errbuf,
349*7c478bd9Sstevel@tonic-gate 				    gettext("invalid machine name (%s)"),
350*7c478bd9Sstevel@tonic-gate 				    obj_val);
351*7c478bd9Sstevel@tonic-gate 				error_str = errbuf;
352*7c478bd9Sstevel@tonic-gate 				return (-1);
353*7c478bd9Sstevel@tonic-gate 			}
354*7c478bd9Sstevel@tonic-gate 		}
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 		if (he->h_addrtype == AF_INET6) {
357*7c478bd9Sstevel@tonic-gate 			/* LINTED */
358*7c478bd9Sstevel@tonic-gate 			if (IN6_IS_ADDR_V4MAPPED((in6_addr_t *)
359*7c478bd9Sstevel@tonic-gate 				he->h_addr_list[0])) {
360*7c478bd9Sstevel@tonic-gate 				/* address is IPv4 (32 bits) */
361*7c478bd9Sstevel@tonic-gate 				(void) memcpy(&obj_id, he->h_addr_list[0], 4);
362*7c478bd9Sstevel@tonic-gate 				ip_type = AU_IPv4;
363*7c478bd9Sstevel@tonic-gate 			} else {
364*7c478bd9Sstevel@tonic-gate 				(void) memcpy(ip_ipv6, he->h_addr_list[0], 16);
365*7c478bd9Sstevel@tonic-gate 				ip_type = AU_IPv6;
366*7c478bd9Sstevel@tonic-gate 			}
367*7c478bd9Sstevel@tonic-gate 		} else {
368*7c478bd9Sstevel@tonic-gate 			/* address is IPv4 (32 bits) */
369*7c478bd9Sstevel@tonic-gate 			(void) memcpy(&obj_id, he->h_addr_list[0], 4);
370*7c478bd9Sstevel@tonic-gate 			ip_type = AU_IPv4;
371*7c478bd9Sstevel@tonic-gate 		}
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 		freehostent(he);
374*7c478bd9Sstevel@tonic-gate 		socket_flag = SOCKFLG_MACHINE;
375*7c478bd9Sstevel@tonic-gate 		return (0);
376*7c478bd9Sstevel@tonic-gate 		break;
377*7c478bd9Sstevel@tonic-gate 	case OBJ_MSG:
378*7c478bd9Sstevel@tonic-gate 	case OBJ_SEM:
379*7c478bd9Sstevel@tonic-gate 	case OBJ_SHM:
380*7c478bd9Sstevel@tonic-gate 	case OBJ_PROC:
381*7c478bd9Sstevel@tonic-gate 		obj_id = atol(obj_val);
382*7c478bd9Sstevel@tonic-gate 		return (0);
383*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
384*7c478bd9Sstevel@tonic-gate 	case OBJ_FGROUP:
385*7c478bd9Sstevel@tonic-gate 	case OBJ_MSGGROUP:
386*7c478bd9Sstevel@tonic-gate 	case OBJ_SEMGROUP:
387*7c478bd9Sstevel@tonic-gate 	case OBJ_SHMGROUP:
388*7c478bd9Sstevel@tonic-gate 	case OBJ_PGROUP:
389*7c478bd9Sstevel@tonic-gate 		return (proc_group(obj_val, &obj_group));
390*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
391*7c478bd9Sstevel@tonic-gate 	case OBJ_FOWNER:
392*7c478bd9Sstevel@tonic-gate 	case OBJ_MSGOWNER:
393*7c478bd9Sstevel@tonic-gate 	case OBJ_SEMOWNER:
394*7c478bd9Sstevel@tonic-gate 	case OBJ_SHMOWNER:
395*7c478bd9Sstevel@tonic-gate 	case OBJ_POWNER:
396*7c478bd9Sstevel@tonic-gate 		return (proc_user(obj_val, &obj_owner));
397*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
398*7c478bd9Sstevel@tonic-gate 	case OBJ_LP: /* lp objects have not yet been defined */
399*7c478bd9Sstevel@tonic-gate 	default: /* impossible */
400*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid object type (%s)"),
401*7c478bd9Sstevel@tonic-gate 		    obj_str);
402*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
403*7c478bd9Sstevel@tonic-gate 		return (-1);
404*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
405*7c478bd9Sstevel@tonic-gate 	} /* switch */
406*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
407*7c478bd9Sstevel@tonic-gate }
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate obj_ent_t *
411*7c478bd9Sstevel@tonic-gate obj_lkup(char *obj_str)
412*7c478bd9Sstevel@tonic-gate {
413*7c478bd9Sstevel@tonic-gate 	int	i;
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (obj_tbl) / sizeof (obj_ent_t); i++)
416*7c478bd9Sstevel@tonic-gate 		if (strcmp(obj_str, obj_tbl[i].obj_str) == 0)
417*7c478bd9Sstevel@tonic-gate 			return (&obj_tbl[i]);
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	/* not in table */
420*7c478bd9Sstevel@tonic-gate 	return ((obj_ent_t *)0);
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate /*
425*7c478bd9Sstevel@tonic-gate  * .func	proc_type - process record type.
426*7c478bd9Sstevel@tonic-gate  * .desc	Process a record type. It is either as a number or a mnemonic.
427*7c478bd9Sstevel@tonic-gate  * .call	ret = proc_type(optstr).
428*7c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to name or number.
429*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
430*7c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (error_str contains description).
431*7c478bd9Sstevel@tonic-gate  */
432*7c478bd9Sstevel@tonic-gate int
433*7c478bd9Sstevel@tonic-gate proc_type(char *optstr)
434*7c478bd9Sstevel@tonic-gate {
435*7c478bd9Sstevel@tonic-gate 	struct au_event_ent *aep;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	/*
438*7c478bd9Sstevel@tonic-gate 	 * Either a number or a name.
439*7c478bd9Sstevel@tonic-gate 	 */
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	if (flags & M_TYPE) {
442*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'m' option specified multiple times");
443*7c478bd9Sstevel@tonic-gate 		return (-1);
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 	flags |= M_TYPE;
446*7c478bd9Sstevel@tonic-gate 	m_type = 0;
447*7c478bd9Sstevel@tonic-gate 	if (a_isnum(optstr, TRUE)) {
448*7c478bd9Sstevel@tonic-gate 		if ((aep = getauevnam(optstr)) != (struct au_event_ent *)NULL)
449*7c478bd9Sstevel@tonic-gate 			m_type = aep->ae_number;
450*7c478bd9Sstevel@tonic-gate 	} else {
451*7c478bd9Sstevel@tonic-gate 		if ((aep = getauevnum((au_event_t)atoi(optstr))) !=
452*7c478bd9Sstevel@tonic-gate 		    (struct au_event_ent *)NULL)
453*7c478bd9Sstevel@tonic-gate 			m_type = aep->ae_number;
454*7c478bd9Sstevel@tonic-gate 	}
455*7c478bd9Sstevel@tonic-gate 	if ((m_type == 0)) {
456*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid event (%s)"), optstr);
457*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
458*7c478bd9Sstevel@tonic-gate 		return (-1);
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 	return (0);
461*7c478bd9Sstevel@tonic-gate }
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate /*
465*7c478bd9Sstevel@tonic-gate  * .func	a_isnum - is it a number?
466*7c478bd9Sstevel@tonic-gate  * .desc	Determine if a string is a number or a name.
467*7c478bd9Sstevel@tonic-gate  *	A number may have a leading '+' or '-', but then must be
468*7c478bd9Sstevel@tonic-gate  *	all digits.
469*7c478bd9Sstevel@tonic-gate  * .call	ret = a_isnum(str).
470*7c478bd9Sstevel@tonic-gate  * .arg	str - ptr to the string.
471*7c478bd9Sstevel@tonic-gate  * .arg	leading	- TRUE if leading '+-' allowed.
472*7c478bd9Sstevel@tonic-gate  * .ret	0	- is a number.
473*7c478bd9Sstevel@tonic-gate  * .ret	1	- is not a number.
474*7c478bd9Sstevel@tonic-gate  */
475*7c478bd9Sstevel@tonic-gate int
476*7c478bd9Sstevel@tonic-gate a_isnum(char *str, int leading)
477*7c478bd9Sstevel@tonic-gate {
478*7c478bd9Sstevel@tonic-gate 	char	*strs;
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	if ((leading == TRUE) && (*str == '-' || *str == '+'))
481*7c478bd9Sstevel@tonic-gate 		strs = str + 1;
482*7c478bd9Sstevel@tonic-gate 	else
483*7c478bd9Sstevel@tonic-gate 		strs = str;
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (strlen(strs) == strspn(strs, "0123456789"))
486*7c478bd9Sstevel@tonic-gate 		return (0);
487*7c478bd9Sstevel@tonic-gate 	else
488*7c478bd9Sstevel@tonic-gate 		return (1);
489*7c478bd9Sstevel@tonic-gate }
490*7c478bd9Sstevel@tonic-gate 
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate /*
493*7c478bd9Sstevel@tonic-gate  * .func	proc_id	- process user/group id's/
494*7c478bd9Sstevel@tonic-gate  * .desc	Process either a user number/name or group number/name.
495*7c478bd9Sstevel@tonic-gate  *	For names check to see if the name is active in the system
496*7c478bd9Sstevel@tonic-gate  *	to derive the number. If it is not active then fail. For a number
497*7c478bd9Sstevel@tonic-gate  *	also check to see if it is active, but only print a warning if it
498*7c478bd9Sstevel@tonic-gate  *	is not. An administrator may be looking at activity of a 'phantom'
499*7c478bd9Sstevel@tonic-gate  *	user.
500*7c478bd9Sstevel@tonic-gate  * .call	ret = proc_id(optstr, opt).
501*7c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to name or number.
502*7c478bd9Sstevel@tonic-gate  * .arg	opt	- 'u' - audit user, 'e' - effective user, 'r' - real user,
503*7c478bd9Sstevel@tonic-gate  *		  'g' - group, 'f' - effective group.
504*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
505*7c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (error_str contains description).
506*7c478bd9Sstevel@tonic-gate  */
507*7c478bd9Sstevel@tonic-gate int
508*7c478bd9Sstevel@tonic-gate proc_id(char *optstr, int opt)
509*7c478bd9Sstevel@tonic-gate {
510*7c478bd9Sstevel@tonic-gate 	switch (opt) {
511*7c478bd9Sstevel@tonic-gate 	case 'e': 		/* effective user id */
512*7c478bd9Sstevel@tonic-gate 		if (flags & M_USERE) {
513*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
514*7c478bd9Sstevel@tonic-gate 			    "'e' option specified multiple times");
515*7c478bd9Sstevel@tonic-gate 			return (-1);
516*7c478bd9Sstevel@tonic-gate 		}
517*7c478bd9Sstevel@tonic-gate 		flags |= M_USERE;
518*7c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_usere));
519*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
520*7c478bd9Sstevel@tonic-gate 	case 'f': 		/* effective group id */
521*7c478bd9Sstevel@tonic-gate 		if (flags & M_GROUPE) {
522*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
523*7c478bd9Sstevel@tonic-gate 			    "'f' option specified multiple times");
524*7c478bd9Sstevel@tonic-gate 			return (-1);
525*7c478bd9Sstevel@tonic-gate 		}
526*7c478bd9Sstevel@tonic-gate 		flags |= M_GROUPE;
527*7c478bd9Sstevel@tonic-gate 		return (proc_group(optstr, &m_groupe));
528*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
529*7c478bd9Sstevel@tonic-gate 	case 'r': 		/* real user id */
530*7c478bd9Sstevel@tonic-gate 		if (flags & M_USERR) {
531*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
532*7c478bd9Sstevel@tonic-gate 			    "'r' option specified multiple times");
533*7c478bd9Sstevel@tonic-gate 			return (-1);
534*7c478bd9Sstevel@tonic-gate 		}
535*7c478bd9Sstevel@tonic-gate 		flags |= M_USERR;
536*7c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_userr));
537*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
538*7c478bd9Sstevel@tonic-gate 	case 'u': 		/* audit user id */
539*7c478bd9Sstevel@tonic-gate 		if (flags & M_USERA) {
540*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
541*7c478bd9Sstevel@tonic-gate 			    "'u' option specified multiple times");
542*7c478bd9Sstevel@tonic-gate 			return (-1);
543*7c478bd9Sstevel@tonic-gate 		}
544*7c478bd9Sstevel@tonic-gate 		flags |= M_USERA;
545*7c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_usera));
546*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
547*7c478bd9Sstevel@tonic-gate 	case 'g': 		/* real group id */
548*7c478bd9Sstevel@tonic-gate 		if (flags & M_GROUPR) {
549*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
550*7c478bd9Sstevel@tonic-gate 			    "'g' option specified multiple times");
551*7c478bd9Sstevel@tonic-gate 			return (-1);
552*7c478bd9Sstevel@tonic-gate 		}
553*7c478bd9Sstevel@tonic-gate 		flags |= M_GROUPR;
554*7c478bd9Sstevel@tonic-gate 		return (proc_group(optstr, &m_groupr));
555*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
556*7c478bd9Sstevel@tonic-gate 	default: 		/* impossible */
557*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("'%c' unknown option"), opt);
558*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
559*7c478bd9Sstevel@tonic-gate 		return (-1);
560*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
563*7c478bd9Sstevel@tonic-gate }
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate int
567*7c478bd9Sstevel@tonic-gate proc_group(char *optstr, gid_t *gid)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	struct group *grp;
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate 	if ((grp = getgrnam(optstr)) == NULL) {
572*7c478bd9Sstevel@tonic-gate 		if (!a_isnum(optstr, TRUE)) {
573*7c478bd9Sstevel@tonic-gate 			*gid = (gid_t)atoi(optstr);
574*7c478bd9Sstevel@tonic-gate 			return (0);
575*7c478bd9Sstevel@tonic-gate 		}
576*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("group name invalid (%s)"),
577*7c478bd9Sstevel@tonic-gate 		    optstr);
578*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
579*7c478bd9Sstevel@tonic-gate 		return (-1);
580*7c478bd9Sstevel@tonic-gate 	}
581*7c478bd9Sstevel@tonic-gate 	*gid = grp->gr_gid;
582*7c478bd9Sstevel@tonic-gate 	return (0);
583*7c478bd9Sstevel@tonic-gate }
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate int
587*7c478bd9Sstevel@tonic-gate proc_user(char *optstr, uid_t *uid)
588*7c478bd9Sstevel@tonic-gate {
589*7c478bd9Sstevel@tonic-gate 	struct passwd *usr;
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	if ((usr = getpwnam(optstr)) == NULL) {
592*7c478bd9Sstevel@tonic-gate 		if (!a_isnum(optstr, TRUE)) {
593*7c478bd9Sstevel@tonic-gate 			*uid = (uid_t)atoi(optstr);
594*7c478bd9Sstevel@tonic-gate 			return (0);
595*7c478bd9Sstevel@tonic-gate 		}
596*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("user name invalid (%s)"),
597*7c478bd9Sstevel@tonic-gate 		    optstr);
598*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
599*7c478bd9Sstevel@tonic-gate 		return (-1);
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 	*uid = usr->pw_uid;
602*7c478bd9Sstevel@tonic-gate 	return (0);
603*7c478bd9Sstevel@tonic-gate }
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate /*
607*7c478bd9Sstevel@tonic-gate  * .func proc_date - process date argument.
608*7c478bd9Sstevel@tonic-gate  * .desc Handle a date/time argument. See if the user has erred in combining
609*7c478bd9Sstevel@tonic-gate  *	the types of date arguments. Then parse the string and check for
610*7c478bd9Sstevel@tonic-gate  *	validity of each part.
611*7c478bd9Sstevel@tonic-gate  * .call	ret = proc_date(optstr, opt).
612*7c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to date/time string.
613*7c478bd9Sstevel@tonic-gate  * .arg	opt	- 'd' for day, 'a' for after, or 'b' for before.
614*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
615*7c478bd9Sstevel@tonic-gate  * .ret	-1	- errors detected (error_str knows what it is).
616*7c478bd9Sstevel@tonic-gate  */
617*7c478bd9Sstevel@tonic-gate int
618*7c478bd9Sstevel@tonic-gate proc_date(char *optstr, int opt)
619*7c478bd9Sstevel@tonic-gate {
620*7c478bd9Sstevel@tonic-gate 	static int	m_day = FALSE;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	if (opt == 'd') {
623*7c478bd9Sstevel@tonic-gate 		if (m_day == TRUE) {
624*7c478bd9Sstevel@tonic-gate 			error_str = gettext(
625*7c478bd9Sstevel@tonic-gate 			    "'d' option may not be used with 'a' or 'b'");
626*7c478bd9Sstevel@tonic-gate 			return (-1);
627*7c478bd9Sstevel@tonic-gate 		}
628*7c478bd9Sstevel@tonic-gate 		m_day = TRUE;
629*7c478bd9Sstevel@tonic-gate 	}
630*7c478bd9Sstevel@tonic-gate 	if ((opt == 'd') && (m_before || m_after)) {
631*7c478bd9Sstevel@tonic-gate 		error_str = gettext(
632*7c478bd9Sstevel@tonic-gate 		    "'d' option may not be used with 'a' or 'b'");
633*7c478bd9Sstevel@tonic-gate 		return (-1);
634*7c478bd9Sstevel@tonic-gate 	}
635*7c478bd9Sstevel@tonic-gate 	if ((opt == 'a' || opt == 'b') && m_day) {
636*7c478bd9Sstevel@tonic-gate 		error_str = gettext(
637*7c478bd9Sstevel@tonic-gate 		    "'a' or 'b' option may not be used with 'd'");
638*7c478bd9Sstevel@tonic-gate 		return (-1);
639*7c478bd9Sstevel@tonic-gate 	}
640*7c478bd9Sstevel@tonic-gate 	if ((opt == 'a') && (m_after != 0)) {
641*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'a' option specified multiple times");
642*7c478bd9Sstevel@tonic-gate 		return (-1);
643*7c478bd9Sstevel@tonic-gate 	}
644*7c478bd9Sstevel@tonic-gate 	if ((opt == 'b') && (m_before != 0)) {
645*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'b' option specified multiple times");
646*7c478bd9Sstevel@tonic-gate 		return (-1);
647*7c478bd9Sstevel@tonic-gate 	}
648*7c478bd9Sstevel@tonic-gate 	if (parse_time(optstr, opt))
649*7c478bd9Sstevel@tonic-gate 		return (-1);
650*7c478bd9Sstevel@tonic-gate 	return (0);
651*7c478bd9Sstevel@tonic-gate }
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate /*
655*7c478bd9Sstevel@tonic-gate  * .func	proc_class - process message class argument.
656*7c478bd9Sstevel@tonic-gate  * .desc	Process class type and see if it is for real.
657*7c478bd9Sstevel@tonic-gate  * .call	ret = proc_class(optstr).
658*7c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to class.
659*7c478bd9Sstevel@tonic-gate  * .ret	0	- class has class.
660*7c478bd9Sstevel@tonic-gate  * .ret	-1	- class in no good.
661*7c478bd9Sstevel@tonic-gate  */
662*7c478bd9Sstevel@tonic-gate int
663*7c478bd9Sstevel@tonic-gate proc_class(char *optstr)
664*7c478bd9Sstevel@tonic-gate {
665*7c478bd9Sstevel@tonic-gate 	if (flags & M_CLASS) {
666*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'c' option specified multiple times");
667*7c478bd9Sstevel@tonic-gate 		return (-1);
668*7c478bd9Sstevel@tonic-gate 	}
669*7c478bd9Sstevel@tonic-gate 	flags |= M_CLASS;
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	if (getauditflagsbin(optstr, &mask) != 0) {
672*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("unknown class (%s)"), optstr);
673*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
674*7c478bd9Sstevel@tonic-gate 		return (-1);
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	if (mask.am_success != mask.am_failure) {
678*7c478bd9Sstevel@tonic-gate 		flags |= M_SORF;
679*7c478bd9Sstevel@tonic-gate 	}
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate 	return (0);
682*7c478bd9Sstevel@tonic-gate }
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate /*
686*7c478bd9Sstevel@tonic-gate  * .func process_fileopt - process command line file options.
687*7c478bd9Sstevel@tonic-gate  * .desc Process the command line file options and gather the specified files
688*7c478bd9Sstevel@tonic-gate  *	together in file groups based upon file name suffix. The user can
689*7c478bd9Sstevel@tonic-gate  *	specify files explicitly on the command line or via a directory.
690*7c478bd9Sstevel@tonic-gate  *	This is called after the command line flags are processed (as
691*7c478bd9Sstevel@tonic-gate  *	denoted by '-').
692*7c478bd9Sstevel@tonic-gate  * .call	ret = process_fileopt(argc, argv, optindex).
693*7c478bd9Sstevel@tonic-gate  * .arg	argc	- current value of argc.
694*7c478bd9Sstevel@tonic-gate  * .arg	argv	- current value of argv.
695*7c478bd9Sstevel@tonic-gate  * .arg	optindex- current index into argv (as setup by getopt()).
696*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
697*7c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (message already printed).
698*7c478bd9Sstevel@tonic-gate  */
699*7c478bd9Sstevel@tonic-gate int
700*7c478bd9Sstevel@tonic-gate process_fileopt(int argc, char **argv, int optindex)
701*7c478bd9Sstevel@tonic-gate {
702*7c478bd9Sstevel@tonic-gate 	int	f_mode = FM_ALLDIR;
703*7c478bd9Sstevel@tonic-gate 	char	f_dr[MAXNAMLEN+1];
704*7c478bd9Sstevel@tonic-gate 	char	*f_dir = f_dr;
705*7c478bd9Sstevel@tonic-gate 	char	*fname;
706*7c478bd9Sstevel@tonic-gate 	static char	*std = "standard input";
707*7c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb;
708*7c478bd9Sstevel@tonic-gate 	DIR * dirp;
709*7c478bd9Sstevel@tonic-gate 	struct dirent *dp;
710*7c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 	/*
713*7c478bd9Sstevel@tonic-gate 	 * Take input from stdin, not any files.
714*7c478bd9Sstevel@tonic-gate 	 * Use a single fcb to do this.
715*7c478bd9Sstevel@tonic-gate 	 */
716*7c478bd9Sstevel@tonic-gate 	if (f_stdin) {
717*7c478bd9Sstevel@tonic-gate 		fcb = (audit_fcb_t *)a_calloc(1, sizeof (*fcb) + strlen(std));
718*7c478bd9Sstevel@tonic-gate 		(void) strcpy(fcb->fcb_file, std);
719*7c478bd9Sstevel@tonic-gate 		fcb->fcb_suffix = fcb->fcb_name = fcb->fcb_file;
720*7c478bd9Sstevel@tonic-gate 		fcb->fcb_next = NULL;
721*7c478bd9Sstevel@tonic-gate 		fcb->fcb_start = 0;
722*7c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
723*7c478bd9Sstevel@tonic-gate 		if ((pcb = get_next_pcb((char *)NULL)) == (audit_pcb_t *)NULL)
724*7c478bd9Sstevel@tonic-gate 			return (-1);
725*7c478bd9Sstevel@tonic-gate 		pcb->pcb_suffix = fcb->fcb_file;
726*7c478bd9Sstevel@tonic-gate 		pcb->pcb_dfirst = pcb->pcb_first = fcb;	/* one-item list */
727*7c478bd9Sstevel@tonic-gate 		pcb->pcb_dlast = pcb->pcb_last = fcb;
728*7c478bd9Sstevel@tonic-gate 		pcb->pcb_cur = fcb;
729*7c478bd9Sstevel@tonic-gate 	}
730*7c478bd9Sstevel@tonic-gate 	/*
731*7c478bd9Sstevel@tonic-gate 	 * No files specified on the command line.
732*7c478bd9Sstevel@tonic-gate 	 * Process a directory of files or subdirectories.
733*7c478bd9Sstevel@tonic-gate 	 */
734*7c478bd9Sstevel@tonic-gate 	else if (argc == optindex) {
735*7c478bd9Sstevel@tonic-gate 		/*
736*7c478bd9Sstevel@tonic-gate 		 * A specific server directory was requested.
737*7c478bd9Sstevel@tonic-gate 		 */
738*7c478bd9Sstevel@tonic-gate 		if (f_server) {
739*7c478bd9Sstevel@tonic-gate 			if (strchr(f_server, '/')) {	/* given full path */
740*7c478bd9Sstevel@tonic-gate 				f_dir = f_server;
741*7c478bd9Sstevel@tonic-gate 				f_mode = FM_ALLFILE;	/* all files here */
742*7c478bd9Sstevel@tonic-gate 			} else {		/* directory off audit root */
743*7c478bd9Sstevel@tonic-gate 				f_dir[0] = '\0';
744*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_root);
745*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, "/");
746*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_server);
747*7c478bd9Sstevel@tonic-gate 				f_mode = FM_ALLFILE;
748*7c478bd9Sstevel@tonic-gate 			}
749*7c478bd9Sstevel@tonic-gate 		}
750*7c478bd9Sstevel@tonic-gate 		/*
751*7c478bd9Sstevel@tonic-gate 		 * Gather all of the files in the directory 'f_dir'.
752*7c478bd9Sstevel@tonic-gate 		 */
753*7c478bd9Sstevel@tonic-gate 		if (f_mode == FM_ALLFILE) {
754*7c478bd9Sstevel@tonic-gate 			if (gather_dir(f_dir)) { /* get those files together */
755*7c478bd9Sstevel@tonic-gate 				return (-1);
756*7c478bd9Sstevel@tonic-gate 			}
757*7c478bd9Sstevel@tonic-gate 		} else {
758*7c478bd9Sstevel@tonic-gate 			/*
759*7c478bd9Sstevel@tonic-gate 			 * Gather all of the files in all of the
760*7c478bd9Sstevel@tonic-gate 			 * directories in 'f_root'.
761*7c478bd9Sstevel@tonic-gate 			 */
762*7c478bd9Sstevel@tonic-gate 			if ((dirp = opendir(f_root)) == NULL) {
763*7c478bd9Sstevel@tonic-gate 				(void) sprintf(errbuf, gettext(
764*7c478bd9Sstevel@tonic-gate 				    "%s can't open directory %s"), ar, f_root);
765*7c478bd9Sstevel@tonic-gate 				perror(errbuf);
766*7c478bd9Sstevel@tonic-gate 				return (-1);
767*7c478bd9Sstevel@tonic-gate 			}
768*7c478bd9Sstevel@tonic-gate 			/* read the directory and process all of the subs */
769*7c478bd9Sstevel@tonic-gate 			for (dp = readdir(dirp);
770*7c478bd9Sstevel@tonic-gate 			    dp != NULL; dp = readdir(dirp)) {
771*7c478bd9Sstevel@tonic-gate 				if (dp->d_name[0] == '.')
772*7c478bd9Sstevel@tonic-gate 					continue;
773*7c478bd9Sstevel@tonic-gate 				f_dir[0] = '\0';
774*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_root);
775*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, "/");
776*7c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, dp->d_name);
777*7c478bd9Sstevel@tonic-gate 				if (gather_dir(f_dir))	/* process a sub */
778*7c478bd9Sstevel@tonic-gate 					return (-1);
779*7c478bd9Sstevel@tonic-gate 			}
780*7c478bd9Sstevel@tonic-gate 			(void) closedir(dirp);
781*7c478bd9Sstevel@tonic-gate 		}
782*7c478bd9Sstevel@tonic-gate 	} else {
783*7c478bd9Sstevel@tonic-gate 		/*
784*7c478bd9Sstevel@tonic-gate 		 * User specified filenames on the comm and line.
785*7c478bd9Sstevel@tonic-gate 		 */
786*7c478bd9Sstevel@tonic-gate 		f_cmdline = TRUE;
787*7c478bd9Sstevel@tonic-gate 		for (; optindex < argc; optindex++) {
788*7c478bd9Sstevel@tonic-gate 			fname = argv[optindex];		/* get a filename */
789*7c478bd9Sstevel@tonic-gate 			if (proc_file(fname, FALSE))
790*7c478bd9Sstevel@tonic-gate 				return (-1);
791*7c478bd9Sstevel@tonic-gate 		}
792*7c478bd9Sstevel@tonic-gate 	}
793*7c478bd9Sstevel@tonic-gate 	return (0);
794*7c478bd9Sstevel@tonic-gate }
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate /*
798*7c478bd9Sstevel@tonic-gate  * .func	gather_dir - gather a directory's files together.
799*7c478bd9Sstevel@tonic-gate  * .desc	Process all of the files in a specific directory. The files may
800*7c478bd9Sstevel@tonic-gate  *	be checked for adherence to the file name form at.
801*7c478bd9Sstevel@tonic-gate  *	If the directory can't be opened that is ok - just print
802*7c478bd9Sstevel@tonic-gate  *	a message and continue.
803*7c478bd9Sstevel@tonic-gate  * .call	ret = gather_dir(dir).
804*7c478bd9Sstevel@tonic-gate  * .arg	dir	- ptr to full pathname of directory.
805*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
806*7c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (message already printed).
807*7c478bd9Sstevel@tonic-gate  */
808*7c478bd9Sstevel@tonic-gate int
809*7c478bd9Sstevel@tonic-gate gather_dir(char *dir)
810*7c478bd9Sstevel@tonic-gate {
811*7c478bd9Sstevel@tonic-gate 	char	dname[MAXNAMLEN+1];
812*7c478bd9Sstevel@tonic-gate 	char	fname[MAXNAMLEN+1];
813*7c478bd9Sstevel@tonic-gate 	DIR * dirp;
814*7c478bd9Sstevel@tonic-gate 	struct dirent *dp;
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 	(void) snprintf(dname, sizeof (dname), "%s/files", dir);
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate 	if ((dirp = opendir(dname)) == NULL) {
819*7c478bd9Sstevel@tonic-gate 		if (errno != ENOTDIR) {
820*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
821*7c478bd9Sstevel@tonic-gate 			    gettext("%s can't open directory - %s"), ar, dname);
822*7c478bd9Sstevel@tonic-gate 			perror(errbuf);
823*7c478bd9Sstevel@tonic-gate 		}
824*7c478bd9Sstevel@tonic-gate 		return (0);
825*7c478bd9Sstevel@tonic-gate 	}
826*7c478bd9Sstevel@tonic-gate 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
827*7c478bd9Sstevel@tonic-gate 		if (dp->d_name[0] == '.')	/* can't see hidden files */
828*7c478bd9Sstevel@tonic-gate 			continue;
829*7c478bd9Sstevel@tonic-gate 		fname[0] = '\0';
830*7c478bd9Sstevel@tonic-gate 		(void) strcat(fname, dname);	/* create pathname of file */
831*7c478bd9Sstevel@tonic-gate 		(void) strcat(fname, "/");
832*7c478bd9Sstevel@tonic-gate 		(void) strcat(fname, dp->d_name);
833*7c478bd9Sstevel@tonic-gate 		if (proc_file(fname, TRUE))
834*7c478bd9Sstevel@tonic-gate 			return (-1);
835*7c478bd9Sstevel@tonic-gate 	}
836*7c478bd9Sstevel@tonic-gate 	(void) closedir(dirp);
837*7c478bd9Sstevel@tonic-gate 	return (0);
838*7c478bd9Sstevel@tonic-gate }
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate /*
842*7c478bd9Sstevel@tonic-gate  * .func	proc_file - process a single candidate file.
843*7c478bd9Sstevel@tonic-gate  * .desc	Check out a file to see if it should be used in the merge.
844*7c478bd9Sstevel@tonic-gate  *	This includes checking the name (mode is TRUE) against the
845*7c478bd9Sstevel@tonic-gate  *	file format, checking access rights to the file, and thence
846*7c478bd9Sstevel@tonic-gate  *	getting and fcb and installing the fcb into the correct pcb.
847*7c478bd9Sstevel@tonic-gate  *	If the file fails then the fcb is not installed into a pcb
848*7c478bd9Sstevel@tonic-gate  *	and the file dissapears from view.
849*7c478bd9Sstevel@tonic-gate  * .call	proc_file(fname, mode).
850*7c478bd9Sstevel@tonic-gate  * .arg	fname	- ptr to full pathna me of file.
851*7c478bd9Sstevel@tonic-gate  * .arg	mode	- TRUE if checking adherence to file name format.
852*7c478bd9Sstevel@tonic-gate  * .ret	0	- no fatal errors detected.
853*7c478bd9Sstevel@tonic-gate  * .ret	-1	- fatal error detected - quit altogether
854*7c478bd9Sstevel@tonic-gate  *		  (message already printed).
855*7c478bd9Sstevel@tonic-gate  */
856*7c478bd9Sstevel@tonic-gate int
857*7c478bd9Sstevel@tonic-gate proc_file(char *fname, int mode)
858*7c478bd9Sstevel@tonic-gate {
859*7c478bd9Sstevel@tonic-gate 	int reject = FALSE;
860*7c478bd9Sstevel@tonic-gate 	size_t len;
861*7c478bd9Sstevel@tonic-gate 	struct stat stat_buf;
862*7c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb, *fcbp, *fcbprev;
863*7c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate 	/*
866*7c478bd9Sstevel@tonic-gate 	 * See if it is a weird file like a directory or
867*7c478bd9Sstevel@tonic-gate 	 * character special (around here?).
868*7c478bd9Sstevel@tonic-gate 	 */
869*7c478bd9Sstevel@tonic-gate 	if (stat(fname, &stat_buf)) {
870*7c478bd9Sstevel@tonic-gate 		return (0);
871*7c478bd9Sstevel@tonic-gate 	}
872*7c478bd9Sstevel@tonic-gate 	if ((stat_buf.st_mode & S_IFREG) == 0)
873*7c478bd9Sstevel@tonic-gate 		return (0);
874*7c478bd9Sstevel@tonic-gate 	/*
875*7c478bd9Sstevel@tonic-gate 	 * Allocate a new fcb to hold fcb and full filename.
876*7c478bd9Sstevel@tonic-gate 	 */
877*7c478bd9Sstevel@tonic-gate 	len = sizeof (audit_fcb_t) + strlen(fname);
878*7c478bd9Sstevel@tonic-gate 	fcb = (audit_fcb_t *)a_calloc(1, len);
879*7c478bd9Sstevel@tonic-gate 	(void) strcpy(fcb->fcb_file, fname);
880*7c478bd9Sstevel@tonic-gate 	if (check_file(fcb, mode)) { /* check file name */
881*7c478bd9Sstevel@tonic-gate 		if (!f_quiet) {
882*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s %s:\n  %s.\n", ar,
883*7c478bd9Sstevel@tonic-gate 			    error_str, fname);
884*7c478bd9Sstevel@tonic-gate 		}
885*7c478bd9Sstevel@tonic-gate 		reject = TRUE;
886*7c478bd9Sstevel@tonic-gate 	} else {
887*7c478bd9Sstevel@tonic-gate 		/*
888*7c478bd9Sstevel@tonic-gate 		 * Check against file criteria.
889*7c478bd9Sstevel@tonic-gate 		 * Check finish-time here, and start-time later on
890*7c478bd9Sstevel@tonic-gate 		 * while processing.
891*7c478bd9Sstevel@tonic-gate 		 * This is because the start time on a file can be after
892*7c478bd9Sstevel@tonic-gate 		 * the first record(s).
893*7c478bd9Sstevel@tonic-gate 		 */
894*7c478bd9Sstevel@tonic-gate 		if (f_complete && (fcb->fcb_flags & FF_NOTTERM) && !f_cmdline)
895*7c478bd9Sstevel@tonic-gate 			reject = TRUE;
896*7c478bd9Sstevel@tonic-gate 		if (!f_all && (fcb->fcb_end < m_after))
897*7c478bd9Sstevel@tonic-gate 			reject = TRUE;
898*7c478bd9Sstevel@tonic-gate 		if (f_machine) {
899*7c478bd9Sstevel@tonic-gate 			if (strlen(fcb->fcb_suffix) != strlen(f_machine) ||
900*7c478bd9Sstevel@tonic-gate 			    (strcmp(fcb->fcb_suffix, f_machine) != 0)) {
901*7c478bd9Sstevel@tonic-gate 				reject = TRUE;
902*7c478bd9Sstevel@tonic-gate 			}
903*7c478bd9Sstevel@tonic-gate 		}
904*7c478bd9Sstevel@tonic-gate 	}
905*7c478bd9Sstevel@tonic-gate 	if (reject == FALSE) {
906*7c478bd9Sstevel@tonic-gate 		filenum++;	/* count of total files to be processed */
907*7c478bd9Sstevel@tonic-gate 		fcb->fcb_next = NULL;
908*7c478bd9Sstevel@tonic-gate 		if ((pcb = get_next_pcb(fcb->fcb_suffix)) == NULL) {
909*7c478bd9Sstevel@tonic-gate 			return (-1);
910*7c478bd9Sstevel@tonic-gate 		}
911*7c478bd9Sstevel@tonic-gate 		/* Place FCB into the PCB in order - oldest first.  */
912*7c478bd9Sstevel@tonic-gate 		fcbp = pcb->pcb_first;
913*7c478bd9Sstevel@tonic-gate 		fcbprev = NULL;
914*7c478bd9Sstevel@tonic-gate 		while (fcbp != NULL) {
915*7c478bd9Sstevel@tonic-gate 			if (fcb->fcb_start < fcbp->fcb_start) {
916*7c478bd9Sstevel@tonic-gate 				if (fcbprev)
917*7c478bd9Sstevel@tonic-gate 					fcbprev->fcb_next = fcb;
918*7c478bd9Sstevel@tonic-gate 				else
919*7c478bd9Sstevel@tonic-gate 					pcb->pcb_dfirst = pcb->pcb_first = fcb;
920*7c478bd9Sstevel@tonic-gate 				fcb->fcb_next = fcbp;
921*7c478bd9Sstevel@tonic-gate 				break;
922*7c478bd9Sstevel@tonic-gate 			}
923*7c478bd9Sstevel@tonic-gate 			fcbprev = fcbp;
924*7c478bd9Sstevel@tonic-gate 			fcbp = fcbp->fcb_next;
925*7c478bd9Sstevel@tonic-gate 		}
926*7c478bd9Sstevel@tonic-gate 		/* younger than all || empty list */
927*7c478bd9Sstevel@tonic-gate 		if (!fcb->fcb_next) {
928*7c478bd9Sstevel@tonic-gate 			if (pcb->pcb_first == NULL)
929*7c478bd9Sstevel@tonic-gate 				pcb->pcb_dfirst = pcb->pcb_first = fcb;
930*7c478bd9Sstevel@tonic-gate 			pcb->pcb_dlast = pcb->pcb_last = fcb;
931*7c478bd9Sstevel@tonic-gate 			if (fcbprev)
932*7c478bd9Sstevel@tonic-gate 				fcbprev->fcb_next = fcb;
933*7c478bd9Sstevel@tonic-gate 		}
934*7c478bd9Sstevel@tonic-gate 	} else {
935*7c478bd9Sstevel@tonic-gate 		free((char *)fcb);	/* rejected */
936*7c478bd9Sstevel@tonic-gate 	}
937*7c478bd9Sstevel@tonic-gate 	return (0);
938*7c478bd9Sstevel@tonic-gate }
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate  * .func	check_file - check filename and setup fcb.
943*7c478bd9Sstevel@tonic-gate  * .desc	Check adherence to the file format (do_check is TRUE) and setup
944*7c478bd9Sstevel@tonic-gate  *	the fcb with useful information.
945*7c478bd9Sstevel@tonic-gate  *	filename format: yyyymmddhhmmss.yyyymmddhhmmss.suffix
946*7c478bd9Sstevel@tonic-gate  *			 yyyymmddhhmmss.not_terminated.suffix
947*7c478bd9Sstevel@tonic-gate  *	If do_check is FALSE then still see if the filename does confirm
948*7c478bd9Sstevel@tonic-gate  *	to the format. If it does then extract useful information from
949*7c478bd9Sstevel@tonic-gate  *	it (start time and end time).  But if it doesn't then don't print
950*7c478bd9Sstevel@tonic-gate  *	any error messages.
951*7c478bd9Sstevel@tonic-gate  * .call	ret = check_file(fcb, do_check).
952*7c478bd9Sstevel@tonic-gate  * .arg	fcb	- ptr to fcb that holds the file.
953*7c478bd9Sstevel@tonic-gate  * .arg	do_check - if TRUE do check adherence to file format.
954*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
955*7c478bd9Sstevel@tonic-gate  * .ret	-1	- file failed somehow (error_str tells why).
956*7c478bd9Sstevel@tonic-gate  */
957*7c478bd9Sstevel@tonic-gate int
958*7c478bd9Sstevel@tonic-gate check_file(audit_fcb_t *fcb, int do_check)
959*7c478bd9Sstevel@tonic-gate {
960*7c478bd9Sstevel@tonic-gate 	int	ret;
961*7c478bd9Sstevel@tonic-gate 	char	*namep, *slp;
962*7c478bd9Sstevel@tonic-gate 	char	errb[256];		/* build error message */
963*7c478bd9Sstevel@tonic-gate 	struct tm tme;
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	errb[0] = '\0';
966*7c478bd9Sstevel@tonic-gate 	/* get just the filename */
967*7c478bd9Sstevel@tonic-gate 	for (slp = namep = fcb->fcb_file; *namep; namep++) {
968*7c478bd9Sstevel@tonic-gate 		if (*namep == '/')
969*7c478bd9Sstevel@tonic-gate 			slp = namep + 1; /* slp -> the filename itself */
970*7c478bd9Sstevel@tonic-gate 	}
971*7c478bd9Sstevel@tonic-gate 	if (do_check == FALSE) {
972*7c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
973*7c478bd9Sstevel@tonic-gate 		fcb->fcb_suffix = NULL;
974*7c478bd9Sstevel@tonic-gate 		fcb->fcb_name = slp;
975*7c478bd9Sstevel@tonic-gate 		ret = 0;
976*7c478bd9Sstevel@tonic-gate 	} else {
977*7c478bd9Sstevel@tonic-gate 		ret = -1;
978*7c478bd9Sstevel@tonic-gate 	}
979*7c478bd9Sstevel@tonic-gate 	if ((int)strlen(slp) < 31) {
980*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("filename too short (%d)"),
981*7c478bd9Sstevel@tonic-gate 		    strlen(slp));
982*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
983*7c478bd9Sstevel@tonic-gate 		return (ret);
984*7c478bd9Sstevel@tonic-gate 	}
985*7c478bd9Sstevel@tonic-gate 	/*
986*7c478bd9Sstevel@tonic-gate 	 * Get working copy of filename.
987*7c478bd9Sstevel@tonic-gate 	 */
988*7c478bd9Sstevel@tonic-gate 	namep = (char *)a_calloc(1, strlen(slp) + 1);
989*7c478bd9Sstevel@tonic-gate 	(void) strcpy(namep, slp);
990*7c478bd9Sstevel@tonic-gate 	if (namep[14] != '.' || namep[29] != '.') {
991*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
992*7c478bd9Sstevel@tonic-gate 		    gettext("invalid filename format (%c or %c)"), namep[14],
993*7c478bd9Sstevel@tonic-gate 		    namep[29]);
994*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
995*7c478bd9Sstevel@tonic-gate 		free(namep);
996*7c478bd9Sstevel@tonic-gate 		return (ret);
997*7c478bd9Sstevel@tonic-gate 	}
998*7c478bd9Sstevel@tonic-gate 	namep[14] = '\0';			/* mark off start time */
999*7c478bd9Sstevel@tonic-gate 	namep[29] = '\0';			/* mark off finish time */
1000*7c478bd9Sstevel@tonic-gate 	if (derive_date(namep, &tme)) {
1001*7c478bd9Sstevel@tonic-gate 		(void) strcat(errb, gettext("starting time-stamp invalid - "));
1002*7c478bd9Sstevel@tonic-gate 		(void) strcat(errb, error_str);
1003*7c478bd9Sstevel@tonic-gate 		(void) strcpy(errbuf, errb);
1004*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
1005*7c478bd9Sstevel@tonic-gate 		free(namep);
1006*7c478bd9Sstevel@tonic-gate 		return (ret);
1007*7c478bd9Sstevel@tonic-gate 	}
1008*7c478bd9Sstevel@tonic-gate 	/*
1009*7c478bd9Sstevel@tonic-gate 	 * Keep start time from filename. Use it to order files in
1010*7c478bd9Sstevel@tonic-gate 	 * the file list. Later we will update this when we read
1011*7c478bd9Sstevel@tonic-gate 	 * the first record from the file.
1012*7c478bd9Sstevel@tonic-gate 	 */
1013*7c478bd9Sstevel@tonic-gate 	fcb->fcb_start = tm_to_secs(&tme);
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 	if (strcmp(&namep[15], "not_terminated") == 0) {
1016*7c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
1017*7c478bd9Sstevel@tonic-gate 		/*
1018*7c478bd9Sstevel@tonic-gate 		 * Only treat a 'not_terminated' file as such if
1019*7c478bd9Sstevel@tonic-gate 		 * it is not on the command line.
1020*7c478bd9Sstevel@tonic-gate 		 */
1021*7c478bd9Sstevel@tonic-gate 		if (do_check == TRUE)
1022*7c478bd9Sstevel@tonic-gate 			fcb->fcb_flags |= FF_NOTTERM;
1023*7c478bd9Sstevel@tonic-gate 	} else if (derive_date(&namep[15], &tme)) {
1024*7c478bd9Sstevel@tonic-gate 		(void) strcat(errb, gettext("ending time-stamp invalid - "));
1025*7c478bd9Sstevel@tonic-gate 		(void) strcat(errb, error_str);
1026*7c478bd9Sstevel@tonic-gate 		(void) strcpy(errbuf, errb);
1027*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
1028*7c478bd9Sstevel@tonic-gate 		free(namep);
1029*7c478bd9Sstevel@tonic-gate 		return (ret);
1030*7c478bd9Sstevel@tonic-gate 	} else {
1031*7c478bd9Sstevel@tonic-gate 		fcb->fcb_end = tm_to_secs(&tme);
1032*7c478bd9Sstevel@tonic-gate 	}
1033*7c478bd9Sstevel@tonic-gate 	fcb->fcb_name = slp;
1034*7c478bd9Sstevel@tonic-gate 	fcb->fcb_suffix = &slp[30];
1035*7c478bd9Sstevel@tonic-gate 	free(namep);
1036*7c478bd9Sstevel@tonic-gate 	return (0);
1037*7c478bd9Sstevel@tonic-gate }
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate 
1040*7c478bd9Sstevel@tonic-gate /*
1041*7c478bd9Sstevel@tonic-gate  * .func get_next_pcb - get a pcb to use.
1042*7c478bd9Sstevel@tonic-gate  * .desc	The pcb's in the array audit_pcbs are used to hold single file
1043*7c478bd9Sstevel@tonic-gate  *	groups in the form of a linked list. Each pcb holds files that
1044*7c478bd9Sstevel@tonic-gate  *	are tied together by a common suffix in the file name. Here we
1045*7c478bd9Sstevel@tonic-gate  *	get either 1. the existing pcb holding a specified sufix or
1046*7c478bd9Sstevel@tonic-gate  *	2. a new pcb if we can't find an existing one.
1047*7c478bd9Sstevel@tonic-gate  * .call	pcb = get_next_pcb(suffix).
1048*7c478bd9Sstevel@tonic-gate  * .arg	suffix	- ptr to suffix we are seeking.
1049*7c478bd9Sstevel@tonic-gate  * .ret	pcb	- ptr to pcb that hold s the sought suffix.
1050*7c478bd9Sstevel@tonic-gate  * .ret	NULL- serious failure in memory allocation. Quit processing.
1051*7c478bd9Sstevel@tonic-gate  */
1052*7c478bd9Sstevel@tonic-gate audit_pcb_t *
1053*7c478bd9Sstevel@tonic-gate get_next_pcb(char *suffix)
1054*7c478bd9Sstevel@tonic-gate {
1055*7c478bd9Sstevel@tonic-gate 	int	i = 0;
1056*7c478bd9Sstevel@tonic-gate 	int	zerosize;
1057*7c478bd9Sstevel@tonic-gate 	unsigned int	size;
1058*7c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	/* Search through (maybe) entire array. */
1061*7c478bd9Sstevel@tonic-gate 	while (i < pcbsize) {
1062*7c478bd9Sstevel@tonic-gate 		pcb = &audit_pcbs[i++];
1063*7c478bd9Sstevel@tonic-gate 		if (pcb->pcb_first == NULL) {
1064*7c478bd9Sstevel@tonic-gate 			proc_pcb(pcb, suffix, i);
1065*7c478bd9Sstevel@tonic-gate 			return (pcb);	/* came to an unused one */
1066*7c478bd9Sstevel@tonic-gate 		}
1067*7c478bd9Sstevel@tonic-gate 		if (suffix) {
1068*7c478bd9Sstevel@tonic-gate 			if (strcmp(pcb->pcb_suffix, suffix) == 0)
1069*7c478bd9Sstevel@tonic-gate 				return (pcb);	/* matched one with suffix */
1070*7c478bd9Sstevel@tonic-gate 		}
1071*7c478bd9Sstevel@tonic-gate 	}
1072*7c478bd9Sstevel@tonic-gate 	/*
1073*7c478bd9Sstevel@tonic-gate 	 * Uh-oh, the entire array is used and we haven't gotten one yet.
1074*7c478bd9Sstevel@tonic-gate 	 * Allocate a bigger array.
1075*7c478bd9Sstevel@tonic-gate 	 */
1076*7c478bd9Sstevel@tonic-gate 	pcbsize += PCB_INC;
1077*7c478bd9Sstevel@tonic-gate 	size = pcbsize * sizeof (audit_pcb_t);
1078*7c478bd9Sstevel@tonic-gate 	zerosize = size - ((pcbsize - PCB_INC) * sizeof (audit_pcb_t));
1079*7c478bd9Sstevel@tonic-gate 	if ((audit_pcbs = (audit_pcb_t *)realloc((char *)audit_pcbs, size)) ==
1080*7c478bd9Sstevel@tonic-gate 	    NULL) {
1081*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
1082*7c478bd9Sstevel@tonic-gate 		    gettext("%s memory reallocation failed (%d bytes)"), ar,
1083*7c478bd9Sstevel@tonic-gate 		    size);
1084*7c478bd9Sstevel@tonic-gate 		perror(errbuf);
1085*7c478bd9Sstevel@tonic-gate 		audit_stats();		/* give user statistics on usage */
1086*7c478bd9Sstevel@tonic-gate 		return (NULL);		/* really bad thing to have happen */
1087*7c478bd9Sstevel@tonic-gate 	}
1088*7c478bd9Sstevel@tonic-gate 	/*
1089*7c478bd9Sstevel@tonic-gate 	 * Don't know if realloc clears the new memory like calloc would.
1090*7c478bd9Sstevel@tonic-gate 	 */
1091*7c478bd9Sstevel@tonic-gate 	(void) memset((void *) & audit_pcbs[pcbsize-PCB_INC], 0,
1092*7c478bd9Sstevel@tonic-gate 	    (size_t)zerosize);
1093*7c478bd9Sstevel@tonic-gate 	pcb = &audit_pcbs[pcbsize-PCB_INC];	/* allocate the first new one */
1094*7c478bd9Sstevel@tonic-gate 	proc_pcb(pcb, suffix, pcbsize - PCB_INC);
1095*7c478bd9Sstevel@tonic-gate 	return (pcb);
1096*7c478bd9Sstevel@tonic-gate }
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate 
1099*7c478bd9Sstevel@tonic-gate /*
1100*7c478bd9Sstevel@tonic-gate  * .func proc_pcb - process pcb.
1101*7c478bd9Sstevel@tonic-gate  * .desc	Common pcb processing for above routine.
1102*7c478bd9Sstevel@tonic-gate  * .call	proc_pcb(pcb, suffix, i).
1103*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb.
1104*7c478bd9Sstevel@tonic-gate  * .arg	suffix	- prt to suffix tha t ties this group together.
1105*7c478bd9Sstevel@tonic-gate  * .arg	i	- index into audit_pcbs[ ].
1106*7c478bd9Sstevel@tonic-gate  * .ret	void.
1107*7c478bd9Sstevel@tonic-gate  */
1108*7c478bd9Sstevel@tonic-gate void
1109*7c478bd9Sstevel@tonic-gate proc_pcb(audit_pcb_t *pcb, char *suffix, int i)
1110*7c478bd9Sstevel@tonic-gate {
1111*7c478bd9Sstevel@tonic-gate 	if (suffix)
1112*7c478bd9Sstevel@tonic-gate 		pcb->pcb_suffix = suffix;
1113*7c478bd9Sstevel@tonic-gate 	pcbnum++;	/* one more pcb in use */
1114*7c478bd9Sstevel@tonic-gate 	pcb->pcb_size = AUDITBUFSIZE;
1115*7c478bd9Sstevel@tonic-gate 	pcb->pcb_rec = (char *)a_calloc(1, AUDITBUFSIZE);
1116*7c478bd9Sstevel@tonic-gate 	pcb->pcb_time = -1;
1117*7c478bd9Sstevel@tonic-gate 	pcb->pcb_flags |= PF_FILE;	/* note this one controls files */
1118*7c478bd9Sstevel@tonic-gate 	pcb->pcb_procno = i;	/* save index into audit_pcbs [] for id */
1119*7c478bd9Sstevel@tonic-gate }
1120*7c478bd9Sstevel@tonic-gate 
1121*7c478bd9Sstevel@tonic-gate 
1122*7c478bd9Sstevel@tonic-gate #ifdef	TSOL
1123*7c478bd9Sstevel@tonic-gate /*
1124*7c478bd9Sstevel@tonic-gate  * .func	proc_slabel - process sensitivity label range argument.
1125*7c478bd9Sstevel@tonic-gate  * .desc	Parse sensitivity label range sl:sl
1126*7c478bd9Sstevel@tonic-gate  * .call	ret = proc_slabel(optstr).
1127*7c478bd9Sstevel@tonic-gate  * .arg	opstr	- ptr to label range string
1128*7c478bd9Sstevel@tonic-gate  * .ret 0	- no errors detected.
1129*7c478bd9Sstevel@tonic-gate  * .ret -1	- errors detected or not Trusted Solaris (error_str set).
1130*7c478bd9Sstevel@tonic-gate  */
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate int
1133*7c478bd9Sstevel@tonic-gate proc_slabel(char *optstr)
1134*7c478bd9Sstevel@tonic-gate {
1135*7c478bd9Sstevel@tonic-gate 	char	*p;
1136*7c478bd9Sstevel@tonic-gate 	int	error;
1137*7c478bd9Sstevel@tonic-gate 
1138*7c478bd9Sstevel@tonic-gate 	if (flags & M_SLABEL) {
1139*7c478bd9Sstevel@tonic-gate 		error_str = gettext("'s' option specified multiple times");
1140*7c478bd9Sstevel@tonic-gate 		return (-1);
1141*7c478bd9Sstevel@tonic-gate 	}
1142*7c478bd9Sstevel@tonic-gate 
1143*7c478bd9Sstevel@tonic-gate 	flags |= M_SLABEL;
1144*7c478bd9Sstevel@tonic-gate 	p = strchr(optstr, ':');
1145*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
1146*7c478bd9Sstevel@tonic-gate 		/* exact label match, lower and upper range bounds the same */
1147*7c478bd9Sstevel@tonic-gate 		if (stobsl(optstr, &m_slabel.lower_bound, NO_CORRECTION,
1148*7c478bd9Sstevel@tonic-gate 		    &error) == 0) {
1149*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
1150*7c478bd9Sstevel@tonic-gate 			    gettext("invalid sensitivity label (%s) err %d"),
1151*7c478bd9Sstevel@tonic-gate 			    optstr, error);
1152*7c478bd9Sstevel@tonic-gate 			error_str = errbuf;
1153*7c478bd9Sstevel@tonic-gate 			return (-1);
1154*7c478bd9Sstevel@tonic-gate 		}
1155*7c478bd9Sstevel@tonic-gate 		m_slabel.upper_bound = m_slabel.lower_bound;
1156*7c478bd9Sstevel@tonic-gate 		return (0);
1157*7c478bd9Sstevel@tonic-gate 	}
1158*7c478bd9Sstevel@tonic-gate 	if (p == optstr) {
1159*7c478bd9Sstevel@tonic-gate 		/* lower bound is not specified .. default is admin_low */
1160*7c478bd9Sstevel@tonic-gate 		bsllow(&m_slabel.lower_bound);
1161*7c478bd9Sstevel@tonic-gate 		if (stobsl(p + 1, &m_slabel.upper_bound, NO_CORRECTION,
1162*7c478bd9Sstevel@tonic-gate 		    &error) == 0) {
1163*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
1164*7c478bd9Sstevel@tonic-gate 			    gettext("invalid sensitivity label (%s) err %d"),
1165*7c478bd9Sstevel@tonic-gate 			    p + 1, error);
1166*7c478bd9Sstevel@tonic-gate 			error_str = errbuf;
1167*7c478bd9Sstevel@tonic-gate 			return (-1);
1168*7c478bd9Sstevel@tonic-gate 		}
1169*7c478bd9Sstevel@tonic-gate 		return (0);
1170*7c478bd9Sstevel@tonic-gate 	}
1171*7c478bd9Sstevel@tonic-gate 	*p++ = '\0';
1172*7c478bd9Sstevel@tonic-gate 	if (stobsl(optstr, &m_slabel.lower_bound, NO_CORRECTION, &error) == 0) {
1173*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
1174*7c478bd9Sstevel@tonic-gate 		    gettext("invalid sensitivity label (%s) err %d"), optstr,
1175*7c478bd9Sstevel@tonic-gate 		    error);
1176*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
1177*7c478bd9Sstevel@tonic-gate 		return (-1);
1178*7c478bd9Sstevel@tonic-gate 	}
1179*7c478bd9Sstevel@tonic-gate 	if (*p == '\0')
1180*7c478bd9Sstevel@tonic-gate 		/* upper bound is not specified .. default is admin_high */
1181*7c478bd9Sstevel@tonic-gate 		bslhigh(&m_slabel.upper_bound);
1182*7c478bd9Sstevel@tonic-gate 	else {
1183*7c478bd9Sstevel@tonic-gate 		if (stobsl(p, &m_slabel.upper_bound, NO_CORRECTION, &error) ==
1184*7c478bd9Sstevel@tonic-gate 		    0) {
1185*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
1186*7c478bd9Sstevel@tonic-gate 			    gettext("invalid sensitivity label (%s) err %d"),
1187*7c478bd9Sstevel@tonic-gate 			    p, error);
1188*7c478bd9Sstevel@tonic-gate 			error_str = errbuf;
1189*7c478bd9Sstevel@tonic-gate 			return (-1);
1190*7c478bd9Sstevel@tonic-gate 		}
1191*7c478bd9Sstevel@tonic-gate 	}
1192*7c478bd9Sstevel@tonic-gate 	/* make sure that upper bound dominates the lower bound */
1193*7c478bd9Sstevel@tonic-gate 	if (!bldominates(&m_slabel.upper_bound, &m_slabel.lower_bound)) {
1194*7c478bd9Sstevel@tonic-gate 		*--p = ':';
1195*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
1196*7c478bd9Sstevel@tonic-gate 		    gettext("invalid sensitivity label range (%s)"), optstr);
1197*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
1198*7c478bd9Sstevel@tonic-gate 		return (-1);
1199*7c478bd9Sstevel@tonic-gate 	}
1200*7c478bd9Sstevel@tonic-gate 	return (0);
1201*7c478bd9Sstevel@tonic-gate }
1202*7c478bd9Sstevel@tonic-gate #endif	/* !TSOL */
1203*7c478bd9Sstevel@tonic-gate 
1204*7c478bd9Sstevel@tonic-gate /*
1205*7c478bd9Sstevel@tonic-gate  * proc_zonename - pick up zone name.
1206*7c478bd9Sstevel@tonic-gate  *
1207*7c478bd9Sstevel@tonic-gate  * all non-empty and not-too-long strings are valid since any name
1208*7c478bd9Sstevel@tonic-gate  * may be valid.
1209*7c478bd9Sstevel@tonic-gate  *
1210*7c478bd9Sstevel@tonic-gate  * ret 0:	non-empty string
1211*7c478bd9Sstevel@tonic-gate  * ret -1:	empty string or string is too long.
1212*7c478bd9Sstevel@tonic-gate  */
1213*7c478bd9Sstevel@tonic-gate static int
1214*7c478bd9Sstevel@tonic-gate proc_zonename(char *optstr)
1215*7c478bd9Sstevel@tonic-gate {
1216*7c478bd9Sstevel@tonic-gate 	size_t	length = strlen(optstr);
1217*7c478bd9Sstevel@tonic-gate 	if ((length < 1) || (length > ZONENAME_MAX)) {
1218*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
1219*7c478bd9Sstevel@tonic-gate 		    gettext("invalid zone name: %s"), optstr);
1220*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
1221*7c478bd9Sstevel@tonic-gate 		return (-1);
1222*7c478bd9Sstevel@tonic-gate 	}
1223*7c478bd9Sstevel@tonic-gate 	zonename = strdup(optstr);
1224*7c478bd9Sstevel@tonic-gate 	flags |= M_ZONENAME;
1225*7c478bd9Sstevel@tonic-gate 	return (0);
1226*7c478bd9Sstevel@tonic-gate }
1227