xref: /illumos-gate/usr/src/cmd/auditreduce/proc.c (revision 406d6273)
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
5d0fa49b7STony Nguyen  * Common Development and Distribution License (the "License").
6d0fa49b7STony Nguyen  * 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 /*
22d0fa49b7STony Nguyen  * Copyright 2008 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  * Main processor for auditreduce.
287c478bd9Sstevel@tonic-gate  * Mproc() is the entry point for this module. It is the only visible
297c478bd9Sstevel@tonic-gate  * function in this module.
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <locale.h>
347c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
35d0fa49b7STony Nguyen #include <bsm/audit.h>
367c478bd9Sstevel@tonic-gate #include "auditr.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate extern int	write_header();
397c478bd9Sstevel@tonic-gate extern int	token_processing();
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static void	asort();
427c478bd9Sstevel@tonic-gate static audit_pcb_t *aget();
437c478bd9Sstevel@tonic-gate static int	get_file();
447c478bd9Sstevel@tonic-gate static int	write_recs();
457c478bd9Sstevel@tonic-gate static int	get_recs();
467c478bd9Sstevel@tonic-gate static int	check_rec();
477c478bd9Sstevel@tonic-gate static void	check_order();
487c478bd9Sstevel@tonic-gate static int	check_header();
497c478bd9Sstevel@tonic-gate static int	get_record();
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static char	empty_file_token[] = {
527c478bd9Sstevel@tonic-gate #ifdef _LP64
537c478bd9Sstevel@tonic-gate 		AUT_OTHER_FILE64, /* token id */
547c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */
557c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */
567c478bd9Sstevel@tonic-gate #else
577c478bd9Sstevel@tonic-gate 		AUT_OTHER_FILE32, /* token id */
587c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, /* seconds of time */
597c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, /* microseconds of time */
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate 		0, 0, /* length of path name */
627c478bd9Sstevel@tonic-gate };
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * .func	mproc - main processor.
677c478bd9Sstevel@tonic-gate  * .desc	Mproc controls a single process's actions.
687c478bd9Sstevel@tonic-gate  *	First one record is retreived from each pcb. As they are retreived
697c478bd9Sstevel@tonic-gate  *	they are placed into a linked list sorted with oldest first. Then
707c478bd9Sstevel@tonic-gate  *	the first one from the list is written out and another record
717c478bd9Sstevel@tonic-gate  *	read in to replace it. The new record is placed into the list.
727c478bd9Sstevel@tonic-gate  *	This continues until the list is empty.
737c478bd9Sstevel@tonic-gate  * .call	ret = mproc(pcbr).
747c478bd9Sstevel@tonic-gate  * .arg	pcbr	- ptr to pcb for this process.
757c478bd9Sstevel@tonic-gate  * .ret	0	- no errors in processing.
767c478bd9Sstevel@tonic-gate  * .ret	-1	- errors in processing (message already printed).
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate int
mproc(pcbr)797c478bd9Sstevel@tonic-gate mproc(pcbr)
807c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr;
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate 	int	i, ret, junk;
837c478bd9Sstevel@tonic-gate 	int	nrecs = 0;		/* number of records read from stream */
847c478bd9Sstevel@tonic-gate 	int	nprecs = 0;		/* number of records put to stream */
857c478bd9Sstevel@tonic-gate 	register audit_pcb_t *pcb;
867c478bd9Sstevel@tonic-gate 	audit_pcb_t *aget();
877c478bd9Sstevel@tonic-gate 	void	asort();
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate #if AUDIT_PROC_TRACE
907c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "mproc: count %d lo %d hi %d\n",
917c478bd9Sstevel@tonic-gate 	    pcbr->pcb_count, pcbr->pcb_lo, pcbr->pcb_hi);
927c478bd9Sstevel@tonic-gate #endif
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate 	/*
957c478bd9Sstevel@tonic-gate 	 * First load up a record from each input group.
967c478bd9Sstevel@tonic-gate 	 */
977c478bd9Sstevel@tonic-gate 	for (i = pcbr->pcb_lo; i <= pcbr->pcb_hi; i++) {
987c478bd9Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[i]); /* get next PCB */
997c478bd9Sstevel@tonic-gate 		while (pcb->pcb_time < 0) { /* while no active record ... */
1007c478bd9Sstevel@tonic-gate 			if ((ret = get_file(pcb)) == -1)
1017c478bd9Sstevel@tonic-gate 				break;		/*  no files - finished PCB */
1027c478bd9Sstevel@tonic-gate 			if (ret == -2)
1037c478bd9Sstevel@tonic-gate 				return (-1);	/* quit processing - failed */
1047c478bd9Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
1057c478bd9Sstevel@tonic-gate 				asort(pcb);	/* got a rec - put in list */
1067c478bd9Sstevel@tonic-gate 		}
1077c478bd9Sstevel@tonic-gate 	}
1087c478bd9Sstevel@tonic-gate 	/*
1097c478bd9Sstevel@tonic-gate 	 * Now process all of the records.
1107c478bd9Sstevel@tonic-gate 	 */
1117c478bd9Sstevel@tonic-gate 	while ((pcb = aget()) != NULL) {	/* get oldest record */
1127c478bd9Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &nprecs))
1137c478bd9Sstevel@tonic-gate 			return (-1);
1147c478bd9Sstevel@tonic-gate 		while (pcb->pcb_time < 0) {	/* while we don't have a rec */
1157c478bd9Sstevel@tonic-gate 			if (pcb->pcb_fpr == NULL) {	/* no active file ... */
1167c478bd9Sstevel@tonic-gate 				if ((ret = get_file(pcb)) == -1)
1177c478bd9Sstevel@tonic-gate 					break;	/* no files - finished pcb */
1187c478bd9Sstevel@tonic-gate 				else if (ret == -2)
1197c478bd9Sstevel@tonic-gate 					return (-1);	/* quit - failed */
1207c478bd9Sstevel@tonic-gate 			}
1217c478bd9Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
1227c478bd9Sstevel@tonic-gate 				asort(pcb);		/* put record in list */
1237c478bd9Sstevel@tonic-gate 		}
1247c478bd9Sstevel@tonic-gate 	}
1257c478bd9Sstevel@tonic-gate 	/*
1267c478bd9Sstevel@tonic-gate 	 * For root: write outfile header if no records were encountered.
1277c478bd9Sstevel@tonic-gate 	 * For non-root: write trailer to pipe and close pipe.
1287c478bd9Sstevel@tonic-gate 	 */
1297c478bd9Sstevel@tonic-gate 	if (pcbr->pcb_flags & PF_ROOT) {
1307c478bd9Sstevel@tonic-gate 		if (nprecs == 0) {
1317c478bd9Sstevel@tonic-gate 			if (write_header())	/* write header if no records */
1327c478bd9Sstevel@tonic-gate 				return (-1);
1337c478bd9Sstevel@tonic-gate 		}
1347c478bd9Sstevel@tonic-gate 	} else {
1357c478bd9Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[0]);	/* any old PCB will do */
1367c478bd9Sstevel@tonic-gate 		pcb->pcb_rec = empty_file_token;
1377c478bd9Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &junk))
1387c478bd9Sstevel@tonic-gate 			return (-1);
1397c478bd9Sstevel@tonic-gate 		if (fclose(pcbr->pcb_fpw) == EOF) {
1407c478bd9Sstevel@tonic-gate 			if (!f_quiet)
1417c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1427c478bd9Sstevel@tonic-gate 				    gettext("%s couldn't close pipe.\n"), ar);
1437c478bd9Sstevel@tonic-gate 		}
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	/*
1467c478bd9Sstevel@tonic-gate 	 * For root process tell how many records were written.
1477c478bd9Sstevel@tonic-gate 	 */
1487c478bd9Sstevel@tonic-gate 	if (f_verbose && (pcbr->pcb_flags & PF_ROOT)) {
1497c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1507c478bd9Sstevel@tonic-gate 		    gettext("%s %d record(s) total were written out.\n"),
1517c478bd9Sstevel@tonic-gate 			ar, nprecs);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	return (0);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /*
1587c478bd9Sstevel@tonic-gate  * Head of linked-list of pcbs - sorted by time - oldest first.
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate static audit_pcb_t		*pcbls = NULL;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate  * .func	asort - audit sort.
1647c478bd9Sstevel@tonic-gate  * .desc	Place a pcb in the list sorted by time - oldest first.
1657c478bd9Sstevel@tonic-gate  * .call	asort(pcb);
1667c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb to install in list.
1677c478bd9Sstevel@tonic-gate  * .ret	void.
1687c478bd9Sstevel@tonic-gate  */
1697c478bd9Sstevel@tonic-gate static void
asort(pcb)1707c478bd9Sstevel@tonic-gate asort(pcb)
1717c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	register audit_pcb_t *pcbc, *pcbp;
1747c478bd9Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	pcb->pcb_next = NULL;
1777c478bd9Sstevel@tonic-gate 	if (pcbls == NULL) {
1787c478bd9Sstevel@tonic-gate 		pcbls = pcb;		/* empty list */
1797c478bd9Sstevel@tonic-gate 		return;
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 	pcbc = pcbls;			/* current pcb */
1827c478bd9Sstevel@tonic-gate 	pcbp = pcbls;			/* previous pcb */
1837c478bd9Sstevel@tonic-gate 	while (pcbc != NULL) {
1847c478bd9Sstevel@tonic-gate 		if (pcb->pcb_time < pcbc->pcb_time) {
1857c478bd9Sstevel@tonic-gate 			if (pcbp == pcbc) {
1867c478bd9Sstevel@tonic-gate 				pcb->pcb_next = pcbls;	/* new -> 1st in list */
1877c478bd9Sstevel@tonic-gate 				pcbls = pcb;
1887c478bd9Sstevel@tonic-gate 				return;
1897c478bd9Sstevel@tonic-gate 			}
1907c478bd9Sstevel@tonic-gate 			pcbp->pcb_next = pcb;
1917c478bd9Sstevel@tonic-gate 			pcb->pcb_next = pcbc;		/* new in the inside */
1927c478bd9Sstevel@tonic-gate 			return;
1937c478bd9Sstevel@tonic-gate 		}
1947c478bd9Sstevel@tonic-gate 		pcbp = pcbc;
1957c478bd9Sstevel@tonic-gate 		pcbc = pcbc->pcb_next;
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 	pcbp->pcb_next = pcb;				/* new -> last */
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate  * .func	aget - audit get.
2037c478bd9Sstevel@tonic-gate  * .desc	Get the first pcb from the list. Pcb is removed from list, too.
2047c478bd9Sstevel@tonic-gate  * .call	pcb = aget().
2057c478bd9Sstevel@tonic-gate  * .arg	none.
2067c478bd9Sstevel@tonic-gate  * .ret	pcb	- ptr to pcb that was the first.
2077c478bd9Sstevel@tonic-gate  */
2087c478bd9Sstevel@tonic-gate static audit_pcb_t *
aget()2097c478bd9Sstevel@tonic-gate aget()
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcbret;
2127c478bd9Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (pcbls == NULL)
2157c478bd9Sstevel@tonic-gate 		return (pcbls);		/* empty list */
2167c478bd9Sstevel@tonic-gate 	pcbret = pcbls;
2177c478bd9Sstevel@tonic-gate 	pcbls = pcbls->pcb_next;	/* 2nd becomes 1st */
2187c478bd9Sstevel@tonic-gate 	return (pcbret);
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate  * .func	get_file - get a new file.
2247c478bd9Sstevel@tonic-gate  * .desc	Get the next file from the pcb's list. Check the header to see
2257c478bd9Sstevel@tonic-gate  *	if the file really is an audit file. If there are no more then
2267c478bd9Sstevel@tonic-gate  *	quit. If a file open (fopen) fails because the system file table
2277c478bd9Sstevel@tonic-gate  *	is full or the process file table is full then quit processing
2287c478bd9Sstevel@tonic-gate  *	altogether.
2297c478bd9Sstevel@tonic-gate  * .call	ret = get_file(pcb).
2307c478bd9Sstevel@tonic-gate  * .arg	pcb	- pcb holding the fcb's (files).
2317c478bd9Sstevel@tonic-gate  * .ret	0	- new file opened for processing.
2327c478bd9Sstevel@tonic-gate  * .ret	-1	- no more files - pcb finished.
2337c478bd9Sstevel@tonic-gate  * .ret	-2	- fatal error - quit processing.
2347c478bd9Sstevel@tonic-gate  */
2357c478bd9Sstevel@tonic-gate static int
get_file(pcb)2367c478bd9Sstevel@tonic-gate get_file(pcb)
2377c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	FILE *fp;
2407c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	/*
2437c478bd9Sstevel@tonic-gate 	 * Process file list until a good one if found or empty.
2447c478bd9Sstevel@tonic-gate 	 */
2457c478bd9Sstevel@tonic-gate 	while (pcb->pcb_fpr == NULL) {
2467c478bd9Sstevel@tonic-gate 		if ((fcb = pcb->pcb_first) == NULL) {
2477c478bd9Sstevel@tonic-gate 			pcb->pcb_time = -1;
2487c478bd9Sstevel@tonic-gate 			return (-1);	/* pcb is all done */
2497c478bd9Sstevel@tonic-gate 		} else {
2507c478bd9Sstevel@tonic-gate 		/*
2517c478bd9Sstevel@tonic-gate 		 * If we are reading from files then open the next one.
2527c478bd9Sstevel@tonic-gate 		 */
2537c478bd9Sstevel@tonic-gate 			if (!f_stdin) {
2547c478bd9Sstevel@tonic-gate 				if ((fp = fopen(fcb->fcb_file, "r")) == NULL) {
2557c478bd9Sstevel@tonic-gate 					if (!f_quiet) {
2567c478bd9Sstevel@tonic-gate 						(void) sprintf(errbuf, gettext(
2577c478bd9Sstevel@tonic-gate 						"%s couldn't open:\n  %s"),
2587c478bd9Sstevel@tonic-gate 						ar, fcb->fcb_file);
2597c478bd9Sstevel@tonic-gate 						perror(errbuf);
2607c478bd9Sstevel@tonic-gate 					}
2617c478bd9Sstevel@tonic-gate 					/*
2627c478bd9Sstevel@tonic-gate 					 * See if file space is depleted.
2637c478bd9Sstevel@tonic-gate 					 * If it is then we quit.
2647c478bd9Sstevel@tonic-gate 					 */
2657c478bd9Sstevel@tonic-gate 					if (errno == ENFILE || errno == EMFILE)
2667c478bd9Sstevel@tonic-gate 					{
2677c478bd9Sstevel@tonic-gate 						return (-2);
2687c478bd9Sstevel@tonic-gate 					}
2697c478bd9Sstevel@tonic-gate 					pcb->pcb_first = fcb->fcb_next;
2707c478bd9Sstevel@tonic-gate 					continue;	/* try another file */
2717c478bd9Sstevel@tonic-gate 				}
2727c478bd9Sstevel@tonic-gate 			} else {
2737c478bd9Sstevel@tonic-gate 				/*
2747c478bd9Sstevel@tonic-gate 				 * Read from standard input.
2757c478bd9Sstevel@tonic-gate 				 */
2767c478bd9Sstevel@tonic-gate 				fp = stdin;
2777c478bd9Sstevel@tonic-gate 			}
2787c478bd9Sstevel@tonic-gate 			/*
2797c478bd9Sstevel@tonic-gate 			 * Check header of audit file.
2807c478bd9Sstevel@tonic-gate 			 */
2817c478bd9Sstevel@tonic-gate 			if (check_header(fp, fcb->fcb_name)) {
2827c478bd9Sstevel@tonic-gate 				if (!f_quiet) {
2837c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
2847c478bd9Sstevel@tonic-gate 					    "%s %s:\n  %s.\n",
2857c478bd9Sstevel@tonic-gate 					    ar, error_str, fcb->fcb_file);
2867c478bd9Sstevel@tonic-gate 				}
2877c478bd9Sstevel@tonic-gate 				if (fclose(fp) == EOF) {
2887c478bd9Sstevel@tonic-gate 					if (!f_quiet) {
2897c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, gettext(
2907c478bd9Sstevel@tonic-gate 						"%s couldn't close %s.\n"),
2917c478bd9Sstevel@tonic-gate 						ar, fcb->fcb_file);
2927c478bd9Sstevel@tonic-gate 					}
2937c478bd9Sstevel@tonic-gate 				}
2947c478bd9Sstevel@tonic-gate 				pcb->pcb_first = fcb->fcb_next;
2957c478bd9Sstevel@tonic-gate 				continue;		/* try another file */
2967c478bd9Sstevel@tonic-gate 			}
2977c478bd9Sstevel@tonic-gate 			/*
2987c478bd9Sstevel@tonic-gate 			 * Found a good audit file.
2997c478bd9Sstevel@tonic-gate 			 * Initalize pcb for processing.
3007c478bd9Sstevel@tonic-gate 			 */
3017c478bd9Sstevel@tonic-gate 			pcb->pcb_first = fcb->fcb_next;
3027c478bd9Sstevel@tonic-gate 			pcb->pcb_cur = fcb;
3037c478bd9Sstevel@tonic-gate 			pcb->pcb_fpr = fp;
3047c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs = 0;
3057c478bd9Sstevel@tonic-gate 			pcb->pcb_nprecs = 0;
3067c478bd9Sstevel@tonic-gate 			pcb->pcb_otime = -1;
3077c478bd9Sstevel@tonic-gate 		}
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 	return (0);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate  * .func	write_recs - write records.
3157c478bd9Sstevel@tonic-gate  * .desc	Write record from a buffer to output stream. Keep an eye out
3167c478bd9Sstevel@tonic-gate  *	for the first and last records of the root's output stream.
3177c478bd9Sstevel@tonic-gate  * .call	ret = write_recs(pcbr, pcb, nprecs).
3187c478bd9Sstevel@tonic-gate  * .arg	pcbr	- ptr to node pcb.
3197c478bd9Sstevel@tonic-gate  * .arg	pcb		- ptr to pcb holding the stream.
3207c478bd9Sstevel@tonic-gate  * .arg	nprecs	- ptr to the number of put records. Updated here.
3217c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
3227c478bd9Sstevel@tonic-gate  * .ret	-1	- error in writing. Quit processing.
3237c478bd9Sstevel@tonic-gate  */
3247c478bd9Sstevel@tonic-gate static int
write_recs(pcbr,pcb,nprecs)3257c478bd9Sstevel@tonic-gate write_recs(pcbr, pcb, nprecs)
3267c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr, *pcb;
3277c478bd9Sstevel@tonic-gate int	*nprecs;
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	adr_t adr;
3307c478bd9Sstevel@tonic-gate 	char	id;
3317c478bd9Sstevel@tonic-gate 	int32_t	size;
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
3347c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &id, 1);
3357c478bd9Sstevel@tonic-gate 	(void) adrm_int32(&adr, &size, 1);
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	/*
3387c478bd9Sstevel@tonic-gate 	 * Scan for first record to be written to outfile.
3397c478bd9Sstevel@tonic-gate 	 * When we find it then write the header and
3407c478bd9Sstevel@tonic-gate 	 * save the time for the outfile name.
3417c478bd9Sstevel@tonic-gate 	 */
3427c478bd9Sstevel@tonic-gate 	if ((*nprecs)++ == 0) {
3437c478bd9Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
3447c478bd9Sstevel@tonic-gate 			f_start = pcb->pcb_time;	/* save start time */
3457c478bd9Sstevel@tonic-gate 			if (write_header())
3467c478bd9Sstevel@tonic-gate 				return (-1);
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 	f_end = pcb->pcb_time;			/* find last record's time */
3507c478bd9Sstevel@tonic-gate 	pcb->pcb_time = -1;			/* disable just written rec */
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if ((fwrite(pcb->pcb_rec, sizeof (char), size, pcbr->pcb_fpw)) !=
3537c478bd9Sstevel@tonic-gate 			size) {
3547c478bd9Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
3557c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf, gettext(
3567c478bd9Sstevel@tonic-gate 				"%s write failed to %s"),
3577c478bd9Sstevel@tonic-gate 				ar, f_outfile ? f_outfile : gettext("stdout"));
3587c478bd9Sstevel@tonic-gate 			perror(errbuf);
3597c478bd9Sstevel@tonic-gate 		} else {
3607c478bd9Sstevel@tonic-gate 			perror(gettext("auditreduce: write failed to pipe"));
3617c478bd9Sstevel@tonic-gate 		}
3627c478bd9Sstevel@tonic-gate 		return (-1);
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 	free(pcb->pcb_rec);
3657c478bd9Sstevel@tonic-gate 	return (0);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate  * .func get_recs - get records.
3707c478bd9Sstevel@tonic-gate  * .desc Get records from a stream until one passing the current selection
3717c478bd9Sstevel@tonic-gate  *	criteria is found or the stream is emptied.
3727c478bd9Sstevel@tonic-gate  * .call	ret = get_recs(pcb, nr).
3737c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb that holds this stream.
3747c478bd9Sstevel@tonic-gate  * .arg	nr	- ptr to number of records read. Updated by this routine.
3757c478bd9Sstevel@tonic-gate  * .ret	0	- got a record.
3767c478bd9Sstevel@tonic-gate  * .ret	-1	- stream is finished.
3777c478bd9Sstevel@tonic-gate  */
3787c478bd9Sstevel@tonic-gate static int
get_recs(pcb,nr)3797c478bd9Sstevel@tonic-gate get_recs(pcb, nr)
3807c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
3817c478bd9Sstevel@tonic-gate int	*nr;
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	adr_t adr;
3847c478bd9Sstevel@tonic-gate 	time_t secs;
3857c478bd9Sstevel@tonic-gate 	int	tmp;
3867c478bd9Sstevel@tonic-gate 	int	ret, ret2;
3877c478bd9Sstevel@tonic-gate 	int	nrecs = 0;	/* count how many records read this call */
3887c478bd9Sstevel@tonic-gate 	int	getrec = TRUE;
3897c478bd9Sstevel@tonic-gate 	int	alldone = FALSE;
3907c478bd9Sstevel@tonic-gate 	char	header_type;
3917c478bd9Sstevel@tonic-gate 	short	e;
3927c478bd9Sstevel@tonic-gate 	char	*str;
3937c478bd9Sstevel@tonic-gate #if AUDIT_FILE
3947c478bd9Sstevel@tonic-gate 	static void	get_trace();
3957c478bd9Sstevel@tonic-gate #endif
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	while (getrec) {
3987c478bd9Sstevel@tonic-gate 		ret = get_record(pcb->pcb_fpr, &pcb->pcb_rec,
3997c478bd9Sstevel@tonic-gate 			pcb->pcb_cur->fcb_name);
4007c478bd9Sstevel@tonic-gate 		if (ret > 0) {
4017c478bd9Sstevel@tonic-gate 			adrm_start(&adr, pcb->pcb_rec);
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 			/* get token id */
4047c478bd9Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&header_type, 1);
4057c478bd9Sstevel@tonic-gate 			/* skip over byte count */
4067c478bd9Sstevel@tonic-gate 			(void) adrm_int32(&adr, (int32_t *)&tmp, 1);
4077c478bd9Sstevel@tonic-gate 			/* skip over version # */
4087c478bd9Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&tmp, 1);
4097c478bd9Sstevel@tonic-gate 			/* skip over event id */
4107c478bd9Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&e, 1);
4117c478bd9Sstevel@tonic-gate 			/* skip over event id modifier */
4127c478bd9Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&tmp, 1);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 			if (header_type == AUT_HEADER32) {
4157c478bd9Sstevel@tonic-gate 			    int32_t s, m;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 			    /* get seconds */
4187c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
4197c478bd9Sstevel@tonic-gate 			    /* get microseconds */
4207c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
4217c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
4227c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER32_EX) {
4237c478bd9Sstevel@tonic-gate 			    int32_t s, m;
4247c478bd9Sstevel@tonic-gate 			    int32_t t, junk[4];	/* at_type + at_addr[4] */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 			    /* skip type and ip address field */
4277c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
4287c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 			    /* get seconds */
4317c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
4327c478bd9Sstevel@tonic-gate 			    /* get microseconds */
4337c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
4347c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
4357c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64) {
4367c478bd9Sstevel@tonic-gate 			    int64_t s, m;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 			    /* get seconds */
4397c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
4407c478bd9Sstevel@tonic-gate 			    /* get microseconds */
4417c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
4427c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
4437c478bd9Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
4447c478bd9Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
4457c478bd9Sstevel@tonic-gate 					secs = 0;
4467c478bd9Sstevel@tonic-gate 			    else
4477c478bd9Sstevel@tonic-gate 					secs = (time_t)s;
4487c478bd9Sstevel@tonic-gate #else
4497c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
4507c478bd9Sstevel@tonic-gate #endif
4517c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64_EX) {
4527c478bd9Sstevel@tonic-gate 			    int64_t s, m;
4537c478bd9Sstevel@tonic-gate 			    int32_t t, junk[4];
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate 			    /* skip type and ip address field */
4567c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
4577c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 			    /* get seconds */
4607c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
4617c478bd9Sstevel@tonic-gate 			    /* get microseconds */
4627c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
4637c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
4647c478bd9Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
4657c478bd9Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
4667c478bd9Sstevel@tonic-gate 					secs = 0;
4677c478bd9Sstevel@tonic-gate 			    else
4687c478bd9Sstevel@tonic-gate 					secs = (time_t)s;
4697c478bd9Sstevel@tonic-gate #else
4707c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
4717c478bd9Sstevel@tonic-gate #endif
4727c478bd9Sstevel@tonic-gate 			}
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate #if AUDIT_REC
4767c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "get_recs: %d ret %d recno %d\n",
4777c478bd9Sstevel@tonic-gate 			pcb->pcb_procno, ret, pcb->pcb_nrecs + 1);
4787c478bd9Sstevel@tonic-gate #endif
4797c478bd9Sstevel@tonic-gate 		/*
4807c478bd9Sstevel@tonic-gate 		 * See if entire file is after the time window specified.
4817c478bd9Sstevel@tonic-gate 		 * Must be check here because the start time of the file name
4827c478bd9Sstevel@tonic-gate 		 * may be after the first record(s).
4837c478bd9Sstevel@tonic-gate 		 */
484*406d6273SPalle Lyckegaard 		if (pcb->pcb_nrecs == 0 && (pcb->pcb_flags & PF_USEFILE)) {
4857c478bd9Sstevel@tonic-gate 			/*
4867c478bd9Sstevel@tonic-gate 			 * If the first record read failed then use the time
4877c478bd9Sstevel@tonic-gate 			 * that was in the filename to judge.
4887c478bd9Sstevel@tonic-gate 			 */
4897c478bd9Sstevel@tonic-gate 			if (ret > 0)
4907c478bd9Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_start = secs;
4917c478bd9Sstevel@tonic-gate 			if (!f_all && (m_before <= (pcb->pcb_cur)->fcb_start)) {
4927c478bd9Sstevel@tonic-gate 				(void) fclose(pcb->pcb_fpr); /* ignore file */
4937c478bd9Sstevel@tonic-gate 				pcb->pcb_fpr = NULL;
4947c478bd9Sstevel@tonic-gate 				pcb->pcb_time = -1;
4957c478bd9Sstevel@tonic-gate 				return (-1);
4967c478bd9Sstevel@tonic-gate 			} else {
4977c478bd9Sstevel@tonic-gate 				/* Give belated announcement of file opening. */
4987c478bd9Sstevel@tonic-gate 				if (f_verbose) {
4997c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
5007c478bd9Sstevel@tonic-gate 						gettext("%s opened:\n  %s.\n"),
5017c478bd9Sstevel@tonic-gate 						ar, (pcb->pcb_cur)->fcb_file);
5027c478bd9Sstevel@tonic-gate 				}
5037c478bd9Sstevel@tonic-gate 			}
5047c478bd9Sstevel@tonic-gate 		}
5057c478bd9Sstevel@tonic-gate 		/* Succesful acquisition of a record.  */
5067c478bd9Sstevel@tonic-gate 		if (ret > 0) {
5077c478bd9Sstevel@tonic-gate 			pcb->pcb_time = secs;	/* time of record */
5087c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read recs from stream */
5097c478bd9Sstevel@tonic-gate 			nrecs++;		/* # of recs read this call */
5107c478bd9Sstevel@tonic-gate 			/* Only check record if at bottom of process tree. */
511*406d6273SPalle Lyckegaard 			if (pcb->pcb_flags & PF_USEFILE) {
5127c478bd9Sstevel@tonic-gate 				check_order(pcb); /* check time sequence */
5137c478bd9Sstevel@tonic-gate 				if ((ret2 = check_rec(pcb)) == 0) {
5147c478bd9Sstevel@tonic-gate 					pcb->pcb_nprecs++;
5157c478bd9Sstevel@tonic-gate 					getrec = FALSE;
5167c478bd9Sstevel@tonic-gate 				} else if (ret2 == -2) {
5177c478bd9Sstevel@tonic-gate 					/* error */
5187c478bd9Sstevel@tonic-gate 					getrec = FALSE;	/* get no more recs */
5197c478bd9Sstevel@tonic-gate 					alldone = TRUE;	/* quit this file */
5207c478bd9Sstevel@tonic-gate 					free(pcb->pcb_rec);
5217c478bd9Sstevel@tonic-gate 				} else {
5227c478bd9Sstevel@tonic-gate 					/* -1: record not interesting */
5237c478bd9Sstevel@tonic-gate 					free(pcb->pcb_rec);
5247c478bd9Sstevel@tonic-gate 				}
5257c478bd9Sstevel@tonic-gate 			} else {
5267c478bd9Sstevel@tonic-gate 				pcb->pcb_nprecs++;
5277c478bd9Sstevel@tonic-gate 				getrec = FALSE;
5287c478bd9Sstevel@tonic-gate 			}
5297c478bd9Sstevel@tonic-gate 		} else {
5307c478bd9Sstevel@tonic-gate 			/* Error with record read or all done with stream. */
5317c478bd9Sstevel@tonic-gate 			getrec = FALSE;
5327c478bd9Sstevel@tonic-gate 			alldone = TRUE;
5337c478bd9Sstevel@tonic-gate 		}
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate 	if (alldone == TRUE) {
5367c478bd9Sstevel@tonic-gate #if AUDIT_FILE
5377c478bd9Sstevel@tonic-gate 		get_trace(pcb);
5387c478bd9Sstevel@tonic-gate #endif
5397c478bd9Sstevel@tonic-gate 		/* Error in record read. Display messages. */
5407c478bd9Sstevel@tonic-gate 		if (ret < 0 || ret2 == -2) {
5417c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read records */
5427c478bd9Sstevel@tonic-gate 			if (!f_quiet) {
543*406d6273SPalle Lyckegaard 				if (pcb->pcb_flags & PF_USEFILE) {
5447c478bd9Sstevel@tonic-gate 					/* Ignore if this is not_terminated. */
5457c478bd9Sstevel@tonic-gate 					if (!strstr((pcb->pcb_cur)->fcb_file,
5467c478bd9Sstevel@tonic-gate 							"not_terminated")) {
5477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in %s at record %d.\n"), ar,
5487c478bd9Sstevel@tonic-gate 	(pcb->pcb_cur)->fcb_file, pcb->pcb_nrecs);
5497c478bd9Sstevel@tonic-gate 					}
5507c478bd9Sstevel@tonic-gate 				} else {
5517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in pipe at record %d.\n"), ar,
5527c478bd9Sstevel@tonic-gate 	pcb->pcb_nrecs);
5537c478bd9Sstevel@tonic-gate 				}
5547c478bd9Sstevel@tonic-gate 			}
5557c478bd9Sstevel@tonic-gate 		} else {
5567c478bd9Sstevel@tonic-gate 			/*
5577c478bd9Sstevel@tonic-gate 			 * Only mark infile for deleting if we have succesfully
5587c478bd9Sstevel@tonic-gate 			 * processed all of it.
5597c478bd9Sstevel@tonic-gate 			 */
560*406d6273SPalle Lyckegaard 			if (pcb->pcb_flags & PF_USEFILE)
5617c478bd9Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_flags |= FF_DELETE;
5627c478bd9Sstevel@tonic-gate 		}
5637c478bd9Sstevel@tonic-gate 		if (fclose(pcb->pcb_fpr) == EOF) {
5647c478bd9Sstevel@tonic-gate 			if (!f_quiet) {
565*406d6273SPalle Lyckegaard 				if (pcb->pcb_flags & PF_USEFILE) {
5667c478bd9Sstevel@tonic-gate 					str = (pcb->pcb_cur)->fcb_file;
5677c478bd9Sstevel@tonic-gate 				} else {
5687c478bd9Sstevel@tonic-gate 					str = "pipe";
5697c478bd9Sstevel@tonic-gate 				}
5707c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
5717c478bd9Sstevel@tonic-gate 					gettext("%s couldn't close %s.\n"),
5727c478bd9Sstevel@tonic-gate 					ar, str);
5737c478bd9Sstevel@tonic-gate 			}
5747c478bd9Sstevel@tonic-gate 		}
5757c478bd9Sstevel@tonic-gate 		pcb->pcb_fpr = NULL;
5767c478bd9Sstevel@tonic-gate 		pcb->pcb_time = -1;
5777c478bd9Sstevel@tonic-gate 		*nr += nrecs;
5787c478bd9Sstevel@tonic-gate 		return (-1);
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 	*nr += nrecs;
5817c478bd9Sstevel@tonic-gate 	return (0);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate #if AUDIT_FILE
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate  * .func get_trace - get trace.
5887c478bd9Sstevel@tonic-gate  * .desc If we are tracing file action (AUDIT_FILE is on) then print out
5897c478bd9Sstevel@tonic-gate  *	a message when the file is closed regarding how many records
5907c478bd9Sstevel@tonic-gate  *	were handled.
5917c478bd9Sstevel@tonic-gate  * .call	get_trace(pcb).
5927c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding file/pipe.
5937c478bd9Sstevel@tonic-gate  * .ret	void.
5947c478bd9Sstevel@tonic-gate  */
5957c478bd9Sstevel@tonic-gate static void
get_trace(pcb)5967c478bd9Sstevel@tonic-gate get_trace(pcb)
5977c478bd9Sstevel@tonic-gate audit_pcb_t *pcb;
5987c478bd9Sstevel@tonic-gate {
5997c478bd9Sstevel@tonic-gate 	/*
6007c478bd9Sstevel@tonic-gate 	 * For file give filename, too.
6017c478bd9Sstevel@tonic-gate 	 */
602*406d6273SPalle Lyckegaard 	if (pcb->pcb_flags & PF_USEFILE) {
6037c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s closed %s: %d records read recs: \
6047c478bd9Sstevel@tonic-gate 		%d record written.\n", ar, (pcb->pcb_cur)->fcb_file,
6057c478bd9Sstevel@tonic-gate 		pcb->pcb_nrecs, pcb->pcb_nprecs);
6067c478bd9Sstevel@tonic-gate 	} else {
6077c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s closed pipe: %d records read: \
6087c478bd9Sstevel@tonic-gate 			%d records written .\n", ar, pcb->pcb_nrecs,
6097c478bd9Sstevel@tonic-gate 			pcb->pcb_nprecs);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate #endif
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate /*
6167c478bd9Sstevel@tonic-gate  * .func	check_rec - check a record.
6177c478bd9Sstevel@tonic-gate  * .desc	Check a record against the user's selection criteria.
6187c478bd9Sstevel@tonic-gate  * .call	ret = check_rec(pcb).
6197c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the record.
6207c478bd9Sstevel@tonic-gate  * .ret	0	- record accepted.
6217c478bd9Sstevel@tonic-gate  * .ret	-1	- record rejected - continue processing file.
6227c478bd9Sstevel@tonic-gate  * .ret	-2	- record rejected - quit processing file.
6237c478bd9Sstevel@tonic-gate  */
6247c478bd9Sstevel@tonic-gate static int
check_rec(pcb)6257c478bd9Sstevel@tonic-gate check_rec(pcb)
6267c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
6277c478bd9Sstevel@tonic-gate {
6287c478bd9Sstevel@tonic-gate 	adr_t adr;
6297c478bd9Sstevel@tonic-gate 	struct timeval tv;
6307c478bd9Sstevel@tonic-gate 	uint_t	bytes;
631d0fa49b7STony Nguyen 	au_emod_t id_modifier;
6327c478bd9Sstevel@tonic-gate 	char	version;
633d0fa49b7STony Nguyen 	au_event_t event_type;
6347c478bd9Sstevel@tonic-gate 	char	tokenid;
6357c478bd9Sstevel@tonic-gate 	int	rc;	 /* return code */
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
6387c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &tokenid, 1);
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate 	/*
6417c478bd9Sstevel@tonic-gate 	 * checkflags will be my data structure for determining if
6427c478bd9Sstevel@tonic-gate 	 * a record has met ALL the selection criteria.  Once
6437c478bd9Sstevel@tonic-gate 	 * checkflags == flags, we have seen all we need to of the
6447c478bd9Sstevel@tonic-gate 	 * record, and can go to the next one.  If when we finish
6457c478bd9Sstevel@tonic-gate 	 * processing the record we still have stuff to see,
6467c478bd9Sstevel@tonic-gate 	 * checkflags != flags, and thus we should return a -1
6477c478bd9Sstevel@tonic-gate 	 * from this function meaning reject this record.
6487c478bd9Sstevel@tonic-gate 	 */
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	checkflags = 0;
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	/* must be header token -- sanity check */
6537c478bd9Sstevel@tonic-gate 	if (tokenid != AUT_HEADER32 && tokenid != AUT_HEADER64 &&
6547c478bd9Sstevel@tonic-gate 	    tokenid != AUT_HEADER32_EX && tokenid != AUT_HEADER64_EX) {
6557c478bd9Sstevel@tonic-gate #if AUDIT_REC
6567c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6577c478bd9Sstevel@tonic-gate 		    "check_rec: %d recno %d no header %d found\n",
6587c478bd9Sstevel@tonic-gate 		    pcb->pcb_procno, pcb->pcb_nrecs, tokenid);
6597c478bd9Sstevel@tonic-gate #endif
6607c478bd9Sstevel@tonic-gate 		return (-2);
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	/*
6647c478bd9Sstevel@tonic-gate 	 * The header token is:
6657c478bd9Sstevel@tonic-gate 	 *	attribute id:		char
6667c478bd9Sstevel@tonic-gate 	 *	byte count:		int
6677c478bd9Sstevel@tonic-gate 	 *	version #:		char
6687c478bd9Sstevel@tonic-gate 	 *	event ID:		short
6697c478bd9Sstevel@tonic-gate 	 *	ID modifier:		short
6707c478bd9Sstevel@tonic-gate 	 *	seconds (date):		int
6717c478bd9Sstevel@tonic-gate 	 *	time (microsecs):	int
6727c478bd9Sstevel@tonic-gate 	 */
6737c478bd9Sstevel@tonic-gate 	(void) adrm_u_int32(&adr, (uint32_t *)&bytes, 1);
6747c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &version, 1);
6757c478bd9Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &event_type, 1);
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	/*
6787c478bd9Sstevel@tonic-gate 	 * Used by s5_IPC_token to set the ipc_type so
6797c478bd9Sstevel@tonic-gate 	 * s5_IPC_perm_token can test.
6807c478bd9Sstevel@tonic-gate 	 */
6817c478bd9Sstevel@tonic-gate 	ipc_type = (char)0;
6827c478bd9Sstevel@tonic-gate 
6837c478bd9Sstevel@tonic-gate 	if (flags & M_TYPE) {
6847c478bd9Sstevel@tonic-gate 		checkflags |= M_TYPE;
6857c478bd9Sstevel@tonic-gate 		if (m_type != event_type)
6867c478bd9Sstevel@tonic-gate 			return (-1);
6877c478bd9Sstevel@tonic-gate 	}
6887c478bd9Sstevel@tonic-gate 	if (flags & M_CLASS) {
6897c478bd9Sstevel@tonic-gate 		au_event_ent_t *ev = NULL;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 		checkflags |= M_CLASS;
6927c478bd9Sstevel@tonic-gate 		if (cacheauevent(&ev, event_type) <= 0) {
6937c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr, gettext(
6947c478bd9Sstevel@tonic-gate 			"Warning: invalid event no %d in audit trail."),
6957c478bd9Sstevel@tonic-gate 			event_type);
6967c478bd9Sstevel@tonic-gate 		    return (-1);
6977c478bd9Sstevel@tonic-gate 		}
6987c478bd9Sstevel@tonic-gate 		global_class = ev->ae_class;
6997c478bd9Sstevel@tonic-gate 		if (!(flags & M_SORF) && !(mask.am_success & global_class))
7007c478bd9Sstevel@tonic-gate 			return (-1);
7017c478bd9Sstevel@tonic-gate 	}
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &id_modifier, 1);
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	/*
7067c478bd9Sstevel@tonic-gate 	 * Check record against time criteria.
7077c478bd9Sstevel@tonic-gate 	 * If the 'A' option was used then no time checking is done.
7087c478bd9Sstevel@tonic-gate 	 * The 'a' parameter is inclusive and the 'b' exclusive.
7097c478bd9Sstevel@tonic-gate 	 */
7107c478bd9Sstevel@tonic-gate 	if (tokenid == AUT_HEADER32) {
7117c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
7127c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
7137c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
7147c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7157c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7167c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER32_EX) {
7177c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
7187c478bd9Sstevel@tonic-gate 	    int32_t t, junk[5];	/* at_type + at_addr[4] */
7197c478bd9Sstevel@tonic-gate 	    /* skip type and ip address field */
7207c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
7217c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
7227c478bd9Sstevel@tonic-gate 	    /* get time */
7237c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
7247c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
7257c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7267c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7277c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64) {
7287c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
7297c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
7307c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
7317c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
7327c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
7337c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
7347c478bd9Sstevel@tonic-gate 			tv.tv_sec = 0;
7357c478bd9Sstevel@tonic-gate 	    else
7367c478bd9Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
7377c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
7387c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
7397c478bd9Sstevel@tonic-gate 			tv.tv_usec = 0;
7407c478bd9Sstevel@tonic-gate 	    else
7417c478bd9Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
7427c478bd9Sstevel@tonic-gate #else
7437c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7447c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7457c478bd9Sstevel@tonic-gate #endif
7467c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64_EX) {
7477c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
7487c478bd9Sstevel@tonic-gate 	    int32_t t, junk[4];	/* at_type + at_addr[4] */
7497c478bd9Sstevel@tonic-gate 	    /* skip type and ip address field */
7507c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
7517c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
7527c478bd9Sstevel@tonic-gate 	    /* get time */
7537c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
7547c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
7557c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
7567c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
7577c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
7587c478bd9Sstevel@tonic-gate 			tv.tv_sec = 0;
7597c478bd9Sstevel@tonic-gate 	    else
7607c478bd9Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
7617c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
7627c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
7637c478bd9Sstevel@tonic-gate 			tv.tv_usec = 0;
7647c478bd9Sstevel@tonic-gate 	    else
7657c478bd9Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
7667c478bd9Sstevel@tonic-gate #else
7677c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
7687c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
7697c478bd9Sstevel@tonic-gate #endif
7707c478bd9Sstevel@tonic-gate 	}
7717c478bd9Sstevel@tonic-gate 	pcb->pcb_otime = pcb->pcb_time;
7727c478bd9Sstevel@tonic-gate 	if (!f_all) {
7737c478bd9Sstevel@tonic-gate 		if (m_after > tv.tv_sec)
7747c478bd9Sstevel@tonic-gate 			return (-1);
7757c478bd9Sstevel@tonic-gate 		if (m_before <= tv.tv_sec)
7767c478bd9Sstevel@tonic-gate 			return (-1);
7777c478bd9Sstevel@tonic-gate 	}
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 	/* if no selection flags were passed, select everything */
7807c478bd9Sstevel@tonic-gate 	if (!flags)
7817c478bd9Sstevel@tonic-gate 		return (0);
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	/*
7847c478bd9Sstevel@tonic-gate 	 * If all information can be found in header,
7857c478bd9Sstevel@tonic-gate 	 * there is no need to continue processing the tokens.
7867c478bd9Sstevel@tonic-gate 	 */
7877c478bd9Sstevel@tonic-gate 	if (flags == checkflags)
7887c478bd9Sstevel@tonic-gate 		return (0);
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	/*
7917c478bd9Sstevel@tonic-gate 	 * Process tokens until we hit the end of the record
7927c478bd9Sstevel@tonic-gate 	 */
7937c478bd9Sstevel@tonic-gate 	while ((uint_t)(adr.adr_now - adr.adr_stream) < bytes) {
7947c478bd9Sstevel@tonic-gate 		adrm_char(&adr, &tokenid, 1);
7957c478bd9Sstevel@tonic-gate 		rc = token_processing(&adr, tokenid);
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 		/* Any Problems? */
7987c478bd9Sstevel@tonic-gate 		if (rc == -2) {
7997c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8007c478bd9Sstevel@tonic-gate 			    gettext("auditreduce: bad token %u, terminating "
8017c478bd9Sstevel@tonic-gate 			    "file %s\n"), tokenid, (pcb->pcb_cur)->fcb_file);
8027c478bd9Sstevel@tonic-gate 			return (-2);
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 		/* Are we finished? */
8067c478bd9Sstevel@tonic-gate 		if (flags == checkflags)
8077c478bd9Sstevel@tonic-gate 			return (0);
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate 	/*
8117c478bd9Sstevel@tonic-gate 	 * So, we haven't seen all that we need to see.  Reject record.
8127c478bd9Sstevel@tonic-gate 	 */
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	return (-1);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate  * .func check_order - Check temporal sequence.
8207c478bd9Sstevel@tonic-gate  * .call check_order(pcb).
8217c478bd9Sstevel@tonic-gate  * .arg	 pcb - ptr to audit_pcb_t.
8227c478bd9Sstevel@tonic-gate  * .desc	Check to see if the records are out of temporal sequence, ie,
8237c478bd9Sstevel@tonic-gate  *	a record has a time stamp older than its predecessor.
8247c478bd9Sstevel@tonic-gate  *	Also check to see if the current record is within the bounds of
8257c478bd9Sstevel@tonic-gate  *	the file itself.
8267c478bd9Sstevel@tonic-gate  *	This routine prints a diagnostic message, unless the QUIET
8277c478bd9Sstevel@tonic-gate  *	option was selected.
8287c478bd9Sstevel@tonic-gate  * .call	check_order(pcb).
8297c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the records.
8307c478bd9Sstevel@tonic-gate  * .ret	void.
8317c478bd9Sstevel@tonic-gate  */
8327c478bd9Sstevel@tonic-gate static void
check_order(pcb)8337c478bd9Sstevel@tonic-gate check_order(pcb)
8347c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate 	char	cptr1[28], cptr2[28];	/* for error reporting */
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	/*
8397c478bd9Sstevel@tonic-gate 	 * If the record-past is not the oldest then say so.
8407c478bd9Sstevel@tonic-gate 	 */
8417c478bd9Sstevel@tonic-gate 	if (pcb->pcb_otime > pcb->pcb_time) {
8427c478bd9Sstevel@tonic-gate 		if (!f_quiet) {
8437c478bd9Sstevel@tonic-gate 			(void) memcpy((void *)cptr1,
8447c478bd9Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_otime), 26);
8457c478bd9Sstevel@tonic-gate 			cptr1[24] = ' ';
8467c478bd9Sstevel@tonic-gate 			(void) memcpy((void *)cptr2,
8477c478bd9Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_time), 26);
8487c478bd9Sstevel@tonic-gate 			cptr2[24] = ' ';
8497c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
8507c478bd9Sstevel@tonic-gate 	gettext("%s %s had records out of order: %s was followed by %s.\n"),
8517c478bd9Sstevel@tonic-gate 				ar, (pcb->pcb_cur)->fcb_file, cptr1, cptr2);
8527c478bd9Sstevel@tonic-gate 		}
8537c478bd9Sstevel@tonic-gate 	}
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate /*
8587c478bd9Sstevel@tonic-gate  * .func	check_header.
8597c478bd9Sstevel@tonic-gate  * .desc	Read in and check the header for an audit file.
8607c478bd9Sstevel@tonic-gate  *	The header must read-in properly and have the magic #.
8617c478bd9Sstevel@tonic-gate  * .call	err = check_header(fp).
8627c478bd9Sstevel@tonic-gate  * .arg	fp	- file stream.
8637c478bd9Sstevel@tonic-gate  * .ret	0	no problems.
8647c478bd9Sstevel@tonic-gate  * .ret	-1	problems.
8657c478bd9Sstevel@tonic-gate  */
8667c478bd9Sstevel@tonic-gate static int
check_header(fp,fn)8677c478bd9Sstevel@tonic-gate check_header(fp, fn)
8687c478bd9Sstevel@tonic-gate FILE *fp;
8697c478bd9Sstevel@tonic-gate char	*fn;
8707c478bd9Sstevel@tonic-gate {
8717c478bd9Sstevel@tonic-gate 	char	id;
8727c478bd9Sstevel@tonic-gate 	char	*fname;
8737c478bd9Sstevel@tonic-gate 	short	pathlength;
8747c478bd9Sstevel@tonic-gate 	adr_t	adr;
8757c478bd9Sstevel@tonic-gate 	adrf_t	adrf;
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate 	adrf_start(&adrf, &adr, fp);
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
8807c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s is empty"), fn);
8817c478bd9Sstevel@tonic-gate 		error_str = errbuf;
8827c478bd9Sstevel@tonic-gate 		return (-1);
8837c478bd9Sstevel@tonic-gate 	}
8847c478bd9Sstevel@tonic-gate 	if (!(id == AUT_OTHER_FILE32 || id == AUT_OTHER_FILE64)) {
8857c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s not an audit file "), fn);
8867c478bd9Sstevel@tonic-gate 		error_str = errbuf;
8877c478bd9Sstevel@tonic-gate 		return (-1);
8887c478bd9Sstevel@tonic-gate 	}
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	if (id == AUT_OTHER_FILE32) {
8917c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
8927c478bd9Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&secs, 1);
8937c478bd9Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
8947c478bd9Sstevel@tonic-gate 	} else {
8957c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
8967c478bd9Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&secs, 1);
8977c478bd9Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
8987c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
8997c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
9007c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX) {
9017c478bd9Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
9027c478bd9Sstevel@tonic-gate 		    return (-1);
9037c478bd9Sstevel@tonic-gate 	    }
9047c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
9057c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX) {
9067c478bd9Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
9077c478bd9Sstevel@tonic-gate 		    return (-1);
9087c478bd9Sstevel@tonic-gate 	    }
9097c478bd9Sstevel@tonic-gate #endif
9107c478bd9Sstevel@tonic-gate 	}
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	if (adrf_short(&adrf, &pathlength, 1)) {
9137c478bd9Sstevel@tonic-gate 		error_str = gettext("incomplete file header");
9147c478bd9Sstevel@tonic-gate 		return (-1);
9157c478bd9Sstevel@tonic-gate 	}
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	if (pathlength != 0) {
9187c478bd9Sstevel@tonic-gate 		fname = (char *)a_calloc(1, (size_t)pathlength);
9197c478bd9Sstevel@tonic-gate 		if ((fread(fname, sizeof (char), pathlength, fp)) !=
9207c478bd9Sstevel@tonic-gate 				pathlength) {
9217c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
9227c478bd9Sstevel@tonic-gate 				gettext("error in header/filename read in %s"),
9237c478bd9Sstevel@tonic-gate 				fn);
9247c478bd9Sstevel@tonic-gate 			error_str = errbuf;
9257c478bd9Sstevel@tonic-gate 			return (-1);
9267c478bd9Sstevel@tonic-gate 		}
9277c478bd9Sstevel@tonic-gate 		free(fname);
9287c478bd9Sstevel@tonic-gate 	}
9297c478bd9Sstevel@tonic-gate 	return (0);
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate /*
9347c478bd9Sstevel@tonic-gate  * .func	get_record - get a single record.
9357c478bd9Sstevel@tonic-gate  * .desc	Read a single record from stream fp. If the record to be read
9367c478bd9Sstevel@tonic-gate  *	is larger than the buffer given to hold it (as determined by
9377c478bd9Sstevel@tonic-gate  *	cur_size) then free that buffer and allocate a new and bigger
9387c478bd9Sstevel@tonic-gate  *	one, making sure to store its size.
9397c478bd9Sstevel@tonic-gate  * .call	ret = get_record(fp, buf, cur_size, flags).
9407c478bd9Sstevel@tonic-gate  * .arg	fp	- stream to read from.
9417c478bd9Sstevel@tonic-gate  * .arg	buf	- ptr to ptr to buffer to place record in.
9427c478bd9Sstevel@tonic-gate  * .arg	cur_size- ptr to the size of the buffer that *buf points to.
9437c478bd9Sstevel@tonic-gate  * .arg	flags	- flags from fcb (to get FF_NOTTERM).
9447c478bd9Sstevel@tonic-gate  * .ret	+number	- number of chars in the record.
9457c478bd9Sstevel@tonic-gate  * .ret	0	- trailer seen - file done.
9467c478bd9Sstevel@tonic-gate  * .ret	-1	- read error (error_str know what type).
9477c478bd9Sstevel@tonic-gate  */
9487c478bd9Sstevel@tonic-gate static int
get_record(fp,buf,fn)9497c478bd9Sstevel@tonic-gate get_record(fp, buf, fn)
9507c478bd9Sstevel@tonic-gate FILE *fp;
9517c478bd9Sstevel@tonic-gate char	**buf;
9527c478bd9Sstevel@tonic-gate char	*fn;
9537c478bd9Sstevel@tonic-gate {
9547c478bd9Sstevel@tonic-gate 	adr_t	adr;
9557c478bd9Sstevel@tonic-gate 	adrf_t	adrf;
9567c478bd9Sstevel@tonic-gate 	int	leadin;
9577c478bd9Sstevel@tonic-gate 	char	id;
9587c478bd9Sstevel@tonic-gate 	int	lsize;
9597c478bd9Sstevel@tonic-gate 	short	ssize;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	/*
9627c478bd9Sstevel@tonic-gate 	 * Get the token type. It will be either a header or a file
9637c478bd9Sstevel@tonic-gate 	 * token.
9647c478bd9Sstevel@tonic-gate 	 */
9657c478bd9Sstevel@tonic-gate 	(void) adrf_start(&adrf, &adr, fp);
9667c478bd9Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
9677c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext(
9687c478bd9Sstevel@tonic-gate 			"record expected but not found in %s"),
9697c478bd9Sstevel@tonic-gate 			fn);
9707c478bd9Sstevel@tonic-gate 		error_str = errbuf;
9717c478bd9Sstevel@tonic-gate 		return (-1);
9727c478bd9Sstevel@tonic-gate 	}
9737c478bd9Sstevel@tonic-gate 	switch (id) {
9747c478bd9Sstevel@tonic-gate 	case AUT_HEADER32:
9757c478bd9Sstevel@tonic-gate 	case AUT_HEADER32_EX:
9767c478bd9Sstevel@tonic-gate 	case AUT_HEADER64:
9777c478bd9Sstevel@tonic-gate 	case AUT_HEADER64_EX:
9787c478bd9Sstevel@tonic-gate 		/*
9797c478bd9Sstevel@tonic-gate 		 * The header token is:
9807c478bd9Sstevel@tonic-gate 		 *	attribute id:		char
9817c478bd9Sstevel@tonic-gate 		 *	byte count:		int
9827c478bd9Sstevel@tonic-gate 		 *	version #:		char
9837c478bd9Sstevel@tonic-gate 		 *	event ID:		short
9847c478bd9Sstevel@tonic-gate 		 *	ID modifier:		short
9857c478bd9Sstevel@tonic-gate 		 *	IP address type		int	(_EX only)
9867c478bd9Sstevel@tonic-gate 		 *	IP address		1/4*int (_EX only)
9877c478bd9Sstevel@tonic-gate 		 *	seconds (date):		long
9887c478bd9Sstevel@tonic-gate 		 *	time (microsecs):	long
9897c478bd9Sstevel@tonic-gate 		 */
9907c478bd9Sstevel@tonic-gate 		leadin = sizeof (int32_t) + sizeof (char);
9917c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, &lsize, 1);
9927c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(lsize + leadin));
9937c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
9947c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
9957c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&lsize, 1);
9967c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), lsize - leadin, fp) !=
9977c478bd9Sstevel@tonic-gate 			lsize - leadin) {
9987c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
9997c478bd9Sstevel@tonic-gate 				gettext("header token read failure in %s"), fn);
10007c478bd9Sstevel@tonic-gate 			error_str = errbuf;
10017c478bd9Sstevel@tonic-gate 			return (-1);
10027c478bd9Sstevel@tonic-gate 		}
10037c478bd9Sstevel@tonic-gate 		return (lsize + leadin);
10047c478bd9Sstevel@tonic-gate 	case AUT_OTHER_FILE32: {
10057c478bd9Sstevel@tonic-gate 		int32_t secs, msecs;
10067c478bd9Sstevel@tonic-gate 		leadin =  2 * sizeof (int32_t) +
10077c478bd9Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
10087c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&secs, 1);
10097c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
10107c478bd9Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
10117c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
10127c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
10137c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
10147c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&secs, 1);
10157c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&msecs, 1);
10167c478bd9Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
10177c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
10187c478bd9Sstevel@tonic-gate 			error_str = gettext("file token read failure");
10197c478bd9Sstevel@tonic-gate 			return (-1);
10207c478bd9Sstevel@tonic-gate 		}
10217c478bd9Sstevel@tonic-gate 		return (0);		/* done! */
10227c478bd9Sstevel@tonic-gate 	}
10237c478bd9Sstevel@tonic-gate 	case AUT_OTHER_FILE64: {
10247c478bd9Sstevel@tonic-gate 		int64_t secs, msecs;
10257c478bd9Sstevel@tonic-gate 		leadin =  2 * sizeof (int64_t) +
10267c478bd9Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
10277c478bd9Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&secs, 1);
10287c478bd9Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
10297c478bd9Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
10307c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
10317c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
10327c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
10337c478bd9Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&secs, 1);
10347c478bd9Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&msecs, 1);
10357c478bd9Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
10367c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
10377c478bd9Sstevel@tonic-gate 			error_str = gettext("file token read failure");
10387c478bd9Sstevel@tonic-gate 			return (-1);
10397c478bd9Sstevel@tonic-gate 		}
10407c478bd9Sstevel@tonic-gate 		return (0);		/* done! */
10417c478bd9Sstevel@tonic-gate 	}
10427c478bd9Sstevel@tonic-gate 	default:
10437c478bd9Sstevel@tonic-gate 		break;
10447c478bd9Sstevel@tonic-gate 	}
10457c478bd9Sstevel@tonic-gate 	error_str = gettext("record begins without proper token");
10467c478bd9Sstevel@tonic-gate 	return (-1);
10477c478bd9Sstevel@tonic-gate }
1048