1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1998,2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * This file contains native methods for the Java SLP implementation.
29*7c478bd9Sstevel@tonic-gate  * So far this is just the syslog function.
30*7c478bd9Sstevel@tonic-gate  *
31*7c478bd9Sstevel@tonic-gate  * The file also contains two support functions, one for throwing exceptions
32*7c478bd9Sstevel@tonic-gate  * given a class name, and one for correctly converting unicode Strings to C
33*7c478bd9Sstevel@tonic-gate  * byte arrays.
34*7c478bd9Sstevel@tonic-gate  */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include <malloc.h>
37*7c478bd9Sstevel@tonic-gate #include <jni.h>
38*7c478bd9Sstevel@tonic-gate #include <syslog.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #define	CLASS_JAVA_LANG_OUTOFMEMORYERROR "java/lang/OutOfMemoryError"
41*7c478bd9Sstevel@tonic-gate #define	CLASS_JAVA_LANG_STRING "java/lang/String"
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate #define	METHOD_GETBYTES "getBytes"
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #define	SIG_JAVA_LANG_STRING_GETBYTES "()[B"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate /*
48*7c478bd9Sstevel@tonic-gate  * Given a class name of an exception and a message attempt to throw
49*7c478bd9Sstevel@tonic-gate  * a new instance of the exception.
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate static void
JNU_ThrowByName(JNIEnv * env,const char * name,const char * msg)52*7c478bd9Sstevel@tonic-gate JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg)
53*7c478bd9Sstevel@tonic-gate {
54*7c478bd9Sstevel@tonic-gate 	jclass class = (*env)->FindClass(env, name);
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 	/*
57*7c478bd9Sstevel@tonic-gate 	 * If class is NULL FindClass() encountered a problem locating the
58*7c478bd9Sstevel@tonic-gate 	 * desired class and has already called ThrowNew() with an
59*7c478bd9Sstevel@tonic-gate 	 * exception.
60*7c478bd9Sstevel@tonic-gate 	 */
61*7c478bd9Sstevel@tonic-gate 	if (class == NULL) {
62*7c478bd9Sstevel@tonic-gate 		return;
63*7c478bd9Sstevel@tonic-gate 	}
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	(*env)->ThrowNew(env, class, msg);
66*7c478bd9Sstevel@tonic-gate 	(*env)->DeleteLocalRef(env, class);
67*7c478bd9Sstevel@tonic-gate }
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*
70*7c478bd9Sstevel@tonic-gate  * Convert a Java String into a native set of characters using the
71*7c478bd9Sstevel@tonic-gate  * method String.getBytes(). This will ensure that the appropriate
72*7c478bd9Sstevel@tonic-gate  * character set encoding will be used. This is necessary if the
73*7c478bd9Sstevel@tonic-gate  * Java String uses unicode characters that cannot be easily
74*7c478bd9Sstevel@tonic-gate  * encoded into native chars.
75*7c478bd9Sstevel@tonic-gate  *
76*7c478bd9Sstevel@tonic-gate  * The buffer returned must be released by using free() once it is
77*7c478bd9Sstevel@tonic-gate  * finished with.
78*7c478bd9Sstevel@tonic-gate  *
79*7c478bd9Sstevel@tonic-gate  * This function returns NULL if an exception has been thrown during its
80*7c478bd9Sstevel@tonic-gate  * execution.
81*7c478bd9Sstevel@tonic-gate  */
82*7c478bd9Sstevel@tonic-gate static char
JNU_GetStringNativeChars(JNIEnv * env,jstring jstr)83*7c478bd9Sstevel@tonic-gate *JNU_GetStringNativeChars(JNIEnv *env, jstring jstr)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	jclass class;
86*7c478bd9Sstevel@tonic-gate 	jmethodID method;
87*7c478bd9Sstevel@tonic-gate 	jint len;
88*7c478bd9Sstevel@tonic-gate 	jbyteArray bytes = NULL;
89*7c478bd9Sstevel@tonic-gate 	char *result = NULL;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 	/*
92*7c478bd9Sstevel@tonic-gate 	 * Need a local reference for (1) FindClass(), (2) the bytes and
93*7c478bd9Sstevel@tonic-gate 	 * (3) the FindClass() in ThrowByName() if all goes wrong.
94*7c478bd9Sstevel@tonic-gate 	 */
95*7c478bd9Sstevel@tonic-gate 	if ((*env)->EnsureLocalCapacity(env, 3) < 0) {
96*7c478bd9Sstevel@tonic-gate 		JNU_ThrowByName(
97*7c478bd9Sstevel@tonic-gate 		    env,
98*7c478bd9Sstevel@tonic-gate 		    CLASS_JAVA_LANG_OUTOFMEMORYERROR,
99*7c478bd9Sstevel@tonic-gate 		    NULL);
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 		return (NULL);
102*7c478bd9Sstevel@tonic-gate 	}
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	class = (*env)->FindClass(env, CLASS_JAVA_LANG_STRING);
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	/*
107*7c478bd9Sstevel@tonic-gate 	 * If class is NULL FindClass() encountered a problem locating the
108*7c478bd9Sstevel@tonic-gate 	 * desired class and has already called ThrowNew() with an
109*7c478bd9Sstevel@tonic-gate 	 * exception.
110*7c478bd9Sstevel@tonic-gate 	 */
111*7c478bd9Sstevel@tonic-gate 	if (class == NULL) {
112*7c478bd9Sstevel@tonic-gate 		return (NULL);
113*7c478bd9Sstevel@tonic-gate 	}
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	method = (*env)->GetMethodID(
116*7c478bd9Sstevel@tonic-gate 	    env,
117*7c478bd9Sstevel@tonic-gate 	    class,
118*7c478bd9Sstevel@tonic-gate 	    METHOD_GETBYTES,
119*7c478bd9Sstevel@tonic-gate 	    SIG_JAVA_LANG_STRING_GETBYTES);
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/*
122*7c478bd9Sstevel@tonic-gate 	 * If method is NULL GetMethodID() encountered a problem
123*7c478bd9Sstevel@tonic-gate 	 * locating the desired method and has already called
124*7c478bd9Sstevel@tonic-gate 	 * ThrowNew() with an exception.
125*7c478bd9Sstevel@tonic-gate 	 */
126*7c478bd9Sstevel@tonic-gate 	if (method != NULL) {
127*7c478bd9Sstevel@tonic-gate 		/*
128*7c478bd9Sstevel@tonic-gate 		 * Call String.getBytes(), creating our temporary
129*7c478bd9Sstevel@tonic-gate 		 * byte array
130*7c478bd9Sstevel@tonic-gate 		 */
131*7c478bd9Sstevel@tonic-gate 		bytes = (*env)->CallObjectMethod(env, jstr, method);
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 		/* See if CallObjectMethod() threw an exception */
134*7c478bd9Sstevel@tonic-gate 		if ((*env)->ExceptionCheck(env) == JNI_FALSE) {
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 			len = (*env)->GetArrayLength(env, bytes);
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 			/*
139*7c478bd9Sstevel@tonic-gate 			 * Allocate a buffer for the native characters,
140*7c478bd9Sstevel@tonic-gate 			 * need an extra char for string terminator.
141*7c478bd9Sstevel@tonic-gate 			 * Note: calloc will provide the terminating
142*7c478bd9Sstevel@tonic-gate 			 * '\0' for us.
143*7c478bd9Sstevel@tonic-gate 			 */
144*7c478bd9Sstevel@tonic-gate 			result = (char *)calloc(len + 1, sizeof (char));
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 			/*
147*7c478bd9Sstevel@tonic-gate 			 * If allocation failed assume we are out of
148*7c478bd9Sstevel@tonic-gate 			 * memory
149*7c478bd9Sstevel@tonic-gate 			 */
150*7c478bd9Sstevel@tonic-gate 			if (result == NULL) {
151*7c478bd9Sstevel@tonic-gate 				JNU_ThrowByName(
152*7c478bd9Sstevel@tonic-gate 				    env,
153*7c478bd9Sstevel@tonic-gate 				    CLASS_JAVA_LANG_OUTOFMEMORYERROR,
154*7c478bd9Sstevel@tonic-gate 				    NULL);
155*7c478bd9Sstevel@tonic-gate 			} else {
156*7c478bd9Sstevel@tonic-gate 				/*
157*7c478bd9Sstevel@tonic-gate 				 * Copy the encoded bytes into the
158*7c478bd9Sstevel@tonic-gate 				 * native string buffer
159*7c478bd9Sstevel@tonic-gate 				 */
160*7c478bd9Sstevel@tonic-gate 				(*env)->GetByteArrayRegion(
161*7c478bd9Sstevel@tonic-gate 				    env,
162*7c478bd9Sstevel@tonic-gate 				    bytes,
163*7c478bd9Sstevel@tonic-gate 				    0,
164*7c478bd9Sstevel@tonic-gate 				    len,
165*7c478bd9Sstevel@tonic-gate 				    (jbyte *)result);
166*7c478bd9Sstevel@tonic-gate 			}
167*7c478bd9Sstevel@tonic-gate 		}
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 		if (bytes != NULL) {
170*7c478bd9Sstevel@tonic-gate 		    (*env)->DeleteLocalRef(env, bytes);
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	/* Clean up by deleting the local references */
175*7c478bd9Sstevel@tonic-gate 	(*env)->DeleteLocalRef(env, class);
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	return (result);
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate  * Class:     com_sun_slp_Syslog
182*7c478bd9Sstevel@tonic-gate  * Method:    syslog
183*7c478bd9Sstevel@tonic-gate  * Signature: (ILjava/lang/String;)V
184*7c478bd9Sstevel@tonic-gate  */
185*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
186*7c478bd9Sstevel@tonic-gate JNIEXPORT
Java_com_sun_slp_Syslog_syslog(JNIEnv * env,jobject obj,jint priority,jstring jmsg)187*7c478bd9Sstevel@tonic-gate void JNICALL Java_com_sun_slp_Syslog_syslog(JNIEnv *env,
188*7c478bd9Sstevel@tonic-gate 					    jobject obj,
189*7c478bd9Sstevel@tonic-gate 					    jint priority,
190*7c478bd9Sstevel@tonic-gate 					    jstring jmsg) {
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	char *msg = JNU_GetStringNativeChars(env, jmsg);
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	/*
195*7c478bd9Sstevel@tonic-gate 	 * Check to see if the String conversion was successful,
196*7c478bd9Sstevel@tonic-gate 	 * if it wasn't an exception will have already been thrown.
197*7c478bd9Sstevel@tonic-gate 	 */
198*7c478bd9Sstevel@tonic-gate 	if (msg != NULL) {
199*7c478bd9Sstevel@tonic-gate 		openlog("slpd", LOG_PID, LOG_DAEMON);
200*7c478bd9Sstevel@tonic-gate 		syslog(priority, "%s", msg);
201*7c478bd9Sstevel@tonic-gate 		closelog();
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 		free(msg);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate }
206