xref: /titanic_41/usr/src/lib/libbsm/common/audit_event.c (revision dfc7be02c381b7c61998fdb9ecbf069933d62381)
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 /*
23*dfc7be02SJan Friedel  * Copyright 2010 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 
70*dfc7be02SJan Friedel #ifdef DEBUG2
71*dfc7be02SJan Friedel void
printevent(au_event_ent_t * p_event)72*dfc7be02SJan Friedel printevent(au_event_ent_t *p_event)
73*dfc7be02SJan Friedel {
74*dfc7be02SJan Friedel 	(void) printf("%d:%s:%s:%d\n", p_event->ae_number, p_event->ae_name,
75*dfc7be02SJan Friedel 	    p_event->ae_desc, p_event->ae_class);
76*dfc7be02SJan Friedel 	(void) fflush(stdout);
77*dfc7be02SJan Friedel }
78*dfc7be02SJan Friedel #endif
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate void
setauevent()817c478bd9Sstevel@tonic-gate setauevent()
827c478bd9Sstevel@tonic-gate {
837257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
847c478bd9Sstevel@tonic-gate 	if (au_event_file) {
857c478bd9Sstevel@tonic-gate 		(void) fseek(au_event_file, 0L, 0);
867c478bd9Sstevel@tonic-gate 	}
877257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate void
endauevent()917c478bd9Sstevel@tonic-gate endauevent()
927c478bd9Sstevel@tonic-gate {
937257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
947c478bd9Sstevel@tonic-gate 	if (au_event_file) {
957c478bd9Sstevel@tonic-gate 		(void) fclose(au_event_file);
967c478bd9Sstevel@tonic-gate 		au_event_file = (FILE *)0;
977c478bd9Sstevel@tonic-gate 	}
987257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevent()1027c478bd9Sstevel@tonic-gate getauevent()
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	static au_event_ent_t au_event_entry;
1057c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
1067c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
1097c478bd9Sstevel@tonic-gate 	au_event_entry.ae_name = ename;
1107c478bd9Sstevel@tonic-gate 	au_event_entry.ae_desc = edesc;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	return (getauevent_r(&au_event_entry));
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevent_r(au_event_ent_t * au_event_entry)116*dfc7be02SJan Friedel getauevent_r(au_event_ent_t *au_event_entry)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate 	int	i, error = 0, found = 0;
1197c478bd9Sstevel@tonic-gate 	char	*s, input[AU_EVENT_LINE_MAX];
1207c478bd9Sstevel@tonic-gate 	char	trim_buf[AU_EVENT_NAME_MAX+1];
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/* open audit event file if it isn't already */
1237257d1b4Sraf 	(void) mutex_lock(&mutex_eventfile);
1247c478bd9Sstevel@tonic-gate 	if (!au_event_file)
125004388ebScasper 		if (!(au_event_file = fopen(au_event_fname, "rF"))) {
1267257d1b4Sraf 			(void) mutex_unlock(&mutex_eventfile);
127d0fa49b7STony Nguyen 			return (NULL);
1287c478bd9Sstevel@tonic-gate 		}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	while (fgets(input, AU_EVENT_LINE_MAX, au_event_file)) {
1317c478bd9Sstevel@tonic-gate 		if (input[0] != '#') {
1327c478bd9Sstevel@tonic-gate 			s = input + strspn(input, " \t\r\n");
1337c478bd9Sstevel@tonic-gate 			if ((*s == '\0') || (*s == '#')) {
1347c478bd9Sstevel@tonic-gate 				continue;
1357c478bd9Sstevel@tonic-gate 			}
1367c478bd9Sstevel@tonic-gate 			found = 1;
1377c478bd9Sstevel@tonic-gate 			s = input;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 			/* parse number */
1407c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1417c478bd9Sstevel@tonic-gate 			s[i] = '\0';
142d0fa49b7STony Nguyen 			(void) sscanf(s, "%hu", &au_event_entry->ae_number);
1437c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 			/* parse event name */
1467c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1477c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1487c478bd9Sstevel@tonic-gate 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
1497c478bd9Sstevel@tonic-gate 			    trim_buf);
1507c478bd9Sstevel@tonic-gate 			(void) strncpy(au_event_entry->ae_name, trim_buf,
1517c478bd9Sstevel@tonic-gate 			    AU_EVENT_NAME_MAX);
1527c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 			/* parse event description */
1557c478bd9Sstevel@tonic-gate 			i = strcspn(s, ":");
1567c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1577c478bd9Sstevel@tonic-gate 			(void) strncpy(au_event_entry->ae_desc, s,
1587c478bd9Sstevel@tonic-gate 			    AU_EVENT_DESC_MAX);
1597c478bd9Sstevel@tonic-gate 			s = &s[i+1];
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 			/* parse class */
1627c478bd9Sstevel@tonic-gate 			i = strcspn(s, "\n\0");
1637c478bd9Sstevel@tonic-gate 			s[i] = '\0';
1647c478bd9Sstevel@tonic-gate 			(void) sscanf(s, "%" VAL2STR(AU_EVENT_NAME_MAX) "s",
1657c478bd9Sstevel@tonic-gate 			    trim_buf);
1667c478bd9Sstevel@tonic-gate 			au_event_entry->ae_class = flagstohex(trim_buf);
167e4163c9bSpaulson 			if (cacheauclass_failure == 1) {
168e4163c9bSpaulson 				error = 1;
169e4163c9bSpaulson 				cacheauclass_failure = 0;
170e4163c9bSpaulson 			}
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 			break;
1737c478bd9Sstevel@tonic-gate 		}
1747c478bd9Sstevel@tonic-gate 	}
1757257d1b4Sraf 	(void) mutex_unlock(&mutex_eventfile);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	if (!error && found) {
1787c478bd9Sstevel@tonic-gate 		return (au_event_entry);
1797c478bd9Sstevel@tonic-gate 	} else {
180d0fa49b7STony Nguyen 		return (NULL);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevnam(char * name)1857c478bd9Sstevel@tonic-gate getauevnam(char *name)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	static au_event_ent_t au_event_entry;
1887c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
1897c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
1927c478bd9Sstevel@tonic-gate 	au_event_entry.ae_name = ename;
1937c478bd9Sstevel@tonic-gate 	au_event_entry.ae_desc = edesc;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	return (getauevnam_r(&au_event_entry, name));
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevnam_r(au_event_ent_t * e,char * name)1997c478bd9Sstevel@tonic-gate getauevnam_r(au_event_ent_t *e, char *name)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	setauevent();
2027c478bd9Sstevel@tonic-gate 	while (getauevent_r(e) != NULL) {
2037c478bd9Sstevel@tonic-gate 		if (strcmp(e->ae_name, name) == 0) {
2047c478bd9Sstevel@tonic-gate 			endauevent();
2057c478bd9Sstevel@tonic-gate 			return (e);
2067c478bd9Sstevel@tonic-gate 		}
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 	endauevent();
209d0fa49b7STony Nguyen 	return (NULL);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevnum_r(au_event_ent_t * e,au_event_t event_number)2137c478bd9Sstevel@tonic-gate getauevnum_r(au_event_ent_t *e, au_event_t event_number)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	setauevent();
2167c478bd9Sstevel@tonic-gate 	while (getauevent_r(e) != NULL) {
2177c478bd9Sstevel@tonic-gate 		if (e->ae_number == event_number) {
2187c478bd9Sstevel@tonic-gate 			endauevent();
2197c478bd9Sstevel@tonic-gate 			return (e);
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	endauevent();
223d0fa49b7STony Nguyen 	return (NULL);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate au_event_ent_t *
getauevnum(au_event_t event_number)2277c478bd9Sstevel@tonic-gate getauevnum(au_event_t event_number)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	static au_event_ent_t e;
2307c478bd9Sstevel@tonic-gate 	static char	ename[AU_EVENT_NAME_MAX];
2317c478bd9Sstevel@tonic-gate 	static char	edesc[AU_EVENT_DESC_MAX];
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
2347c478bd9Sstevel@tonic-gate 	e.ae_name = ename;
2357c478bd9Sstevel@tonic-gate 	e.ae_desc = edesc;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	return (getauevnum_r(&e, event_number));
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate au_event_t
getauevnonam(char * event_name)2417c478bd9Sstevel@tonic-gate getauevnonam(char *event_name)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	au_event_ent_t e;
2447c478bd9Sstevel@tonic-gate 	char ename[AU_EVENT_NAME_MAX];
2457c478bd9Sstevel@tonic-gate 	char edesc[AU_EVENT_DESC_MAX];
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	/* initialize au_event_entry structure */
2487c478bd9Sstevel@tonic-gate 	e.ae_name = ename;
2497c478bd9Sstevel@tonic-gate 	e.ae_desc = edesc;
2507c478bd9Sstevel@tonic-gate 
251d0fa49b7STony Nguyen 	if (getauevnam_r(&e, event_name) == NULL) {
252d0fa49b7STony Nguyen 		return (0);
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 	return (e.ae_number);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * cacheauevent:
2597c478bd9Sstevel@tonic-gate  *	Read the entire audit_event file into memory.
2607c478bd9Sstevel@tonic-gate  *	Set a pointer to the requested entry in the cache
2617c478bd9Sstevel@tonic-gate  *	or a pointer to an invalid entry if the event number
2627c478bd9Sstevel@tonic-gate  *	is not known.
2637c478bd9Sstevel@tonic-gate  *
2647c478bd9Sstevel@tonic-gate  *	Return < 0, if error.
2657c478bd9Sstevel@tonic-gate  *	Return   0, if event number not in cache.
2667c478bd9Sstevel@tonic-gate  *	Return   1, if event number is in cache.
2677c478bd9Sstevel@tonic-gate  */
2687c478bd9Sstevel@tonic-gate int
cacheauevent(au_event_ent_t ** result,au_event_t event_number)2697c478bd9Sstevel@tonic-gate cacheauevent(au_event_ent_t **result, au_event_t event_number)
2707c478bd9Sstevel@tonic-gate {
271d0fa49b7STony Nguyen 	static au_event_t max; /* the highest event number in the file */
272d0fa49b7STony Nguyen 	static au_event_t min; /* the lowest event number in the file */
2737c478bd9Sstevel@tonic-gate 	static int	invalid; /* 1+index of the highest event number */
2747c478bd9Sstevel@tonic-gate 	static au_event_ent_t **index_tbl;
2757c478bd9Sstevel@tonic-gate 	static au_event_ent_t **p_tbl;
2767c478bd9Sstevel@tonic-gate 	static int	called_once = 0;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	char	line[AU_EVENT_LINE_MAX];
2797c478bd9Sstevel@tonic-gate 	int	lines = 0;
2807c478bd9Sstevel@tonic-gate 	FILE	*fp;
2817c478bd9Sstevel@tonic-gate 	au_event_ent_t *p_event;
2827c478bd9Sstevel@tonic-gate 	int	i, size;
2837c478bd9Sstevel@tonic-gate 	int	hit = 0;
2847c478bd9Sstevel@tonic-gate 	char	*s;
2857c478bd9Sstevel@tonic-gate 
2867257d1b4Sraf 	(void) mutex_lock(&mutex_eventcache);
2877c478bd9Sstevel@tonic-gate 	if (called_once == 0) {
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		/* Count number of lines in the events file */
290004388ebScasper 		if ((fp = fopen(au_event_fname, "rF")) == NULL) {
2917257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
2927c478bd9Sstevel@tonic-gate 			return (-1);
2937c478bd9Sstevel@tonic-gate 		}
2947c478bd9Sstevel@tonic-gate 		while (fgets(line, AU_EVENT_LINE_MAX, fp) != NULL) {
2957c478bd9Sstevel@tonic-gate 			s = line + strspn(line, " \t\r\n");
2967c478bd9Sstevel@tonic-gate 			if ((*s == '\0') || (*s == '#')) {
2977c478bd9Sstevel@tonic-gate 				continue;
2987c478bd9Sstevel@tonic-gate 			}
2997c478bd9Sstevel@tonic-gate 			lines++;
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
3027c478bd9Sstevel@tonic-gate 		size = lines;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		/*
3057c478bd9Sstevel@tonic-gate 		 * Make an array in which each element in an entry in the
3067c478bd9Sstevel@tonic-gate 		 * events file.  Make the next to last element an invalid
3077c478bd9Sstevel@tonic-gate 		 * event.  Make the last element a NULL pointer.
3087c478bd9Sstevel@tonic-gate 		 */
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 		p_tbl = calloc(lines + 1, sizeof (au_event_ent_t));
3117c478bd9Sstevel@tonic-gate 		if (p_tbl == NULL) {
3127257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3137c478bd9Sstevel@tonic-gate 			return (-2);
3147c478bd9Sstevel@tonic-gate 		}
3157c478bd9Sstevel@tonic-gate 		lines = 0;
3167c478bd9Sstevel@tonic-gate 		max = 0;
3177c478bd9Sstevel@tonic-gate 		min = 65535;
3187c478bd9Sstevel@tonic-gate 		setauevent();
3197c478bd9Sstevel@tonic-gate 		while ((p_event = getauevent()) != NULL) {
3207c478bd9Sstevel@tonic-gate 			p_tbl[lines] = (au_event_ent_t *)
3217c478bd9Sstevel@tonic-gate 			    malloc(sizeof (au_event_ent_t));
3227c478bd9Sstevel@tonic-gate 			if (p_tbl[lines] == NULL) {
3237257d1b4Sraf 				(void) mutex_unlock(&mutex_eventcache);
3247c478bd9Sstevel@tonic-gate 				return (-3);
3257c478bd9Sstevel@tonic-gate 			}
3267c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_number = p_event->ae_number;
3277c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_name   = strdup(p_event->ae_name);
3287c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_desc   = strdup(p_event->ae_desc);
3297c478bd9Sstevel@tonic-gate 			p_tbl[lines]->ae_class  = p_event->ae_class;
3307c478bd9Sstevel@tonic-gate #ifdef DEBUG2
3317c478bd9Sstevel@tonic-gate 			printevent(p_tbl[lines]);
3327c478bd9Sstevel@tonic-gate #endif
333d0fa49b7STony Nguyen 			if (p_event->ae_number > max) {
3347c478bd9Sstevel@tonic-gate 				max = p_event->ae_number;
3357c478bd9Sstevel@tonic-gate 			}
336d0fa49b7STony Nguyen 			if (p_event->ae_number < min) {
3377c478bd9Sstevel@tonic-gate 				min = p_event->ae_number;
3387c478bd9Sstevel@tonic-gate 			}
3397c478bd9Sstevel@tonic-gate 			lines++;
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 		endauevent();
3427c478bd9Sstevel@tonic-gate 		invalid = lines;
3437c478bd9Sstevel@tonic-gate 		p_tbl[invalid] = (au_event_ent_t *)
3447c478bd9Sstevel@tonic-gate 		    malloc(sizeof (au_event_ent_t));
3457c478bd9Sstevel@tonic-gate 		if (p_tbl[invalid] == NULL) {
3467257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3477c478bd9Sstevel@tonic-gate 			return (-4);
3487c478bd9Sstevel@tonic-gate 		}
349d0fa49b7STony Nguyen 		p_tbl[invalid]->ae_number = (au_event_t)-1;
3507c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_name   = "invalid event number";
3517c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_desc   = p_tbl[invalid]->ae_name;
3527c478bd9Sstevel@tonic-gate 		p_tbl[invalid]->ae_class  = (au_class_t)-1;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate #ifdef DEBUG2
3557c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
356*dfc7be02SJan Friedel 			(void) printf("%d:%s:%s:%d\n", p_tbl[i]->ae_number,
3577c478bd9Sstevel@tonic-gate 			    p_tbl[i]->ae_name, p_tbl[i]->ae_desc,
3587c478bd9Sstevel@tonic-gate 			    p_tbl[i]->ae_class);
3597c478bd9Sstevel@tonic-gate 		}
3607c478bd9Sstevel@tonic-gate #endif
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 		/* get space for the index_tbl */
3637c478bd9Sstevel@tonic-gate 		index_tbl = calloc(max+1, sizeof (au_event_ent_t *));
3647c478bd9Sstevel@tonic-gate 		if (index_tbl == NULL) {
3657257d1b4Sraf 			(void) mutex_unlock(&mutex_eventcache);
3667c478bd9Sstevel@tonic-gate 			return (-5);
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 		/* intialize the index_tbl to the invalid event number */
370d0fa49b7STony Nguyen 		for (i = 0; (au_event_t)i < max; i++) {
3717c478bd9Sstevel@tonic-gate 			index_tbl[i] = p_tbl[invalid];
3727c478bd9Sstevel@tonic-gate 		}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 		/* point each index_tbl element at the corresponding event */
3757c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
376d0fa49b7STony Nguyen 			index_tbl[p_tbl[i]->ae_number] = p_tbl[i];
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 		called_once = 1;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
383d0fa49b7STony Nguyen 	if (event_number > max || event_number < min) {
3847c478bd9Sstevel@tonic-gate 		*result = index_tbl[invalid];
3857c478bd9Sstevel@tonic-gate 	} else {
386d0fa49b7STony Nguyen 		*result = index_tbl[event_number];
3877c478bd9Sstevel@tonic-gate 		hit = 1;
3887c478bd9Sstevel@tonic-gate 	}
3897257d1b4Sraf 	(void) mutex_unlock(&mutex_eventcache);
3907c478bd9Sstevel@tonic-gate 	return (hit);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate static au_class_t
flagstohex(char * flags)3947c478bd9Sstevel@tonic-gate flagstohex(char *flags)
3957c478bd9Sstevel@tonic-gate {
3967c478bd9Sstevel@tonic-gate 	au_class_ent_t *p_class;
397e4163c9bSpaulson 	au_class_t	hex = 0;
3987c478bd9Sstevel@tonic-gate 	char	*comma = ",";
3997c478bd9Sstevel@tonic-gate 	char	*s;
4007c478bd9Sstevel@tonic-gate 	char	*last;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	s = strtok_r(flags, comma, &last);
4037c478bd9Sstevel@tonic-gate 	while (s != NULL) {
404e4163c9bSpaulson 		if ((cacheauclassnam(&p_class, s)) < 0) {
405e4163c9bSpaulson 			cacheauclass_failure = 1;
406e4163c9bSpaulson 			return ((au_class_t)-1);
407e4163c9bSpaulson 		}
4087c478bd9Sstevel@tonic-gate 		hex |= p_class->ac_class;
4097c478bd9Sstevel@tonic-gate 		s = strtok_r(NULL, comma, &last);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	return (hex);
4127c478bd9Sstevel@tonic-gate }
413