1#!/usr/perl5/bin/perl -w
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27# auditxml_jni [-d] <xml input file>
28
29# auditxml takes the audit record description (.xml file) and
30# generates the files needed for the Java
31
32use auditxml;
33use Getopt::Std;
34use vars qw($opt_d);
35use strict;
36
37
38our $debug = 0; # normal use is to set via the file being parsed.
39               # <debug set="on"/> or <debug set="off"/> or <debug/>
40               # if the set attribute is omitted, debug state is toggled
41               # Override with appDebug, but toggle won't do what you
42               # want.
43my $appDebug = 0; # used after return from "new auditxml";
44
45my $genNotice = "
46DO NOT EDIT. This file is auto generated by the Solaris Audit
47system from adt.xml.
48
49See http://opensolaris.org/os/project/audit/
50";
51
52# trim leading/trailing newlines
53$genNotice =~ s/^\n//s;
54$genNotice =~ s/\n$//s;
55my $prog = $0; $prog =~ s|.*/||g;
56my $usage = "usage: $prog [-d] file.xml\n";
57
58getopts('d');
59
60$appDebug = $opt_d;
61
62my $uniLabel = "adr";
63my $xlateUniLabelInc = 0;
64
65die $usage if ($#ARGV < 0);
66
67# where everything comes from and where it goes:
68
69my $templatePath = './';
70my $javaPath     = $templatePath;
71my $bsmBuildPath = "../libbsm";
72
73my $jniBuildPath = "$javaPath";
74
75my $buildPathJ	 = "$jniBuildPath/com/sun/audit";
76my $buildPathJNI = "$jniBuildPath/common";
77
78my $auditEventJ = "$buildPathJ/AuditEvent.java";
79my $jniC = "$buildPathJNI/adt_jni_event.c";
80my $mapFile = "$jniBuildPath/common/mapfile-vers";
81
82my $doc = new auditxml ($ARGV[0]);  # input XML file
83
84$debug = $appDebug;
85
86my %jniEventTable = ();
87my %externalIdNo = ();
88my %msg_list = ();
89my %eventCode = ();
90
91readAuditEventFile("$bsmBuildPath/audit_event.txt");
92
93my $event;
94while ($event = $doc->getNextEvent()) {
95    my $eventId = $event->getId();
96    my $idNo = $event->getIdNo();
97    $externalIdNo{$eventId} = $idNo;
98    my $super;
99    my $omit = $event->getOmit();
100    my $eventType = '';
101    if ($super = $event->getSuperClass()) {
102	$event = $super;
103	$eventType = 'instance';
104    } else {
105	$eventType = $event->getType();
106    }
107
108    # c file table for translation
109    generateTableC($event, $eventId, $eventType, undef, $omit);
110}
111
112while (my $textList = $doc->getNextMsgId()) {
113    generateMsgLists($textList);  # enum -> text mappings
114}
115
116printJavaFiles($jniC, $auditEventJ, $buildPathJ, $mapFile);
117
118exit 0;
119
120
121
122sub printJavaFiles {
123    my $jniFile = shift;
124    my $javaFile = shift;
125    my $subclassPath = shift;
126    my $mapFile = shift;
127
128    # warning: time_t is equated to jlong since there is no
129    # way to use sys/types.h in Java code.
130    # java long is C long long, 64 bits.
131    # java int is 32 bits.
132
133    my %java_jni = ('ADT_DATE'		=> ['long',	'jlong'],
134		    'ADT_UINT'		=> ['int',	'jint'],
135		    'ADT_INT'		=> ['int',	'jint'],
136		    'ADT_INT32'		=> ['int',	'jint'],
137		    'ADT_UID'		=> ['int',	'jint'],
138		    'ADT_GID'		=> ['int',	'jint'],
139		    'ADT_UIDSTAR'	=> ['int[]',	'jintArray'],
140		    'ADT_GIDSTAR'	=> ['int[]',	'jintArray'],
141		    'ADT_CHAR'		=> ['String',	'jchar'],
142		    'ADT_CHARSTAR'	=> ['String',	'jstring'],
143		    'ADT_CHAR2STAR'	=> ['String[]',	'jstring'],
144		    'ADT_MSG'		=> ['int',	'jint'],
145		    'ADT_PID'		=> ['int',	'jint'],
146# ADT_PRIVSTAR omitted -- not implemented and the audit records that
147# use it must be coded to emit no java.  We'll cross that bridge
148# when someone in Java land needs to generate a priv token.
149		    'ADT_LONG'		=> ['int',	'jint'],
150		    'ADT_TERMIDSTAR'	=> ['String',	'jstring'],	# hostname -> termid
151		    'ADT_ULONG'		=> ['int',	'jint'],
152		    'ADT_UINT16'	=> ['int',	'jint'],
153		    'ADT_UINT32'	=> ['int',	'jint'],
154		    'ADT_UINT32STAR'	=> ['int[]',	'jintArray'],
155# ADT_UINT32ARRAY omitted; no Java implementation yet
156		    'ADT_UINT64'	=> ['long',	'jlong'],
157		    'ADT_UINT64STAR'	=> ['long[]',	'jlongArray']
158		   );
159    my $noMemory = 'gettext("Out of memory")';
160
161    # open output files
162    open (Cfile, ">$jniFile") or
163	die "can't open output file ($jniFile): $!\n";
164    open (Jfile, ">$javaFile") or
165	die "can't open output file ($javaFile): $!\n";
166    open (MapFile, ">$mapFile") or
167	die "can't open output file ($mapFile): $!\n";
168
169    # write headers
170    my $notice = $genNotice;
171    $notice =~ s/\n/\n * /gs;
172    $notice =~ s/\s+\n/\n/gs;
173    print Cfile <<EOF;
174/*
175 * $notice
176 */
177
178#include "../../libbsm/common/adt_xlate.h"
179#include <jni.h>
180#include "../com/sun/audit/AuditSession.h"	/* javah output */
181#include "adt_jni.h"
182#include <stdlib.h>
183#include <string.h>
184
185static char *except_class = "java/lang/Exception";
186
187EOF
188    print Jfile <<EOF;
189/*
190 * $notice
191 */
192
193package com.sun.audit;
194
195public class AuditEvent {
196	protected AuditSession sh;	// associated session object
197
198	public AuditEvent(AuditSession auSession)
199	    throws Error
200	{
201
202		sh = auSession;
203	}
204
205	// Manifest values: keep them in sync with generated <bsm/adt_event.h>.
206	// It is generated by \$SRC/lib/libbsm/auditxml
207
208	public static final int ADT_SUCCESS = 0;	// generated
209	public static final int ADT_FAILURE = -1;	// generated
210
211	// See the subclasses of AuditEvent for mapping message codes
212	// to events
213EOF
214
215    my $notice_map = $genNotice;
216    $notice_map =~ s/\n/\n# /gs;
217    $notice_map =~ s/\s+\n/\n/gs;
218    print MapFile <<EOF;
219#
220# $notice_map
221#
222
223SUNWprivate_1.1 {
224    global:
225	c2j_pointer;
226	j2c_pointer;
227	Java_com_sun_audit_AuditSession_bsmAuditOn;
228	Java_com_sun_audit_AuditSession_startSession;
229	Java_com_sun_audit_AuditSession_endSession;
230	Java_com_sun_audit_AuditSession_dupSession;
231	Java_com_sun_audit_AuditSession_getSessionId;
232	Java_com_sun_audit_AuditSession_exportSessionData;
233	Java_com_sun_audit_AuditSession_sessionAttr;
234
235# One subclass of AuditEvent per audit record...
236EOF
237
238    # generate java final int classes to line up with string/enums
239
240    foreach my $listName (sort keys %msg_list) {
241        my $shortName = uc $listName;
242        $shortName =~ s/_TEXT//;
243        my ($listRef, $headref) = @{$msg_list{$listName}};
244        my @listValue =  @$listRef;
245        my ($header, $enumValue, $public, $deprecated) = @$headref;
246        my $listValue;
247
248        print Jfile "\n\t// adt_$listName" . "\n\n";
249        print Jfile "\tpublic static final int ADT_$shortName",
250    		" = $enumValue;\n" if $enumValue;
251
252        next unless ($#listValue >= 0);
253        print Jfile "\t// Deprecated message list\n" if $deprecated;
254        foreach $listValue (@listValue) {
255            my ($id, $text) = split(/\s*::\s*/, $listValue);
256    	    print Jfile "\t// $text\n";
257    	    print Jfile "\tpublic static final int ADT_$shortName";
258	    print Jfile "_$id = $enumValue;\n";
259    	    $enumValue++;
260        }
261    }
262
263    # generate event creation and access functions and event
264    # generation for both Java and JNI
265    # com.sun.audit.AuditEvent_xxx.java
266    foreach my $eventId (sort keys %jniEventTable) {
267	my ($ref1, $eventType, $allowedIds, $header) = @{$jniEventTable{$eventId}};
268	$eventCode{$eventId} = -1 if ($eventType eq 'generic');
269	my @entries = @$ref1;
270	my $entries = $#entries;
271	my $root = $eventId;
272	$root =~ s/AUE_//;
273	my $javaPutEvent = 'putEvent';
274	my $putMethod = "_$root";
275	$putMethod =~ s/_/_1/g;
276
277	my $jniPutEvent = "Java_com_sun_audit_AuditEvent$putMethod" . "_$javaPutEvent";
278
279	# the subclass file template isn't used; it may be needed to get
280	# the right file header stuff in place.  The subclassPath is
281	# the directory that contains 'em.
282
283	my $validSfile = 1;
284	unless (open(Sfile, ">$subclassPath/AuditEvent_$root.java")) {
285	    print STDERR "can't open class file AuditEvent_$root.java: $!\n";
286	    $validSfile = 0;
287	}
288	if ($eventCode{"AUE_$root"}) {
289	    if ($validSfile) {
290		print Sfile <<EOF;
291/*
292 * $notice
293 */
294
295package com.sun.audit;
296
297// audit event:  $eventId = $eventCode{"AUE_$root"}
298
299public class AuditEvent_$root extends AuditEvent {
300
301EOF
302	    }
303	} else {
304	    print STDERR "no event code for $eventId.  Is audit_event current?\n";
305	}
306	my $nativeParameterList = '';
307	my $jniParameterList = '';
308	my $specParameterList = '';
309	my $jniStorageList = '';
310	my $needCleanupTarget = 0;
311	my $jniFreeList = '';
312
313	my $haveStringDef = 0;
314	my $haveCDef = 0;
315	my $haveLengthDef = 0;
316	my $haveStringArrayDef = 0;
317	my $cntTermidDef = 0;
318	my $jniDefine;
319	my $needLocaleDefined = 0;
320	my $jniADTalloc;
321	if (defined $header && ($header > 0) ) {
322	    $jniDefine = "union union_of_events	*event;\n" .
323		"\tadt_session_data_t	*session;\n";
324	    $jniADTalloc = '(union union_of_events *)adt_alloc_event';
325	} else {
326	    $jniDefine = "adt_event_data_t	*event;\n" .
327		"\tadt_session_data_t	*session;\n";
328	    $jniADTalloc = 'adt_alloc_event';
329	}
330	my $ref2;
331	foreach $ref2 (@entries) {
332	    my ($id, $type) = @$ref2;
333	    my $jniRoot = $root . $id;
334	    $jniRoot =~ s/_/_1/g;  # escape unicode "_"
335
336	    my $p_event;
337	    if (defined $header && ($header > 0) ) {
338		$p_event = "event->d$header.adt_$root.$id";
339	    } else {
340		$p_event = "event->adt_$root.$id";
341	    }
342
343	    if ($type eq 'ADT_UINT32STAR') { # int array
344	        $needLocaleDefined = 1;
345
346
347	        $jniStorageList .= <<EOF;
348	/* $id */
349	length = (*env)->GetArrayLength(env, $id);
350	$p_event =
351	    (int *)malloc(length * sizeof (int));
352	if ($p_event == NULL) {
353		locale = I18N_SETUP;
354		local_throw(env, except_class,
355		    $noMemory);
356		(void) setlocale(LC_MESSAGES, locale);
357		goto cleanup;
358	}
359	(*env)->GetIntArrayRegion(env, $id, 0, length,
360	    (int *)$p_event);
361EOF
362
363
364		$jniFreeList .= "\n\tif ($p_event != NULL)\n" .
365		    "\t\tfree($p_event);\n";
366		unless ($haveLengthDef) {
367		    $haveLengthDef = 1;
368		    $jniDefine .= "\tint\t\t\tlength;\n";
369		}
370		$nativeParameterList .= ",\n\t    int[]\t$id";
371		$jniParameterList .= ",\n    jintArray\t$id";
372		$specParameterList .= ", jintArray";
373		$needCleanupTarget = 1;
374	    } elsif (($type eq 'ADT_UIDSTAR') ||
375		     ($type eq 'ADT_GIDSTAR')) { # gid_t array
376		my $cType = 'uid_t';
377		$cType = 'gid_t' if ($type eq 'ADT_GIDSTAR');
378		$needLocaleDefined = 1;
379
380
381		$jniStorageList .= <<EOF;
382	/* $id */
383	length = (*env)->GetArrayLength(env, $id);
384	$p_event =
385	    ($cType *)malloc(length * sizeof ($cType));
386	if ($p_event == NULL) {
387		locale = I18N_SETUP;
388		local_throw(env, except_class,
389		    $noMemory);
390		(void) setlocale(LC_MESSAGES, locale);
391		goto cleanup;
392	}
393	(*env)->GetIntArrayRegion(env, $id, 0, length,
394	    (int *)$p_event);
395EOF
396
397
398		$jniFreeList .=
399		    "\n\tif ($p_event != NULL)\n" .
400		    "\t\tfree($p_event);\n";
401		unless ($haveLengthDef) {
402		    $haveLengthDef = 1;
403		    $jniDefine .= "\tint\t\t\tlength;\n";
404		}
405		$nativeParameterList .= ",\n\t    int[]\t$id";
406		$jniParameterList .= ",\n    jintArray\t$id";
407		$specParameterList .= ", jintArray";
408		$needCleanupTarget = 1;
409	    } elsif ($type eq 'ADT_UINT64STAR') { # long array
410	        $needLocaleDefined = 1;
411	        $jniStorageList .= <<EOF;
412	/* $id */
413	length = (*env)->GetArrayLength(env, $id);
414	$p_event =
415	    (long *)malloc(length * sizeof (long long));
416	if ($p_event == NULL) {
417		locale = I18N_SETUP;
418		local_throw(env, except_class,
419		    $noMemory);
420		(void) setlocale(LC_MESSAGES, locale);
421		goto cleanup;
422	}
423	(*env)->GetLongArrayRegion(env, $id, 0, length,
424	    $p_event);
425EOF
426		$jniFreeList .= "\n\tif ($p_event != NULL)\n" .
427		    "\t\tfree($p_event);\n";
428		unless ($haveLengthDef) {
429		    $haveLengthDef = 1;
430		    $jniDefine .= "\tint\t\t\tlength;\n";
431		}
432		$nativeParameterList .= ",\n\t    long[]\t$id";
433		$jniParameterList .= ",\n    jlongArray\t$id";
434		$specParameterList .= ", jlongArray";
435		$needCleanupTarget = 1;
436	    } elsif ($type eq 'ADT_CHAR') { # string in Java, char in C
437		$jniStorageList .= <<EOF;
438
439	/* $id */
440	c = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
441	if (c == NULL)
442		goto cleanup; /* exception thrown */
443	$p_event = *c;
444	(*env)->ReleaseStringUTFChars(env, $id, c);
445EOF
446		# no need to free anything
447		unless ($haveCDef) {
448		    $haveCDef = 1;
449		    $jniDefine .= "\tchar\t\t\t*c\n";
450		}
451		$nativeParameterList .= ",\n\t    String\t$id";
452		$jniParameterList .= ",\n    jstring\t$id";
453		$specParameterList .= ", jstring";
454	    } elsif ($type eq 'ADT_CHARSTAR') {
455	        $needLocaleDefined = 1;
456		$jniStorageList .= <<EOF;
457	/* $id */
458	if ($id != NULL) {
459		string = (char *)(*env)->GetStringUTFChars(
460		    env, $id, NULL);
461		if (string == NULL)
462			goto cleanup; /* exception thrown */
463		$p_event = strdup(string);
464		(*env)->ReleaseStringUTFChars(env, $id, string);
465		if ($p_event == NULL) {
466			locale = I18N_SETUP;
467			local_throw(env, except_class,
468			    $noMemory);
469			(void) setlocale(LC_MESSAGES, locale);
470			goto cleanup;
471		}
472	}
473EOF
474		$jniFreeList .= "\n\tif ($p_event != NULL)\n" .
475		    "\t\tfree($p_event);\n";
476		unless ($haveStringDef) {
477		    $haveStringDef = 1;
478		    $jniDefine .= "\tchar\t\t\t*string;\n";
479		}
480		$nativeParameterList .= ",\n\t    String\t$id";
481		$jniParameterList .= ",\n    jstring\t$id";
482		$specParameterList .= ", jstring";
483		$needCleanupTarget = 1;
484	    } elsif ($type eq 'ADT_CHAR2STAR') { # array of string
485	        $needLocaleDefined = 1;
486		$jniStorageList .= <<EOF;
487	/* $id */
488	length = (*env)->GetArrayLength(env, $id);
489	$p_event = (char **)malloc(length
490	    * sizeof (char *));
491	if ($p_event == NULL) {
492		locale = I18N_SETUP;
493		local_throw(env, except_class,
494		    $noMemory);
495		(void) setlocale(LC_MESSAGES, locale);
496		goto cleanup;
497	}
498	p = $p_event;
499	for (i = 0; i < length; i++) {
500		jString = (*env)->GetObjectArrayElement(env, $id, i);
501		string = (char *)(*env)->GetStringUTFChars(
502		    env, jString, NULL);
503		if (string == NULL)
504			goto cleanup; /* exception thrown */
505		*p = strdup(string);
506		(*env)->ReleaseStringUTFChars(env, jString, string);
507		if (*p == NULL) {
508			locale = I18N_SETUP;
509			local_throw(env, except_class,
510			    $noMemory);
511			(void) setlocale(LC_MESSAGES, locale);
512			while (p >= $p_event)
513				free(*p--);
514			goto cleanup;
515		}
516		p++;
517	}
518EOF
519		$jniFreeList .=
520		    "\n\tif ($p_event != NULL)\n" .
521		    "\t\tfree($p_event);\n";
522		unless ($haveStringArrayDef) {
523		    unless ($haveStringDef) {
524			$haveStringDef = 1;
525			$jniDefine .= <<EOF;
526	char			*string;
527EOF
528		    }
529		    unless ($haveLengthDef) {
530			$haveLengthDef = 1;
531			$jniDefine .= <<EOF;
532	int			length;
533EOF
534		    }
535		    $haveStringArrayDef = 1;
536		    $jniDefine .= <<EOF;
537	int			i;
538	char			**p;
539	jstring			jString;
540EOF
541		}
542		$nativeParameterList .= ",\n\t    String[]\t$id";
543		$jniParameterList .= ",\n    jstring\t$id";
544		$specParameterList .= ", jstring";
545		$needCleanupTarget = 1;
546	      } elsif ($type eq 'ADT_TERMIDSTAR') {
547	        $needLocaleDefined = 1;
548
549	        $jniStorageList .= <<EOF;
550	/* $id */
551	hostname$cntTermidDef = (char *)(*env)->GetStringUTFChars(env, $id, NULL);
552
553	if (adt_load_hostname((const char *)hostname$cntTermidDef, &termid$cntTermidDef)) {
554		local_throw(env, except_class,
555			gettext("hostname lookup failed"));
556	}
557	$p_event = termid$cntTermidDef;
558
559	(*env)->ReleaseStringUTFChars(env, $id, hostname$cntTermidDef);
560EOF
561
562		$jniFreeList .= "\n\tif (hostname$cntTermidDef != NULL)\n" .
563		    "\t\tfree(hostname$cntTermidDef);\n";
564		$jniFreeList .= "\n\tif (termid$cntTermidDef != NULL)\n" .
565		    "\t\tfree(termid$cntTermidDef);\n";
566
567		$jniDefine .= "\tchar\t\t\t*hostname$cntTermidDef;\n";
568		$jniDefine .= "\tadt_termid_t\t\t*termid$cntTermidDef;\n"; #djdj
569
570		$cntTermidDef++;
571
572		my ($nativeParameter, $jniParameter) = @{$java_jni{$type}};
573		$nativeParameterList .= ",\n\t    $nativeParameter\t$id";
574		$jniParameterList .= ",\n    $jniParameter\t$id";
575		$specParameterList .= ", $jniParameter";
576		$needCleanupTarget = 1;
577	    } else {  # all others are primitive types
578		$jniStorageList .= "\n\t$p_event = $id;\n";
579		my ($nativeParameter, $jniParameter) = @{$java_jni{$type}};
580		$nativeParameter = "$nativeParameter\t"
581		    if length $nativeParameter < 4;  # why?
582		$nativeParameterList .= ",\n\t    $nativeParameter\t$id";
583		$jniParameterList .= ",\n    $jniParameter\t$id";
584		$specParameterList .= ", $jniParameter";
585	    }
586	}
587	if ($needLocaleDefined) {
588		$jniDefine .= <<EOF
589	char			*locale;
590EOF
591	}
592	my $genericOverride = '';
593	my $idParameter = $eventId;
594	$idParameter =~ s/AUE_/ADT_/;
595	if ($eventType eq 'generic') {
596	    $genericOverride = ', jint eventId';
597	    $idParameter = 'eventId';
598	}
599	$jniFreeList = "\tcleanup:\n" . $jniFreeList if $needCleanupTarget;
600
601	print Cfile qq{/* ARGSUSED */
602JNIEXPORT void JNICALL
603$jniPutEvent(
604    JNIEnv	*env,
605    jobject	self,
606    jbyteArray	jsession$genericOverride,
607    jint	status,
608    jint	ret_val$jniParameterList)
609{
610	$jniDefine
611	(void) j2c_pointer(env, jsession, (char **)&session);
612
613	event = $jniADTalloc(session, $idParameter);
614
615$jniStorageList
616	(void) adt_put_event((adt_event_data_t *)event, status, ret_val);
617
618$jniFreeList
619	adt_free_event((adt_event_data_t *)event);
620}
621};
622	print MapFile qq{
623	$jniPutEvent; };
624	my $overrideParameter = '';
625	if ($eventType eq 'generic') {
626	    $overrideParameter = 'int eventId,';
627	    my @allowed = @$allowedIds;
628	    if (@allowed) {
629		my $i;
630		if ($validSfile) {
631		    print Sfile "\t// Allowed values for eventId in putEvent:\n";
632		    for ($i = 0; $i <= $#allowed; $i++) {
633			my $idNo = $externalIdNo{$allowed[$i]};
634			$allowed[$i] =~ s/AUE_/ADT_/;
635			print Sfile "\tstatic final int $allowed[$i] = ",
636			     "$idNo;\n";
637		    }
638		    print Sfile "\n";
639		}
640	    } else {
641		print STDERR "Generic event with no allowed instances: $eventId\n";
642	    }
643	}
644	if ($validSfile) {
645	    print Sfile <<EOF;
646	private native void $javaPutEvent(byte[]session, $overrideParameter
647	    int status, int ret_val$nativeParameterList);
648
649	public AuditEvent_$root(AuditSession session)
650		throws Exception
651	{
652		super(session);
653	}
654
655EOF
656	    my $javaParameterList = '';
657	    foreach $ref2 (@entries) {
658		my ($id, $type, $format, $jComment, $required) = @$ref2;
659
660		# generate java native method prototypes
661		# and the corresponding C method implementation
662
663		my $javaMethodName = "$id";
664		my $javaStorageName = $javaMethodName . '_val';
665		my $jniMethodName = $root . $id;
666		my $storage;
667		my $enumUsage = '';
668		my $jParam = @{$java_jni{$type}}[0];
669		my $comment = '';
670		if ($required) {
671		    if ($format ne 'NULL') {
672			$comment = "\t// (required) formatted:  $format";
673		    } else {
674			$comment = "\t// required";
675		    }
676		} else {
677		    if ($format ne 'NULL') {
678			$comment = "\t// (optional) formatted:  $format";
679		    } else {
680			$comment = "\t// optional";
681		    }
682		}
683		if (($type eq 'ADT_UINT32STAR') ||
684		    ($type eq 'ADT_UIDSTAR') ||
685		    ($type eq 'ADT_GIDSTAR')) { # int array
686		    $storage = "int[] $javaStorageName" . ($required ?
687							   ' = {}' : '');
688		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
689		} elsif ($type eq 'ADT_UINT64STAR') { # long array
690		    $storage = "long[] $javaStorageName" . ($required ?
691							    ' = {}' : '');
692		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
693		} elsif (($type eq 'ADT_CHARSTAR') ||
694			 ($type eq 'ADT_CHAR')) { # string
695		    $storage = "String $javaStorageName" . ($required ?
696							    ' = ""' : '');
697		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
698		} elsif ($type eq 'ADT_CHAR2STAR') { # array of string
699		    $storage = "String[] $javaStorageName" . ($required ?
700							      ' = {}' : '');
701		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
702		} elsif ($type eq 'ADT_TERMIDSTAR') { # array of string
703		    $storage = "String $javaStorageName" . ($required ?
704							    ' = ""' : '');
705		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
706		} else {  # all others are primitive types
707		    $storage = "$jParam $javaStorageName = 0";
708		    $javaParameterList .= ",\n\t\t\t    $javaStorageName";
709		    $enumUsage = "\n\t// See $jComment in AuditEvent.java for valid values"
710			if $jComment;
711		}
712		print Sfile <<EOF;
713$enumUsage
714	private $storage;$comment
715	public void $javaMethodName($jParam setTo)
716	{
717		$javaStorageName = setTo;
718	}
719EOF
720	    }	# end foreach (@entries)
721	    if ($eventType eq 'generic') {
722		print Sfile <<EOF;
723
724	public void putEvent(int status, int ret_val, int eventId)
725	{
726		byte[]	session = super.sh.getSession();
727
728		if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
729			$javaPutEvent(session, eventId,
730			    status, ret_val$javaParameterList);
731	}
732}
733EOF
734	    } else {
735		print Sfile <<EOF;
736
737	public void putEvent(int status, int ret_val)
738	{
739		byte[]	session = super.sh.getSession();
740
741		if ((super.sh.AuditIsOn) && (super.sh.ValidSession))
742			$javaPutEvent(session, status, ret_val$javaParameterList);
743	}
744}
745EOF
746	    }
747	    close Sfile;
748	}	# end if ($validSfile);
749    }
750
751    # write trailers
752    print Jfile <<EOF;
753
754}
755EOF
756    print MapFile <<EOF;
757
758    local:
759	*;
760};
761EOF
762    close Cfile;
763    close Jfile;
764    close MapFile;
765}
766
767sub generateTableC {
768    my $event = shift;
769    my $eventId = shift;
770    my $eventType = shift;
771    my $eventHeader = shift;
772    my $omit = shift;
773
774    my %tokenType = (
775		  'acl'			=> 'AUT_ACL',
776		  'arbitrary'		=> 'AUT_ARBITRARY',
777		  'arg'			=> 'AUT_ARG',
778		  'attr'		=> 'AUT_ATTR',
779		  'command'		=> 'AUT_CMD',
780		  'command_1'		=> 'ADT_CMD_ALT',	# dummy token id
781		  'date'		=> 'AUT_TEXT',
782		  'exec_args'   	=> 'AUT_EXEC_ARGS',
783		  'exec_env'    	=> 'AUT_EXEC_ENV',
784		  'exit'        	=> 'AUT_EXIT',
785		  'file'        	=> 'AUT_FILE',
786		  'fmri'        	=> 'AUT_FMRI',
787		  'groups'      	=> 'AUT_GROUPS',
788	#	  'header'      	=> 'AUT_HEADER',	# not used
789		  'in_addr'     	=> 'AUT_IN_ADDR',
790		  'tid'          	=> 'AUT_TID',
791		  'ipc'         	=> 'AUT_IPC',
792		  'ipc_perm'    	=> 'AUT_IPC_PERM',
793		  'iport'		=> 'AUT_IPORT',
794		  'label'		=> 'AUT_LABEL',
795		  'newgroups'   	=> 'AUT_NEWGROUPS',
796		  'opaque'      	=> 'AUT_OPAQUE',
797		  'path'        	=> 'AUT_PATH',
798		  'path_list'		=> '-AUT_PATH',		# dummy token id
799		  'process'     	=> 'AUT_PROCESS',
800		  'priv_effective'	=> 'ADT_AUT_PRIV_E',	# dummy token id
801		  'priv_limit'		=> 'ADT_AUT_PRIV_L', 	# dummy token id
802		  'priv_inherit'	=> 'ADT_AUT_PRIV_I',	# dummy token id
803		  'return'      	=> 'AUT_RETURN',
804		  'seq'         	=> 'AUT_SEQ',
805		  'socket'      	=> 'AUT_SOCKET',
806		  'socket-inet' 	=> 'AUT_SOCKET_INET',
807		  'subject'     	=> 'AUT_SUBJECT',
808		  'text'        	=> 'AUT_TEXT',
809	#	  'trailer'     	=> 'AUT_TRAILER',	# not used
810		  'uauth'		=> 'AUT_UAUTH',
811		  'zonename'		=> 'AUT_ZONENAME'
812		 );
813
814    my @xlateEntryList = ();
815    my @jniEntryList = ();
816
817    my $external = $event->getExternal();
818    my $internal = $event->getInternal();
819
820    unless ($external) {
821	print STDERR "No external object captured for event $eventId\n";
822	return;
823    }
824    unless ($internal) {
825	print STDERR "No internal object captured for event $eventId\n";
826	return;
827    }
828    my @entryRef = $internal->getEntries();
829    my $entryRef;
830    my @tokenOrder = ();
831    my $firstTokenIndex = 0; # djdj not used yet, djdj BUG!
832    			     # needs to be used by translate table
833
834    if ($internal->isReorder()) { # prescan the entry list to get the token order
835      my @inputOrder;
836      foreach $entryRef (@entryRef) {
837	my ($intEntry, $entry) = @$entryRef;
838	push (@inputOrder, $intEntry->getAttr('order'));
839      }
840
841      my $i; # walk down the inputOrder list once
842      my $k = 1; # discover next in line
843      my $l = 0; # who should point to next in line
844      for ($i = 0; $i <= $#inputOrder; $i++) {
845	my $j;
846	for ($j = 0; $j <= $#inputOrder; $j++) {
847	  if ($k == $inputOrder[$j]) {
848	    if ($k == 1) {
849	        $firstTokenIndex = $j;
850	    } else {
851	        $tokenOrder[$l] = "&(selfReference[$j])";
852	    }
853	    $l = $j;
854	    last;
855	  }
856	}
857	$k++;
858      }
859      $tokenOrder[$l] = 'NULL';
860    }
861    else { # default order -- input order same as output
862      my $i;
863      my $j;
864      for ($i = 0; $i < $#entryRef; $i++) {
865	my $j = $i + 1;
866	$tokenOrder[$i] = "&(selfReference[$j])";
867      }
868      $tokenOrder[$#entryRef] = 'NULL';
869    }
870
871    my $sequence = 0;
872    foreach $entryRef (@entryRef) {
873      my ($intEntry, $entry) = @$entryRef;
874      my $entryId = $entry->getAttr('id');
875
876      my ($extEntry, $unusedEntry, $tokenId) =
877	$external->getEntry($entryId);
878      my $opt = $extEntry->getAttr('opt');
879
880      if ($opt eq 'none') {
881	if (defined ($doc->getToken($tokenId))) {
882	  if (defined ($tokenType{$tokenId})) {
883	    $tokenId = $tokenType{$tokenId};
884	  }
885	  else {
886	    print STDERR "token id $tokenId not implemented\n";
887	  }
888	}
889	else {
890	  print STDERR "token = $tokenId is undefined\n";
891	  $tokenId = 'error';
892	}
893	my ($xlate, $jni) =
894	  formatTableEntry ('', $tokenId, $eventId, '', 0, 0, $tokenOrder[$sequence],
895			    'NULL', '');
896	push (@xlateEntryList, $xlate);
897	push (@jniEntryList, @$jni);
898      }
899      else {
900	my $dataType = $extEntry->getAttr('type');
901	$dataType =~ s/\s+//g;   # remove blanks (char * => char*)
902
903	my $enumGroup = '';
904	if ($dataType =~ /^msg/i) {
905	    $enumGroup = $dataType;
906	    $enumGroup =~ s/^msg\s*//i;
907	    $enumGroup = 'adt_' . $enumGroup;
908	}
909	my $required = ($opt eq 'required') ? 1 : 0;
910	my $tsol = 0;
911	my $tokenId = $intEntry->getAttr('token');
912	my $token;
913	my $tokenName;
914	my $tokenFormat = $intEntry->getAttr('format');
915	if (defined ($tokenFormat)) {
916	  $tokenFormat = "\"$tokenFormat\"";
917	}
918	else {
919	  $tokenFormat = 'NULL';
920	}
921
922	if (defined ($token = $doc->getToken($tokenId))) {
923	  $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0;
924	  if (defined ($tokenType{$tokenId})) {
925	    $tokenName = $tokenType{$tokenId};
926	  }
927	  else {
928	    print STDERR "token id $tokenId not implemented\n";
929	  }
930	}
931	else {
932	  print STDERR
933	    "$tokenId is an unimplemented token ($entryId in $eventId)\n";
934	  $tokenName = 'AUT_TEXT';
935	}
936	my ($xlate, $jni) =
937	  formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required,
938			   $tsol, $tokenOrder[$sequence], $tokenFormat,
939			   $enumGroup, (uc $omit eq 'JNI'));
940	push (@xlateEntryList, $xlate);
941	push (@jniEntryList, @$jni);
942      }
943      $sequence++;
944    }
945    $jniEventTable{$eventId} = [\@jniEntryList, $eventType,
946				$external->getAllowedTypes(), $eventHeader]
947	unless (uc $omit eq 'JNI') || ($omit eq 'always');
948}
949
950sub formatTableEntry {
951    my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format, $enumGroup,
952	$omitJNI) = @_;
953
954
955    # does this map belong in the xml source?  (at least the defaults?)
956    # fill in the default value only if it is other than zero.
957    #		      base type		    adt name,	default value
958    my %entryDef = ( 'au_asid_t'       	=> ['ADT_UINT32',	''],
959		     'uint_t'		=> ['ADT_UINT32',      	''],
960		     'int'		=> ['ADT_INT',		''],
961		     'int32_t'		=> ['ADT_INT32',	''],
962		     'uid_t'		=> ['ADT_UID',		'AU_NOAUDITID'],
963		     'gid_t'		=> ['ADT_GID',		'AU_NOAUDITID'],
964		     'uid_t*'		=> ['ADT_UIDSTAR',	''],
965		     'gid_t*'		=> ['ADT_GIDSTAR',	''],
966		     'char'		=> ['ADT_CHAR',		''],
967		     'char*'		=> ['ADT_CHARSTAR',	''],
968		     'char**'		=> ['ADT_CHAR2STAR',	''],
969		     'long'		=> ['ADT_LONG',		''],
970		     'pid_t'		=> ['ADT_PID',		''],
971		     'priv_set_t*'	=> ['ADT_PRIVSTAR',	''],
972		     'ulong_t'		=> ['ADT_ULONG',	''],
973		     'uint16_t',	=> ['ADT_UINT16',	''],
974		     'uint32_t'		=> ['ADT_UINT32',	''],
975		     'uint32_t*'	=> ['ADT_UINT32STAR',	''],
976		     'uint32_t[]'	=> ['ADT_UINT32ARRAY',  ''],
977		     'uint64_t'		=> ['ADT_UINT64',	''],
978		     'uint64_t*'	=> ['ADT_UINT64STAR',	''],
979		     'm_label_t*'	=> ['ADT_MLABELSTAR',	''],
980		    );
981    my $xlateLabel = $uniLabel.$xlateUniLabelInc;
982    my $xlateLabelInc = 0;
983    my $xlateLine = '';
984    my @jniLine = ();
985
986	# the list handling should be a simple loop with a loop of one
987        # falling out naturally.
988
989    unless ($type =~ /,/) {	# if list, then generate sequence of entries
990      my $dataType;
991      my $dataSize;
992      my $xlateLabelRef = '';
993
994      my $arraySize = '';
995      $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/);
996
997      my $entryType = ${$entryDef{$type}}[0];
998
999      my @xlateType = ();	# for adt_xlate.c
1000      my $typeCount = 1;
1001
1002      if ($entryType) {
1003	$dataType = $entryType;
1004	$type =~ s/([^*]+)\s*(\*+)/$1 $2/;
1005	$type =~ s/\[\]//;
1006	$dataSize = "sizeof ($type)";
1007	if ($arraySize) {
1008		$dataSize = "$arraySize * " . $dataSize;
1009	}
1010	$xlateLine = "{{$dataType, $dataSize}}";
1011	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
1012      } elsif ($type eq '') {
1013	  $xlateLabelRef = 'NULL';
1014      } elsif ($type =~ /^msg/i) {
1015	$type =~ s/^msg//i;
1016	$dataType = 'ADT_MSG';
1017	my $dataEnum = 'ADT_LIST_' . uc $type;
1018	$xlateLine = "{{$dataType, $dataEnum}}";
1019	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
1020      } elsif ($type =~ /time_t/i) {
1021	$dataType = 'ADT_DATE';
1022	$dataSize = "sizeof (time_t)";
1023	$xlateLine = "{{$dataType, $dataSize}}";
1024	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
1025      } elsif ($type =~ /termid/i) {
1026	$dataType = 'ADT_TERMIDSTAR';
1027	$dataSize = "sizeof (au_tid_addr_t *)";
1028	$xlateLine = "{{$dataType, $dataSize}}";
1029	push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]);
1030      } elsif ($omitJNI) {
1031	$xlateLabelRef = 'NULL';
1032      } else {
1033	print STDERR "$type is not an implemented data type\n";
1034	$xlateLabelRef = 'NULL';
1035      }
1036      $xlateLabelRef = '&' . $xlateLabel . '[0]'
1037	unless $xlateLabelRef eq 'NULL';
1038
1039      # "EOL" is where a comma should go unless end of list
1040      $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" .
1041	  "\t\t0,\t$required,\t$tsol,\t$format}EOL";
1042
1043    } else {	# is a list
1044      my @type = split(/,/, $type);
1045      my @arraySize = ();
1046      my @id   = split(/,/, $id);
1047      my @jniId  = @id;
1048      my $dataType;
1049      my $typeCount = ($#type + 1);
1050      my @xlateType = ();
1051      my @default = ();
1052
1053      foreach my $dtype (@type) {
1054	my $jniId = shift @jniId;
1055	my $id = shift @id;
1056	my $arraySize = '';
1057	$arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/);
1058
1059	my $entryType = ${$entryDef{$dtype}}[0];
1060	if ($entryType) {
1061	  my $type = $dtype;
1062	  $type =~ s/([^*]+)\s*(\*+)/$1 $2/;
1063	  $type =~ s/\[\]//;
1064
1065	  my $sizeString = "sizeof";
1066	  $sizeString = "$arraySize * " . $sizeString if $arraySize;
1067	  push (@xlateType, "\{$entryType, $sizeString ($type)\}");
1068	  push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
1069	} elsif ($type =~ /^msg/i) {
1070	  $type =~ s/^msg//i;
1071	  $dataType = 'ADT_MSG';
1072	  my $dataEnum = 'ADT_LIST_' . uc $type;
1073	  push (@xlateType, "\{$dataType, $dataEnum\}};");
1074	  push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
1075	} elsif ($type =~ /time_t/i) {
1076	  $dataType = 'ADT_DATE';
1077	  push (@xlateType, "\{$entryType, sizeof ($type)\}");
1078	  push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]);
1079	} elsif ($type =~ /termid/i) {
1080	  $dataType = 'ADT_TERMIDSTAR';
1081	  push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}");
1082	  push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]);
1083	} elsif ($omitJNI) {
1084	  # nothing to do.
1085	} else {
1086	  print STDERR "$dtype is not an implemented data type\n";
1087	}
1088	if (${$entryDef{$dtype}}[1]) {
1089	  push (@default, $id, ${$entryDef{$dtype}}[1]);
1090	}
1091      }
1092      my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};";
1093
1094      $xlateLine =
1095	"{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" .
1096        "\t\t0,\t$required,\t$tsol,\t$format}EOL";
1097    }
1098    $xlateUniLabelInc++ if $xlateLabelInc;
1099    return ($xlateLine, \@jniLine);
1100}
1101
1102sub generateMsgLists {
1103    my $textList = shift;
1104
1105    my $textName = $textList->getId();
1106    my $header = $textList->getHeader();
1107    my $start = $textList->getMsgStart();
1108    my $public = $textList->getMsgPublic();
1109    my $deprecated = $textList->getDeprecated();
1110
1111    print "$textName starts at $start\n" if $debug;
1112
1113    my $entry;
1114    my @entry;
1115    while ($entry = $textList->getNextMsg()) {
1116        if ($debug) {
1117	    my ($id, $text) = split(/\s*::\s*/, $entry);
1118	    print "   $id = $text\n";
1119	}
1120	unshift (@entry, $entry);
1121    }
1122    $msg_list{$textName} =
1123	[\@entry, [$header, $start, $public, $deprecated]];
1124}
1125sub readAuditEventFile {
1126    my $eventListFile = shift;
1127
1128  open(Event, $eventListFile)
1129    or die "can't open $eventListFile: $!\n";
1130  while(<Event>) {
1131    next if /^\s*#/;
1132    next if /^\s*$/;
1133    my ($value, $name) = split(/\s*:\s*/);
1134    next if $value < 6000;
1135    $eventCode{$name} = $value;
1136  }
1137  close Event;
1138}
1139