xref: /illumos-gate/usr/src/cmd/auditreduce/proc.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Main processor for auditreduce.
32*7c478bd9Sstevel@tonic-gate  * Mproc() is the entry point for this module. It is the only visible
33*7c478bd9Sstevel@tonic-gate  * function in this module.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
37*7c478bd9Sstevel@tonic-gate #include <locale.h>
38*7c478bd9Sstevel@tonic-gate #include <bsm/libbsm.h>
39*7c478bd9Sstevel@tonic-gate #include "auditr.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate extern int	write_header();
42*7c478bd9Sstevel@tonic-gate extern int	token_processing();
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate static void	asort();
45*7c478bd9Sstevel@tonic-gate static audit_pcb_t *aget();
46*7c478bd9Sstevel@tonic-gate static int	get_file();
47*7c478bd9Sstevel@tonic-gate static int	write_recs();
48*7c478bd9Sstevel@tonic-gate static int	get_recs();
49*7c478bd9Sstevel@tonic-gate static int	check_rec();
50*7c478bd9Sstevel@tonic-gate static void	check_order();
51*7c478bd9Sstevel@tonic-gate static int	check_header();
52*7c478bd9Sstevel@tonic-gate static int	get_record();
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate static char	empty_file_token[] = {
55*7c478bd9Sstevel@tonic-gate #ifdef _LP64
56*7c478bd9Sstevel@tonic-gate 		AUT_OTHER_FILE64, /* token id */
57*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */
58*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */
59*7c478bd9Sstevel@tonic-gate #else
60*7c478bd9Sstevel@tonic-gate 		AUT_OTHER_FILE32, /* token id */
61*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, /* seconds of time */
62*7c478bd9Sstevel@tonic-gate 		0, 0, 0, 0, /* microseconds of time */
63*7c478bd9Sstevel@tonic-gate #endif
64*7c478bd9Sstevel@tonic-gate 		0, 0, /* length of path name */
65*7c478bd9Sstevel@tonic-gate };
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * .func	mproc - main processor.
70*7c478bd9Sstevel@tonic-gate  * .desc	Mproc controls a single process's actions.
71*7c478bd9Sstevel@tonic-gate  *	First one record is retreived from each pcb. As they are retreived
72*7c478bd9Sstevel@tonic-gate  *	they are placed into a linked list sorted with oldest first. Then
73*7c478bd9Sstevel@tonic-gate  *	the first one from the list is written out and another record
74*7c478bd9Sstevel@tonic-gate  *	read in to replace it. The new record is placed into the list.
75*7c478bd9Sstevel@tonic-gate  *	This continues until the list is empty.
76*7c478bd9Sstevel@tonic-gate  * .call	ret = mproc(pcbr).
77*7c478bd9Sstevel@tonic-gate  * .arg	pcbr	- ptr to pcb for this process.
78*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors in processing.
79*7c478bd9Sstevel@tonic-gate  * .ret	-1	- errors in processing (message already printed).
80*7c478bd9Sstevel@tonic-gate  */
81*7c478bd9Sstevel@tonic-gate int
82*7c478bd9Sstevel@tonic-gate mproc(pcbr)
83*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr;
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	int	i, ret, junk;
86*7c478bd9Sstevel@tonic-gate 	int	nrecs = 0;		/* number of records read from stream */
87*7c478bd9Sstevel@tonic-gate 	int	nprecs = 0;		/* number of records put to stream */
88*7c478bd9Sstevel@tonic-gate 	register audit_pcb_t *pcb;
89*7c478bd9Sstevel@tonic-gate 	audit_pcb_t *aget();
90*7c478bd9Sstevel@tonic-gate 	void	asort();
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate #if AUDIT_PROC_TRACE
93*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "mproc: count %d lo %d hi %d\n",
94*7c478bd9Sstevel@tonic-gate 	    pcbr->pcb_count, pcbr->pcb_lo, pcbr->pcb_hi);
95*7c478bd9Sstevel@tonic-gate #endif
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	/*
98*7c478bd9Sstevel@tonic-gate 	 * First load up a record from each input group.
99*7c478bd9Sstevel@tonic-gate 	 */
100*7c478bd9Sstevel@tonic-gate 	for (i = pcbr->pcb_lo; i <= pcbr->pcb_hi; i++) {
101*7c478bd9Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[i]); /* get next PCB */
102*7c478bd9Sstevel@tonic-gate 		while (pcb->pcb_time < 0) { /* while no active record ... */
103*7c478bd9Sstevel@tonic-gate 			if ((ret = get_file(pcb)) == -1)
104*7c478bd9Sstevel@tonic-gate 				break;		/*  no files - finished PCB */
105*7c478bd9Sstevel@tonic-gate 			if (ret == -2)
106*7c478bd9Sstevel@tonic-gate 				return (-1);	/* quit processing - failed */
107*7c478bd9Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
108*7c478bd9Sstevel@tonic-gate 				asort(pcb);	/* got a rec - put in list */
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 	/*
112*7c478bd9Sstevel@tonic-gate 	 * Now process all of the records.
113*7c478bd9Sstevel@tonic-gate 	 */
114*7c478bd9Sstevel@tonic-gate 	while ((pcb = aget()) != NULL) {	/* get oldest record */
115*7c478bd9Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &nprecs))
116*7c478bd9Sstevel@tonic-gate 			return (-1);
117*7c478bd9Sstevel@tonic-gate 		while (pcb->pcb_time < 0) {	/* while we don't have a rec */
118*7c478bd9Sstevel@tonic-gate 			if (pcb->pcb_fpr == NULL) {	/* no active file ... */
119*7c478bd9Sstevel@tonic-gate 				if ((ret = get_file(pcb)) == -1)
120*7c478bd9Sstevel@tonic-gate 					break;	/* no files - finished pcb */
121*7c478bd9Sstevel@tonic-gate 				else if (ret == -2)
122*7c478bd9Sstevel@tonic-gate 					return (-1);	/* quit - failed */
123*7c478bd9Sstevel@tonic-gate 			}
124*7c478bd9Sstevel@tonic-gate 			if (get_recs(pcb, &nrecs) == 0)
125*7c478bd9Sstevel@tonic-gate 				asort(pcb);		/* put record in list */
126*7c478bd9Sstevel@tonic-gate 		}
127*7c478bd9Sstevel@tonic-gate 	}
128*7c478bd9Sstevel@tonic-gate 	/*
129*7c478bd9Sstevel@tonic-gate 	 * For root: write outfile header if no records were encountered.
130*7c478bd9Sstevel@tonic-gate 	 * For non-root: write trailer to pipe and close pipe.
131*7c478bd9Sstevel@tonic-gate 	 */
132*7c478bd9Sstevel@tonic-gate 	if (pcbr->pcb_flags & PF_ROOT) {
133*7c478bd9Sstevel@tonic-gate 		if (nprecs == 0) {
134*7c478bd9Sstevel@tonic-gate 			if (write_header())	/* write header if no records */
135*7c478bd9Sstevel@tonic-gate 				return (-1);
136*7c478bd9Sstevel@tonic-gate 		}
137*7c478bd9Sstevel@tonic-gate 	} else {
138*7c478bd9Sstevel@tonic-gate 		pcb = &(pcbr->pcb_below[0]);	/* any old PCB will do */
139*7c478bd9Sstevel@tonic-gate 		pcb->pcb_rec = empty_file_token;
140*7c478bd9Sstevel@tonic-gate 		if (write_recs(pcbr, pcb, &junk))
141*7c478bd9Sstevel@tonic-gate 			return (-1);
142*7c478bd9Sstevel@tonic-gate 		if (fclose(pcbr->pcb_fpw) == EOF) {
143*7c478bd9Sstevel@tonic-gate 			if (!f_quiet)
144*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
145*7c478bd9Sstevel@tonic-gate 				    gettext("%s couldn't close pipe.\n"), ar);
146*7c478bd9Sstevel@tonic-gate 		}
147*7c478bd9Sstevel@tonic-gate 	}
148*7c478bd9Sstevel@tonic-gate 	/*
149*7c478bd9Sstevel@tonic-gate 	 * For root process tell how many records were written.
150*7c478bd9Sstevel@tonic-gate 	 */
151*7c478bd9Sstevel@tonic-gate 	if (f_verbose && (pcbr->pcb_flags & PF_ROOT)) {
152*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
153*7c478bd9Sstevel@tonic-gate 		    gettext("%s %d record(s) total were written out.\n"),
154*7c478bd9Sstevel@tonic-gate 			ar, nprecs);
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 	return (0);
157*7c478bd9Sstevel@tonic-gate }
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate /*
161*7c478bd9Sstevel@tonic-gate  * Head of linked-list of pcbs - sorted by time - oldest first.
162*7c478bd9Sstevel@tonic-gate  */
163*7c478bd9Sstevel@tonic-gate static audit_pcb_t		*pcbls = NULL;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate /*
166*7c478bd9Sstevel@tonic-gate  * .func	asort - audit sort.
167*7c478bd9Sstevel@tonic-gate  * .desc	Place a pcb in the list sorted by time - oldest first.
168*7c478bd9Sstevel@tonic-gate  * .call	asort(pcb);
169*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb to install in list.
170*7c478bd9Sstevel@tonic-gate  * .ret	void.
171*7c478bd9Sstevel@tonic-gate  */
172*7c478bd9Sstevel@tonic-gate static void
173*7c478bd9Sstevel@tonic-gate asort(pcb)
174*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
175*7c478bd9Sstevel@tonic-gate {
176*7c478bd9Sstevel@tonic-gate 	register audit_pcb_t *pcbc, *pcbp;
177*7c478bd9Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	pcb->pcb_next = NULL;
180*7c478bd9Sstevel@tonic-gate 	if (pcbls == NULL) {
181*7c478bd9Sstevel@tonic-gate 		pcbls = pcb;		/* empty list */
182*7c478bd9Sstevel@tonic-gate 		return;
183*7c478bd9Sstevel@tonic-gate 	}
184*7c478bd9Sstevel@tonic-gate 	pcbc = pcbls;			/* current pcb */
185*7c478bd9Sstevel@tonic-gate 	pcbp = pcbls;			/* previous pcb */
186*7c478bd9Sstevel@tonic-gate 	while (pcbc != NULL) {
187*7c478bd9Sstevel@tonic-gate 		if (pcb->pcb_time < pcbc->pcb_time) {
188*7c478bd9Sstevel@tonic-gate 			if (pcbp == pcbc) {
189*7c478bd9Sstevel@tonic-gate 				pcb->pcb_next = pcbls;	/* new -> 1st in list */
190*7c478bd9Sstevel@tonic-gate 				pcbls = pcb;
191*7c478bd9Sstevel@tonic-gate 				return;
192*7c478bd9Sstevel@tonic-gate 			}
193*7c478bd9Sstevel@tonic-gate 			pcbp->pcb_next = pcb;
194*7c478bd9Sstevel@tonic-gate 			pcb->pcb_next = pcbc;		/* new in the inside */
195*7c478bd9Sstevel@tonic-gate 			return;
196*7c478bd9Sstevel@tonic-gate 		}
197*7c478bd9Sstevel@tonic-gate 		pcbp = pcbc;
198*7c478bd9Sstevel@tonic-gate 		pcbc = pcbc->pcb_next;
199*7c478bd9Sstevel@tonic-gate 	}
200*7c478bd9Sstevel@tonic-gate 	pcbp->pcb_next = pcb;				/* new -> last */
201*7c478bd9Sstevel@tonic-gate }
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate  * .func	aget - audit get.
206*7c478bd9Sstevel@tonic-gate  * .desc	Get the first pcb from the list. Pcb is removed from list, too.
207*7c478bd9Sstevel@tonic-gate  * .call	pcb = aget().
208*7c478bd9Sstevel@tonic-gate  * .arg	none.
209*7c478bd9Sstevel@tonic-gate  * .ret	pcb	- ptr to pcb that was the first.
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate static audit_pcb_t *
212*7c478bd9Sstevel@tonic-gate aget()
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate 	audit_pcb_t *pcbret;
215*7c478bd9Sstevel@tonic-gate 	extern audit_pcb_t *pcbls;	/* ptr to start of list */
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate 	if (pcbls == NULL)
218*7c478bd9Sstevel@tonic-gate 		return (pcbls);		/* empty list */
219*7c478bd9Sstevel@tonic-gate 	pcbret = pcbls;
220*7c478bd9Sstevel@tonic-gate 	pcbls = pcbls->pcb_next;	/* 2nd becomes 1st */
221*7c478bd9Sstevel@tonic-gate 	return (pcbret);
222*7c478bd9Sstevel@tonic-gate }
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate /*
226*7c478bd9Sstevel@tonic-gate  * .func	get_file - get a new file.
227*7c478bd9Sstevel@tonic-gate  * .desc	Get the next file from the pcb's list. Check the header to see
228*7c478bd9Sstevel@tonic-gate  *	if the file really is an audit file. If there are no more then
229*7c478bd9Sstevel@tonic-gate  *	quit. If a file open (fopen) fails because the system file table
230*7c478bd9Sstevel@tonic-gate  *	is full or the process file table is full then quit processing
231*7c478bd9Sstevel@tonic-gate  *	altogether.
232*7c478bd9Sstevel@tonic-gate  * .call	ret = get_file(pcb).
233*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- pcb holding the fcb's (files).
234*7c478bd9Sstevel@tonic-gate  * .ret	0	- new file opened for processing.
235*7c478bd9Sstevel@tonic-gate  * .ret	-1	- no more files - pcb finished.
236*7c478bd9Sstevel@tonic-gate  * .ret	-2	- fatal error - quit processing.
237*7c478bd9Sstevel@tonic-gate  */
238*7c478bd9Sstevel@tonic-gate static int
239*7c478bd9Sstevel@tonic-gate get_file(pcb)
240*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
241*7c478bd9Sstevel@tonic-gate {
242*7c478bd9Sstevel@tonic-gate 	FILE *fp;
243*7c478bd9Sstevel@tonic-gate 	audit_fcb_t *fcb;
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	/*
246*7c478bd9Sstevel@tonic-gate 	 * Process file list until a good one if found or empty.
247*7c478bd9Sstevel@tonic-gate 	 */
248*7c478bd9Sstevel@tonic-gate 	while (pcb->pcb_fpr == NULL) {
249*7c478bd9Sstevel@tonic-gate 		if ((fcb = pcb->pcb_first) == NULL) {
250*7c478bd9Sstevel@tonic-gate 			pcb->pcb_time = -1;
251*7c478bd9Sstevel@tonic-gate 			return (-1);	/* pcb is all done */
252*7c478bd9Sstevel@tonic-gate 		} else {
253*7c478bd9Sstevel@tonic-gate 		/*
254*7c478bd9Sstevel@tonic-gate 		 * If we are reading from files then open the next one.
255*7c478bd9Sstevel@tonic-gate 		 */
256*7c478bd9Sstevel@tonic-gate 			if (!f_stdin) {
257*7c478bd9Sstevel@tonic-gate 				if ((fp = fopen(fcb->fcb_file, "r")) == NULL) {
258*7c478bd9Sstevel@tonic-gate 					if (!f_quiet) {
259*7c478bd9Sstevel@tonic-gate 						(void) sprintf(errbuf, gettext(
260*7c478bd9Sstevel@tonic-gate 						"%s couldn't open:\n  %s"),
261*7c478bd9Sstevel@tonic-gate 						ar, fcb->fcb_file);
262*7c478bd9Sstevel@tonic-gate 						perror(errbuf);
263*7c478bd9Sstevel@tonic-gate 					}
264*7c478bd9Sstevel@tonic-gate 					/*
265*7c478bd9Sstevel@tonic-gate 					 * See if file space is depleted.
266*7c478bd9Sstevel@tonic-gate 					 * If it is then we quit.
267*7c478bd9Sstevel@tonic-gate 					 */
268*7c478bd9Sstevel@tonic-gate 					if (errno == ENFILE || errno == EMFILE)
269*7c478bd9Sstevel@tonic-gate 					{
270*7c478bd9Sstevel@tonic-gate 						return (-2);
271*7c478bd9Sstevel@tonic-gate 					}
272*7c478bd9Sstevel@tonic-gate 					pcb->pcb_first = fcb->fcb_next;
273*7c478bd9Sstevel@tonic-gate 					continue;	/* try another file */
274*7c478bd9Sstevel@tonic-gate 				}
275*7c478bd9Sstevel@tonic-gate 			} else {
276*7c478bd9Sstevel@tonic-gate 				/*
277*7c478bd9Sstevel@tonic-gate 				 * Read from standard input.
278*7c478bd9Sstevel@tonic-gate 				 */
279*7c478bd9Sstevel@tonic-gate 				fp = stdin;
280*7c478bd9Sstevel@tonic-gate 			}
281*7c478bd9Sstevel@tonic-gate 			/*
282*7c478bd9Sstevel@tonic-gate 			 * Check header of audit file.
283*7c478bd9Sstevel@tonic-gate 			 */
284*7c478bd9Sstevel@tonic-gate 			if (check_header(fp, fcb->fcb_name)) {
285*7c478bd9Sstevel@tonic-gate 				if (!f_quiet) {
286*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
287*7c478bd9Sstevel@tonic-gate 					    "%s %s:\n  %s.\n",
288*7c478bd9Sstevel@tonic-gate 					    ar, error_str, fcb->fcb_file);
289*7c478bd9Sstevel@tonic-gate 				}
290*7c478bd9Sstevel@tonic-gate 				if (fclose(fp) == EOF) {
291*7c478bd9Sstevel@tonic-gate 					if (!f_quiet) {
292*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr, gettext(
293*7c478bd9Sstevel@tonic-gate 						"%s couldn't close %s.\n"),
294*7c478bd9Sstevel@tonic-gate 						ar, fcb->fcb_file);
295*7c478bd9Sstevel@tonic-gate 					}
296*7c478bd9Sstevel@tonic-gate 				}
297*7c478bd9Sstevel@tonic-gate 				pcb->pcb_first = fcb->fcb_next;
298*7c478bd9Sstevel@tonic-gate 				continue;		/* try another file */
299*7c478bd9Sstevel@tonic-gate 			}
300*7c478bd9Sstevel@tonic-gate 			/*
301*7c478bd9Sstevel@tonic-gate 			 * Found a good audit file.
302*7c478bd9Sstevel@tonic-gate 			 * Initalize pcb for processing.
303*7c478bd9Sstevel@tonic-gate 			 */
304*7c478bd9Sstevel@tonic-gate 			pcb->pcb_first = fcb->fcb_next;
305*7c478bd9Sstevel@tonic-gate 			pcb->pcb_cur = fcb;
306*7c478bd9Sstevel@tonic-gate 			pcb->pcb_fpr = fp;
307*7c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs = 0;
308*7c478bd9Sstevel@tonic-gate 			pcb->pcb_nprecs = 0;
309*7c478bd9Sstevel@tonic-gate 			pcb->pcb_otime = -1;
310*7c478bd9Sstevel@tonic-gate 		}
311*7c478bd9Sstevel@tonic-gate 	}
312*7c478bd9Sstevel@tonic-gate 	return (0);
313*7c478bd9Sstevel@tonic-gate }
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate /*
317*7c478bd9Sstevel@tonic-gate  * .func	write_recs - write records.
318*7c478bd9Sstevel@tonic-gate  * .desc	Write record from a buffer to output stream. Keep an eye out
319*7c478bd9Sstevel@tonic-gate  *	for the first and last records of the root's output stream.
320*7c478bd9Sstevel@tonic-gate  * .call	ret = write_recs(pcbr, pcb, nprecs).
321*7c478bd9Sstevel@tonic-gate  * .arg	pcbr	- ptr to node pcb.
322*7c478bd9Sstevel@tonic-gate  * .arg	pcb		- ptr to pcb holding the stream.
323*7c478bd9Sstevel@tonic-gate  * .arg	nprecs	- ptr to the number of put records. Updated here.
324*7c478bd9Sstevel@tonic-gate  * .ret	0	- no errors detected.
325*7c478bd9Sstevel@tonic-gate  * .ret	-1	- error in writing. Quit processing.
326*7c478bd9Sstevel@tonic-gate  */
327*7c478bd9Sstevel@tonic-gate static int
328*7c478bd9Sstevel@tonic-gate write_recs(pcbr, pcb, nprecs)
329*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcbr, *pcb;
330*7c478bd9Sstevel@tonic-gate int	*nprecs;
331*7c478bd9Sstevel@tonic-gate {
332*7c478bd9Sstevel@tonic-gate 	adr_t adr;
333*7c478bd9Sstevel@tonic-gate 	char	id;
334*7c478bd9Sstevel@tonic-gate 	int32_t	size;
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
337*7c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &id, 1);
338*7c478bd9Sstevel@tonic-gate 	(void) adrm_int32(&adr, &size, 1);
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 	/*
341*7c478bd9Sstevel@tonic-gate 	 * Scan for first record to be written to outfile.
342*7c478bd9Sstevel@tonic-gate 	 * When we find it then write the header and
343*7c478bd9Sstevel@tonic-gate 	 * save the time for the outfile name.
344*7c478bd9Sstevel@tonic-gate 	 */
345*7c478bd9Sstevel@tonic-gate 	if ((*nprecs)++ == 0) {
346*7c478bd9Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
347*7c478bd9Sstevel@tonic-gate 			f_start = pcb->pcb_time;	/* save start time */
348*7c478bd9Sstevel@tonic-gate 			if (write_header())
349*7c478bd9Sstevel@tonic-gate 				return (-1);
350*7c478bd9Sstevel@tonic-gate 		}
351*7c478bd9Sstevel@tonic-gate 	}
352*7c478bd9Sstevel@tonic-gate 	f_end = pcb->pcb_time;			/* find last record's time */
353*7c478bd9Sstevel@tonic-gate 	pcb->pcb_time = -1;			/* disable just written rec */
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	if ((fwrite(pcb->pcb_rec, sizeof (char), size, pcbr->pcb_fpw)) !=
356*7c478bd9Sstevel@tonic-gate 			size) {
357*7c478bd9Sstevel@tonic-gate 		if (pcbr->pcb_flags & PF_ROOT) {
358*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf, gettext(
359*7c478bd9Sstevel@tonic-gate 				"%s write failed to %s"),
360*7c478bd9Sstevel@tonic-gate 				ar, f_outfile ? f_outfile : gettext("stdout"));
361*7c478bd9Sstevel@tonic-gate 			perror(errbuf);
362*7c478bd9Sstevel@tonic-gate 		} else {
363*7c478bd9Sstevel@tonic-gate 			perror(gettext("auditreduce: write failed to pipe"));
364*7c478bd9Sstevel@tonic-gate 		}
365*7c478bd9Sstevel@tonic-gate 		return (-1);
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 	free(pcb->pcb_rec);
368*7c478bd9Sstevel@tonic-gate 	return (0);
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate /*
372*7c478bd9Sstevel@tonic-gate  * .func get_recs - get records.
373*7c478bd9Sstevel@tonic-gate  * .desc Get records from a stream until one passing the current selection
374*7c478bd9Sstevel@tonic-gate  *	criteria is found or the stream is emptied.
375*7c478bd9Sstevel@tonic-gate  * .call	ret = get_recs(pcb, nr).
376*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb that holds this stream.
377*7c478bd9Sstevel@tonic-gate  * .arg	nr	- ptr to number of records read. Updated by this routine.
378*7c478bd9Sstevel@tonic-gate  * .ret	0	- got a record.
379*7c478bd9Sstevel@tonic-gate  * .ret	-1	- stream is finished.
380*7c478bd9Sstevel@tonic-gate  */
381*7c478bd9Sstevel@tonic-gate static int
382*7c478bd9Sstevel@tonic-gate get_recs(pcb, nr)
383*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
384*7c478bd9Sstevel@tonic-gate int	*nr;
385*7c478bd9Sstevel@tonic-gate {
386*7c478bd9Sstevel@tonic-gate 	adr_t adr;
387*7c478bd9Sstevel@tonic-gate 	time_t secs;
388*7c478bd9Sstevel@tonic-gate 	int	tmp;
389*7c478bd9Sstevel@tonic-gate 	int	ret, ret2;
390*7c478bd9Sstevel@tonic-gate 	int	nrecs = 0;	/* count how many records read this call */
391*7c478bd9Sstevel@tonic-gate 	int	getrec = TRUE;
392*7c478bd9Sstevel@tonic-gate 	int	alldone = FALSE;
393*7c478bd9Sstevel@tonic-gate 	char	header_type;
394*7c478bd9Sstevel@tonic-gate 	short	e;
395*7c478bd9Sstevel@tonic-gate 	char	*str;
396*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE
397*7c478bd9Sstevel@tonic-gate 	static void	get_trace();
398*7c478bd9Sstevel@tonic-gate #endif
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	while (getrec) {
401*7c478bd9Sstevel@tonic-gate 		ret = get_record(pcb->pcb_fpr, &pcb->pcb_rec,
402*7c478bd9Sstevel@tonic-gate 			pcb->pcb_cur->fcb_name);
403*7c478bd9Sstevel@tonic-gate 		if (ret > 0) {
404*7c478bd9Sstevel@tonic-gate 			adrm_start(&adr, pcb->pcb_rec);
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 			/* get token id */
407*7c478bd9Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&header_type, 1);
408*7c478bd9Sstevel@tonic-gate 			/* skip over byte count */
409*7c478bd9Sstevel@tonic-gate 			(void) adrm_int32(&adr, (int32_t *)&tmp, 1);
410*7c478bd9Sstevel@tonic-gate 			/* skip over version # */
411*7c478bd9Sstevel@tonic-gate 			(void) adrm_char(&adr, (char *)&tmp, 1);
412*7c478bd9Sstevel@tonic-gate 			/* skip over event id */
413*7c478bd9Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&e, 1);
414*7c478bd9Sstevel@tonic-gate 			/* skip over event id modifier */
415*7c478bd9Sstevel@tonic-gate 			(void) adrm_short(&adr, (short *)&tmp, 1);
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 			if (header_type == AUT_HEADER32) {
418*7c478bd9Sstevel@tonic-gate 			    int32_t s, m;
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 			    /* get seconds */
421*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
422*7c478bd9Sstevel@tonic-gate 			    /* get microseconds */
423*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
424*7c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
425*7c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER32_EX) {
426*7c478bd9Sstevel@tonic-gate 			    int32_t s, m;
427*7c478bd9Sstevel@tonic-gate 			    int32_t t, junk[4];	/* at_type + at_addr[4] */
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 			    /* skip type and ip address field */
430*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
431*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 			    /* get seconds */
434*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&s, 1);
435*7c478bd9Sstevel@tonic-gate 			    /* get microseconds */
436*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&m, 1);
437*7c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
438*7c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64) {
439*7c478bd9Sstevel@tonic-gate 			    int64_t s, m;
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 			    /* get seconds */
442*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
443*7c478bd9Sstevel@tonic-gate 			    /* get microseconds */
444*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
445*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
446*7c478bd9Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
447*7c478bd9Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
448*7c478bd9Sstevel@tonic-gate 					secs = 0;
449*7c478bd9Sstevel@tonic-gate 			    else
450*7c478bd9Sstevel@tonic-gate 					secs = (time_t)s;
451*7c478bd9Sstevel@tonic-gate #else
452*7c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
453*7c478bd9Sstevel@tonic-gate #endif
454*7c478bd9Sstevel@tonic-gate 			} else if (header_type == AUT_HEADER64_EX) {
455*7c478bd9Sstevel@tonic-gate 			    int64_t s, m;
456*7c478bd9Sstevel@tonic-gate 			    int32_t t, junk[4];
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 			    /* skip type and ip address field */
459*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&t, 1);
460*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 			    /* get seconds */
463*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&s, 1);
464*7c478bd9Sstevel@tonic-gate 			    /* get microseconds */
465*7c478bd9Sstevel@tonic-gate 			    (void) adrm_int64(&adr, (int64_t *)&m, 1);
466*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
467*7c478bd9Sstevel@tonic-gate 			    if (s < (time_t)INT32_MIN ||
468*7c478bd9Sstevel@tonic-gate 				s > (time_t)INT32_MAX)
469*7c478bd9Sstevel@tonic-gate 					secs = 0;
470*7c478bd9Sstevel@tonic-gate 			    else
471*7c478bd9Sstevel@tonic-gate 					secs = (time_t)s;
472*7c478bd9Sstevel@tonic-gate #else
473*7c478bd9Sstevel@tonic-gate 			    secs = (time_t)s;
474*7c478bd9Sstevel@tonic-gate #endif
475*7c478bd9Sstevel@tonic-gate 			}
476*7c478bd9Sstevel@tonic-gate 		}
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate #if AUDIT_REC
479*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "get_recs: %d ret %d recno %d\n",
480*7c478bd9Sstevel@tonic-gate 			pcb->pcb_procno, ret, pcb->pcb_nrecs + 1);
481*7c478bd9Sstevel@tonic-gate #endif
482*7c478bd9Sstevel@tonic-gate 		/*
483*7c478bd9Sstevel@tonic-gate 		 * See if entire file is after the time window specified.
484*7c478bd9Sstevel@tonic-gate 		 * Must be check here because the start time of the file name
485*7c478bd9Sstevel@tonic-gate 		 * may be after the first record(s).
486*7c478bd9Sstevel@tonic-gate 		 */
487*7c478bd9Sstevel@tonic-gate 		if (pcb->pcb_nrecs == 0 && (pcb->pcb_flags & PF_FILE)) {
488*7c478bd9Sstevel@tonic-gate 			/*
489*7c478bd9Sstevel@tonic-gate 			 * If the first record read failed then use the time
490*7c478bd9Sstevel@tonic-gate 			 * that was in the filename to judge.
491*7c478bd9Sstevel@tonic-gate 			 */
492*7c478bd9Sstevel@tonic-gate 			if (ret > 0)
493*7c478bd9Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_start = secs;
494*7c478bd9Sstevel@tonic-gate 			if (!f_all && (m_before <= (pcb->pcb_cur)->fcb_start)) {
495*7c478bd9Sstevel@tonic-gate 				(void) fclose(pcb->pcb_fpr); /* ignore file */
496*7c478bd9Sstevel@tonic-gate 				pcb->pcb_fpr = NULL;
497*7c478bd9Sstevel@tonic-gate 				pcb->pcb_time = -1;
498*7c478bd9Sstevel@tonic-gate 				return (-1);
499*7c478bd9Sstevel@tonic-gate 			} else {
500*7c478bd9Sstevel@tonic-gate 				/* Give belated announcement of file opening. */
501*7c478bd9Sstevel@tonic-gate 				if (f_verbose) {
502*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
503*7c478bd9Sstevel@tonic-gate 						gettext("%s opened:\n  %s.\n"),
504*7c478bd9Sstevel@tonic-gate 						ar, (pcb->pcb_cur)->fcb_file);
505*7c478bd9Sstevel@tonic-gate 				}
506*7c478bd9Sstevel@tonic-gate 			}
507*7c478bd9Sstevel@tonic-gate 		}
508*7c478bd9Sstevel@tonic-gate 		/* Succesful acquisition of a record.  */
509*7c478bd9Sstevel@tonic-gate 		if (ret > 0) {
510*7c478bd9Sstevel@tonic-gate 			pcb->pcb_time = secs;	/* time of record */
511*7c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read recs from stream */
512*7c478bd9Sstevel@tonic-gate 			nrecs++;		/* # of recs read this call */
513*7c478bd9Sstevel@tonic-gate 			/* Only check record if at bottom of process tree. */
514*7c478bd9Sstevel@tonic-gate 			if (pcb->pcb_flags & PF_FILE) {
515*7c478bd9Sstevel@tonic-gate 				check_order(pcb); /* check time sequence */
516*7c478bd9Sstevel@tonic-gate 				if ((ret2 = check_rec(pcb)) == 0) {
517*7c478bd9Sstevel@tonic-gate 					pcb->pcb_nprecs++;
518*7c478bd9Sstevel@tonic-gate 					getrec = FALSE;
519*7c478bd9Sstevel@tonic-gate 				} else if (ret2 == -2) {
520*7c478bd9Sstevel@tonic-gate 					/* error */
521*7c478bd9Sstevel@tonic-gate 					getrec = FALSE;	/* get no more recs */
522*7c478bd9Sstevel@tonic-gate 					alldone = TRUE;	/* quit this file */
523*7c478bd9Sstevel@tonic-gate 					free(pcb->pcb_rec);
524*7c478bd9Sstevel@tonic-gate 				} else {
525*7c478bd9Sstevel@tonic-gate 					/* -1: record not interesting */
526*7c478bd9Sstevel@tonic-gate 					free(pcb->pcb_rec);
527*7c478bd9Sstevel@tonic-gate 				}
528*7c478bd9Sstevel@tonic-gate 			} else {
529*7c478bd9Sstevel@tonic-gate 				pcb->pcb_nprecs++;
530*7c478bd9Sstevel@tonic-gate 				getrec = FALSE;
531*7c478bd9Sstevel@tonic-gate 			}
532*7c478bd9Sstevel@tonic-gate 		} else {
533*7c478bd9Sstevel@tonic-gate 			/* Error with record read or all done with stream. */
534*7c478bd9Sstevel@tonic-gate 			getrec = FALSE;
535*7c478bd9Sstevel@tonic-gate 			alldone = TRUE;
536*7c478bd9Sstevel@tonic-gate 		}
537*7c478bd9Sstevel@tonic-gate 	}
538*7c478bd9Sstevel@tonic-gate 	if (alldone == TRUE) {
539*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE
540*7c478bd9Sstevel@tonic-gate 		get_trace(pcb);
541*7c478bd9Sstevel@tonic-gate #endif
542*7c478bd9Sstevel@tonic-gate 		/* Error in record read. Display messages. */
543*7c478bd9Sstevel@tonic-gate 		if (ret < 0 || ret2 == -2) {
544*7c478bd9Sstevel@tonic-gate 			pcb->pcb_nrecs++;	/* # of read records */
545*7c478bd9Sstevel@tonic-gate 			if (!f_quiet) {
546*7c478bd9Sstevel@tonic-gate 				if (pcb->pcb_flags & PF_FILE) {
547*7c478bd9Sstevel@tonic-gate 					/* Ignore if this is not_terminated. */
548*7c478bd9Sstevel@tonic-gate 					if (!strstr((pcb->pcb_cur)->fcb_file,
549*7c478bd9Sstevel@tonic-gate 							"not_terminated")) {
550*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in %s at record %d.\n"), ar,
551*7c478bd9Sstevel@tonic-gate 	(pcb->pcb_cur)->fcb_file, pcb->pcb_nrecs);
552*7c478bd9Sstevel@tonic-gate 					}
553*7c478bd9Sstevel@tonic-gate 				} else {
554*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s read error in pipe at record %d.\n"), ar,
555*7c478bd9Sstevel@tonic-gate 	pcb->pcb_nrecs);
556*7c478bd9Sstevel@tonic-gate 				}
557*7c478bd9Sstevel@tonic-gate 			}
558*7c478bd9Sstevel@tonic-gate 		} else {
559*7c478bd9Sstevel@tonic-gate 			/*
560*7c478bd9Sstevel@tonic-gate 			 * Only mark infile for deleting if we have succesfully
561*7c478bd9Sstevel@tonic-gate 			 * processed all of it.
562*7c478bd9Sstevel@tonic-gate 			 */
563*7c478bd9Sstevel@tonic-gate 			if (pcb->pcb_flags & PF_FILE)
564*7c478bd9Sstevel@tonic-gate 				(pcb->pcb_cur)->fcb_flags |= FF_DELETE;
565*7c478bd9Sstevel@tonic-gate 		}
566*7c478bd9Sstevel@tonic-gate 		if (fclose(pcb->pcb_fpr) == EOF) {
567*7c478bd9Sstevel@tonic-gate 			if (!f_quiet) {
568*7c478bd9Sstevel@tonic-gate 				if (pcb->pcb_flags & PF_FILE) {
569*7c478bd9Sstevel@tonic-gate 					str = (pcb->pcb_cur)->fcb_file;
570*7c478bd9Sstevel@tonic-gate 				} else {
571*7c478bd9Sstevel@tonic-gate 					str = "pipe";
572*7c478bd9Sstevel@tonic-gate 				}
573*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
574*7c478bd9Sstevel@tonic-gate 					gettext("%s couldn't close %s.\n"),
575*7c478bd9Sstevel@tonic-gate 					ar, str);
576*7c478bd9Sstevel@tonic-gate 			}
577*7c478bd9Sstevel@tonic-gate 		}
578*7c478bd9Sstevel@tonic-gate 		pcb->pcb_fpr = NULL;
579*7c478bd9Sstevel@tonic-gate 		pcb->pcb_time = -1;
580*7c478bd9Sstevel@tonic-gate 		*nr += nrecs;
581*7c478bd9Sstevel@tonic-gate 		return (-1);
582*7c478bd9Sstevel@tonic-gate 	}
583*7c478bd9Sstevel@tonic-gate 	*nr += nrecs;
584*7c478bd9Sstevel@tonic-gate 	return (0);
585*7c478bd9Sstevel@tonic-gate }
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate #if AUDIT_FILE
589*7c478bd9Sstevel@tonic-gate /*
590*7c478bd9Sstevel@tonic-gate  * .func get_trace - get trace.
591*7c478bd9Sstevel@tonic-gate  * .desc If we are tracing file action (AUDIT_FILE is on) then print out
592*7c478bd9Sstevel@tonic-gate  *	a message when the file is closed regarding how many records
593*7c478bd9Sstevel@tonic-gate  *	were handled.
594*7c478bd9Sstevel@tonic-gate  * .call	get_trace(pcb).
595*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding file/pipe.
596*7c478bd9Sstevel@tonic-gate  * .ret	void.
597*7c478bd9Sstevel@tonic-gate  */
598*7c478bd9Sstevel@tonic-gate static void
599*7c478bd9Sstevel@tonic-gate get_trace(pcb)
600*7c478bd9Sstevel@tonic-gate audit_pcb_t *pcb;
601*7c478bd9Sstevel@tonic-gate {
602*7c478bd9Sstevel@tonic-gate 	/*
603*7c478bd9Sstevel@tonic-gate 	 * For file give filename, too.
604*7c478bd9Sstevel@tonic-gate 	 */
605*7c478bd9Sstevel@tonic-gate 	if (pcb->pcb_flags & PF_FILE) {
606*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s closed %s: %d records read recs: \
607*7c478bd9Sstevel@tonic-gate 		%d record written.\n", ar, (pcb->pcb_cur)->fcb_file,
608*7c478bd9Sstevel@tonic-gate 		pcb->pcb_nrecs, pcb->pcb_nprecs);
609*7c478bd9Sstevel@tonic-gate 	} else {
610*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s closed pipe: %d records read: \
611*7c478bd9Sstevel@tonic-gate 			%d records written .\n", ar, pcb->pcb_nrecs,
612*7c478bd9Sstevel@tonic-gate 			pcb->pcb_nprecs);
613*7c478bd9Sstevel@tonic-gate 	}
614*7c478bd9Sstevel@tonic-gate }
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate #endif
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate /*
619*7c478bd9Sstevel@tonic-gate  * .func	check_rec - check a record.
620*7c478bd9Sstevel@tonic-gate  * .desc	Check a record against the user's selection criteria.
621*7c478bd9Sstevel@tonic-gate  * .call	ret = check_rec(pcb).
622*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the record.
623*7c478bd9Sstevel@tonic-gate  * .ret	0	- record accepted.
624*7c478bd9Sstevel@tonic-gate  * .ret	-1	- record rejected - continue processing file.
625*7c478bd9Sstevel@tonic-gate  * .ret	-2	- record rejected - quit processing file.
626*7c478bd9Sstevel@tonic-gate  */
627*7c478bd9Sstevel@tonic-gate static int
628*7c478bd9Sstevel@tonic-gate check_rec(pcb)
629*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
630*7c478bd9Sstevel@tonic-gate {
631*7c478bd9Sstevel@tonic-gate 	adr_t adr;
632*7c478bd9Sstevel@tonic-gate 	struct timeval tv;
633*7c478bd9Sstevel@tonic-gate 	uint_t	bytes;
634*7c478bd9Sstevel@tonic-gate 	ushort_t id_modifier;
635*7c478bd9Sstevel@tonic-gate 	char	version;
636*7c478bd9Sstevel@tonic-gate 	ushort_t event_type;
637*7c478bd9Sstevel@tonic-gate 	char	tokenid;
638*7c478bd9Sstevel@tonic-gate 	int	rc;	 /* return code */
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate 	adrm_start(&adr, pcb->pcb_rec);
641*7c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &tokenid, 1);
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 	/*
644*7c478bd9Sstevel@tonic-gate 	 * checkflags will be my data structure for determining if
645*7c478bd9Sstevel@tonic-gate 	 * a record has met ALL the selection criteria.  Once
646*7c478bd9Sstevel@tonic-gate 	 * checkflags == flags, we have seen all we need to of the
647*7c478bd9Sstevel@tonic-gate 	 * record, and can go to the next one.  If when we finish
648*7c478bd9Sstevel@tonic-gate 	 * processing the record we still have stuff to see,
649*7c478bd9Sstevel@tonic-gate 	 * checkflags != flags, and thus we should return a -1
650*7c478bd9Sstevel@tonic-gate 	 * from this function meaning reject this record.
651*7c478bd9Sstevel@tonic-gate 	 */
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate 	checkflags = 0;
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	/* must be header token -- sanity check */
656*7c478bd9Sstevel@tonic-gate 	if (tokenid != AUT_HEADER32 && tokenid != AUT_HEADER64 &&
657*7c478bd9Sstevel@tonic-gate 	    tokenid != AUT_HEADER32_EX && tokenid != AUT_HEADER64_EX) {
658*7c478bd9Sstevel@tonic-gate #if AUDIT_REC
659*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
660*7c478bd9Sstevel@tonic-gate 		    "check_rec: %d recno %d no header %d found\n",
661*7c478bd9Sstevel@tonic-gate 		    pcb->pcb_procno, pcb->pcb_nrecs, tokenid);
662*7c478bd9Sstevel@tonic-gate #endif
663*7c478bd9Sstevel@tonic-gate 		return (-2);
664*7c478bd9Sstevel@tonic-gate 	}
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate 	/*
667*7c478bd9Sstevel@tonic-gate 	 * The header token is:
668*7c478bd9Sstevel@tonic-gate 	 *	attribute id:		char
669*7c478bd9Sstevel@tonic-gate 	 *	byte count:		int
670*7c478bd9Sstevel@tonic-gate 	 *	version #:		char
671*7c478bd9Sstevel@tonic-gate 	 *	event ID:		short
672*7c478bd9Sstevel@tonic-gate 	 *	ID modifier:		short
673*7c478bd9Sstevel@tonic-gate 	 *	seconds (date):		int
674*7c478bd9Sstevel@tonic-gate 	 *	time (microsecs):	int
675*7c478bd9Sstevel@tonic-gate 	 */
676*7c478bd9Sstevel@tonic-gate 	(void) adrm_u_int32(&adr, (uint32_t *)&bytes, 1);
677*7c478bd9Sstevel@tonic-gate 	(void) adrm_char(&adr, &version, 1);
678*7c478bd9Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &event_type, 1);
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	/*
681*7c478bd9Sstevel@tonic-gate 	 * Used by s5_IPC_token to set the ipc_type so
682*7c478bd9Sstevel@tonic-gate 	 * s5_IPC_perm_token can test.
683*7c478bd9Sstevel@tonic-gate 	 */
684*7c478bd9Sstevel@tonic-gate 	ipc_type = (char)0;
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	if (flags & M_TYPE) {
687*7c478bd9Sstevel@tonic-gate 		checkflags |= M_TYPE;
688*7c478bd9Sstevel@tonic-gate 		if (m_type != event_type)
689*7c478bd9Sstevel@tonic-gate 			return (-1);
690*7c478bd9Sstevel@tonic-gate 	}
691*7c478bd9Sstevel@tonic-gate 	if (flags & M_CLASS) {
692*7c478bd9Sstevel@tonic-gate 		au_event_ent_t *ev = NULL;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 		checkflags |= M_CLASS;
695*7c478bd9Sstevel@tonic-gate 		if (cacheauevent(&ev, event_type) <= 0) {
696*7c478bd9Sstevel@tonic-gate 		    (void) fprintf(stderr, gettext(
697*7c478bd9Sstevel@tonic-gate 			"Warning: invalid event no %d in audit trail."),
698*7c478bd9Sstevel@tonic-gate 			event_type);
699*7c478bd9Sstevel@tonic-gate 		    return (-1);
700*7c478bd9Sstevel@tonic-gate 		}
701*7c478bd9Sstevel@tonic-gate 		global_class = ev->ae_class;
702*7c478bd9Sstevel@tonic-gate 		if (!(flags & M_SORF) && !(mask.am_success & global_class))
703*7c478bd9Sstevel@tonic-gate 			return (-1);
704*7c478bd9Sstevel@tonic-gate 	}
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate 	(void) adrm_u_short(&adr, &id_modifier, 1);
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 	/*
709*7c478bd9Sstevel@tonic-gate 	 * Check record against time criteria.
710*7c478bd9Sstevel@tonic-gate 	 * If the 'A' option was used then no time checking is done.
711*7c478bd9Sstevel@tonic-gate 	 * The 'a' parameter is inclusive and the 'b' exclusive.
712*7c478bd9Sstevel@tonic-gate 	 */
713*7c478bd9Sstevel@tonic-gate 	if (tokenid == AUT_HEADER32) {
714*7c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
715*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
716*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
717*7c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
718*7c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
719*7c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER32_EX) {
720*7c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
721*7c478bd9Sstevel@tonic-gate 	    int32_t t, junk[5];	/* at_type + at_addr[4] */
722*7c478bd9Sstevel@tonic-gate 	    /* skip type and ip address field */
723*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
724*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
725*7c478bd9Sstevel@tonic-gate 	    /* get time */
726*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&secs, 1);
727*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&msecs, 1);
728*7c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
729*7c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
730*7c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64) {
731*7c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
732*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
733*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
734*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
735*7c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
736*7c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
737*7c478bd9Sstevel@tonic-gate 			tv.tv_sec = 0;
738*7c478bd9Sstevel@tonic-gate 	    else
739*7c478bd9Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
740*7c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
741*7c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
742*7c478bd9Sstevel@tonic-gate 			tv.tv_usec = 0;
743*7c478bd9Sstevel@tonic-gate 	    else
744*7c478bd9Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
745*7c478bd9Sstevel@tonic-gate #else
746*7c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
747*7c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
748*7c478bd9Sstevel@tonic-gate #endif
749*7c478bd9Sstevel@tonic-gate 	} else if (tokenid == AUT_HEADER64_EX) {
750*7c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
751*7c478bd9Sstevel@tonic-gate 	    int32_t t, junk[4];	/* at_type + at_addr[4] */
752*7c478bd9Sstevel@tonic-gate 	    /* skip type and ip address field */
753*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&t, 1);
754*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int32(&adr, (int32_t *)&junk[0], t/4);
755*7c478bd9Sstevel@tonic-gate 	    /* get time */
756*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&secs, 1);
757*7c478bd9Sstevel@tonic-gate 	    (void) adrm_int64(&adr, (int64_t *)&msecs, 1);
758*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
759*7c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
760*7c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX)
761*7c478bd9Sstevel@tonic-gate 			tv.tv_sec = 0;
762*7c478bd9Sstevel@tonic-gate 	    else
763*7c478bd9Sstevel@tonic-gate 			tv.tv_sec = (time_t)secs;
764*7c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
765*7c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX)
766*7c478bd9Sstevel@tonic-gate 			tv.tv_usec = 0;
767*7c478bd9Sstevel@tonic-gate 	    else
768*7c478bd9Sstevel@tonic-gate 			tv.tv_usec = (suseconds_t)msecs;
769*7c478bd9Sstevel@tonic-gate #else
770*7c478bd9Sstevel@tonic-gate 	    tv.tv_sec = (time_t)secs;
771*7c478bd9Sstevel@tonic-gate 	    tv.tv_usec = (suseconds_t)msecs;
772*7c478bd9Sstevel@tonic-gate #endif
773*7c478bd9Sstevel@tonic-gate 	}
774*7c478bd9Sstevel@tonic-gate 	pcb->pcb_otime = pcb->pcb_time;
775*7c478bd9Sstevel@tonic-gate 	if (!f_all) {
776*7c478bd9Sstevel@tonic-gate 		if (m_after > tv.tv_sec)
777*7c478bd9Sstevel@tonic-gate 			return (-1);
778*7c478bd9Sstevel@tonic-gate 		if (m_before <= tv.tv_sec)
779*7c478bd9Sstevel@tonic-gate 			return (-1);
780*7c478bd9Sstevel@tonic-gate 	}
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 	/* if no selection flags were passed, select everything */
783*7c478bd9Sstevel@tonic-gate 	if (!flags)
784*7c478bd9Sstevel@tonic-gate 		return (0);
785*7c478bd9Sstevel@tonic-gate 
786*7c478bd9Sstevel@tonic-gate 	/*
787*7c478bd9Sstevel@tonic-gate 	 * If all information can be found in header,
788*7c478bd9Sstevel@tonic-gate 	 * there is no need to continue processing the tokens.
789*7c478bd9Sstevel@tonic-gate 	 */
790*7c478bd9Sstevel@tonic-gate 	if (flags == checkflags)
791*7c478bd9Sstevel@tonic-gate 		return (0);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	/*
794*7c478bd9Sstevel@tonic-gate 	 * Process tokens until we hit the end of the record
795*7c478bd9Sstevel@tonic-gate 	 */
796*7c478bd9Sstevel@tonic-gate 	while ((uint_t)(adr.adr_now - adr.adr_stream) < bytes) {
797*7c478bd9Sstevel@tonic-gate 		adrm_char(&adr, &tokenid, 1);
798*7c478bd9Sstevel@tonic-gate 		rc = token_processing(&adr, tokenid);
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 		/* Any Problems? */
801*7c478bd9Sstevel@tonic-gate 		if (rc == -2) {
802*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
803*7c478bd9Sstevel@tonic-gate 			    gettext("auditreduce: bad token %u, terminating "
804*7c478bd9Sstevel@tonic-gate 			    "file %s\n"), tokenid, (pcb->pcb_cur)->fcb_file);
805*7c478bd9Sstevel@tonic-gate 			return (-2);
806*7c478bd9Sstevel@tonic-gate 		}
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 		/* Are we finished? */
809*7c478bd9Sstevel@tonic-gate 		if (flags == checkflags)
810*7c478bd9Sstevel@tonic-gate 			return (0);
811*7c478bd9Sstevel@tonic-gate 	}
812*7c478bd9Sstevel@tonic-gate 
813*7c478bd9Sstevel@tonic-gate 	/*
814*7c478bd9Sstevel@tonic-gate 	 * So, we haven't seen all that we need to see.  Reject record.
815*7c478bd9Sstevel@tonic-gate 	 */
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 	return (-1);
818*7c478bd9Sstevel@tonic-gate }
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate /*
822*7c478bd9Sstevel@tonic-gate  * .func check_order - Check temporal sequence.
823*7c478bd9Sstevel@tonic-gate  * .call check_order(pcb).
824*7c478bd9Sstevel@tonic-gate  * .arg	 pcb - ptr to audit_pcb_t.
825*7c478bd9Sstevel@tonic-gate  * .desc	Check to see if the records are out of temporal sequence, ie,
826*7c478bd9Sstevel@tonic-gate  *	a record has a time stamp older than its predecessor.
827*7c478bd9Sstevel@tonic-gate  *	Also check to see if the current record is within the bounds of
828*7c478bd9Sstevel@tonic-gate  *	the file itself.
829*7c478bd9Sstevel@tonic-gate  *	This routine prints a diagnostic message, unless the QUIET
830*7c478bd9Sstevel@tonic-gate  *	option was selected.
831*7c478bd9Sstevel@tonic-gate  * .call	check_order(pcb).
832*7c478bd9Sstevel@tonic-gate  * .arg	pcb	- ptr to pcb holding the records.
833*7c478bd9Sstevel@tonic-gate  * .ret	void.
834*7c478bd9Sstevel@tonic-gate  */
835*7c478bd9Sstevel@tonic-gate static void
836*7c478bd9Sstevel@tonic-gate check_order(pcb)
837*7c478bd9Sstevel@tonic-gate register audit_pcb_t *pcb;
838*7c478bd9Sstevel@tonic-gate {
839*7c478bd9Sstevel@tonic-gate 	char	cptr1[28], cptr2[28];	/* for error reporting */
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate 	/*
842*7c478bd9Sstevel@tonic-gate 	 * If the record-past is not the oldest then say so.
843*7c478bd9Sstevel@tonic-gate 	 */
844*7c478bd9Sstevel@tonic-gate 	if (pcb->pcb_otime > pcb->pcb_time) {
845*7c478bd9Sstevel@tonic-gate 		if (!f_quiet) {
846*7c478bd9Sstevel@tonic-gate 			(void) memcpy((void *)cptr1,
847*7c478bd9Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_otime), 26);
848*7c478bd9Sstevel@tonic-gate 			cptr1[24] = ' ';
849*7c478bd9Sstevel@tonic-gate 			(void) memcpy((void *)cptr2,
850*7c478bd9Sstevel@tonic-gate 				(void *)ctime(&pcb->pcb_time), 26);
851*7c478bd9Sstevel@tonic-gate 			cptr2[24] = ' ';
852*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
853*7c478bd9Sstevel@tonic-gate 	gettext("%s %s had records out of order: %s was followed by %s.\n"),
854*7c478bd9Sstevel@tonic-gate 				ar, (pcb->pcb_cur)->fcb_file, cptr1, cptr2);
855*7c478bd9Sstevel@tonic-gate 		}
856*7c478bd9Sstevel@tonic-gate 	}
857*7c478bd9Sstevel@tonic-gate }
858*7c478bd9Sstevel@tonic-gate 
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate /*
861*7c478bd9Sstevel@tonic-gate  * .func	check_header.
862*7c478bd9Sstevel@tonic-gate  * .desc	Read in and check the header for an audit file.
863*7c478bd9Sstevel@tonic-gate  *	The header must read-in properly and have the magic #.
864*7c478bd9Sstevel@tonic-gate  * .call	err = check_header(fp).
865*7c478bd9Sstevel@tonic-gate  * .arg	fp	- file stream.
866*7c478bd9Sstevel@tonic-gate  * .ret	0	no problems.
867*7c478bd9Sstevel@tonic-gate  * .ret	-1	problems.
868*7c478bd9Sstevel@tonic-gate  */
869*7c478bd9Sstevel@tonic-gate static int
870*7c478bd9Sstevel@tonic-gate check_header(fp, fn)
871*7c478bd9Sstevel@tonic-gate FILE *fp;
872*7c478bd9Sstevel@tonic-gate char	*fn;
873*7c478bd9Sstevel@tonic-gate {
874*7c478bd9Sstevel@tonic-gate 	char	id;
875*7c478bd9Sstevel@tonic-gate 	char	*fname;
876*7c478bd9Sstevel@tonic-gate 	short	pathlength;
877*7c478bd9Sstevel@tonic-gate 	adr_t	adr;
878*7c478bd9Sstevel@tonic-gate 	adrf_t	adrf;
879*7c478bd9Sstevel@tonic-gate 
880*7c478bd9Sstevel@tonic-gate 	adrf_start(&adrf, &adr, fp);
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
883*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s is empty"), fn);
884*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
885*7c478bd9Sstevel@tonic-gate 		return (-1);
886*7c478bd9Sstevel@tonic-gate 	}
887*7c478bd9Sstevel@tonic-gate 	if (!(id == AUT_OTHER_FILE32 || id == AUT_OTHER_FILE64)) {
888*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext("%s not an audit file "), fn);
889*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
890*7c478bd9Sstevel@tonic-gate 		return (-1);
891*7c478bd9Sstevel@tonic-gate 	}
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 	if (id == AUT_OTHER_FILE32) {
894*7c478bd9Sstevel@tonic-gate 	    int32_t secs, msecs;
895*7c478bd9Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&secs, 1);
896*7c478bd9Sstevel@tonic-gate 	    (void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
897*7c478bd9Sstevel@tonic-gate 	} else {
898*7c478bd9Sstevel@tonic-gate 	    int64_t secs, msecs;
899*7c478bd9Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&secs, 1);
900*7c478bd9Sstevel@tonic-gate 	    (void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
901*7c478bd9Sstevel@tonic-gate #if ((!defined(_LP64)) || defined(_SYSCALL32))
902*7c478bd9Sstevel@tonic-gate 	    if (secs < (time_t)INT32_MIN ||
903*7c478bd9Sstevel@tonic-gate 		secs > (time_t)INT32_MAX) {
904*7c478bd9Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
905*7c478bd9Sstevel@tonic-gate 		    return (-1);
906*7c478bd9Sstevel@tonic-gate 	    }
907*7c478bd9Sstevel@tonic-gate 	    if (msecs < (suseconds_t)INT32_MIN ||
908*7c478bd9Sstevel@tonic-gate 		msecs > (suseconds_t)INT32_MAX) {
909*7c478bd9Sstevel@tonic-gate 		    error_str = gettext("bad time stamp in file header");
910*7c478bd9Sstevel@tonic-gate 		    return (-1);
911*7c478bd9Sstevel@tonic-gate 	    }
912*7c478bd9Sstevel@tonic-gate #endif
913*7c478bd9Sstevel@tonic-gate 	}
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	if (adrf_short(&adrf, &pathlength, 1)) {
916*7c478bd9Sstevel@tonic-gate 		error_str = gettext("incomplete file header");
917*7c478bd9Sstevel@tonic-gate 		return (-1);
918*7c478bd9Sstevel@tonic-gate 	}
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	if (pathlength != 0) {
921*7c478bd9Sstevel@tonic-gate 		fname = (char *)a_calloc(1, (size_t)pathlength);
922*7c478bd9Sstevel@tonic-gate 		if ((fread(fname, sizeof (char), pathlength, fp)) !=
923*7c478bd9Sstevel@tonic-gate 				pathlength) {
924*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
925*7c478bd9Sstevel@tonic-gate 				gettext("error in header/filename read in %s"),
926*7c478bd9Sstevel@tonic-gate 				fn);
927*7c478bd9Sstevel@tonic-gate 			error_str = errbuf;
928*7c478bd9Sstevel@tonic-gate 			return (-1);
929*7c478bd9Sstevel@tonic-gate 		}
930*7c478bd9Sstevel@tonic-gate 		free(fname);
931*7c478bd9Sstevel@tonic-gate 	}
932*7c478bd9Sstevel@tonic-gate 	return (0);
933*7c478bd9Sstevel@tonic-gate }
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate /*
937*7c478bd9Sstevel@tonic-gate  * .func	get_record - get a single record.
938*7c478bd9Sstevel@tonic-gate  * .desc	Read a single record from stream fp. If the record to be read
939*7c478bd9Sstevel@tonic-gate  *	is larger than the buffer given to hold it (as determined by
940*7c478bd9Sstevel@tonic-gate  *	cur_size) then free that buffer and allocate a new and bigger
941*7c478bd9Sstevel@tonic-gate  *	one, making sure to store its size.
942*7c478bd9Sstevel@tonic-gate  * .call	ret = get_record(fp, buf, cur_size, flags).
943*7c478bd9Sstevel@tonic-gate  * .arg	fp	- stream to read from.
944*7c478bd9Sstevel@tonic-gate  * .arg	buf	- ptr to ptr to buffer to place record in.
945*7c478bd9Sstevel@tonic-gate  * .arg	cur_size- ptr to the size of the buffer that *buf points to.
946*7c478bd9Sstevel@tonic-gate  * .arg	flags	- flags from fcb (to get FF_NOTTERM).
947*7c478bd9Sstevel@tonic-gate  * .ret	+number	- number of chars in the record.
948*7c478bd9Sstevel@tonic-gate  * .ret	0	- trailer seen - file done.
949*7c478bd9Sstevel@tonic-gate  * .ret	-1	- read error (error_str know what type).
950*7c478bd9Sstevel@tonic-gate  */
951*7c478bd9Sstevel@tonic-gate static int
952*7c478bd9Sstevel@tonic-gate get_record(fp, buf, fn)
953*7c478bd9Sstevel@tonic-gate FILE *fp;
954*7c478bd9Sstevel@tonic-gate char	**buf;
955*7c478bd9Sstevel@tonic-gate char	*fn;
956*7c478bd9Sstevel@tonic-gate {
957*7c478bd9Sstevel@tonic-gate 	adr_t	adr;
958*7c478bd9Sstevel@tonic-gate 	adrf_t	adrf;
959*7c478bd9Sstevel@tonic-gate 	int	leadin;
960*7c478bd9Sstevel@tonic-gate 	char	id;
961*7c478bd9Sstevel@tonic-gate 	int	lsize;
962*7c478bd9Sstevel@tonic-gate 	short	ssize;
963*7c478bd9Sstevel@tonic-gate 
964*7c478bd9Sstevel@tonic-gate 	/*
965*7c478bd9Sstevel@tonic-gate 	 * Get the token type. It will be either a header or a file
966*7c478bd9Sstevel@tonic-gate 	 * token.
967*7c478bd9Sstevel@tonic-gate 	 */
968*7c478bd9Sstevel@tonic-gate 	(void) adrf_start(&adrf, &adr, fp);
969*7c478bd9Sstevel@tonic-gate 	if (adrf_char(&adrf, &id, 1)) {
970*7c478bd9Sstevel@tonic-gate 		(void) sprintf(errbuf, gettext(
971*7c478bd9Sstevel@tonic-gate 			"record expected but not found in %s"),
972*7c478bd9Sstevel@tonic-gate 			fn);
973*7c478bd9Sstevel@tonic-gate 		error_str = errbuf;
974*7c478bd9Sstevel@tonic-gate 		return (-1);
975*7c478bd9Sstevel@tonic-gate 	}
976*7c478bd9Sstevel@tonic-gate 	switch (id) {
977*7c478bd9Sstevel@tonic-gate 	case AUT_HEADER32:
978*7c478bd9Sstevel@tonic-gate 	case AUT_HEADER32_EX:
979*7c478bd9Sstevel@tonic-gate 	case AUT_HEADER64:
980*7c478bd9Sstevel@tonic-gate 	case AUT_HEADER64_EX:
981*7c478bd9Sstevel@tonic-gate 		/*
982*7c478bd9Sstevel@tonic-gate 		 * The header token is:
983*7c478bd9Sstevel@tonic-gate 		 *	attribute id:		char
984*7c478bd9Sstevel@tonic-gate 		 *	byte count:		int
985*7c478bd9Sstevel@tonic-gate 		 *	version #:		char
986*7c478bd9Sstevel@tonic-gate 		 *	event ID:		short
987*7c478bd9Sstevel@tonic-gate 		 *	ID modifier:		short
988*7c478bd9Sstevel@tonic-gate 		 *	IP address type		int	(_EX only)
989*7c478bd9Sstevel@tonic-gate 		 *	IP address		1/4*int (_EX only)
990*7c478bd9Sstevel@tonic-gate 		 *	seconds (date):		long
991*7c478bd9Sstevel@tonic-gate 		 *	time (microsecs):	long
992*7c478bd9Sstevel@tonic-gate 		 */
993*7c478bd9Sstevel@tonic-gate 		leadin = sizeof (int32_t) + sizeof (char);
994*7c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, &lsize, 1);
995*7c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(lsize + leadin));
996*7c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
997*7c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
998*7c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&lsize, 1);
999*7c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), lsize - leadin, fp) !=
1000*7c478bd9Sstevel@tonic-gate 			lsize - leadin) {
1001*7c478bd9Sstevel@tonic-gate 			(void) sprintf(errbuf,
1002*7c478bd9Sstevel@tonic-gate 				gettext("header token read failure in %s"), fn);
1003*7c478bd9Sstevel@tonic-gate 			error_str = errbuf;
1004*7c478bd9Sstevel@tonic-gate 			return (-1);
1005*7c478bd9Sstevel@tonic-gate 		}
1006*7c478bd9Sstevel@tonic-gate 		return (lsize + leadin);
1007*7c478bd9Sstevel@tonic-gate 	case AUT_OTHER_FILE32: {
1008*7c478bd9Sstevel@tonic-gate 		int32_t secs, msecs;
1009*7c478bd9Sstevel@tonic-gate 		leadin =  2 * sizeof (int32_t) +
1010*7c478bd9Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
1011*7c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&secs, 1);
1012*7c478bd9Sstevel@tonic-gate 		(void) adrf_int32(&adrf, (int32_t *)&msecs, 1);
1013*7c478bd9Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
1014*7c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
1015*7c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
1016*7c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
1017*7c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&secs, 1);
1018*7c478bd9Sstevel@tonic-gate 		adr_int32(&adr, (int32_t *)&msecs, 1);
1019*7c478bd9Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
1020*7c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
1021*7c478bd9Sstevel@tonic-gate 			error_str = gettext("file token read failure");
1022*7c478bd9Sstevel@tonic-gate 			return (-1);
1023*7c478bd9Sstevel@tonic-gate 		}
1024*7c478bd9Sstevel@tonic-gate 		return (0);		/* done! */
1025*7c478bd9Sstevel@tonic-gate 	}
1026*7c478bd9Sstevel@tonic-gate 	case AUT_OTHER_FILE64: {
1027*7c478bd9Sstevel@tonic-gate 		int64_t secs, msecs;
1028*7c478bd9Sstevel@tonic-gate 		leadin =  2 * sizeof (int64_t) +
1029*7c478bd9Sstevel@tonic-gate 				sizeof (short) + sizeof (char);
1030*7c478bd9Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&secs, 1);
1031*7c478bd9Sstevel@tonic-gate 		(void) adrf_int64(&adrf, (int64_t *)&msecs, 1);
1032*7c478bd9Sstevel@tonic-gate 		(void) adrf_short(&adrf, &ssize, 1);
1033*7c478bd9Sstevel@tonic-gate 		*buf = (char *)a_calloc(1, (size_t)(ssize + leadin));
1034*7c478bd9Sstevel@tonic-gate 		adr_start(&adr, *buf);
1035*7c478bd9Sstevel@tonic-gate 		adr_char(&adr, &id, 1);
1036*7c478bd9Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&secs, 1);
1037*7c478bd9Sstevel@tonic-gate 		adr_int64(&adr, (int64_t *)&msecs, 1);
1038*7c478bd9Sstevel@tonic-gate 		adr_short(&adr, &ssize, 1);
1039*7c478bd9Sstevel@tonic-gate 		if (fread(*buf + leadin, sizeof (char), ssize, fp) != ssize) {
1040*7c478bd9Sstevel@tonic-gate 			error_str = gettext("file token read failure");
1041*7c478bd9Sstevel@tonic-gate 			return (-1);
1042*7c478bd9Sstevel@tonic-gate 		}
1043*7c478bd9Sstevel@tonic-gate 		return (0);		/* done! */
1044*7c478bd9Sstevel@tonic-gate 	}
1045*7c478bd9Sstevel@tonic-gate 	default:
1046*7c478bd9Sstevel@tonic-gate 		break;
1047*7c478bd9Sstevel@tonic-gate 	}
1048*7c478bd9Sstevel@tonic-gate 	error_str = gettext("record begins without proper token");
1049*7c478bd9Sstevel@tonic-gate 	return (-1);
1050*7c478bd9Sstevel@tonic-gate }
1051