Home | History | Annotate | Download | only in libadt_jni
      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 
     32 use auditxml;
     33 use Getopt::Std;
     34 use vars qw($opt_d);
     35 use strict;
     36 
     37 
     38 our $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.
     43 my $appDebug = 0; # used after return from "new auditxml";
     44 
     45 my $genNotice = "
     46 DO NOT EDIT. This file is auto generated by the Solaris Audit
     47 system from adt.xml.
     48 
     49 See http://opensolaris.org/os/project/audit/
     50 ";
     51 
     52 # trim leading/trailing newlines
     53 $genNotice =~ s/^\n//s;
     54 $genNotice =~ s/\n$//s;
     55 my $prog = $0; $prog =~ s|.*/||g;
     56 my $usage = "usage: $prog [-d] file.xml\n";
     57 
     58 getopts('d');
     59 
     60 $appDebug = $opt_d;
     61 
     62 my $uniLabel = "adr";
     63 my $xlateUniLabelInc = 0;
     64 
     65 die $usage if ($#ARGV < 0);
     66 
     67 # where everything comes from and where it goes:
     68 
     69 my $templatePath = './';
     70 my $javaPath     = $templatePath;
     71 my $bsmBuildPath = "../libbsm";
     72 
     73 my $jniBuildPath = "$javaPath";
     74 
     75 my $buildPathJ	 = "$jniBuildPath/com/sun/audit";
     76 my $buildPathJNI = "$jniBuildPath/common";
     77 
     78 my $auditEventJ = "$buildPathJ/AuditEvent.java";
     79 my $jniC = "$buildPathJNI/adt_jni_event.c";
     80 my $mapFile = "$jniBuildPath/common/mapfile-vers";
     81 
     82 my $doc = new auditxml ($ARGV[0]);  # input XML file
     83 
     84 $debug = $appDebug;
     85 
     86 my %jniEventTable = ();
     87 my %externalIdNo = ();
     88 my %msg_list = ();
     89 my %eventCode = ();
     90 
     91 readAuditEventFile("$bsmBuildPath/audit_event.txt");
     92 
     93 my $event;
     94 while ($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 
    112 while (my $textList = $doc->getNextMsgId()) {
    113     generateMsgLists($textList);  # enum -> text mappings
    114 }
    115 
    116 printJavaFiles($jniC, $auditEventJ, $buildPathJ, $mapFile);
    117 
    118 exit 0;
    119 
    120 
    121 
    122 sub 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 
    185 static char *except_class = "java/lang/Exception";
    186 
    187 EOF
    188     print Jfile <<EOF;
    189 /*
    190  * $notice
    191  */
    192 
    193 package com.sun.audit;
    194 
    195 public 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
    213 EOF
    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 
    223 SUNWprivate_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...
    236 EOF
    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 
    295 package com.sun.audit;
    296 
    297 // audit event:  $eventId = $eventCode{"AUE_$root"}
    298 
    299 public class AuditEvent_$root extends AuditEvent {
    300 
    301 EOF
    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);
    361 EOF
    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);
    395 EOF
    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);
    425 EOF
    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);
    445 EOF
    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 	}
    473 EOF
    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 	}
    518 EOF
    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;
    527 EOF
    528 		    }
    529 		    unless ($haveLengthDef) {
    530 			$haveLengthDef = 1;
    531 			$jniDefine .= <<EOF;
    532 	int			length;
    533 EOF
    534 		    }
    535 		    $haveStringArrayDef = 1;
    536 		    $jniDefine .= <<EOF;
    537 	int			i;
    538 	char			**p;
    539 	jstring			jString;
    540 EOF
    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);
    560 EOF
    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;
    590 EOF
    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 */
    602 JNIEXPORT 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 
    655 EOF
    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 	}
    719 EOF
    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 }
    733 EOF
    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 }
    745 EOF
    746 	    }
    747 	    close Sfile;
    748 	}	# end if ($validSfile);
    749     }
    750  
    751     # write trailers
    752     print Jfile <<EOF;
    753 
    754 }
    755 EOF
    756     print MapFile <<EOF;
    757 
    758     local:
    759 	*;
    760 };
    761 EOF
    762     close Cfile;
    763     close Jfile;
    764     close MapFile;
    765 }
    766 
    767 sub 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 
    950 sub 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 
   1102 sub 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 }
   1125 sub 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