#!/usr/perl5/bin/perl -w # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # # auditxml_jni [-d] <xml input file> # auditxml takes the audit record description (.xml file) and # generates the files needed for the Java use auditxml; use Getopt::Std; use vars qw($opt_d); use strict; our $debug = 0; # normal use is to set via the file being parsed. # <debug set="on"/> or <debug set="off"/> or <debug/> # if the set attribute is omitted, debug state is toggled # Override with appDebug, but toggle won't do what you # want. my $appDebug = 0; # used after return from "new auditxml"; my $genNotice = " DO NOT EDIT. This file is auto generated by the Solaris Audit system from adt.xml. See http://opensolaris.org/os/project/audit/ "; # trim leading/trailing newlines $genNotice =~ s/^\n//s; $genNotice =~ s/\n$//s; my $prog = $0; $prog =~ s|.*/||g; my $usage = "usage: $prog [-d] file.xml\n"; getopts('d'); $appDebug = $opt_d; my $uniLabel = "adr"; my $xlateUniLabelInc = 0; die $usage if ($#ARGV < 0); # where everything comes from and where it goes: my $templatePath = './'; my $javaPath = $templatePath; my $bsmBuildPath = "../libbsm"; my $jniBuildPath = "$javaPath"; my $buildPathJ = "$jniBuildPath/com/sun/audit"; my $buildPathJNI = "$jniBuildPath/common"; my $auditEventJ = "$buildPathJ/AuditEvent.java"; my $jniC = "$buildPathJNI/adt_jni_event.c"; my $mapFile = "$jniBuildPath/common/mapfile-vers"; my $doc = new auditxml ($ARGV[0]); # input XML file $debug = $appDebug; my %jniEventTable = (); my %externalIdNo = (); my %msg_list = (); my %eventCode = (); readAuditEventFile("$bsmBuildPath/audit_event.txt"); my $event; while ($event = $doc->getNextEvent()) { my $eventId = $event->getId(); my $idNo = $event->getIdNo(); $externalIdNo{$eventId} = $idNo; my $super; my $omit = $event->getOmit(); my $eventType = ''; if ($super = $event->getSuperClass()) { $event = $super; $eventType = 'instance'; } else { $eventType = $event->getType(); } # c file table for translation generateTableC($event, $eventId, $eventType, undef, $omit); } while (my $textList = $doc->getNextMsgId()) { generateMsgLists($textList); # enum -> text mappings } printJavaFiles($jniC, $auditEventJ, $buildPathJ, $mapFile); exit 0; sub printJavaFiles { my $jniFile = shift; my $javaFile = shift; my $subclassPath = shift; my $mapFile = shift; # warning: time_t is equated to jlong since there is no # way to use sys/types.h in Java code. # java long is C long long, 64 bits. # java int is 32 bits. my %java_jni = ('ADT_DATE' => ['long', 'jlong'], 'ADT_UINT' => ['int', 'jint'], 'ADT_INT' => ['int', 'jint'], 'ADT_INT32' => ['int', 'jint'], 'ADT_UID' => ['int', 'jint'], 'ADT_GID' => ['int', 'jint'], 'ADT_UIDSTAR' => ['int[]', 'jintArray'], 'ADT_GIDSTAR' => ['int[]', 'jintArray'], 'ADT_CHAR' => ['String', 'jchar'], 'ADT_CHARSTAR' => ['String', 'jstring'], 'ADT_CHAR2STAR' => ['String[]', 'jstring'], 'ADT_MSG' => ['int', 'jint'], 'ADT_PID' => ['int', 'jint'], # ADT_PRIVSTAR omitted -- not implemented and the audit records that # use it must be coded to emit no java. We'll cross that bridge # when someone in Java land needs to generate a priv token. 'ADT_LONG' => ['int', 'jint'], 'ADT_TERMIDSTAR' => ['String', 'jstring'], # hostname -> termid 'ADT_ULONG' => ['int', 'jint'], 'ADT_UINT16' => ['int', 'jint'], 'ADT_UINT32' => ['int', 'jint'], 'ADT_UINT32STAR' => ['int[]', 'jintArray'], # ADT_UINT32ARRAY omitted; no Java implementation yet 'ADT_UINT64' => ['long', 'jlong'], 'ADT_UINT64STAR' => ['long[]', 'jlongArray'] ); my $noMemory = 'gettext("Out of memory")'; # open output files open (Cfile, ">$jniFile") or die "can't open output file ($jniFile): $!\n"; open (Jfile, ">$javaFile") or die "can't open output file ($javaFile): $!\n"; open (MapFile, ">$mapFile") or die "can't open output file ($mapFile): $!\n"; # write headers my $notice = $genNotice; $notice =~ s/\n/\n * /gs; $notice =~ s/\s+\n/\n/gs; print Cfile <<EOF; /* * $notice */ #include "../../libbsm/common/adt_xlate.h" #include <jni.h> #include "../com/sun/audit/AuditSession.h" /* javah output */ #include "adt_jni.h" #include <stdlib.h> #include <string.h> static char *except_class = "java/lang/Exception"; EOF print Jfile <<EOF; /* * $notice */ package com.sun.audit; public class AuditEvent { protected AuditSession sh; // associated session object public AuditEvent(AuditSession auSession) throws Error { sh = auSession; } // See the subclasses of AuditEvent for mapping message codes // to events EOF my $notice_map = $genNotice; $notice_map =~ s/\n/\n# /gs; $notice_map =~ s/\s+\n/\n/gs; print MapFile <<EOF; # # $notice_map # SUNWprivate_1.1 { global: c2j_pointer; j2c_pointer; Java_com_sun_audit_AuditSession_bsmAuditOn; Java_com_sun_audit_AuditSession_startSession; Java_com_sun_audit_AuditSession_endSession; Java_com_sun_audit_AuditSession_dupSession; Java_com_sun_audit_AuditSession_getSessionId; Java_com_sun_audit_AuditSession_exportSessionData; Java_com_sun_audit_AuditSession_sessionAttr; # One subclass of AuditEvent per audit record... EOF # generate java final int classes to line up with string/enums foreach my $listName (sort keys %msg_list) { my $shortName = uc $listName; $shortName =~ s/_TEXT//; my ($listRef, $headref) = @{$msg_list{$listName}}; my @listValue = @$listRef; my ($header, $enumValue, $public, $deprecated) = @$headref; my $listValue; print Jfile "\n\t// adt_$listName" . "\n\n"; print Jfile "\tpublic static final int ADT_$shortName", " = $enumValue;\n" if $enumValue; next unless ($#listValue >= 0); print Jfile "\t// Deprecated message list\n" if $deprecated; foreach $listValue (@listValue) { my ($id, $text) = split(/\s*::\s*/, $listValue); print Jfile "\t// $text\n"; print Jfile "\tpublic static final int ADT_$shortName"; print Jfile "_$id = $enumValue;\n"; $enumValue++; } } # generate event creation and access functions and event # generation for both Java and JNI # com.sun.audit.AuditEvent_xxx.java foreach my $eventId (sort keys %jniEventTable) { my ($ref1, $eventType, $allowedIds, $header) = @{$jniEventTable{$eventId}}; $eventCode{$eventId} = -1 if ($eventType eq 'generic'); my @entries = @$ref1; my $entries = $#entries; my $root = $eventId; $root =~ s/AUE_//; my $javaPutEvent = 'putEvent'; my $putMethod = "_$root"; $putMethod =~ s/_/_1/g; my $jniPutEvent = "Java_com_sun_audit_AuditEvent$putMethod" . "_$javaPutEvent"; # the subclass file template isn't used; it may be needed to get # the right file header stuff in place. The subclassPath is # the directory that contains 'em. my $validSfile = 1; unless (open(Sfile, ">$subclassPath/AuditEvent_$root.java")) { print STDERR "can't open class file AuditEvent_$root.java: $!\n"; $validSfile = 0; } if ($eventCode{"AUE_$root"}) { if ($validSfile) { print Sfile <<EOF; /* * $notice */ package com.sun.audit; // audit event: $eventId = $eventCode{"AUE_$root"} public class AuditEvent_$root extends AuditEvent { EOF } } else { print STDERR "no event code for $eventId. Is audit_event current?\n"; } my $nativeParameterList = ''; my $jniParameterList = ''; my $specParameterList = ''; my $jniStorageList = ''; my $needCleanupTarget = 0; my $jniFreeList = ''; my $haveStringDef = 0; my $haveCDef = 0; my $haveLengthDef = 0; my $haveStringArrayDef = 0; my $cntTermidDef = 0; my $jniDefine; my $needLocaleDefined = 0; my $jniADTalloc; if (defined $header && ($header > 0) ) { $jniDefine = "union union_of_events *event;\n" . "\tadt_session_data_t *session;\n"; $jniADTalloc = '(union union_of_events *)adt_alloc_event'; } else { $jniDefine = "adt_event_data_t *event;\n" . "\tadt_session_data_t *session;\n"; $jniADTalloc = 'adt_alloc_event'; } my $ref2; foreach $ref2 (@entries) { my ($id, $type) = @$ref2; my $jniRoot = $root . $id; $jniRoot =~ s/_/_1/g; # escape unicode "_" my $p_event; if (defined $header && ($header > 0) ) { $p_event = "event->d$header.adt_$root.$id"; } else { $p_event = "event->adt_$root.$id"; } if ($type eq 'ADT_UINT32STAR') { # int array $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ length = (*env)->GetArrayLength(env, $id); $p_event = (int *)malloc(length * sizeof (int)); if ($p_event == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); goto cleanup; } (*env)->GetIntArrayRegion(env, $id, 0, length, (int *)$p_event); EOF $jniFreeList .= "\n\tif ($p_event != NULL)\n" . "\t\tfree($p_event);\n"; unless ($haveLengthDef) { $haveLengthDef = 1; $jniDefine .= "\tint\t\t\tlength;\n"; } $nativeParameterList .= ",\n\t int[]\t$id"; $jniParameterList .= ",\n jintArray\t$id"; $specParameterList .= ", jintArray"; $needCleanupTarget = 1; } elsif (($type eq 'ADT_UIDSTAR') || ($type eq 'ADT_GIDSTAR')) { # gid_t array my $cType = 'uid_t'; $cType = 'gid_t' if ($type eq 'ADT_GIDSTAR'); $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ length = (*env)->GetArrayLength(env, $id); $p_event = ($cType *)malloc(length * sizeof ($cType)); if ($p_event == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); goto cleanup; } (*env)->GetIntArrayRegion(env, $id, 0, length, (int *)$p_event); EOF $jniFreeList .= "\n\tif ($p_event != NULL)\n" . "\t\tfree($p_event);\n"; unless ($haveLengthDef) { $haveLengthDef = 1; $jniDefine .= "\tint\t\t\tlength;\n"; } $nativeParameterList .= ",\n\t int[]\t$id"; $jniParameterList .= ",\n jintArray\t$id"; $specParameterList .= ", jintArray"; $needCleanupTarget = 1; } elsif ($type eq 'ADT_UINT64STAR') { # long array $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ length = (*env)->GetArrayLength(env, $id); $p_event = (long *)malloc(length * sizeof (long long)); if ($p_event == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); goto cleanup; } (*env)->GetLongArrayRegion(env, $id, 0, length, $p_event); EOF $jniFreeList .= "\n\tif ($p_event != NULL)\n" . "\t\tfree($p_event);\n"; unless ($haveLengthDef) { $haveLengthDef = 1; $jniDefine .= "\tint\t\t\tlength;\n"; } $nativeParameterList .= ",\n\t long[]\t$id"; $jniParameterList .= ",\n jlongArray\t$id"; $specParameterList .= ", jlongArray"; $needCleanupTarget = 1; } elsif ($type eq 'ADT_CHAR') { # string in Java, char in C $jniStorageList .= <<EOF; /* $id */ c = (char *)(*env)->GetStringUTFChars(env, $id, NULL); if (c == NULL) goto cleanup; /* exception thrown */ $p_event = *c; (*env)->ReleaseStringUTFChars(env, $id, c); EOF # no need to free anything unless ($haveCDef) { $haveCDef = 1; $jniDefine .= "\tchar\t\t\t*c\n"; } $nativeParameterList .= ",\n\t String\t$id"; $jniParameterList .= ",\n jstring\t$id"; $specParameterList .= ", jstring"; } elsif ($type eq 'ADT_CHARSTAR') { $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ if ($id != NULL) { string = (char *)(*env)->GetStringUTFChars( env, $id, NULL); if (string == NULL) goto cleanup; /* exception thrown */ $p_event = strdup(string); (*env)->ReleaseStringUTFChars(env, $id, string); if ($p_event == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); goto cleanup; } } EOF $jniFreeList .= "\n\tif ($p_event != NULL)\n" . "\t\tfree($p_event);\n"; unless ($haveStringDef) { $haveStringDef = 1; $jniDefine .= "\tchar\t\t\t*string;\n"; } $nativeParameterList .= ",\n\t String\t$id"; $jniParameterList .= ",\n jstring\t$id"; $specParameterList .= ", jstring"; $needCleanupTarget = 1; } elsif ($type eq 'ADT_CHAR2STAR') { # array of string $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ length = (*env)->GetArrayLength(env, $id); $p_event = (char **)malloc(length * sizeof (char *)); if ($p_event == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); goto cleanup; } p = $p_event; for (i = 0; i < length; i++) { jString = (*env)->GetObjectArrayElement(env, $id, i); string = (char *)(*env)->GetStringUTFChars( env, jString, NULL); if (string == NULL) goto cleanup; /* exception thrown */ *p = strdup(string); (*env)->ReleaseStringUTFChars(env, jString, string); if (*p == NULL) { locale = I18N_SETUP; local_throw(env, except_class, $noMemory); (void) setlocale(LC_MESSAGES, locale); while (p >= $p_event) free(*p--); goto cleanup; } p++; } EOF $jniFreeList .= "\n\tif ($p_event != NULL)\n" . "\t\tfree($p_event);\n"; unless ($haveStringArrayDef) { unless ($haveStringDef) { $haveStringDef = 1; $jniDefine .= <<EOF; char *string; EOF } unless ($haveLengthDef) { $haveLengthDef = 1; $jniDefine .= <<EOF; int length; EOF } $haveStringArrayDef = 1; $jniDefine .= <<EOF; int i; char **p; jstring jString; EOF } $nativeParameterList .= ",\n\t String[]\t$id"; $jniParameterList .= ",\n jstring\t$id"; $specParameterList .= ", jstring"; $needCleanupTarget = 1; } elsif ($type eq 'ADT_TERMIDSTAR') { $needLocaleDefined = 1; $jniStorageList .= <<EOF; /* $id */ hostname$cntTermidDef = (char *)(*env)->GetStringUTFChars(env, $id, NULL); if (adt_load_hostname((const char *)hostname$cntTermidDef, &termid$cntTermidDef)) { local_throw(env, except_class, gettext("hostname lookup failed")); } $p_event = termid$cntTermidDef; (*env)->ReleaseStringUTFChars(env, $id, hostname$cntTermidDef); EOF $jniFreeList .= "\n\tif (hostname$cntTermidDef != NULL)\n" . "\t\tfree(hostname$cntTermidDef);\n"; $jniFreeList .= "\n\tif (termid$cntTermidDef != NULL)\n" . "\t\tfree(termid$cntTermidDef);\n"; $jniDefine .= "\tchar\t\t\t*hostname$cntTermidDef;\n"; $jniDefine .= "\tadt_termid_t\t\t*termid$cntTermidDef;\n"; #djdj $cntTermidDef++; my ($nativeParameter, $jniParameter) = @{$java_jni{$type}}; $nativeParameterList .= ",\n\t $nativeParameter\t$id"; $jniParameterList .= ",\n $jniParameter\t$id"; $specParameterList .= ", $jniParameter"; $needCleanupTarget = 1; } else { # all others are primitive types $jniStorageList .= "\n\t$p_event = $id;\n"; my ($nativeParameter, $jniParameter) = @{$java_jni{$type}}; $nativeParameter = "$nativeParameter\t" if length $nativeParameter < 4; # why? $nativeParameterList .= ",\n\t $nativeParameter\t$id"; $jniParameterList .= ",\n $jniParameter\t$id"; $specParameterList .= ", $jniParameter"; } } if ($needLocaleDefined) { $jniDefine .= <<EOF char *locale; EOF } my $genericOverride = ''; my $idParameter = $eventId; $idParameter =~ s/AUE_/ADT_/; if ($eventType eq 'generic') { $genericOverride = ', jint eventId'; $idParameter = 'eventId'; } $jniFreeList = "\tcleanup:\n" . $jniFreeList if $needCleanupTarget; print Cfile qq{/* ARGSUSED */ JNIEXPORT void JNICALL $jniPutEvent( JNIEnv *env, jobject self, jbyteArray jsession$genericOverride, jint status, jint ret_val$jniParameterList) { $jniDefine (void) j2c_pointer(env, jsession, (char **)&session); event = $jniADTalloc(session, $idParameter); $jniStorageList (void) adt_put_event((adt_event_data_t *)event, status, ret_val); $jniFreeList adt_free_event((adt_event_data_t *)event); } }; print MapFile qq{ $jniPutEvent; }; my $overrideParameter = ''; if ($eventType eq 'generic') { $overrideParameter = 'int eventId,'; my @allowed = @$allowedIds; if (@allowed) { my $i; if ($validSfile) { print Sfile "\t// Allowed values for eventId in putEvent:\n"; for ($i = 0; $i <= $#allowed; $i++) { my $idNo = $externalIdNo{$allowed[$i]}; $allowed[$i] =~ s/AUE_/ADT_/; print Sfile "\tstatic final int $allowed[$i] = ", "$idNo;\n"; } print Sfile "\n"; } } else { print STDERR "Generic event with no allowed instances: $eventId\n"; } } if ($validSfile) { print Sfile <<EOF; private native void $javaPutEvent(byte[]session, $overrideParameter int status, int ret_val$nativeParameterList); public AuditEvent_$root(AuditSession session) throws Exception { super(session); } EOF my $javaParameterList = ''; foreach $ref2 (@entries) { my ($id, $type, $format, $jComment, $required) = @$ref2; # generate java native method prototypes # and the corresponding C method implementation my $javaMethodName = "$id"; my $javaStorageName = $javaMethodName . '_val'; my $jniMethodName = $root . $id; my $storage; my $enumUsage = ''; my $jParam = @{$java_jni{$type}}[0]; my $comment = ''; if ($required) { if ($format ne 'NULL') { $comment = "\t// (required) formatted: $format"; } else { $comment = "\t// required"; } } else { if ($format ne 'NULL') { $comment = "\t// (optional) formatted: $format"; } else { $comment = "\t// optional"; } } if (($type eq 'ADT_UINT32STAR') || ($type eq 'ADT_UIDSTAR') || ($type eq 'ADT_GIDSTAR')) { # int array $storage = "int[] $javaStorageName" . ($required ? ' = {}' : ''); $javaParameterList .= ",\n\t\t\t $javaStorageName"; } elsif ($type eq 'ADT_UINT64STAR') { # long array $storage = "long[] $javaStorageName" . ($required ? ' = {}' : ''); $javaParameterList .= ",\n\t\t\t $javaStorageName"; } elsif (($type eq 'ADT_CHARSTAR') || ($type eq 'ADT_CHAR')) { # string $storage = "String $javaStorageName" . ($required ? ' = ""' : ''); $javaParameterList .= ",\n\t\t\t $javaStorageName"; } elsif ($type eq 'ADT_CHAR2STAR') { # array of string $storage = "String[] $javaStorageName" . ($required ? ' = {}' : ''); $javaParameterList .= ",\n\t\t\t $javaStorageName"; } elsif ($type eq 'ADT_TERMIDSTAR') { # array of string $storage = "String $javaStorageName" . ($required ? ' = ""' : ''); $javaParameterList .= ",\n\t\t\t $javaStorageName"; } else { # all others are primitive types $storage = "$jParam $javaStorageName = 0"; $javaParameterList .= ",\n\t\t\t $javaStorageName"; $enumUsage = "\n\t// See $jComment in AuditEvent.java for valid values" if $jComment; } print Sfile <<EOF; $enumUsage private $storage;$comment public void $javaMethodName($jParam setTo) { $javaStorageName = setTo; } EOF } # end foreach (@entries) if ($eventType eq 'generic') { print Sfile <<EOF; public void putEvent(int status, int ret_val, int eventId) { byte[] session = super.sh.getSession(); if ((super.sh.AuditIsOn) && (super.sh.ValidSession)) $javaPutEvent(session, eventId, status, ret_val$javaParameterList); } } EOF } else { print Sfile <<EOF; public void putEvent(int status, int ret_val) { byte[] session = super.sh.getSession(); if ((super.sh.AuditIsOn) && (super.sh.ValidSession)) $javaPutEvent(session, status, ret_val$javaParameterList); } } EOF } close Sfile; } # end if ($validSfile); } # write trailers print Jfile <<EOF; } EOF print MapFile <<EOF; local: *; }; EOF close Cfile; close Jfile; close MapFile; } sub generateTableC { my $event = shift; my $eventId = shift; my $eventType = shift; my $eventHeader = shift; my $omit = shift; my %tokenType = ( 'acl' => 'AUT_ACL', 'arbitrary' => 'AUT_ARBITRARY', 'arg' => 'AUT_ARG', 'attr' => 'AUT_ATTR', 'command' => 'AUT_CMD', 'command_1' => 'ADT_CMD_ALT', # dummy token id 'date' => 'AUT_TEXT', 'exec_args' => 'AUT_EXEC_ARGS', 'exec_env' => 'AUT_EXEC_ENV', 'exit' => 'AUT_EXIT', 'file' => 'AUT_FILE', 'fmri' => 'AUT_FMRI', 'groups' => 'AUT_GROUPS', # 'header' => 'AUT_HEADER', # not used 'in_addr' => 'AUT_IN_ADDR', 'tid' => 'AUT_TID', 'ipc' => 'AUT_IPC', 'ipc_perm' => 'AUT_IPC_PERM', 'iport' => 'AUT_IPORT', 'label' => 'AUT_LABEL', 'newgroups' => 'AUT_NEWGROUPS', 'opaque' => 'AUT_OPAQUE', 'path' => 'AUT_PATH', 'path_list' => '-AUT_PATH', # dummy token id 'process' => 'AUT_PROCESS', 'priv_effective' => 'ADT_AUT_PRIV_E', # dummy token id 'priv_limit' => 'ADT_AUT_PRIV_L', # dummy token id 'priv_inherit' => 'ADT_AUT_PRIV_I', # dummy token id 'return' => 'AUT_RETURN', 'seq' => 'AUT_SEQ', 'socket' => 'AUT_SOCKET', 'socket-inet' => 'AUT_SOCKET_INET', 'subject' => 'AUT_SUBJECT', 'text' => 'AUT_TEXT', # 'trailer' => 'AUT_TRAILER', # not used 'uauth' => 'AUT_UAUTH', 'zonename' => 'AUT_ZONENAME' ); my @xlateEntryList = (); my @jniEntryList = (); my $external = $event->getExternal(); my $internal = $event->getInternal(); unless ($external) { print STDERR "No external object captured for event $eventId\n"; return; } unless ($internal) { print STDERR "No internal object captured for event $eventId\n"; return; } my @entryRef = $internal->getEntries(); my $entryRef; my @tokenOrder = (); my $firstTokenIndex = 0; # djdj not used yet, djdj BUG! # needs to be used by translate table if ($internal->isReorder()) { # prescan the entry list to get the token order my @inputOrder; foreach $entryRef (@entryRef) { my ($intEntry, $entry) = @$entryRef; push (@inputOrder, $intEntry->getAttr('order')); } my $i; # walk down the inputOrder list once my $k = 1; # discover next in line my $l = 0; # who should point to next in line for ($i = 0; $i <= $#inputOrder; $i++) { my $j; for ($j = 0; $j <= $#inputOrder; $j++) { if ($k == $inputOrder[$j]) { if ($k == 1) { $firstTokenIndex = $j; } else { $tokenOrder[$l] = "&(selfReference[$j])"; } $l = $j; last; } } $k++; } $tokenOrder[$l] = 'NULL'; } else { # default order -- input order same as output my $i; my $j; for ($i = 0; $i < $#entryRef; $i++) { my $j = $i + 1; $tokenOrder[$i] = "&(selfReference[$j])"; } $tokenOrder[$#entryRef] = 'NULL'; } my $sequence = 0; foreach $entryRef (@entryRef) { my ($intEntry, $entry) = @$entryRef; my $entryId = $entry->getAttr('id'); my ($extEntry, $unusedEntry, $tokenId) = $external->getEntry($entryId); my $opt = $extEntry->getAttr('opt'); if ($opt eq 'none') { if (defined ($doc->getToken($tokenId))) { if (defined ($tokenType{$tokenId})) { $tokenId = $tokenType{$tokenId}; } else { print STDERR "token id $tokenId not implemented\n"; } } else { print STDERR "token = $tokenId is undefined\n"; $tokenId = 'error'; } my ($xlate, $jni) = formatTableEntry ('', $tokenId, $eventId, '', 0, 0, $tokenOrder[$sequence], 'NULL', ''); push (@xlateEntryList, $xlate); push (@jniEntryList, @$jni); } else { my $dataType = $extEntry->getAttr('type'); $dataType =~ s/\s+//g; # remove blanks (char * => char*) my $enumGroup = ''; if ($dataType =~ /^msg/i) { $enumGroup = $dataType; $enumGroup =~ s/^msg\s*//i; $enumGroup = 'adt_' . $enumGroup; } my $required = ($opt eq 'required') ? 1 : 0; my $tsol = 0; my $tokenId = $intEntry->getAttr('token'); my $token; my $tokenName; my $tokenFormat = $intEntry->getAttr('format'); if (defined ($tokenFormat)) { $tokenFormat = "\"$tokenFormat\""; } else { $tokenFormat = 'NULL'; } if (defined ($token = $doc->getToken($tokenId))) { $tsol = (lc $token->getUsage() eq 'tsol') ? 1 : 0; if (defined ($tokenType{$tokenId})) { $tokenName = $tokenType{$tokenId}; } else { print STDERR "token id $tokenId not implemented\n"; } } else { print STDERR "$tokenId is an unimplemented token ($entryId in $eventId)\n"; $tokenName = 'AUT_TEXT'; } my ($xlate, $jni) = formatTableEntry($entryId, $tokenName, $eventId, $dataType, $required, $tsol, $tokenOrder[$sequence], $tokenFormat, $enumGroup, (uc $omit eq 'JNI')); push (@xlateEntryList, $xlate); push (@jniEntryList, @$jni); } $sequence++; } $jniEventTable{$eventId} = [\@jniEntryList, $eventType, $external->getAllowedTypes(), $eventHeader] unless (uc $omit eq 'JNI') || ($omit eq 'always'); } sub formatTableEntry { my ($id, $token, $eventId, $type, $required, $tsol, $sequence, $format, $enumGroup, $omitJNI) = @_; # does this map belong in the xml source? (at least the defaults?) # fill in the default value only if it is other than zero. # base type adt name, default value my %entryDef = ( 'au_asid_t' => ['ADT_UINT32', ''], 'uint_t' => ['ADT_UINT32', ''], 'int' => ['ADT_INT', ''], 'int32_t' => ['ADT_INT32', ''], 'uid_t' => ['ADT_UID', 'AU_NOAUDITID'], 'gid_t' => ['ADT_GID', 'AU_NOAUDITID'], 'uid_t*' => ['ADT_UIDSTAR', ''], 'gid_t*' => ['ADT_GIDSTAR', ''], 'char' => ['ADT_CHAR', ''], 'char*' => ['ADT_CHARSTAR', ''], 'char**' => ['ADT_CHAR2STAR', ''], 'long' => ['ADT_LONG', ''], 'pid_t' => ['ADT_PID', ''], 'priv_set_t*' => ['ADT_PRIVSTAR', ''], 'ulong_t' => ['ADT_ULONG', ''], 'uint16_t', => ['ADT_UINT16', ''], 'uint32_t' => ['ADT_UINT32', ''], 'uint32_t*' => ['ADT_UINT32STAR', ''], 'uint32_t[]' => ['ADT_UINT32ARRAY', ''], 'uint64_t' => ['ADT_UINT64', ''], 'uint64_t*' => ['ADT_UINT64STAR', ''], 'm_label_t*' => ['ADT_MLABELSTAR', ''], ); my $xlateLabel = $uniLabel.$xlateUniLabelInc; my $xlateLabelInc = 0; my $xlateLine = ''; my @jniLine = (); # the list handling should be a simple loop with a loop of one # falling out naturally. unless ($type =~ /,/) { # if list, then generate sequence of entries my $dataType; my $dataSize; my $xlateLabelRef = ''; my $arraySize = ''; $arraySize = $1 if ($type =~ s/\[(\d+)\]/[]/); my $entryType = ${$entryDef{$type}}[0]; my @xlateType = (); # for adt_xlate.c my $typeCount = 1; if ($entryType) { $dataType = $entryType; $type =~ s/([^*]+)\s*(\*+)/$1 $2/; $type =~ s/\[\]//; $dataSize = "sizeof ($type)"; if ($arraySize) { $dataSize = "$arraySize * " . $dataSize; } $xlateLine = "{{$dataType, $dataSize}}"; push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); } elsif ($type eq '') { $xlateLabelRef = 'NULL'; } elsif ($type =~ /^msg/i) { $type =~ s/^msg//i; $dataType = 'ADT_MSG'; my $dataEnum = 'ADT_LIST_' . uc $type; $xlateLine = "{{$dataType, $dataEnum}}"; push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); } elsif ($type =~ /time_t/i) { $dataType = 'ADT_DATE'; $dataSize = "sizeof (time_t)"; $xlateLine = "{{$dataType, $dataSize}}"; push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); } elsif ($type =~ /termid/i) { $dataType = 'ADT_TERMIDSTAR'; $dataSize = "sizeof (au_tid_addr_t *)"; $xlateLine = "{{$dataType, $dataSize}}"; push (@jniLine, [$id, $dataType, $format, $enumGroup, $required]); } elsif ($omitJNI) { $xlateLabelRef = 'NULL'; } else { print STDERR "$type is not an implemented data type\n"; $xlateLabelRef = 'NULL'; } $xlateLabelRef = '&' . $xlateLabel . '[0]' unless $xlateLabelRef eq 'NULL'; # "EOL" is where a comma should go unless end of list $xlateLine = "{$token,\t1,\t$xlateLabelRef,\t$sequence,\n" . "\t\t0,\t$required,\t$tsol,\t$format}EOL"; } else { # is a list my @type = split(/,/, $type); my @arraySize = (); my @id = split(/,/, $id); my @jniId = @id; my $dataType; my $typeCount = ($#type + 1); my @xlateType = (); my @default = (); foreach my $dtype (@type) { my $jniId = shift @jniId; my $id = shift @id; my $arraySize = ''; $arraySize = $1 if ($dtype =~ s/\[(\d+)\]/[]/); my $entryType = ${$entryDef{$dtype}}[0]; if ($entryType) { my $type = $dtype; $type =~ s/([^*]+)\s*(\*+)/$1 $2/; $type =~ s/\[\]//; my $sizeString = "sizeof"; $sizeString = "$arraySize * " . $sizeString if $arraySize; push (@xlateType, "\{$entryType, $sizeString ($type)\}"); push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); } elsif ($type =~ /^msg/i) { $type =~ s/^msg//i; $dataType = 'ADT_MSG'; my $dataEnum = 'ADT_LIST_' . uc $type; push (@xlateType, "\{$dataType, $dataEnum\}};"); push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); } elsif ($type =~ /time_t/i) { $dataType = 'ADT_DATE'; push (@xlateType, "\{$entryType, sizeof ($type)\}"); push (@jniLine, [$jniId, $entryType, $format, $enumGroup, $required]); } elsif ($type =~ /termid/i) { $dataType = 'ADT_TERMIDSTAR'; push (@xlateType, "\{$dataType, sizeof (au_tid_addr_t *)\}"); push (@jniLine, [$jniId, $dataType, $format, $enumGroup, $required]); } elsif ($omitJNI) { # nothing to do. } else { print STDERR "$dtype is not an implemented data type\n"; } if (${$entryDef{$dtype}}[1]) { push (@default, $id, ${$entryDef{$dtype}}[1]); } } my $xlateArray = "\[$typeCount\] =\t{" . join(",\n\t\t\t\t", @xlateType) . "};"; $xlateLine = "{$token,\t$typeCount,\t&$xlateLabel\[0\],\t$sequence,\n" . "\t\t0,\t$required,\t$tsol,\t$format}EOL"; } $xlateUniLabelInc++ if $xlateLabelInc; return ($xlateLine, \@jniLine); } sub generateMsgLists { my $textList = shift; my $textName = $textList->getId(); my $header = $textList->getHeader(); my $start = $textList->getMsgStart(); my $public = $textList->getMsgPublic(); my $deprecated = $textList->getDeprecated(); print "$textName starts at $start\n" if $debug; my $entry; my @entry; while ($entry = $textList->getNextMsg()) { if ($debug) { my ($id, $text) = split(/\s*::\s*/, $entry); print " $id = $text\n"; } unshift (@entry, $entry); } $msg_list{$textName} = [\@entry, [$header, $start, $public, $deprecated]]; } sub readAuditEventFile { my $eventListFile = shift; open(Event, $eventListFile) or die "can't open $eventListFile: $!\n"; while(<Event>) { next if /^\s*#/; next if /^\s*$/; my ($value, $name) = split(/\s*:\s*/); next if $value < 6000; $eventCode{$name} = $value; } close Event; }