xref: /illumos-gate/usr/src/cmd/auditreduce/option.c (revision 047f6e6f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
545916cd2Sjpk  * Common Development and Distribution License (the "License").
645916cd2Sjpk  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*047f6e6fSgww  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Command line option processing for auditreduce.
287c478bd9Sstevel@tonic-gate  * The entry point is process_options(), which is called by main().
297c478bd9Sstevel@tonic-gate  * Process_options() is the only function visible outside this module.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <locale.h>
337c478bd9Sstevel@tonic-gate #include <sys/zone.h>	/* for max zonename length */
347c478bd9Sstevel@tonic-gate #include "auditr.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * Object entry.
387c478bd9Sstevel@tonic-gate  * Maps object strings specified on the command line to a flag
397c478bd9Sstevel@tonic-gate  * used when searching by object type.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate struct obj_ent {
437c478bd9Sstevel@tonic-gate 	char	*obj_str; /* string specified on the command line */
447c478bd9Sstevel@tonic-gate 	int	obj_flag; /* flag used when searching */
457c478bd9Sstevel@tonic-gate };
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate typedef struct obj_ent obj_ent_t;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Supports searches by object type.
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate static obj_ent_t obj_tbl[] = {
537c478bd9Sstevel@tonic-gate 			{ "file", OBJ_PATH },
547c478bd9Sstevel@tonic-gate 			{ "filegroup", OBJ_FGROUP },
557c478bd9Sstevel@tonic-gate 			{ "fileowner", OBJ_FOWNER },
56103b2b15Sgww 			{ "fmri", OBJ_FMRI },
577c478bd9Sstevel@tonic-gate 			{ "lp", OBJ_LP   },
587c478bd9Sstevel@tonic-gate 			{ "msgqid", OBJ_MSG  },
597c478bd9Sstevel@tonic-gate 			{ "msgqgroup", OBJ_MSGGROUP },
607c478bd9Sstevel@tonic-gate 			{ "msgqowner", OBJ_MSGOWNER },
617c478bd9Sstevel@tonic-gate 			{ "path", OBJ_PATH },
627c478bd9Sstevel@tonic-gate 			{ "pid", OBJ_PROC },
637c478bd9Sstevel@tonic-gate 			{ "procgroup", OBJ_PGROUP },
647c478bd9Sstevel@tonic-gate 			{ "procowner", OBJ_POWNER },
657c478bd9Sstevel@tonic-gate 			{ "semid", OBJ_SEM  },
667c478bd9Sstevel@tonic-gate 			{ "semgroup", OBJ_SEMGROUP  },
677c478bd9Sstevel@tonic-gate 			{ "semowner", OBJ_SEMOWNER  },
687c478bd9Sstevel@tonic-gate 			{ "shmid", OBJ_SHM  },
697c478bd9Sstevel@tonic-gate 			{ "shmgroup", OBJ_SHMGROUP  },
707c478bd9Sstevel@tonic-gate 			{ "shmowner", OBJ_SHMOWNER  },
71*047f6e6fSgww 			{ "sock", OBJ_SOCK },
72*047f6e6fSgww 			{ "user", OBJ_USER } };
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate extern int	derive_date(char *, struct tm *);
757c478bd9Sstevel@tonic-gate extern int	parse_time(char *, int);
767c478bd9Sstevel@tonic-gate extern char	*re_comp2(char *);
777c478bd9Sstevel@tonic-gate extern time_t	tm_to_secs(struct tm *);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static int	a_isnum(char *, int);
807c478bd9Sstevel@tonic-gate static int	check_file(audit_fcb_t *, int);
817c478bd9Sstevel@tonic-gate static int	gather_dir(char *);
827c478bd9Sstevel@tonic-gate static audit_pcb_t *get_next_pcb(char *);
837c478bd9Sstevel@tonic-gate static obj_ent_t *obj_lkup(char *);
847c478bd9Sstevel@tonic-gate static int	proc_class(char *);
857c478bd9Sstevel@tonic-gate static int	proc_date(char *, int);
867c478bd9Sstevel@tonic-gate static int	proc_file(char *, int);
877c478bd9Sstevel@tonic-gate static int	process_fileopt(int, char *argv[], int);
887c478bd9Sstevel@tonic-gate static int	proc_group(char *, gid_t *);
897c478bd9Sstevel@tonic-gate static int	proc_id(char *, int);
907c478bd9Sstevel@tonic-gate static int	proc_object(char *);
917c478bd9Sstevel@tonic-gate static void	proc_pcb(audit_pcb_t *, char *, int);
92a13cf099Sgww static int	proc_label(char *);
937c478bd9Sstevel@tonic-gate static int	proc_subject(char *);
94924c9144Sgww static int	proc_sid(char *);
957c478bd9Sstevel@tonic-gate static int	proc_type(char *);
967c478bd9Sstevel@tonic-gate static int	proc_user(char *, uid_t *);
977c478bd9Sstevel@tonic-gate static int	proc_zonename(char *);
98103b2b15Sgww static int	proc_fmri(char *);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * .func	process_options - process command line options.
1027c478bd9Sstevel@tonic-gate  * .desc	Process the user's command line options. These are of two types:
1037c478bd9Sstevel@tonic-gate  *	single letter flags that are denoted by '-', and filenames. Some
1047c478bd9Sstevel@tonic-gate  *	of the flags have arguments. Getopt() is used to get the flags.
1057c478bd9Sstevel@tonic-gate  *	When this is done it calls process_fileopt() to handle any filenames
1067c478bd9Sstevel@tonic-gate  *	that were there.
1077c478bd9Sstevel@tonic-gate  * .call	ret = process_options(argc, argv).
1087c478bd9Sstevel@tonic-gate  * .arg	argc	- the original value.
1097c478bd9Sstevel@tonic-gate  * .arg	argv	- the original value.
1107c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
1117c478bd9Sstevel@tonic-gate  * .ret	-1	- command line error detected (message already printed).
1127c478bd9Sstevel@tonic-gate  */
1137c478bd9Sstevel@tonic-gate int
1147c478bd9Sstevel@tonic-gate process_options(int argc, char **argv)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	int	opt;
1177c478bd9Sstevel@tonic-gate 	int	error = FALSE;
1187c478bd9Sstevel@tonic-gate 	int	error_combo = FALSE;
1197c478bd9Sstevel@tonic-gate 	extern int	optind;		/* in getopt() */
1207c478bd9Sstevel@tonic-gate 	extern char	*optarg;	/* in getopt() - holds arg to flag */
1217c478bd9Sstevel@tonic-gate 
122924c9144Sgww 	static char	*options = "ACD:M:NQR:S:VO:"
123924c9144Sgww 	    "a:b:c:d:e:g:j:l:m:o:r:s:t:u:z:";
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	error_str = gettext("general error");
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	zonename = NULL;
1287c478bd9Sstevel@tonic-gate 	/*
1297c478bd9Sstevel@tonic-gate 	 * Big switch to process the flags.
1307c478bd9Sstevel@tonic-gate 	 * Start_over: is for handling the '-' for standard input. Getopt()
1317c478bd9Sstevel@tonic-gate 	 * doesn't recognize it.
1327c478bd9Sstevel@tonic-gate 	 */
1337c478bd9Sstevel@tonic-gate start_over:
1347c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, options)) != EOF) {
1357c478bd9Sstevel@tonic-gate 		switch (opt) {
1367c478bd9Sstevel@tonic-gate 		case 'A':		/* all records from the files */
1377c478bd9Sstevel@tonic-gate 			f_all = TRUE;
1387c478bd9Sstevel@tonic-gate 			break;
1397c478bd9Sstevel@tonic-gate 		case 'C':		/* process only completed files */
1407c478bd9Sstevel@tonic-gate 			f_complete = TRUE;
1417c478bd9Sstevel@tonic-gate 			break;
1427c478bd9Sstevel@tonic-gate 		case 'D':		/* delete the files when done */
1437c478bd9Sstevel@tonic-gate 			/* force 'A' 'C' 'O' to be active */
1447c478bd9Sstevel@tonic-gate 			f_all = f_complete = TRUE;
1457c478bd9Sstevel@tonic-gate 			f_outfile = optarg;
1467c478bd9Sstevel@tonic-gate 			f_delete = TRUE;
1477c478bd9Sstevel@tonic-gate 			break;
1487c478bd9Sstevel@tonic-gate 		case 'M':		/* only files from a certain machine */
1497c478bd9Sstevel@tonic-gate 			f_machine = optarg;
1507c478bd9Sstevel@tonic-gate 			break;
1517c478bd9Sstevel@tonic-gate 		case 'N':		/* new object selection mode */
1527c478bd9Sstevel@tonic-gate 			new_mode = TRUE;
1537c478bd9Sstevel@tonic-gate 			break;
1547c478bd9Sstevel@tonic-gate 		case 'Q':		/* no file error reporting */
1557c478bd9Sstevel@tonic-gate 			f_quiet = TRUE;
1567c478bd9Sstevel@tonic-gate 			break;
1577c478bd9Sstevel@tonic-gate 		case 'R':		/* from specified root */
1587c478bd9Sstevel@tonic-gate 			f_root = optarg;
1597c478bd9Sstevel@tonic-gate 			break;
1607c478bd9Sstevel@tonic-gate 		case 'S':		/* from specified server */
1617c478bd9Sstevel@tonic-gate 			f_server = optarg;
1627c478bd9Sstevel@tonic-gate 			break;
1637c478bd9Sstevel@tonic-gate 		case 'V':		/* list all files as they are opened */
1647c478bd9Sstevel@tonic-gate 			f_verbose = TRUE;
1657c478bd9Sstevel@tonic-gate 			break;
1667c478bd9Sstevel@tonic-gate 		case 'O':		/* write to outfile */
1677c478bd9Sstevel@tonic-gate 			f_outfile = optarg;
1687c478bd9Sstevel@tonic-gate 			break;
1697c478bd9Sstevel@tonic-gate 		case 'a':		/* after 'date' */
1707c478bd9Sstevel@tonic-gate 		case 'b':		/* before 'date' */
1717c478bd9Sstevel@tonic-gate 		case 'd':		/* from 'day' */
1727c478bd9Sstevel@tonic-gate 			if (proc_date(optarg, opt))
1737c478bd9Sstevel@tonic-gate 				error = TRUE;
1747c478bd9Sstevel@tonic-gate 			break;
1757c478bd9Sstevel@tonic-gate 		case 'j':		/* subject */
1767c478bd9Sstevel@tonic-gate 			if (proc_subject(optarg))
1777c478bd9Sstevel@tonic-gate 				error = TRUE;
1787c478bd9Sstevel@tonic-gate 			break;
1797c478bd9Sstevel@tonic-gate 		case 'm':		/* message 'type' */
1807c478bd9Sstevel@tonic-gate 			if (proc_type(optarg))
1817c478bd9Sstevel@tonic-gate 				error = TRUE;
1827c478bd9Sstevel@tonic-gate 			break;
1837c478bd9Sstevel@tonic-gate 		case 'o':		/* object type */
1847c478bd9Sstevel@tonic-gate 			if (proc_object(optarg))
1857c478bd9Sstevel@tonic-gate 				error = TRUE;
1867c478bd9Sstevel@tonic-gate 			break;
1877c478bd9Sstevel@tonic-gate 		case 'c':		/* message class */
1887c478bd9Sstevel@tonic-gate 			if (proc_class(optarg))
1897c478bd9Sstevel@tonic-gate 				error = TRUE;
1907c478bd9Sstevel@tonic-gate 			break;
1917c478bd9Sstevel@tonic-gate 		case 'u':		/* form audit user */
1927c478bd9Sstevel@tonic-gate 		case 'e':		/* form effective user */
1937c478bd9Sstevel@tonic-gate 		case 'r':		/* form real user */
1947c478bd9Sstevel@tonic-gate 		case 'f':		/* form effective group */
1957c478bd9Sstevel@tonic-gate 		case 'g':		/* form real group */
1967c478bd9Sstevel@tonic-gate 			if (proc_id(optarg, opt))
1977c478bd9Sstevel@tonic-gate 				error = TRUE;
1987c478bd9Sstevel@tonic-gate 			break;
199a13cf099Sgww 		case 'l':		/* TX label range */
20045916cd2Sjpk 			if (!is_system_labeled()) {
20145916cd2Sjpk 				(void) fprintf(stderr,
20245916cd2Sjpk 				    gettext("%s option 'l' requires "
20345916cd2Sjpk 				    "Trusted Extensions.\n"), ar);
20445916cd2Sjpk 				return (-1);
20545916cd2Sjpk 			}
206a13cf099Sgww 			if (proc_label(optarg))
2077c478bd9Sstevel@tonic-gate 				error = TRUE;
2087c478bd9Sstevel@tonic-gate 			break;
209924c9144Sgww 		case 's':		/* session ID */
210924c9144Sgww 			if (proc_sid(optarg))
211924c9144Sgww 				error = TRUE;
212924c9144Sgww 			break;
2137c478bd9Sstevel@tonic-gate 		case 'z':		/* zone name */
2147c478bd9Sstevel@tonic-gate 			if (proc_zonename(optarg))
2157c478bd9Sstevel@tonic-gate 				error = TRUE;
2167c478bd9Sstevel@tonic-gate 			break;
217924c9144Sgww 		case 't':		/* termial ID reserved for later */
2187c478bd9Sstevel@tonic-gate 		default:
2197c478bd9Sstevel@tonic-gate 			return (-1);
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 		if (error) {
2227c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
223406d6273SPalle Lyckegaard 			    gettext("%s command line error - %s.\n"),
224406d6273SPalle Lyckegaard 			    ar, error_str);
2257c478bd9Sstevel@tonic-gate 			return (-1);
2267c478bd9Sstevel@tonic-gate 		}
2277c478bd9Sstevel@tonic-gate 	}
2287c478bd9Sstevel@tonic-gate 	/* catch '-' option for stdin processing - getopt() won't see it */
2297c478bd9Sstevel@tonic-gate 	if (optind < argc) {
2307c478bd9Sstevel@tonic-gate 		if (argv[optind][0] == '-' && argv[optind][1] == '\0') {
2317c478bd9Sstevel@tonic-gate 			optind++;
2327c478bd9Sstevel@tonic-gate 			f_stdin = TRUE;
2337c478bd9Sstevel@tonic-gate 			goto start_over;
2347c478bd9Sstevel@tonic-gate 		}
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate 	/*
2377c478bd9Sstevel@tonic-gate 	 * Give a default value for 'b' option if not specified.
2387c478bd9Sstevel@tonic-gate 	 */
2397c478bd9Sstevel@tonic-gate 	if (m_before == 0)
2407c478bd9Sstevel@tonic-gate 		m_before = MAXLONG;	/* forever */
2417c478bd9Sstevel@tonic-gate 	/*
2427c478bd9Sstevel@tonic-gate 	 * Validate combinations of options.
2437c478bd9Sstevel@tonic-gate 	 * The following are done:
2447c478bd9Sstevel@tonic-gate 	 *	1. Can't have 'M' or 'S' or 'R' with filenames.
2457c478bd9Sstevel@tonic-gate 	 *	2. Can't have an after ('a') time after a before ('b') time.
2467c478bd9Sstevel@tonic-gate 	 *	3. Delete ('D') must have 'C' and 'A' and 'O' with it.
2477c478bd9Sstevel@tonic-gate 	 *	4. Input from stdin ('-') can't have filenames too.
2487c478bd9Sstevel@tonic-gate 	 */
2497c478bd9Sstevel@tonic-gate 	if ((f_machine || f_server || f_root) && (argc != optind)) {
2507c478bd9Sstevel@tonic-gate 		error_str = gettext(
2517c478bd9Sstevel@tonic-gate 		    "no filenames allowed with 'M' or 'S' or 'R' options");
2527c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 	if (m_after >= m_before) {
2557c478bd9Sstevel@tonic-gate 		error_str =
256406d6273SPalle Lyckegaard 		    gettext("'a' parameter must be before 'b' parameter");
2577c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 	if (f_delete &&
2607c478bd9Sstevel@tonic-gate 	    (!f_complete || !f_all || !f_outfile)) {
2617c478bd9Sstevel@tonic-gate 		error_str = gettext(
2627c478bd9Sstevel@tonic-gate 		    "'C', 'A', and 'O' must be specified with 'D'");
2637c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 	if (f_stdin && (argc != optind)) {
2667c478bd9Sstevel@tonic-gate 		error_str = gettext("no filenames allowed with '-' option");
2677c478bd9Sstevel@tonic-gate 		error_combo = TRUE;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	/*
2707c478bd9Sstevel@tonic-gate 	 * If error with option combos then print message and exit.
2717c478bd9Sstevel@tonic-gate 	 * If there was an error with just an option then exit.
2727c478bd9Sstevel@tonic-gate 	 */
2737c478bd9Sstevel@tonic-gate 	if (error_combo) {
2747c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
2757c478bd9Sstevel@tonic-gate 		    gettext("%s command line error - %s.\n"), ar, error_str);
2767c478bd9Sstevel@tonic-gate 		return (-1);
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	if (f_root == NULL)
2797c478bd9Sstevel@tonic-gate 		f_root = "/etc/security/audit";
2807c478bd9Sstevel@tonic-gate 	/*
2817c478bd9Sstevel@tonic-gate 	 * Now handle any filenames included in the command line.
2827c478bd9Sstevel@tonic-gate 	 */
2837c478bd9Sstevel@tonic-gate 	return (process_fileopt(argc, argv, optind));
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate int
2877c478bd9Sstevel@tonic-gate proc_subject(char *optarg)
2887c478bd9Sstevel@tonic-gate {
2897c478bd9Sstevel@tonic-gate 	if (flags & M_SUBJECT) {
2907c478bd9Sstevel@tonic-gate 		error_str = gettext("'j' option specified multiple times");
2917c478bd9Sstevel@tonic-gate 		return (-1);
2927c478bd9Sstevel@tonic-gate 	}
2937c478bd9Sstevel@tonic-gate 	flags |= M_SUBJECT;
2947c478bd9Sstevel@tonic-gate 	subj_id = atol(optarg);
2957c478bd9Sstevel@tonic-gate 	return (0);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
298924c9144Sgww int
299924c9144Sgww proc_sid(char *optarg)
300924c9144Sgww {
301924c9144Sgww 	if (flags & M_SID) {
302924c9144Sgww 		error_str = gettext("'s' option specified multiple times");
303924c9144Sgww 		return (-1);
304924c9144Sgww 	}
305924c9144Sgww 	flags |= M_SID;
306d0fa49b7STony Nguyen 	m_sid = (au_asid_t)atol(optarg);
307924c9144Sgww 	return (0);
308924c9144Sgww }
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate int
3117c478bd9Sstevel@tonic-gate proc_object(char *optarg)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	char	*obj_str;
3147c478bd9Sstevel@tonic-gate 	char	*obj_val;
3157c478bd9Sstevel@tonic-gate 	char	*obj_arg;
3167c478bd9Sstevel@tonic-gate 	int	err;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	obj_ent_t *oep;
3197c478bd9Sstevel@tonic-gate 	struct hostent *he;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	if (flags & M_OBJECT) {
3227c478bd9Sstevel@tonic-gate 		error_str = gettext("'o' option specified multiple times");
3237c478bd9Sstevel@tonic-gate 		return (-1);
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 	flags |= M_OBJECT;
3267c478bd9Sstevel@tonic-gate 	if ((obj_arg = strdup(optarg)) == (char *)0)
3277c478bd9Sstevel@tonic-gate 		return (-1);
3287c478bd9Sstevel@tonic-gate 	if ((obj_str = strtok(optarg, "=")) == (char *)0 ||
3297c478bd9Sstevel@tonic-gate 	    (oep = obj_lkup(obj_str)) == (obj_ent_t *)0 ||
3307c478bd9Sstevel@tonic-gate 	    (obj_val = strtok((char *)0, "=")) == (char *)0) {
3317c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid object arg (%s)"),
3327c478bd9Sstevel@tonic-gate 		    obj_arg);
3337c478bd9Sstevel@tonic-gate 		error_str = errbuf;
3347c478bd9Sstevel@tonic-gate 		return (-1);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	obj_flag = oep->obj_flag;
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	switch (obj_flag) {
3407c478bd9Sstevel@tonic-gate 	case OBJ_PATH:
3417c478bd9Sstevel@tonic-gate 		if ((error_str = re_comp2(obj_val)) != (char *)NULL) {
3427c478bd9Sstevel@tonic-gate 			return (-1);
3437c478bd9Sstevel@tonic-gate 		}
3447c478bd9Sstevel@tonic-gate 		return (0);
3457c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
3467c478bd9Sstevel@tonic-gate 	case OBJ_SOCK:
3477c478bd9Sstevel@tonic-gate 		if (!a_isnum(obj_val, TRUE)) {
3487c478bd9Sstevel@tonic-gate 			obj_id = atol(obj_val);
3497c478bd9Sstevel@tonic-gate 			socket_flag = SOCKFLG_PORT;
3507c478bd9Sstevel@tonic-gate 			return (0);
3517c478bd9Sstevel@tonic-gate 		}
3527c478bd9Sstevel@tonic-gate 		if (*obj_val == '0') {
3537c478bd9Sstevel@tonic-gate 			(void) sscanf(obj_val, "%x", (uint_t *)&obj_id);
3547c478bd9Sstevel@tonic-gate 			socket_flag = SOCKFLG_PORT;
3557c478bd9Sstevel@tonic-gate 			return (0);
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		he = getipnodebyname((const void *)obj_val, AF_INET6, 0, &err);
3597c478bd9Sstevel@tonic-gate 		if (he == 0) {
3607c478bd9Sstevel@tonic-gate 			he = getipnodebyname((const void *)obj_val, AF_INET,
3617c478bd9Sstevel@tonic-gate 			    0, &err);
3627c478bd9Sstevel@tonic-gate 			if (he == 0) {
3637c478bd9Sstevel@tonic-gate 				(void) sprintf(errbuf,
3647c478bd9Sstevel@tonic-gate 				    gettext("invalid machine name (%s)"),
3657c478bd9Sstevel@tonic-gate 				    obj_val);
3667c478bd9Sstevel@tonic-gate 				error_str = errbuf;
3677c478bd9Sstevel@tonic-gate 				return (-1);
3687c478bd9Sstevel@tonic-gate 			}
3697c478bd9Sstevel@tonic-gate 		}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 		if (he->h_addrtype == AF_INET6) {
3727c478bd9Sstevel@tonic-gate 			/* LINTED */
373406d6273SPalle Lyckegaard 			if (IN6_IS_ADDR_V4MAPPED(
374406d6273SPalle Lyckegaard 			    (in6_addr_t *)he->h_addr_list[0])) {
3757c478bd9Sstevel@tonic-gate 				/* address is IPv4 (32 bits) */
3769073e376SMarek Pospisil 				(void) memcpy(&obj_id,
3779073e376SMarek Pospisil 				    he->h_addr_list[0] + 12, 4);
3787c478bd9Sstevel@tonic-gate 				ip_type = AU_IPv4;
3797c478bd9Sstevel@tonic-gate 			} else {
3807c478bd9Sstevel@tonic-gate 				(void) memcpy(ip_ipv6, he->h_addr_list[0], 16);
3817c478bd9Sstevel@tonic-gate 				ip_type = AU_IPv6;
3827c478bd9Sstevel@tonic-gate 			}
3837c478bd9Sstevel@tonic-gate 		} else {
3847c478bd9Sstevel@tonic-gate 			/* address is IPv4 (32 bits) */
3857c478bd9Sstevel@tonic-gate 			(void) memcpy(&obj_id, he->h_addr_list[0], 4);
3867c478bd9Sstevel@tonic-gate 			ip_type = AU_IPv4;
3877c478bd9Sstevel@tonic-gate 		}
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 		freehostent(he);
3907c478bd9Sstevel@tonic-gate 		socket_flag = SOCKFLG_MACHINE;
3917c478bd9Sstevel@tonic-gate 		return (0);
3927c478bd9Sstevel@tonic-gate 		break;
3937c478bd9Sstevel@tonic-gate 	case OBJ_MSG:
3947c478bd9Sstevel@tonic-gate 	case OBJ_SEM:
3957c478bd9Sstevel@tonic-gate 	case OBJ_SHM:
3967c478bd9Sstevel@tonic-gate 	case OBJ_PROC:
3977c478bd9Sstevel@tonic-gate 		obj_id = atol(obj_val);
3987c478bd9Sstevel@tonic-gate 		return (0);
3997c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
4007c478bd9Sstevel@tonic-gate 	case OBJ_FGROUP:
4017c478bd9Sstevel@tonic-gate 	case OBJ_MSGGROUP:
4027c478bd9Sstevel@tonic-gate 	case OBJ_SEMGROUP:
4037c478bd9Sstevel@tonic-gate 	case OBJ_SHMGROUP:
4047c478bd9Sstevel@tonic-gate 	case OBJ_PGROUP:
4057c478bd9Sstevel@tonic-gate 		return (proc_group(obj_val, &obj_group));
4067c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
4077c478bd9Sstevel@tonic-gate 	case OBJ_FOWNER:
4087c478bd9Sstevel@tonic-gate 	case OBJ_MSGOWNER:
4097c478bd9Sstevel@tonic-gate 	case OBJ_SEMOWNER:
4107c478bd9Sstevel@tonic-gate 	case OBJ_SHMOWNER:
4117c478bd9Sstevel@tonic-gate 	case OBJ_POWNER:
4127c478bd9Sstevel@tonic-gate 		return (proc_user(obj_val, &obj_owner));
4137c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
414103b2b15Sgww 	case OBJ_FMRI:
415103b2b15Sgww 		return (proc_fmri(obj_val));
416103b2b15Sgww 		/* NOTREACHED */
417*047f6e6fSgww 	case OBJ_USER:
418*047f6e6fSgww 		return (proc_user(obj_val, &obj_user));
419*047f6e6fSgww 		/* NOTREACHED */
4207c478bd9Sstevel@tonic-gate 	case OBJ_LP: /* lp objects have not yet been defined */
4217c478bd9Sstevel@tonic-gate 	default: /* impossible */
4227c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid object type (%s)"),
4237c478bd9Sstevel@tonic-gate 		    obj_str);
4247c478bd9Sstevel@tonic-gate 		error_str = errbuf;
4257c478bd9Sstevel@tonic-gate 		return (-1);
4267c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
4277c478bd9Sstevel@tonic-gate 	} /* switch */
4287c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate obj_ent_t *
4337c478bd9Sstevel@tonic-gate obj_lkup(char *obj_str)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	int	i;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (obj_tbl) / sizeof (obj_ent_t); i++)
4387c478bd9Sstevel@tonic-gate 		if (strcmp(obj_str, obj_tbl[i].obj_str) == 0)
4397c478bd9Sstevel@tonic-gate 			return (&obj_tbl[i]);
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	/* not in table */
442d0fa49b7STony Nguyen 	return (NULL);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * .func	proc_type - process record type.
4487c478bd9Sstevel@tonic-gate  * .desc	Process a record type. It is either as a number or a mnemonic.
4497c478bd9Sstevel@tonic-gate  * .call	ret = proc_type(optstr).
4507c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to name or number.
4517c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
4527c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (error_str contains description).
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate int
4557c478bd9Sstevel@tonic-gate proc_type(char *optstr)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	struct au_event_ent *aep;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	/*
4607c478bd9Sstevel@tonic-gate 	 * Either a number or a name.
4617c478bd9Sstevel@tonic-gate 	 */
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	if (flags & M_TYPE) {
4647c478bd9Sstevel@tonic-gate 		error_str = gettext("'m' option specified multiple times");
4657c478bd9Sstevel@tonic-gate 		return (-1);
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 	flags |= M_TYPE;
4687c478bd9Sstevel@tonic-gate 	m_type = 0;
4697c478bd9Sstevel@tonic-gate 	if (a_isnum(optstr, TRUE)) {
470d0fa49b7STony Nguyen 		if ((aep = getauevnam(optstr)) != NULL)
4717c478bd9Sstevel@tonic-gate 			m_type = aep->ae_number;
4727c478bd9Sstevel@tonic-gate 	} else {
4737c478bd9Sstevel@tonic-gate 		if ((aep = getauevnum((au_event_t)atoi(optstr))) !=
4747c478bd9Sstevel@tonic-gate 		    (struct au_event_ent *)NULL)
4757c478bd9Sstevel@tonic-gate 			m_type = aep->ae_number;
4767c478bd9Sstevel@tonic-gate 	}
4777c478bd9Sstevel@tonic-gate 	if ((m_type == 0)) {
4787c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("invalid event (%s)"), optstr);
4797c478bd9Sstevel@tonic-gate 		error_str = errbuf;
4807c478bd9Sstevel@tonic-gate 		return (-1);
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 	return (0);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate /*
4877c478bd9Sstevel@tonic-gate  * .func	a_isnum - is it a number?
4887c478bd9Sstevel@tonic-gate  * .desc	Determine if a string is a number or a name.
4897c478bd9Sstevel@tonic-gate  *	A number may have a leading '+' or '-', but then must be
4907c478bd9Sstevel@tonic-gate  *	all digits.
4917c478bd9Sstevel@tonic-gate  * .call	ret = a_isnum(str).
4927c478bd9Sstevel@tonic-gate  * .arg	str - ptr to the string.
4937c478bd9Sstevel@tonic-gate  * .arg	leading	- TRUE if leading '+-' allowed.
4947c478bd9Sstevel@tonic-gate  * .ret	0	- is a number.
4957c478bd9Sstevel@tonic-gate  * .ret	1	- is not a number.
4967c478bd9Sstevel@tonic-gate  */
4977c478bd9Sstevel@tonic-gate int
4987c478bd9Sstevel@tonic-gate a_isnum(char *str, int leading)
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate 	char	*strs;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	if ((leading == TRUE) && (*str == '-' || *str == '+'))
5037c478bd9Sstevel@tonic-gate 		strs = str + 1;
5047c478bd9Sstevel@tonic-gate 	else
5057c478bd9Sstevel@tonic-gate 		strs = str;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	if (strlen(strs) == strspn(strs, "0123456789"))
5087c478bd9Sstevel@tonic-gate 		return (0);
5097c478bd9Sstevel@tonic-gate 	else
5107c478bd9Sstevel@tonic-gate 		return (1);
5117c478bd9Sstevel@tonic-gate }
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate /*
5157c478bd9Sstevel@tonic-gate  * .func	proc_id	- process user/group id's/
5167c478bd9Sstevel@tonic-gate  * .desc	Process either a user number/name or group number/name.
5177c478bd9Sstevel@tonic-gate  *	For names check to see if the name is active in the system
5187c478bd9Sstevel@tonic-gate  *	to derive the number. If it is not active then fail. For a number
5197c478bd9Sstevel@tonic-gate  *	also check to see if it is active, but only print a warning if it
5207c478bd9Sstevel@tonic-gate  *	is not. An administrator may be looking at activity of a 'phantom'
5217c478bd9Sstevel@tonic-gate  *	user.
5227c478bd9Sstevel@tonic-gate  * .call	ret = proc_id(optstr, opt).
5237c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to name or number.
5247c478bd9Sstevel@tonic-gate  * .arg	opt	- 'u' - audit user, 'e' - effective user, 'r' - real user,
5257c478bd9Sstevel@tonic-gate  *		  'g' - group, 'f' - effective group.
5267c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
5277c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (error_str contains description).
5287c478bd9Sstevel@tonic-gate  */
5297c478bd9Sstevel@tonic-gate int
5307c478bd9Sstevel@tonic-gate proc_id(char *optstr, int opt)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	switch (opt) {
5337c478bd9Sstevel@tonic-gate 	case 'e': 		/* effective user id */
5347c478bd9Sstevel@tonic-gate 		if (flags & M_USERE) {
5357c478bd9Sstevel@tonic-gate 			error_str = gettext(
5367c478bd9Sstevel@tonic-gate 			    "'e' option specified multiple times");
5377c478bd9Sstevel@tonic-gate 			return (-1);
5387c478bd9Sstevel@tonic-gate 		}
5397c478bd9Sstevel@tonic-gate 		flags |= M_USERE;
5407c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_usere));
5417c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5427c478bd9Sstevel@tonic-gate 	case 'f': 		/* effective group id */
5437c478bd9Sstevel@tonic-gate 		if (flags & M_GROUPE) {
5447c478bd9Sstevel@tonic-gate 			error_str = gettext(
5457c478bd9Sstevel@tonic-gate 			    "'f' option specified multiple times");
5467c478bd9Sstevel@tonic-gate 			return (-1);
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 		flags |= M_GROUPE;
5497c478bd9Sstevel@tonic-gate 		return (proc_group(optstr, &m_groupe));
5507c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5517c478bd9Sstevel@tonic-gate 	case 'r': 		/* real user id */
5527c478bd9Sstevel@tonic-gate 		if (flags & M_USERR) {
5537c478bd9Sstevel@tonic-gate 			error_str = gettext(
5547c478bd9Sstevel@tonic-gate 			    "'r' option specified multiple times");
5557c478bd9Sstevel@tonic-gate 			return (-1);
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 		flags |= M_USERR;
5587c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_userr));
5597c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5607c478bd9Sstevel@tonic-gate 	case 'u': 		/* audit user id */
5617c478bd9Sstevel@tonic-gate 		if (flags & M_USERA) {
5627c478bd9Sstevel@tonic-gate 			error_str = gettext(
5637c478bd9Sstevel@tonic-gate 			    "'u' option specified multiple times");
5647c478bd9Sstevel@tonic-gate 			return (-1);
5657c478bd9Sstevel@tonic-gate 		}
5667c478bd9Sstevel@tonic-gate 		flags |= M_USERA;
5677c478bd9Sstevel@tonic-gate 		return (proc_user(optstr, &m_usera));
5687c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5697c478bd9Sstevel@tonic-gate 	case 'g': 		/* real group id */
5707c478bd9Sstevel@tonic-gate 		if (flags & M_GROUPR) {
5717c478bd9Sstevel@tonic-gate 			error_str = gettext(
5727c478bd9Sstevel@tonic-gate 			    "'g' option specified multiple times");
5737c478bd9Sstevel@tonic-gate 			return (-1);
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 		flags |= M_GROUPR;
5767c478bd9Sstevel@tonic-gate 		return (proc_group(optstr, &m_groupr));
5777c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5787c478bd9Sstevel@tonic-gate 	default: 		/* impossible */
5797c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("'%c' unknown option"), opt);
5807c478bd9Sstevel@tonic-gate 		error_str = errbuf;
5817c478bd9Sstevel@tonic-gate 		return (-1);
5827c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate int
5897c478bd9Sstevel@tonic-gate proc_group(char *optstr, gid_t *gid)
5907c478bd9Sstevel@tonic-gate {
5917c478bd9Sstevel@tonic-gate 	struct group *grp;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	if ((grp = getgrnam(optstr)) == NULL) {
5947c478bd9Sstevel@tonic-gate 		if (!a_isnum(optstr, TRUE)) {
5957c478bd9Sstevel@tonic-gate 			*gid = (gid_t)atoi(optstr);
5967c478bd9Sstevel@tonic-gate 			return (0);
5977c478bd9Sstevel@tonic-gate 		}
5987c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("group name invalid (%s)"),
5997c478bd9Sstevel@tonic-gate 		    optstr);
6007c478bd9Sstevel@tonic-gate 		error_str = errbuf;
6017c478bd9Sstevel@tonic-gate 		return (-1);
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 	*gid = grp->gr_gid;
6047c478bd9Sstevel@tonic-gate 	return (0);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate int
6097c478bd9Sstevel@tonic-gate proc_user(char *optstr, uid_t *uid)
6107c478bd9Sstevel@tonic-gate {
6117c478bd9Sstevel@tonic-gate 	struct passwd *usr;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	if ((usr = getpwnam(optstr)) == NULL) {
6147c478bd9Sstevel@tonic-gate 		if (!a_isnum(optstr, TRUE)) {
6157c478bd9Sstevel@tonic-gate 			*uid = (uid_t)atoi(optstr);
6167c478bd9Sstevel@tonic-gate 			return (0);
6177c478bd9Sstevel@tonic-gate 		}
6187c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("user name invalid (%s)"),
6197c478bd9Sstevel@tonic-gate 		    optstr);
6207c478bd9Sstevel@tonic-gate 		error_str = errbuf;
6217c478bd9Sstevel@tonic-gate 		return (-1);
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate 	*uid = usr->pw_uid;
6247c478bd9Sstevel@tonic-gate 	return (0);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate /*
6297c478bd9Sstevel@tonic-gate  * .func proc_date - process date argument.
6307c478bd9Sstevel@tonic-gate  * .desc Handle a date/time argument. See if the user has erred in combining
6317c478bd9Sstevel@tonic-gate  *	the types of date arguments. Then parse the string and check for
6327c478bd9Sstevel@tonic-gate  *	validity of each part.
6337c478bd9Sstevel@tonic-gate  * .call	ret = proc_date(optstr, opt).
6347c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to date/time string.
6357c478bd9Sstevel@tonic-gate  * .arg	opt	- 'd' for day, 'a' for after, or 'b' for before.
6367c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
6377c478bd9Sstevel@tonic-gate  * .ret	-1	- errors detected (error_str knows what it is).
6387c478bd9Sstevel@tonic-gate  */
6397c478bd9Sstevel@tonic-gate int
6407c478bd9Sstevel@tonic-gate proc_date(char *optstr, int opt)
6417c478bd9Sstevel@tonic-gate {
6427c478bd9Sstevel@tonic-gate 	static int	m_day = FALSE;
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	if (opt == 'd') {
6457c478bd9Sstevel@tonic-gate 		if (m_day == TRUE) {
6467c478bd9Sstevel@tonic-gate 			error_str = gettext(
6477c478bd9Sstevel@tonic-gate 			    "'d' option may not be used with 'a' or 'b'");
6487c478bd9Sstevel@tonic-gate 			return (-1);
6497c478bd9Sstevel@tonic-gate 		}
6507c478bd9Sstevel@tonic-gate 		m_day = TRUE;
6517c478bd9Sstevel@tonic-gate 	}
6527c478bd9Sstevel@tonic-gate 	if ((opt == 'd') && (m_before || m_after)) {
6537c478bd9Sstevel@tonic-gate 		error_str = gettext(
6547c478bd9Sstevel@tonic-gate 		    "'d' option may not be used with 'a' or 'b'");
6557c478bd9Sstevel@tonic-gate 		return (-1);
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate 	if ((opt == 'a' || opt == 'b') && m_day) {
6587c478bd9Sstevel@tonic-gate 		error_str = gettext(
6597c478bd9Sstevel@tonic-gate 		    "'a' or 'b' option may not be used with 'd'");
6607c478bd9Sstevel@tonic-gate 		return (-1);
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 	if ((opt == 'a') && (m_after != 0)) {
6637c478bd9Sstevel@tonic-gate 		error_str = gettext("'a' option specified multiple times");
6647c478bd9Sstevel@tonic-gate 		return (-1);
6657c478bd9Sstevel@tonic-gate 	}
6667c478bd9Sstevel@tonic-gate 	if ((opt == 'b') && (m_before != 0)) {
6677c478bd9Sstevel@tonic-gate 		error_str = gettext("'b' option specified multiple times");
6687c478bd9Sstevel@tonic-gate 		return (-1);
6697c478bd9Sstevel@tonic-gate 	}
6707c478bd9Sstevel@tonic-gate 	if (parse_time(optstr, opt))
6717c478bd9Sstevel@tonic-gate 		return (-1);
6727c478bd9Sstevel@tonic-gate 	return (0);
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate  * .func	proc_class - process message class argument.
6787c478bd9Sstevel@tonic-gate  * .desc	Process class type and see if it is for real.
6797c478bd9Sstevel@tonic-gate  * .call	ret = proc_class(optstr).
6807c478bd9Sstevel@tonic-gate  * .arg	optstr	- ptr to class.
6817c478bd9Sstevel@tonic-gate  * .ret	0	- class has class.
6827c478bd9Sstevel@tonic-gate  * .ret	-1	- class in no good.
6837c478bd9Sstevel@tonic-gate  */
6847c478bd9Sstevel@tonic-gate int
6857c478bd9Sstevel@tonic-gate proc_class(char *optstr)
6867c478bd9Sstevel@tonic-gate {
6877c478bd9Sstevel@tonic-gate 	if (flags & M_CLASS) {
6887c478bd9Sstevel@tonic-gate 		error_str = gettext("'c' option specified multiple times");
6897c478bd9Sstevel@tonic-gate 		return (-1);
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate 	flags |= M_CLASS;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	if (getauditflagsbin(optstr, &mask) != 0) {
6947c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("unknown class (%s)"), optstr);
6957c478bd9Sstevel@tonic-gate 		error_str = errbuf;
6967c478bd9Sstevel@tonic-gate 		return (-1);
6977c478bd9Sstevel@tonic-gate 	}
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	if (mask.am_success != mask.am_failure) {
7007c478bd9Sstevel@tonic-gate 		flags |= M_SORF;
7017c478bd9Sstevel@tonic-gate 	}
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	return (0);
7047c478bd9Sstevel@tonic-gate }
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate /*
7087c478bd9Sstevel@tonic-gate  * .func process_fileopt - process command line file options.
7097c478bd9Sstevel@tonic-gate  * .desc Process the command line file options and gather the specified files
7107c478bd9Sstevel@tonic-gate  *	together in file groups based upon file name suffix. The user can
7117c478bd9Sstevel@tonic-gate  *	specify files explicitly on the command line or via a directory.
7127c478bd9Sstevel@tonic-gate  *	This is called after the command line flags are processed (as
7137c478bd9Sstevel@tonic-gate  *	denoted by '-').
7147c478bd9Sstevel@tonic-gate  * .call	ret = process_fileopt(argc, argv, optindex).
7157c478bd9Sstevel@tonic-gate  * .arg	argc	- current value of argc.
7167c478bd9Sstevel@tonic-gate  * .arg	argv	- current value of argv.
7177c478bd9Sstevel@tonic-gate  * .arg	optindex- current index into argv (as setup by getopt()).
7187c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
7197c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (message already printed).
7207c478bd9Sstevel@tonic-gate  */
7217c478bd9Sstevel@tonic-gate int
7227c478bd9Sstevel@tonic-gate process_fileopt(int argc, char **argv, int optindex)
7237c478bd9Sstevel@tonic-gate {
7247c478bd9Sstevel@tonic-gate 	int	f_mode = FM_ALLDIR;
7257c478bd9Sstevel@tonic-gate 	char	f_dr[MAXNAMLEN+1];
7267c478bd9Sstevel@tonic-gate 	char	*f_dir = f_dr;
7277c478bd9Sstevel@tonic-gate 	char	*fname;
7287c478bd9Sstevel@tonic-gate 	static char	*std = "standard input";
7297c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb;
7307c478bd9Sstevel@tonic-gate 	DIR * dirp;
7317c478bd9Sstevel@tonic-gate 	struct dirent *dp;
7327c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	/*
7357c478bd9Sstevel@tonic-gate 	 * Take input from stdin, not any files.
7367c478bd9Sstevel@tonic-gate 	 * Use a single fcb to do this.
7377c478bd9Sstevel@tonic-gate 	 */
7387c478bd9Sstevel@tonic-gate 	if (f_stdin) {
7397c478bd9Sstevel@tonic-gate 		fcb = (audit_fcb_t *)a_calloc(1, sizeof (*fcb) + strlen(std));
7407c478bd9Sstevel@tonic-gate 		(void) strcpy(fcb->fcb_file, std);
7417c478bd9Sstevel@tonic-gate 		fcb->fcb_suffix = fcb->fcb_name = fcb->fcb_file;
7427c478bd9Sstevel@tonic-gate 		fcb->fcb_next = NULL;
7437c478bd9Sstevel@tonic-gate 		fcb->fcb_start = 0;
7447c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
7457c478bd9Sstevel@tonic-gate 		if ((pcb = get_next_pcb((char *)NULL)) == (audit_pcb_t *)NULL)
7467c478bd9Sstevel@tonic-gate 			return (-1);
7477c478bd9Sstevel@tonic-gate 		pcb->pcb_suffix = fcb->fcb_file;
7487c478bd9Sstevel@tonic-gate 		pcb->pcb_dfirst = pcb->pcb_first = fcb;	/* one-item list */
7497c478bd9Sstevel@tonic-gate 		pcb->pcb_dlast = pcb->pcb_last = fcb;
7507c478bd9Sstevel@tonic-gate 		pcb->pcb_cur = fcb;
7517c478bd9Sstevel@tonic-gate 	}
7527c478bd9Sstevel@tonic-gate 	/*
7537c478bd9Sstevel@tonic-gate 	 * No files specified on the command line.
7547c478bd9Sstevel@tonic-gate 	 * Process a directory of files or subdirectories.
7557c478bd9Sstevel@tonic-gate 	 */
7567c478bd9Sstevel@tonic-gate 	else if (argc == optindex) {
7577c478bd9Sstevel@tonic-gate 		/*
7587c478bd9Sstevel@tonic-gate 		 * A specific server directory was requested.
7597c478bd9Sstevel@tonic-gate 		 */
7607c478bd9Sstevel@tonic-gate 		if (f_server) {
7617c478bd9Sstevel@tonic-gate 			if (strchr(f_server, '/')) {	/* given full path */
7627c478bd9Sstevel@tonic-gate 				f_dir = f_server;
7637c478bd9Sstevel@tonic-gate 				f_mode = FM_ALLFILE;	/* all files here */
7647c478bd9Sstevel@tonic-gate 			} else {		/* directory off audit root */
7657c478bd9Sstevel@tonic-gate 				f_dir[0] = '\0';
7667c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_root);
7677c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, "/");
7687c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_server);
7697c478bd9Sstevel@tonic-gate 				f_mode = FM_ALLFILE;
7707c478bd9Sstevel@tonic-gate 			}
7717c478bd9Sstevel@tonic-gate 		}
7727c478bd9Sstevel@tonic-gate 		/*
7737c478bd9Sstevel@tonic-gate 		 * Gather all of the files in the directory 'f_dir'.
7747c478bd9Sstevel@tonic-gate 		 */
7757c478bd9Sstevel@tonic-gate 		if (f_mode == FM_ALLFILE) {
7767c478bd9Sstevel@tonic-gate 			if (gather_dir(f_dir)) { /* get those files together */
7777c478bd9Sstevel@tonic-gate 				return (-1);
7787c478bd9Sstevel@tonic-gate 			}
7797c478bd9Sstevel@tonic-gate 		} else {
7807c478bd9Sstevel@tonic-gate 			/*
7817c478bd9Sstevel@tonic-gate 			 * Gather all of the files in all of the
7827c478bd9Sstevel@tonic-gate 			 * directories in 'f_root'.
7837c478bd9Sstevel@tonic-gate 			 */
7847c478bd9Sstevel@tonic-gate 			if ((dirp = opendir(f_root)) == NULL) {
7857c478bd9Sstevel@tonic-gate 				(void) sprintf(errbuf, gettext(
7867c478bd9Sstevel@tonic-gate 				    "%s can't open directory %s"), ar, f_root);
7877c478bd9Sstevel@tonic-gate 				perror(errbuf);
7887c478bd9Sstevel@tonic-gate 				return (-1);
7897c478bd9Sstevel@tonic-gate 			}
7907c478bd9Sstevel@tonic-gate 			/* read the directory and process all of the subs */
7917c478bd9Sstevel@tonic-gate 			for (dp = readdir(dirp);
7927c478bd9Sstevel@tonic-gate 			    dp != NULL; dp = readdir(dirp)) {
7937c478bd9Sstevel@tonic-gate 				if (dp->d_name[0] == '.')
7947c478bd9Sstevel@tonic-gate 					continue;
7957c478bd9Sstevel@tonic-gate 				f_dir[0] = '\0';
7967c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, f_root);
7977c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, "/");
7987c478bd9Sstevel@tonic-gate 				(void) strcat(f_dir, dp->d_name);
7997c478bd9Sstevel@tonic-gate 				if (gather_dir(f_dir))	/* process a sub */
8007c478bd9Sstevel@tonic-gate 					return (-1);
8017c478bd9Sstevel@tonic-gate 			}
8027c478bd9Sstevel@tonic-gate 			(void) closedir(dirp);
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 	} else {
8057c478bd9Sstevel@tonic-gate 		/*
8067c478bd9Sstevel@tonic-gate 		 * User specified filenames on the comm and line.
8077c478bd9Sstevel@tonic-gate 		 */
8087c478bd9Sstevel@tonic-gate 		f_cmdline = TRUE;
8097c478bd9Sstevel@tonic-gate 		for (; optindex < argc; optindex++) {
8107c478bd9Sstevel@tonic-gate 			fname = argv[optindex];		/* get a filename */
8117c478bd9Sstevel@tonic-gate 			if (proc_file(fname, FALSE))
8127c478bd9Sstevel@tonic-gate 				return (-1);
8137c478bd9Sstevel@tonic-gate 		}
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 	return (0);
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate /*
8207c478bd9Sstevel@tonic-gate  * .func	gather_dir - gather a directory's files together.
8217c478bd9Sstevel@tonic-gate  * .desc	Process all of the files in a specific directory. The files may
8227c478bd9Sstevel@tonic-gate  *	be checked for adherence to the file name form at.
8237c478bd9Sstevel@tonic-gate  *	If the directory can't be opened that is ok - just print
8247c478bd9Sstevel@tonic-gate  *	a message and continue.
8257c478bd9Sstevel@tonic-gate  * .call	ret = gather_dir(dir).
8267c478bd9Sstevel@tonic-gate  * .arg	dir	- ptr to full pathname of directory.
8277c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
8287c478bd9Sstevel@tonic-gate  * .ret	-1	- error detected (message already printed).
8297c478bd9Sstevel@tonic-gate  */
8307c478bd9Sstevel@tonic-gate int
8317c478bd9Sstevel@tonic-gate gather_dir(char *dir)
8327c478bd9Sstevel@tonic-gate {
8337c478bd9Sstevel@tonic-gate 	char	dname[MAXNAMLEN+1];
8347c478bd9Sstevel@tonic-gate 	char	fname[MAXNAMLEN+1];
8357c478bd9Sstevel@tonic-gate 	DIR * dirp;
8367c478bd9Sstevel@tonic-gate 	struct dirent *dp;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	(void) snprintf(dname, sizeof (dname), "%s/files", dir);
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 	if ((dirp = opendir(dname)) == NULL) {
8417c478bd9Sstevel@tonic-gate 		if (errno != ENOTDIR) {
8427c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
8437c478bd9Sstevel@tonic-gate 			    gettext("%s can't open directory - %s"), ar, dname);
8447c478bd9Sstevel@tonic-gate 			perror(errbuf);
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 		return (0);
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
8497c478bd9Sstevel@tonic-gate 		if (dp->d_name[0] == '.')	/* can't see hidden files */
8507c478bd9Sstevel@tonic-gate 			continue;
8517c478bd9Sstevel@tonic-gate 		fname[0] = '\0';
8527c478bd9Sstevel@tonic-gate 		(void) strcat(fname, dname);	/* create pathname of file */
8537c478bd9Sstevel@tonic-gate 		(void) strcat(fname, "/");
8547c478bd9Sstevel@tonic-gate 		(void) strcat(fname, dp->d_name);
8557c478bd9Sstevel@tonic-gate 		if (proc_file(fname, TRUE))
8567c478bd9Sstevel@tonic-gate 			return (-1);
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 	(void) closedir(dirp);
8597c478bd9Sstevel@tonic-gate 	return (0);
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate /*
8647c478bd9Sstevel@tonic-gate  * .func	proc_file - process a single candidate file.
8657c478bd9Sstevel@tonic-gate  * .desc	Check out a file to see if it should be used in the merge.
8667c478bd9Sstevel@tonic-gate  *	This includes checking the name (mode is TRUE) against the
8677c478bd9Sstevel@tonic-gate  *	file format, checking access rights to the file, and thence
8687c478bd9Sstevel@tonic-gate  *	getting and fcb and installing the fcb into the correct pcb.
8697c478bd9Sstevel@tonic-gate  *	If the file fails then the fcb is not installed into a pcb
8707c478bd9Sstevel@tonic-gate  *	and the file dissapears from view.
8717c478bd9Sstevel@tonic-gate  * .call	proc_file(fname, mode).
8727c478bd9Sstevel@tonic-gate  * .arg	fname	- ptr to full pathna me of file.
8737c478bd9Sstevel@tonic-gate  * .arg	mode	- TRUE if checking adherence to file name format.
8747c478bd9Sstevel@tonic-gate  * .ret	0	- no fatal errors detected.
8757c478bd9Sstevel@tonic-gate  * .ret	-1	- fatal error detected - quit altogether
8767c478bd9Sstevel@tonic-gate  *		  (message already printed).
8777c478bd9Sstevel@tonic-gate  */
8787c478bd9Sstevel@tonic-gate int
8797c478bd9Sstevel@tonic-gate proc_file(char *fname, int mode)
8807c478bd9Sstevel@tonic-gate {
8817c478bd9Sstevel@tonic-gate 	int reject = FALSE;
8827c478bd9Sstevel@tonic-gate 	size_t len;
8837c478bd9Sstevel@tonic-gate 	struct stat stat_buf;
8847c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb, *fcbp, *fcbprev;
8857c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	/*
8887c478bd9Sstevel@tonic-gate 	 * See if it is a weird file like a directory or
8897c478bd9Sstevel@tonic-gate 	 * character special (around here?).
8907c478bd9Sstevel@tonic-gate 	 */
8917c478bd9Sstevel@tonic-gate 	if (stat(fname, &stat_buf)) {
8927c478bd9Sstevel@tonic-gate 		return (0);
8937c478bd9Sstevel@tonic-gate 	}
8944bc0a2efScasper 	if (!S_ISREG(stat_buf.st_mode))
8957c478bd9Sstevel@tonic-gate 		return (0);
8967c478bd9Sstevel@tonic-gate 	/*
8977c478bd9Sstevel@tonic-gate 	 * Allocate a new fcb to hold fcb and full filename.
8987c478bd9Sstevel@tonic-gate 	 */
8997c478bd9Sstevel@tonic-gate 	len = sizeof (audit_fcb_t) + strlen(fname);
9007c478bd9Sstevel@tonic-gate 	fcb = (audit_fcb_t *)a_calloc(1, len);
9017c478bd9Sstevel@tonic-gate 	(void) strcpy(fcb->fcb_file, fname);
9027c478bd9Sstevel@tonic-gate 	if (check_file(fcb, mode)) { /* check file name */
9037c478bd9Sstevel@tonic-gate 		if (!f_quiet) {
9047c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s %s:\n  %s.\n", ar,
9057c478bd9Sstevel@tonic-gate 			    error_str, fname);
9067c478bd9Sstevel@tonic-gate 		}
9077c478bd9Sstevel@tonic-gate 		reject = TRUE;
9087c478bd9Sstevel@tonic-gate 	} else {
9097c478bd9Sstevel@tonic-gate 		/*
9107c478bd9Sstevel@tonic-gate 		 * Check against file criteria.
9117c478bd9Sstevel@tonic-gate 		 * Check finish-time here, and start-time later on
9127c478bd9Sstevel@tonic-gate 		 * while processing.
9137c478bd9Sstevel@tonic-gate 		 * This is because the start time on a file can be after
9147c478bd9Sstevel@tonic-gate 		 * the first record(s).
9157c478bd9Sstevel@tonic-gate 		 */
9167c478bd9Sstevel@tonic-gate 		if (f_complete && (fcb->fcb_flags & FF_NOTTERM) && !f_cmdline)
9177c478bd9Sstevel@tonic-gate 			reject = TRUE;
9187c478bd9Sstevel@tonic-gate 		if (!f_all && (fcb->fcb_end < m_after))
9197c478bd9Sstevel@tonic-gate 			reject = TRUE;
9207c478bd9Sstevel@tonic-gate 		if (f_machine) {
9217c478bd9Sstevel@tonic-gate 			if (strlen(fcb->fcb_suffix) != strlen(f_machine) ||
9227c478bd9Sstevel@tonic-gate 			    (strcmp(fcb->fcb_suffix, f_machine) != 0)) {
9237c478bd9Sstevel@tonic-gate 				reject = TRUE;
9247c478bd9Sstevel@tonic-gate 			}
9257c478bd9Sstevel@tonic-gate 		}
9267c478bd9Sstevel@tonic-gate 	}
9277c478bd9Sstevel@tonic-gate 	if (reject == FALSE) {
9287c478bd9Sstevel@tonic-gate 		filenum++;	/* count of total files to be processed */
9297c478bd9Sstevel@tonic-gate 		fcb->fcb_next = NULL;
9307c478bd9Sstevel@tonic-gate 		if ((pcb = get_next_pcb(fcb->fcb_suffix)) == NULL) {
9317c478bd9Sstevel@tonic-gate 			return (-1);
9327c478bd9Sstevel@tonic-gate 		}
9337c478bd9Sstevel@tonic-gate 		/* Place FCB into the PCB in order - oldest first.  */
9347c478bd9Sstevel@tonic-gate 		fcbp = pcb->pcb_first;
9357c478bd9Sstevel@tonic-gate 		fcbprev = NULL;
9367c478bd9Sstevel@tonic-gate 		while (fcbp != NULL) {
9377c478bd9Sstevel@tonic-gate 			if (fcb->fcb_start < fcbp->fcb_start) {
9387c478bd9Sstevel@tonic-gate 				if (fcbprev)
9397c478bd9Sstevel@tonic-gate 					fcbprev->fcb_next = fcb;
9407c478bd9Sstevel@tonic-gate 				else
9417c478bd9Sstevel@tonic-gate 					pcb->pcb_dfirst = pcb->pcb_first = fcb;
9427c478bd9Sstevel@tonic-gate 				fcb->fcb_next = fcbp;
9437c478bd9Sstevel@tonic-gate 				break;
9447c478bd9Sstevel@tonic-gate 			}
9457c478bd9Sstevel@tonic-gate 			fcbprev = fcbp;
9467c478bd9Sstevel@tonic-gate 			fcbp = fcbp->fcb_next;
9477c478bd9Sstevel@tonic-gate 		}
9487c478bd9Sstevel@tonic-gate 		/* younger than all || empty list */
9497c478bd9Sstevel@tonic-gate 		if (!fcb->fcb_next) {
9507c478bd9Sstevel@tonic-gate 			if (pcb->pcb_first == NULL)
9517c478bd9Sstevel@tonic-gate 				pcb->pcb_dfirst = pcb->pcb_first = fcb;
9527c478bd9Sstevel@tonic-gate 			pcb->pcb_dlast = pcb->pcb_last = fcb;
9537c478bd9Sstevel@tonic-gate 			if (fcbprev)
9547c478bd9Sstevel@tonic-gate 				fcbprev->fcb_next = fcb;
9557c478bd9Sstevel@tonic-gate 		}
9567c478bd9Sstevel@tonic-gate 	} else {
9577c478bd9Sstevel@tonic-gate 		free((char *)fcb);	/* rejected */
9587c478bd9Sstevel@tonic-gate 	}
9597c478bd9Sstevel@tonic-gate 	return (0);
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate /*
9647c478bd9Sstevel@tonic-gate  * .func	check_file - check filename and setup fcb.
9657c478bd9Sstevel@tonic-gate  * .desc	Check adherence to the file format (do_check is TRUE) and setup
9667c478bd9Sstevel@tonic-gate  *	the fcb with useful information.
9677c478bd9Sstevel@tonic-gate  *	filename format: yyyymmddhhmmss.yyyymmddhhmmss.suffix
9687c478bd9Sstevel@tonic-gate  *			 yyyymmddhhmmss.not_terminated.suffix
9697c478bd9Sstevel@tonic-gate  *	If do_check is FALSE then still see if the filename does confirm
9707c478bd9Sstevel@tonic-gate  *	to the format. If it does then extract useful information from
9717c478bd9Sstevel@tonic-gate  *	it (start time and end time).  But if it doesn't then don't print
9727c478bd9Sstevel@tonic-gate  *	any error messages.
9737c478bd9Sstevel@tonic-gate  * .call	ret = check_file(fcb, do_check).
9747c478bd9Sstevel@tonic-gate  * .arg	fcb	- ptr to fcb that holds the file.
9757c478bd9Sstevel@tonic-gate  * .arg	do_check - if TRUE do check adherence to file format.
9767c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
9777c478bd9Sstevel@tonic-gate  * .ret	-1	- file failed somehow (error_str tells why).
9787c478bd9Sstevel@tonic-gate  */
9797c478bd9Sstevel@tonic-gate int
9807c478bd9Sstevel@tonic-gate check_file(audit_fcb_t *fcb, int do_check)
9817c478bd9Sstevel@tonic-gate {
9827c478bd9Sstevel@tonic-gate 	int	ret;
9837c478bd9Sstevel@tonic-gate 	char	*namep, *slp;
9847c478bd9Sstevel@tonic-gate 	char	errb[256];		/* build error message */
9857c478bd9Sstevel@tonic-gate 	struct tm tme;
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 	errb[0] = '\0';
9887c478bd9Sstevel@tonic-gate 	/* get just the filename */
9897c478bd9Sstevel@tonic-gate 	for (slp = namep = fcb->fcb_file; *namep; namep++) {
9907c478bd9Sstevel@tonic-gate 		if (*namep == '/')
9917c478bd9Sstevel@tonic-gate 			slp = namep + 1; /* slp -> the filename itself */
9927c478bd9Sstevel@tonic-gate 	}
9937c478bd9Sstevel@tonic-gate 	if (do_check == FALSE) {
9947c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
9957c478bd9Sstevel@tonic-gate 		fcb->fcb_suffix = NULL;
9967c478bd9Sstevel@tonic-gate 		fcb->fcb_name = slp;
9977c478bd9Sstevel@tonic-gate 		ret = 0;
9987c478bd9Sstevel@tonic-gate 	} else {
9997c478bd9Sstevel@tonic-gate 		ret = -1;
10007c478bd9Sstevel@tonic-gate 	}
10017c478bd9Sstevel@tonic-gate 	if ((int)strlen(slp) < 31) {
10027c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("filename too short (%d)"),
10037c478bd9Sstevel@tonic-gate 		    strlen(slp));
10047c478bd9Sstevel@tonic-gate 		error_str = errbuf;
10057c478bd9Sstevel@tonic-gate 		return (ret);
10067c478bd9Sstevel@tonic-gate 	}
10077c478bd9Sstevel@tonic-gate 	/*
10087c478bd9Sstevel@tonic-gate 	 * Get working copy of filename.
10097c478bd9Sstevel@tonic-gate 	 */
10107c478bd9Sstevel@tonic-gate 	namep = (char *)a_calloc(1, strlen(slp) + 1);
10117c478bd9Sstevel@tonic-gate 	(void) strcpy(namep, slp);
10127c478bd9Sstevel@tonic-gate 	if (namep[14] != '.' || namep[29] != '.') {
10137c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
10147c478bd9Sstevel@tonic-gate 		    gettext("invalid filename format (%c or %c)"), namep[14],
10157c478bd9Sstevel@tonic-gate 		    namep[29]);
10167c478bd9Sstevel@tonic-gate 		error_str = errbuf;
10177c478bd9Sstevel@tonic-gate 		free(namep);
10187c478bd9Sstevel@tonic-gate 		return (ret);
10197c478bd9Sstevel@tonic-gate 	}
10207c478bd9Sstevel@tonic-gate 	namep[14] = '\0';			/* mark off start time */
10217c478bd9Sstevel@tonic-gate 	namep[29] = '\0';			/* mark off finish time */
10227c478bd9Sstevel@tonic-gate 	if (derive_date(namep, &tme)) {
10237c478bd9Sstevel@tonic-gate 		(void) strcat(errb, gettext("starting time-stamp invalid - "));
10247c478bd9Sstevel@tonic-gate 		(void) strcat(errb, error_str);
10257c478bd9Sstevel@tonic-gate 		(void) strcpy(errbuf, errb);
10267c478bd9Sstevel@tonic-gate 		error_str = errbuf;
10277c478bd9Sstevel@tonic-gate 		free(namep);
10287c478bd9Sstevel@tonic-gate 		return (ret);
10297c478bd9Sstevel@tonic-gate 	}
10307c478bd9Sstevel@tonic-gate 	/*
10317c478bd9Sstevel@tonic-gate 	 * Keep start time from filename. Use it to order files in
10327c478bd9Sstevel@tonic-gate 	 * the file list. Later we will update this when we read
10337c478bd9Sstevel@tonic-gate 	 * the first record from the file.
10347c478bd9Sstevel@tonic-gate 	 */
10357c478bd9Sstevel@tonic-gate 	fcb->fcb_start = tm_to_secs(&tme);
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	if (strcmp(&namep[15], "not_terminated") == 0) {
10387c478bd9Sstevel@tonic-gate 		fcb->fcb_end = MAXLONG;		/* forever */
10397c478bd9Sstevel@tonic-gate 		/*
10407c478bd9Sstevel@tonic-gate 		 * Only treat a 'not_terminated' file as such if
10417c478bd9Sstevel@tonic-gate 		 * it is not on the command line.
10427c478bd9Sstevel@tonic-gate 		 */
10437c478bd9Sstevel@tonic-gate 		if (do_check == TRUE)
10447c478bd9Sstevel@tonic-gate 			fcb->fcb_flags |= FF_NOTTERM;
10457c478bd9Sstevel@tonic-gate 	} else if (derive_date(&namep[15], &tme)) {
10467c478bd9Sstevel@tonic-gate 		(void) strcat(errb, gettext("ending time-stamp invalid - "));
10477c478bd9Sstevel@tonic-gate 		(void) strcat(errb, error_str);
10487c478bd9Sstevel@tonic-gate 		(void) strcpy(errbuf, errb);
10497c478bd9Sstevel@tonic-gate 		error_str = errbuf;
10507c478bd9Sstevel@tonic-gate 		free(namep);
10517c478bd9Sstevel@tonic-gate 		return (ret);
10527c478bd9Sstevel@tonic-gate 	} else {
10537c478bd9Sstevel@tonic-gate 		fcb->fcb_end = tm_to_secs(&tme);
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 	fcb->fcb_name = slp;
10567c478bd9Sstevel@tonic-gate 	fcb->fcb_suffix = &slp[30];
10577c478bd9Sstevel@tonic-gate 	free(namep);
10587c478bd9Sstevel@tonic-gate 	return (0);
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate /*
10637c478bd9Sstevel@tonic-gate  * .func get_next_pcb - get a pcb to use.
10647c478bd9Sstevel@tonic-gate  * .desc	The pcb's in the array audit_pcbs are used to hold single file
10657c478bd9Sstevel@tonic-gate  *	groups in the form of a linked list. Each pcb holds files that
10667c478bd9Sstevel@tonic-gate  *	are tied together by a common suffix in the file name. Here we
10677c478bd9Sstevel@tonic-gate  *	get either 1. the existing pcb holding a specified sufix or
10687c478bd9Sstevel@tonic-gate  *	2. a new pcb if we can't find an existing one.
10697c478bd9Sstevel@tonic-gate  * .call	pcb = get_next_pcb(suffix).
10707c478bd9Sstevel@tonic-gate  * .arg	suffix	- ptr to suffix we are seeking.
10717c478bd9Sstevel@tonic-gate  * .ret	pcb	- ptr to pcb that hold s the sought suffix.
10727c478bd9Sstevel@tonic-gate  * .ret	NULL- serious failure in memory allocation. Quit processing.
10737c478bd9Sstevel@tonic-gate  */
10747c478bd9Sstevel@tonic-gate audit_pcb_t *
10757c478bd9Sstevel@tonic-gate get_next_pcb(char *suffix)
10767c478bd9Sstevel@tonic-gate {
10777c478bd9Sstevel@tonic-gate 	int	i = 0;
10787c478bd9Sstevel@tonic-gate 	int	zerosize;
10797c478bd9Sstevel@tonic-gate 	unsigned int	size;
10807c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcb;
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 	/* Search through (maybe) entire array. */
10837c478bd9Sstevel@tonic-gate 	while (i < pcbsize) {
10847c478bd9Sstevel@tonic-gate 		pcb = &audit_pcbs[i++];
10857c478bd9Sstevel@tonic-gate 		if (pcb->pcb_first == NULL) {
10867c478bd9Sstevel@tonic-gate 			proc_pcb(pcb, suffix, i);
10877c478bd9Sstevel@tonic-gate 			return (pcb);	/* came to an unused one */
10887c478bd9Sstevel@tonic-gate 		}
10897c478bd9Sstevel@tonic-gate 		if (suffix) {
10907c478bd9Sstevel@tonic-gate 			if (strcmp(pcb->pcb_suffix, suffix) == 0)
10917c478bd9Sstevel@tonic-gate 				return (pcb);	/* matched one with suffix */
10927c478bd9Sstevel@tonic-gate 		}
10937c478bd9Sstevel@tonic-gate 	}
10947c478bd9Sstevel@tonic-gate 	/*
10957c478bd9Sstevel@tonic-gate 	 * Uh-oh, the entire array is used and we haven't gotten one yet.
10967c478bd9Sstevel@tonic-gate 	 * Allocate a bigger array.
10977c478bd9Sstevel@tonic-gate 	 */
10987c478bd9Sstevel@tonic-gate 	pcbsize += PCB_INC;
10997c478bd9Sstevel@tonic-gate 	size = pcbsize * sizeof (audit_pcb_t);
11007c478bd9Sstevel@tonic-gate 	zerosize = size - ((pcbsize - PCB_INC) * sizeof (audit_pcb_t));
11017c478bd9Sstevel@tonic-gate 	if ((audit_pcbs = (audit_pcb_t *)realloc((char *)audit_pcbs, size)) ==
11027c478bd9Sstevel@tonic-gate 	    NULL) {
11037c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
11047c478bd9Sstevel@tonic-gate 		    gettext("%s memory reallocation failed (%d bytes)"), ar,
11057c478bd9Sstevel@tonic-gate 		    size);
11067c478bd9Sstevel@tonic-gate 		perror(errbuf);
11077c478bd9Sstevel@tonic-gate 		audit_stats();		/* give user statistics on usage */
11087c478bd9Sstevel@tonic-gate 		return (NULL);		/* really bad thing to have happen */
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 	/*
11117c478bd9Sstevel@tonic-gate 	 * Don't know if realloc clears the new memory like calloc would.
11127c478bd9Sstevel@tonic-gate 	 */
11137c478bd9Sstevel@tonic-gate 	(void) memset((void *) & audit_pcbs[pcbsize-PCB_INC], 0,
11147c478bd9Sstevel@tonic-gate 	    (size_t)zerosize);
11157c478bd9Sstevel@tonic-gate 	pcb = &audit_pcbs[pcbsize-PCB_INC];	/* allocate the first new one */
11167c478bd9Sstevel@tonic-gate 	proc_pcb(pcb, suffix, pcbsize - PCB_INC);
11177c478bd9Sstevel@tonic-gate 	return (pcb);
11187c478bd9Sstevel@tonic-gate }
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 
11217c478bd9Sstevel@tonic-gate /*
11227c478bd9Sstevel@tonic-gate  * .func proc_pcb - process pcb.
11237c478bd9Sstevel@tonic-gate  * .desc	Common pcb processing for above routine.
11247c478bd9Sstevel@tonic-gate  * .call	proc_pcb(pcb, suffix, i).
11257c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb.
11267c478bd9Sstevel@tonic-gate  * .arg	suffix	- prt to suffix tha t ties this group together.
11277c478bd9Sstevel@tonic-gate  * .arg	i	- index into audit_pcbs[ ].
11287c478bd9Sstevel@tonic-gate  * .ret	void.
11297c478bd9Sstevel@tonic-gate  */
11307c478bd9Sstevel@tonic-gate void
11317c478bd9Sstevel@tonic-gate proc_pcb(audit_pcb_t *pcb, char *suffix, int i)
11327c478bd9Sstevel@tonic-gate {
11337c478bd9Sstevel@tonic-gate 	if (suffix)
11347c478bd9Sstevel@tonic-gate 		pcb->pcb_suffix = suffix;
11357c478bd9Sstevel@tonic-gate 	pcbnum++;	/* one more pcb in use */
11367c478bd9Sstevel@tonic-gate 	pcb->pcb_size = AUDITBUFSIZE;
11377c478bd9Sstevel@tonic-gate 	pcb->pcb_rec = (char *)a_calloc(1, AUDITBUFSIZE);
11387c478bd9Sstevel@tonic-gate 	pcb->pcb_time = -1;
1139406d6273SPalle Lyckegaard 	pcb->pcb_flags |= PF_USEFILE;	/* note this one controls files */
11407c478bd9Sstevel@tonic-gate 	pcb->pcb_procno = i;	/* save index into audit_pcbs [] for id */
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate /*
1145a13cf099Sgww  * .func	proc_label - process label range argument.
1146a13cf099Sgww  * .desc	Parse label range lower-bound[;upper-bound]
1147a13cf099Sgww  * .call	ret = proc_label(optstr).
11487c478bd9Sstevel@tonic-gate  * .arg	opstr	- ptr to label range string
11497c478bd9Sstevel@tonic-gate  * .ret 0	- no errors detected.
1150a13cf099Sgww  * .ret -1	- errors detected (error_str set).
11517c478bd9Sstevel@tonic-gate  */
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate int
1154a13cf099Sgww proc_label(char *optstr)
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate 	char	*p;
11577c478bd9Sstevel@tonic-gate 	int	error;
11587c478bd9Sstevel@tonic-gate 
1159924c9144Sgww 	if (flags & M_LABEL) {
1160924c9144Sgww 		error_str = gettext("'l' option specified multiple times");
11617c478bd9Sstevel@tonic-gate 		return (-1);
11627c478bd9Sstevel@tonic-gate 	}
1163924c9144Sgww 	flags |= M_LABEL;
116445916cd2Sjpk 
116545916cd2Sjpk 	if ((m_label = malloc(sizeof (m_range_t))) == NULL) {
116645916cd2Sjpk 		return (-1);
116745916cd2Sjpk 	}
116845916cd2Sjpk 	m_label->lower_bound = NULL;
116945916cd2Sjpk 	m_label->upper_bound = NULL;
117045916cd2Sjpk 
117145916cd2Sjpk 	p = strchr(optstr, ';');
11727c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11737c478bd9Sstevel@tonic-gate 		/* exact label match, lower and upper range bounds the same */
117445916cd2Sjpk 		if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
117545916cd2Sjpk 		    L_NO_CORRECTION, &error) == -1) {
11767c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
11777c478bd9Sstevel@tonic-gate 			    gettext("invalid sensitivity label (%s) err %d"),
11787c478bd9Sstevel@tonic-gate 			    optstr, error);
11797c478bd9Sstevel@tonic-gate 			error_str = errbuf;
118045916cd2Sjpk 			goto errout;
11817c478bd9Sstevel@tonic-gate 		}
118245916cd2Sjpk 		m_label->upper_bound = m_label->lower_bound;
11837c478bd9Sstevel@tonic-gate 		return (0);
11847c478bd9Sstevel@tonic-gate 	}
11857c478bd9Sstevel@tonic-gate 	if (p == optstr) {
11867c478bd9Sstevel@tonic-gate 		/* lower bound is not specified .. default is admin_low */
118745916cd2Sjpk 		if (str_to_label(ADMIN_LOW, &m_label->lower_bound, MAC_LABEL,
118845916cd2Sjpk 		    L_NO_CORRECTION, &error) == -1) {
1189a13cf099Sgww 			goto errout;
11907c478bd9Sstevel@tonic-gate 		}
119145916cd2Sjpk 
119245916cd2Sjpk 		p++;
119345916cd2Sjpk 		if (*p == '\0') {
119445916cd2Sjpk 			/* upper bound not specified .. default is admin_high */
119545916cd2Sjpk 			if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
119645916cd2Sjpk 			    MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
1197a13cf099Sgww 				goto errout;
119845916cd2Sjpk 			}
119945916cd2Sjpk 		} else {
120045916cd2Sjpk 			if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
120145916cd2Sjpk 			    L_NO_CORRECTION, &error) == -1) {
120245916cd2Sjpk 				(void) sprintf(errbuf, gettext(
120345916cd2Sjpk 				    "invalid sensitivity label (%s) err %d"),
120445916cd2Sjpk 				    p, error);
120545916cd2Sjpk 				error_str = errbuf;
120645916cd2Sjpk 				goto errout;
120745916cd2Sjpk 			}
120845916cd2Sjpk 		}
12097c478bd9Sstevel@tonic-gate 		return (0);
12107c478bd9Sstevel@tonic-gate 	}
12117c478bd9Sstevel@tonic-gate 	*p++ = '\0';
121245916cd2Sjpk 	if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
121345916cd2Sjpk 	    L_NO_CORRECTION, &error) == -1) {
12147c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
12157c478bd9Sstevel@tonic-gate 		    gettext("invalid sensitivity label (%s) err %d"), optstr,
12167c478bd9Sstevel@tonic-gate 		    error);
12177c478bd9Sstevel@tonic-gate 		error_str = errbuf;
121845916cd2Sjpk 		goto errout;
12197c478bd9Sstevel@tonic-gate 	}
122045916cd2Sjpk 	if (*p == '\0') {
12217c478bd9Sstevel@tonic-gate 		/* upper bound is not specified .. default is admin_high */
122245916cd2Sjpk 		if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
122345916cd2Sjpk 		    MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
1224a13cf099Sgww 			goto errout;
122545916cd2Sjpk 		}
122645916cd2Sjpk 	} else {
122745916cd2Sjpk 		if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
122845916cd2Sjpk 		    L_NO_CORRECTION, &error) == -1) {
12297c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
12307c478bd9Sstevel@tonic-gate 			    gettext("invalid sensitivity label (%s) err %d"),
12317c478bd9Sstevel@tonic-gate 			    p, error);
12327c478bd9Sstevel@tonic-gate 			error_str = errbuf;
123345916cd2Sjpk 			goto errout;
12347c478bd9Sstevel@tonic-gate 		}
12357c478bd9Sstevel@tonic-gate 	}
12367c478bd9Sstevel@tonic-gate 	/* make sure that upper bound dominates the lower bound */
123745916cd2Sjpk 	if (!bldominates(m_label->upper_bound, m_label->lower_bound)) {
123845916cd2Sjpk 		*--p = ';';
12397c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
12407c478bd9Sstevel@tonic-gate 		    gettext("invalid sensitivity label range (%s)"), optstr);
12417c478bd9Sstevel@tonic-gate 		error_str = errbuf;
124245916cd2Sjpk 		goto errout;
12437c478bd9Sstevel@tonic-gate 	}
12447c478bd9Sstevel@tonic-gate 	return (0);
124545916cd2Sjpk 
124645916cd2Sjpk errout:
124745916cd2Sjpk 	m_label_free(m_label->upper_bound);
124845916cd2Sjpk 	m_label_free(m_label->lower_bound);
124945916cd2Sjpk 	free(m_label);
125045916cd2Sjpk 
125145916cd2Sjpk 	return (-1);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate /*
12557c478bd9Sstevel@tonic-gate  * proc_zonename - pick up zone name.
12567c478bd9Sstevel@tonic-gate  *
12577c478bd9Sstevel@tonic-gate  * all non-empty and not-too-long strings are valid since any name
12587c478bd9Sstevel@tonic-gate  * may be valid.
12597c478bd9Sstevel@tonic-gate  *
12607c478bd9Sstevel@tonic-gate  * ret 0:	non-empty string
12617c478bd9Sstevel@tonic-gate  * ret -1:	empty string or string is too long.
12627c478bd9Sstevel@tonic-gate  */
12637c478bd9Sstevel@tonic-gate static int
12647c478bd9Sstevel@tonic-gate proc_zonename(char *optstr)
12657c478bd9Sstevel@tonic-gate {
12667c478bd9Sstevel@tonic-gate 	size_t	length = strlen(optstr);
12677c478bd9Sstevel@tonic-gate 	if ((length < 1) || (length > ZONENAME_MAX)) {
12687c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf,
12697c478bd9Sstevel@tonic-gate 		    gettext("invalid zone name: %s"), optstr);
12707c478bd9Sstevel@tonic-gate 		error_str = errbuf;
12717c478bd9Sstevel@tonic-gate 		return (-1);
12727c478bd9Sstevel@tonic-gate 	}
12737c478bd9Sstevel@tonic-gate 	zonename = strdup(optstr);
12747c478bd9Sstevel@tonic-gate 	flags |= M_ZONENAME;
12757c478bd9Sstevel@tonic-gate 	return (0);
12767c478bd9Sstevel@tonic-gate }
1277103b2b15Sgww 
1278103b2b15Sgww /*
1279103b2b15Sgww  * proc_frmi - set up frmi for pattern matching.
1280103b2b15Sgww  *	Logic ripped off of scf_walk_fmri()
1281103b2b15Sgww  *		Thanks to the smf team.
1282103b2b15Sgww  *
1283103b2b15Sgww  * ret 0:	OK
1284103b2b15Sgww  * ret -1:	error
1285103b2b15Sgww  */
1286103b2b15Sgww static int
1287103b2b15Sgww proc_fmri(char *optstr)
1288103b2b15Sgww {
1289103b2b15Sgww 	if (strpbrk(optstr, "*?[") != NULL) {
1290103b2b15Sgww 		/* have a pattern to glob for */
1291103b2b15Sgww 
1292103b2b15Sgww 		fmri.sp_type = PATTERN_GLOB;
1293103b2b15Sgww 		if (optstr[0] == '*' ||
1294103b2b15Sgww 		    (strlen(optstr) >= 4 && optstr[3] == ':')) {
1295103b2b15Sgww 			fmri.sp_arg = strdup(optstr);
1296103b2b15Sgww 		} else if ((fmri.sp_arg = malloc(strlen(optstr) + 6)) != NULL) {
1297103b2b15Sgww 			(void) snprintf(fmri.sp_arg, strlen(optstr) + 6,
1298103b2b15Sgww 			    "svc:/%s", optstr);
1299103b2b15Sgww 		}
1300103b2b15Sgww 	} else {
1301103b2b15Sgww 		fmri.sp_type = PATTERN_PARTIAL;
1302103b2b15Sgww 		fmri.sp_arg = strdup(optstr);
1303103b2b15Sgww 	}
1304103b2b15Sgww 	if (fmri.sp_arg == NULL)
1305103b2b15Sgww 		return (-1);
1306103b2b15Sgww 
1307103b2b15Sgww 	return (0);
1308103b2b15Sgww }
1309