xref: /illumos-gate/usr/src/lib/libbsm/common/audit_event.c (revision d0fa49b78d1f40d84ec76c363cdc38cf128511dd)
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
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * 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 
227c478bd9Sstevel@tonic-gate /*
237257d1b4Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277257d1b4Sraf 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Interfaces to audit_event(5)  (/etc/security/audit_event)
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * This routine is obsolete.  I have removed its inclusion by removing
347c478bd9Sstevel@tonic-gate  * the .o from the makefile.  Please use cacheauevent() or any of the
357c478bd9Sstevel@tonic-gate  * getauev* routines.
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <limits.h>
407c478bd9Sstevel@tonic-gate #include <stdio.h>
417c478bd9Sstevel@tonic-gate #include <stdlib.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <bsm/audit.h>
447c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
457c478bd9Sstevel@tonic-gate #include <synch.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  *	Macros to produce a quoted string containing the value of a
497c478bd9Sstevel@tonic-gate  *	preprocessor macro. For example, if SIZE is defined to be 256,
507c478bd9Sstevel@tonic-gate  *	VAL2STR(SIZE) is "256". This is used to construct format
517c478bd9Sstevel@tonic-gate  *	strings for scanf-family functions below.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate #define	QUOTE(x)	#x
547c478bd9Sstevel@tonic-gate #define	VAL2STR(x)	QUOTE(x)
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static au_class_t flagstohex(char *);
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate static char	au_event_fname[PATH_MAX] = AUDITEVENTFILE;
597c478bd9Sstevel@tonic-gate static FILE *au_event_file = (FILE *)0;
607c478bd9Sstevel@tonic-gate static mutex_t mutex_eventfile = DEFAULTMUTEX;
617c478bd9Sstevel@tonic-gate static mutex_t mutex_eventcache = DEFAULTMUTEX;
62e4163c9bSpaulson /*
63e4163c9bSpaulson  * If an error occurs during the call to cacheauclassnam() inside
64e4163c9bSpaulson  * flagstohex() any return value could be seen as a valid class mask so
65e4163c9bSpaulson  * the following global variable, cacheauclass_failure, is set to indicate
66e4163c9bSpaulson  * that an error has occurred.
67e4163c9bSpaulson  */
68e4163c9bSpaulson static int cacheauclass_failure = 0;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate void
727c478bd9Sstevel@tonic-gate setauevent()
737c478bd9Sstevel@tonic-gate {
747257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
757c478bd9Sstevel@tonic-gate 	if (au_event_file) {
767c478bd9Sstevel@tonic-gate 		(void) fseek(au_event_file, 0L, 0);
777c478bd9Sstevel@tonic-gate 	}
787257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate void
837c478bd9Sstevel@tonic-gate endauevent()
847c478bd9Sstevel@tonic-gate {
857257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
867c478bd9Sstevel@tonic-gate 	if (au_event_file) {
877c478bd9Sstevel@tonic-gate 		(void) fclose(au_event_file);
887c478bd9Sstevel@tonic-gate 		au_event_file = (FILE *)0;
897c478bd9Sstevel@tonic-gate 	}
907257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate au_event_ent_t *
947c478bd9Sstevel@tonic-gate getauevent()
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	static au_event_ent_t au_event_entry;
977c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
987c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
1017c478bd9Sstevel@tonic-gate 	au_event_entry.ae_name = ename;
1027c478bd9Sstevel@tonic-gate 	au_event_entry.ae_desc = edesc;
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	return (getauevent_r(&au_event_entry));
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate au_event_ent_t *
1087c478bd9Sstevel@tonic-gate getauevent_r(au_event_entry)
1097c478bd9Sstevel@tonic-gate 	au_event_ent_t *au_event_entry;
1107c478bd9Sstevel@tonic-gate {
1117c478bd9Sstevel@tonic-gate 	int	i, error = 0, found = 0;
1127c478bd9Sstevel@tonic-gate 	char	*s, input[AU_EVENT_LINE_MAX];
1137c478bd9Sstevel@tonic-gate 	char	trim_buf[AU_EVENT_NAME_MAX+1];
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/* open audit event file if it isn't already */
1167257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
1177c478bd9Sstevel@tonic-gate 	if (!au_event_file)
118004388ebScasper 		if (!(au_event_file = fopen(au_event_fname, "rF"))) {
1197257d1b4Sraf 			(void) mutex_unlock(&mutex_eventfile);
120*d0fa49b7STony Nguyen 			return (NULL);
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	while (fgets(input, AU_EVENT_LINE_MAX, au_event_file)) {
1247c478bd9Sstevel@tonic-gate 		if (input[0] != '#') {
1257c478bd9Sstevel@tonic-gate 			s = input + strspn(input, " \t\r\n");
1267c478bd9Sstevel@tonic-gate 			if ((*s == '\0') || (*s == '#')) {
1277c478bd9Sstevel@tonic-gate 				continue;
1287c478bd9Sstevel@tonic-gate 			}
1297c478bd9Sstevel@tonic-gate 			found = 1;
1307c478bd9Sstevel@tonic-gate 			s = input;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 			/* parse number */
1337c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1347c478bd9Sstevel@tonic-gate 			s[i] = '\0';
135*d0fa49b7STony Nguyen 			(void) sscanf(s, "%hu", &au_event_entry->ae_number);
1367c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 			/* parse event name */
1397c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1407c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1417c478bd9Sstevel@tonic-gate 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
1427c478bd9Sstevel@tonic-gate 			    trim_buf);
1437c478bd9Sstevel@tonic-gate 			(void) strncpy(au_event_entry->ae_name, trim_buf,
1447c478bd9Sstevel@tonic-gate 				AU_EVENT_NAME_MAX);
1457c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 			/* parse event description */
1487c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1497c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1507c478bd9Sstevel@tonic-gate 			(void) strncpy(au_event_entry->ae_desc, s,
1517c478bd9Sstevel@tonic-gate 				AU_EVENT_DESC_MAX);
1527c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 			/* parse class */
1557c478bd9Sstevel@tonic-gate 			i = strcspn(s, "\n\0");
1567c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1577c478bd9Sstevel@tonic-gate 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
1587c478bd9Sstevel@tonic-gate 			    trim_buf);
1597c478bd9Sstevel@tonic-gate 			au_event_entry->ae_class = flagstohex(trim_buf);
160e4163c9bSpaulson 			if (cacheauclass_failure == 1) {
161e4163c9bSpaulson 				error = 1;
162e4163c9bSpaulson 				cacheauclass_failure = 0;
163e4163c9bSpaulson 			}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 			break;
1667c478bd9Sstevel@tonic-gate 		}
1677c478bd9Sstevel@tonic-gate 	}
1687257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (!error && found) {
1717c478bd9Sstevel@tonic-gate 		return (au_event_entry);
1727c478bd9Sstevel@tonic-gate 	} else {
173*d0fa49b7STony Nguyen 		return (NULL);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate au_event_ent_t *
1797c478bd9Sstevel@tonic-gate getauevnam(char *name)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate 	static au_event_ent_t au_event_entry;
1827c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
1837c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
1867c478bd9Sstevel@tonic-gate 	au_event_entry.ae_name = ename;
1877c478bd9Sstevel@tonic-gate 	au_event_entry.ae_desc = edesc;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	return (getauevnam_r(&au_event_entry, name));
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate au_event_ent_t *
1937c478bd9Sstevel@tonic-gate getauevnam_r(au_event_ent_t *e, char *name)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 	setauevent();
1967c478bd9Sstevel@tonic-gate 	while (getauevent_r(e) != NULL) {
1977c478bd9Sstevel@tonic-gate 		if (strcmp(e->ae_name, name) == 0) {
1987c478bd9Sstevel@tonic-gate 			endauevent();
1997c478bd9Sstevel@tonic-gate 			return (e);
2007c478bd9Sstevel@tonic-gate 		}
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	endauevent();
203*d0fa49b7STony Nguyen 	return (NULL);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate au_event_ent_t *
2077c478bd9Sstevel@tonic-gate getauevnum_r(au_event_ent_t *e, au_event_t event_number)
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	setauevent();
2107c478bd9Sstevel@tonic-gate 	while (getauevent_r(e) != NULL) {
2117c478bd9Sstevel@tonic-gate 		if (e->ae_number == event_number) {
2127c478bd9Sstevel@tonic-gate 			endauevent();
2137c478bd9Sstevel@tonic-gate 			return (e);
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 	endauevent();
217*d0fa49b7STony Nguyen 	return (NULL);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate au_event_ent_t *
2217c478bd9Sstevel@tonic-gate getauevnum(au_event_t event_number)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	static au_event_ent_t e;
2247c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
2257c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
2287c478bd9Sstevel@tonic-gate 	e.ae_name = ename;
2297c478bd9Sstevel@tonic-gate 	e.ae_desc = edesc;
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	return (getauevnum_r(&e, event_number));
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate au_event_t
2357c478bd9Sstevel@tonic-gate getauevnonam(char *event_name)
2367c478bd9Sstevel@tonic-gate {
2377c478bd9Sstevel@tonic-gate 	au_event_ent_t e;
2387c478bd9Sstevel@tonic-gate 	char ename[AU_EVENT_NAME_MAX];
2397c478bd9Sstevel@tonic-gate 	char edesc[AU_EVENT_DESC_MAX];
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
2427c478bd9Sstevel@tonic-gate 	e.ae_name = ename;
2437c478bd9Sstevel@tonic-gate 	e.ae_desc = edesc;
2447c478bd9Sstevel@tonic-gate 
245*d0fa49b7STony Nguyen 	if (getauevnam_r(&e, event_name) == NULL) {
246*d0fa49b7STony Nguyen 		return (0);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	return (e.ae_number);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * cacheauevent:
2537c478bd9Sstevel@tonic-gate  *	Read the entire audit_event file into memory.
2547c478bd9Sstevel@tonic-gate  *	Set a pointer to the requested entry in the cache
2557c478bd9Sstevel@tonic-gate  *	or a pointer to an invalid entry if the event number
2567c478bd9Sstevel@tonic-gate  *	is not known.
2577c478bd9Sstevel@tonic-gate  *
2587c478bd9Sstevel@tonic-gate  *	Return < 0, if error.
2597c478bd9Sstevel@tonic-gate  *	Return   0, if event number not in cache.
2607c478bd9Sstevel@tonic-gate  *	Return   1, if event number is in cache.
2617c478bd9Sstevel@tonic-gate  */
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate int
2647c478bd9Sstevel@tonic-gate cacheauevent(au_event_ent_t **result, au_event_t event_number)
2657c478bd9Sstevel@tonic-gate {
266*d0fa49b7STony Nguyen 	static au_event_t max; /* the highest event number in the file */
267*d0fa49b7STony Nguyen 	static au_event_t min; /* the lowest event number in the file */
2687c478bd9Sstevel@tonic-gate 	static int	invalid; /* 1+index of the highest event number */
2697c478bd9Sstevel@tonic-gate 	static au_event_ent_t **index_tbl;
2707c478bd9Sstevel@tonic-gate 	static au_event_ent_t **p_tbl;
2717c478bd9Sstevel@tonic-gate 	static int	called_once = 0;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	char	line[AU_EVENT_LINE_MAX];
2747c478bd9Sstevel@tonic-gate 	int	lines = 0;
2757c478bd9Sstevel@tonic-gate 	FILE	*fp;
2767c478bd9Sstevel@tonic-gate 	au_event_ent_t *p_event;
2777c478bd9Sstevel@tonic-gate 	int	i, size;
2787c478bd9Sstevel@tonic-gate 	int	hit = 0;
2797c478bd9Sstevel@tonic-gate 	char	*s;
2807c478bd9Sstevel@tonic-gate 
2817257d1b4Sraf 	(void) mutex_lock(&mutex_eventcache);
2827c478bd9Sstevel@tonic-gate 	if (called_once == 0) {
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate 		/* Count number of lines in the events file */
285004388ebScasper 		if ((fp = fopen(au_event_fname, "rF")) == NULL) {
2867257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
2877c478bd9Sstevel@tonic-gate 			return (-1);
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 		while (fgets(line, AU_EVENT_LINE_MAX, fp) != NULL) {
2907c478bd9Sstevel@tonic-gate 			s = line + strspn(line, " \t\r\n");
2917c478bd9Sstevel@tonic-gate 			if ((*s == '\0') || (*s == '#')) {
2927c478bd9Sstevel@tonic-gate 				continue;
2937c478bd9Sstevel@tonic-gate 			}
2947c478bd9Sstevel@tonic-gate 			lines++;
2957c478bd9Sstevel@tonic-gate 		}
2967c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
2977c478bd9Sstevel@tonic-gate 		size = lines;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		/*
3007c478bd9Sstevel@tonic-gate 		 * Make an array in which each element in an entry in the
3017c478bd9Sstevel@tonic-gate 		 * events file.  Make the next to last element an invalid
3027c478bd9Sstevel@tonic-gate 		 * event.  Make the last element a NULL pointer.
3037c478bd9Sstevel@tonic-gate 		 */
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 		p_tbl = calloc(lines + 1, sizeof (au_event_ent_t));
3067c478bd9Sstevel@tonic-gate 		if (p_tbl == NULL) {
3077257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3087c478bd9Sstevel@tonic-gate 			return (-2);
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 		lines = 0;
3117c478bd9Sstevel@tonic-gate 		max = 0;
3127c478bd9Sstevel@tonic-gate 		min = 65535;
3137c478bd9Sstevel@tonic-gate 		setauevent();
3147c478bd9Sstevel@tonic-gate 		while ((p_event = getauevent()) != NULL) {
3157c478bd9Sstevel@tonic-gate 			p_tbl[lines] = (au_event_ent_t *)
3167c478bd9Sstevel@tonic-gate 				malloc(sizeof (au_event_ent_t));
3177c478bd9Sstevel@tonic-gate 			if (p_tbl[lines] == NULL) {
3187257d1b4Sraf 				(void) mutex_unlock(&mutex_eventcache);
3197c478bd9Sstevel@tonic-gate 				return (-3);
3207c478bd9Sstevel@tonic-gate 			}
3217c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_number = p_event->ae_number;
3227c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_name   = strdup(p_event->ae_name);
3237c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_desc   = strdup(p_event->ae_desc);
3247c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_class  = p_event->ae_class;
3257c478bd9Sstevel@tonic-gate #ifdef DEBUG2
3267c478bd9Sstevel@tonic-gate 			printevent(p_tbl[lines]);
3277c478bd9Sstevel@tonic-gate #endif
328*d0fa49b7STony Nguyen 			if (p_event->ae_number > max) {
3297c478bd9Sstevel@tonic-gate 				max = p_event->ae_number;
3307c478bd9Sstevel@tonic-gate 			}
331*d0fa49b7STony Nguyen 			if (p_event->ae_number < min) {
3327c478bd9Sstevel@tonic-gate 				min = p_event->ae_number;
3337c478bd9Sstevel@tonic-gate 			}
3347c478bd9Sstevel@tonic-gate 			lines++;
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 		endauevent();
3377c478bd9Sstevel@tonic-gate 		invalid = lines;
3387c478bd9Sstevel@tonic-gate 		p_tbl[invalid] = (au_event_ent_t *)
3397c478bd9Sstevel@tonic-gate 			malloc(sizeof (au_event_ent_t));
3407c478bd9Sstevel@tonic-gate 		if (p_tbl[invalid] == NULL) {
3417257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3427c478bd9Sstevel@tonic-gate 			return (-4);
3437c478bd9Sstevel@tonic-gate 		}
344*d0fa49b7STony Nguyen 		p_tbl[invalid]->ae_number = (au_event_t)-1;
3457c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_name   = "invalid event number";
3467c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_desc   = p_tbl[invalid]->ae_name;
3477c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_class  = (au_class_t)-1;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate #ifdef DEBUG2
3507c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
3517c478bd9Sstevel@tonic-gate 			printf("%d:%s:%s:%d\n", p_tbl[i]->ae_number,
3527c478bd9Sstevel@tonic-gate 				p_tbl[i]->ae_name, p_tbl[i]->ae_desc,
3537c478bd9Sstevel@tonic-gate 				p_tbl[i]->ae_class);
3547c478bd9Sstevel@tonic-gate 		}
3557c478bd9Sstevel@tonic-gate #endif
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 		/* get space for the index_tbl */
3587c478bd9Sstevel@tonic-gate 		index_tbl = calloc(max+1, sizeof (au_event_ent_t *));
3597c478bd9Sstevel@tonic-gate 		if (index_tbl == NULL) {
3607257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3617c478bd9Sstevel@tonic-gate 			return (-5);
3627c478bd9Sstevel@tonic-gate 		}
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 		/* intialize the index_tbl to the invalid event number */
365*d0fa49b7STony Nguyen 		for (i = 0; (au_event_t)i < max; i++) {
3667c478bd9Sstevel@tonic-gate 			index_tbl[i] = p_tbl[invalid];
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 		/* point each index_tbl element at the corresponding event */
3707c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
371*d0fa49b7STony Nguyen 			index_tbl[p_tbl[i]->ae_number] = p_tbl[i];
3727c478bd9Sstevel@tonic-gate 		}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 		called_once = 1;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 
378*d0fa49b7STony Nguyen 	if (event_number > max || event_number < min) {
3797c478bd9Sstevel@tonic-gate 		*result = index_tbl[invalid];
3807c478bd9Sstevel@tonic-gate 	} else {
381*d0fa49b7STony Nguyen 		*result = index_tbl[event_number];
3827c478bd9Sstevel@tonic-gate 		hit = 1;
3837c478bd9Sstevel@tonic-gate 	}
3847257d1b4Sraf 	(void) mutex_unlock(&mutex_eventcache);
3857c478bd9Sstevel@tonic-gate 	return (hit);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate static au_class_t
3907c478bd9Sstevel@tonic-gate flagstohex(char *flags)
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate 	au_class_ent_t *p_class;
393e4163c9bSpaulson 	au_class_t	hex = 0;
3947c478bd9Sstevel@tonic-gate 	char	*comma = ",";
3957c478bd9Sstevel@tonic-gate 	char	*s;
3967c478bd9Sstevel@tonic-gate 	char	*last;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	s = strtok_r(flags, comma, &last);
3997c478bd9Sstevel@tonic-gate 	while (s != NULL) {
400e4163c9bSpaulson 		if ((cacheauclassnam(&p_class, s)) < 0) {
401e4163c9bSpaulson 			cacheauclass_failure = 1;
402e4163c9bSpaulson 			return ((au_class_t)-1);
403e4163c9bSpaulson 		}
4047c478bd9Sstevel@tonic-gate 		hex |= p_class->ac_class;
4057c478bd9Sstevel@tonic-gate 		s = strtok_r(NULL, comma, &last);
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 	return (hex);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate #ifdef DEBUG2
4127c478bd9Sstevel@tonic-gate void
4137c478bd9Sstevel@tonic-gate printevent(p_event)
4147c478bd9Sstevel@tonic-gate au_event_ent_t *p_event;
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate 	printf("%d:%s:%s:%d\n", p_event->ae_number, p_event->ae_name,
4177c478bd9Sstevel@tonic-gate 		p_event->ae_desc, p_event->ae_class);
4187c478bd9Sstevel@tonic-gate 	fflush(stdout);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate #endif
423