diff options
Diffstat (limited to 'pki/base/osutil/src/com/netscape')
16 files changed, 2074 insertions, 0 deletions
diff --git a/pki/base/osutil/src/com/netscape/osutil/EventMessages.MC b/pki/base/osutil/src/com/netscape/osutil/EventMessages.MC new file mode 100644 index 000000000..0de16fb45 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/EventMessages.MC @@ -0,0 +1,7 @@ +LanguageNames=(Neutral=0x0:MSG00001) + +MessageID=1001 +SymbolicName=GENERIC_MSG +Language=Neutral +%1 +. diff --git a/pki/base/osutil/src/com/netscape/osutil/EventMessages.h b/pki/base/osutil/src/com/netscape/osutil/EventMessages.h new file mode 100644 index 000000000..d5e9cd833 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/EventMessages.h @@ -0,0 +1,45 @@ +// +// Values are 32 bit values layed out as follows: +// +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---+-+-+-----------------------+-------------------------------+ +// |Sev|C|R| Facility | Code | +// +---+-+-+-----------------------+-------------------------------+ +// +// where +// +// Sev - is the severity code +// +// 00 - Success +// 01 - Informational +// 10 - Warning +// 11 - Error +// +// C - is the Customer code flag +// +// R - is a reserved bit +// +// Facility - is the facility code +// +// Code - is the facility's status code +// +// +// Define the facility codes +// + + +// +// Define the severity codes +// + + +// +// MessageId: GENERIC_MSG +// +// MessageText: +// +// %1 +// +#define GENERIC_MSG 0x200003E9L + diff --git a/pki/base/osutil/src/com/netscape/osutil/LibC.c b/pki/base/osutil/src/com/netscape/osutil/LibC.c new file mode 100644 index 000000000..238f9d149 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/LibC.c @@ -0,0 +1,82 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +#include <jni.h> +#include "com_netscape_osutil_LibC.h" +#include "unixdefs.h" +#include <sys/types.h> +#include <unistd.h> +#include <stdlib.h> + + +/* + * Class: com_netscape_osutil_LibC + * Method: getpid + * Signature: ()I + * + * Return the current pid + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_LibC_getpid(JNIEnv *env, jclass cls) +{ + return getpid(); +} + +/* + * Class: com_netscape_osutil_LibC + * Method: getppid + * Signature: ()I + * + * Return the parent pid + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_LibC_getppid(JNIEnv *env, jclass cls) +{ + return getppid(); +} + +/* + * Class: com_netscape_osutil_LibC + * Method: setpgrp + * Signature: ()I + * + * Change the current process group and disconnect from the tty + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_LibC_detach(JNIEnv *env, jclass cls) +{ + int sid, pid; + + pid = fork(); + + if (pid != 0) { + if (pid > 0) { + exit(0); + } else { + /* Adding perror here might be helpful */ + unix_throw_exception(env, RUNTIME, "can't fork"); + return -1; + } + } else { + sid = setsid(); + if (sid < 0) { + unix_throw_exception(env, SECURITY, "permission denied"); + } + return sid; + } +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/LibC.java b/pki/base/osutil/src/com/netscape/osutil/LibC.java new file mode 100644 index 000000000..212b72fd6 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/LibC.java @@ -0,0 +1,50 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +import java.io.*; + + +/** + * This class is a miscellanous collection of Unix system calls + * needed for process control + */ +public class LibC { + + /** + * Return the current process id of the Java VM + */ + public static native int getpid(); + + /** + * Return the parent process id of the Java VM + */ + public static native int getppid(); + + /** + * Change the detach from the current tty + */ + public static native int detach(); + + static { + if (File.separatorChar == '/') + System.loadLibrary("osutil"); + } +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.c b/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.c new file mode 100644 index 000000000..96f1ac6cf --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.c @@ -0,0 +1,382 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +#include <jni.h> +#include <assert.h> +#include <string.h> +#include "com_netscape_osutil_NTEventLogger.h" +#include "EventMessages.h" + +#include <process.h> +#include <stdlib.h> +#include <windows.h> + + +static void +throwMsg(JNIEnv *env, char *throwableClassName, char *message) { + + jclass throwableClass=NULL; + jint result; + + /* validate arguments */ + assert(env!=NULL && throwableClassName!=NULL && message!=NULL); + + if(throwableClassName) { + throwableClass = (*env)->FindClass(env, throwableClassName); + + /* make sure the class was found */ + assert(throwableClass != NULL); + } + if(throwableClass == NULL) { + throwableClass = (*env)->FindClass(env, "java/lang/Exception"); + } + assert(throwableClass != NULL); + + result = (*env)->ThrowNew(env, throwableClass, message); + assert(result == 0); +} + +/** + * Returns an error message using the given error code. Returns NULL if + * something goes wrong. + * Use LocalFree() to free the returned string. + */ +static char* +errCodeToErrMsg(DWORD errCode) +{ + char *errBuf=NULL; + DWORD numBytes; + + numBytes = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL /* source */, + errCode, + 0 /* language */, + (LPTSTR) &errBuf /* this will be set to a new buffer */, + 0 /* min # bytes to allocate */, + NULL /*arg list */ ); + + if( numBytes > 0 ) { + return errBuf; + } else { + assert(FALSE); + return NULL; + } +} + +static void +throwFromErrCode(JNIEnv *env, DWORD errCode, char *context) +{ + char *wholeMsg; + char *errMsg; + BOOL needToFreeErrMsg=TRUE; + + errMsg = errCodeToErrMsg(errCode); + + if( context == NULL ) { + context = ""; + } + + if( errMsg == NULL ) { + needToFreeErrMsg = FALSE; + errMsg = ""; + } + + wholeMsg= (char*)malloc( strlen(context) + strlen(errMsg) + 4); + sprintf(wholeMsg, "%s : %s", context, errMsg); + throwMsg(env, "java/lang/Exception", wholeMsg); + + /* cleanup */ + if(needToFreeErrMsg) { + LocalFree(errMsg); + } + free(wholeMsg); +} + + +/** + * Converts a byte array to a Windows HANDLE. Returns NULL if something + * goes wrong. + */ +static HANDLE +byteArrayToHandle(JNIEnv *env, jbyteArray handleBA) { + + HANDLE handle=NULL; + jbyte *bytes=NULL; + jint len; + + assert(env!=NULL && handleBA!=NULL); + + len = (*env)->GetArrayLength(env, handleBA); + assert(len == sizeof(HANDLE)); + if( len != sizeof(HANDLE) ) { + goto finish; + } + + bytes = (*env)->GetByteArrayElements(env, handleBA, NULL); + if( bytes == NULL ) { + goto finish; + } + + memcpy(&handle, bytes, len); + +finish: + if(bytes) { + (*env)->ReleaseByteArrayElements(env, handleBA, bytes, JNI_ABORT); + } + return handle; +} + +/** + * Converts a Windows HANDLE to a Java byte array + */ +static jbyteArray +handleToByteArray(JNIEnv *env, HANDLE handle) { + jbyteArray handleBA=NULL; + jbyte *bytes=NULL; + + handleBA = (*env)->NewByteArray(env, sizeof(HANDLE)); + if(handleBA == NULL ) { + goto finish; + } + + bytes = (*env)->GetByteArrayElements(env, handleBA, NULL); + if(bytes == NULL) { + goto finish; + } + + memcpy(bytes, &handle, sizeof(handle)); + +finish: + if(bytes) { + (*env)->ReleaseByteArrayElements(env, handleBA, bytes, 0); + } + return handleBA; +} + + + +/****************************************** + * NTEventLogger.reportEventNative + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_NTEventLogger_reportEventNative + (JNIEnv *env, jclass clazz, jbyteArray handleBA, jshort type, + jshort category, jint eventID, jobjectArray jstringArray) +{ + HANDLE logHandle; + const char **strings=NULL; + jshort numStrings=0; + BOOL result; + + assert(env && clazz && handleBA); + + /* + * Recover the windows HANDLE from the byte array that was passed in + */ + logHandle = byteArrayToHandle(env, handleBA); + if( (*env)->ExceptionOccurred(env) ) { + goto finish; + } + assert(logHandle); + + /* + * convert array of Java strings to array of windows strings + */ + if( jstringArray ) { + numStrings = (jshort) (*env)->GetArrayLength(env, jstringArray); + assert( numStrings > 0 ); /* otherwise why isn't the array NULL? */ + + if( numStrings > 0 ) { + int i; + jobject obj; + + strings = (char**) malloc(sizeof(char*) * numStrings); + + /* clear this array of pointers so we can goto finish */ + memset((void*)strings, 0, sizeof(char*) * numStrings); + + for(i=0; i < numStrings; i++) { + obj = (*env)->GetObjectArrayElement(env, jstringArray, i); + if( obj == NULL ) { + assert( (*env)->ExceptionOccurred(env) ); + goto finish; + } + strings[i] = (*env)->GetStringUTFChars(env, obj, NULL); + if( strings[i] == NULL ) { + goto finish; + } + } + } + } + + /* + * Report the event + */ + result = ReportEvent( + logHandle, + type, + category, + eventID, + NULL /* User SID */, + numStrings, + 0 /* data size */, + strings, + NULL /* data */ + ); + + /* + * Throw an exception if the call failed + */ + if( result == 0 ) { + + int errCode = GetLastError(); + char *errBuf = errCodeToErrMsg(errCode); + + if( errBuf ) { + throwMsg(env, "java/lang/Exception", errBuf); + LocalFree(errBuf); + goto finish; + } else { + char buf[200]; + + sprintf(buf, "ReportEvent() failed with error code %d", errCode); + throwMsg(env, "java/lang/Exception", buf); + goto finish; + } + } + + +finish: + /* + * Free the string arrays + */ + if(strings) { + int i; + jobject obj; + assert(numStrings > 0); + for( i=0; i < numStrings; i++) { + obj = (*env)->GetObjectArrayElement(env, jstringArray, i); + if( obj ) { + (*env)->ReleaseStringUTFChars(env, obj, strings[i]); + } + } + free((void*)strings); + } +} + +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_osutil_NTEventLogger_initNTLog + (JNIEnv *env, jclass clazz, jstring sourceName) +{ + jbyteArray handleBA=NULL; + jbyte *handleBytes=NULL; + HANDLE logHandle; + const char *sourceNameChars; + DWORD errCode; + + assert( env!=NULL && clazz!=NULL && sourceName!=NULL); + sourceNameChars = (*env)->GetStringUTFChars(env, sourceName, NULL); + if( sourceNameChars == NULL ) { + goto finish; + } + + logHandle = RegisterEventSource( NULL /* localhost */, sourceNameChars ); + + if( logHandle == 0 ) { + /* RegisterEventSource failed. Get an error string, put it in an + * Exception, and throw it */ + char *errBuf=NULL; + + errCode = GetLastError(); + errBuf = errCodeToErrMsg(errCode); + if( errBuf ) { + throwMsg(env, "java/lang/Exception", errBuf); + LocalFree(errBuf); + goto finish; + } else { + /* FormatMessage failed, create a generic string */ + char buf[200]; + _snprintf(buf, 200, "RegisterEventSource failed with error" + " code %d", errCode); + buf[199] = '\0'; /* ensure it is NULL-terminated */ + throwMsg(env, "java/lang/Exception", buf); + goto finish; + } + } + + /* what to do with handle? return it as a byte array...*/ + handleBA = (*env)->NewByteArray(env, sizeof(HANDLE)); + if(handleBA == NULL ) { + goto finish; + } + handleBytes = (*env)->GetByteArrayElements(env, handleBA, NULL); + if(handleBytes==NULL) { + goto finish; + } + memcpy(handleBytes, &logHandle, sizeof(logHandle)); + +finish: + if(sourceNameChars) { + (*env)->ReleaseStringUTFChars(env, sourceName, sourceNameChars); + } + if(handleBytes) { + assert(handleBA); + (*env)->ReleaseByteArrayElements(env, handleBA, handleBytes, 0); + } + return handleBA; +} + +/************************************************** + * NTEventLogger.shutdownNTLog + * + * Frees the event log handle. + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_NTEventLogger_shutdownNTLog + (JNIEnv* env, jclass clazz, jbyteArray handleBA) +{ + + BOOL result; + HANDLE handle; + + assert(env && clazz && handleBA); + + handle = byteArrayToHandle(env, handleBA); + if( ! handle ) { + assert( (*env)->ExceptionOccurred(env) ); + return; + } + + result = DeregisterEventSource(handle); + + if( result == FALSE ) { + int errCode = GetLastError(); + char *errBuf; + + errBuf = errCodeToErrMsg(errCode); + if( errBuf ) { + throwMsg(env, "java/lang/Exception", errBuf); + LocalFree(errBuf); + } else { + char buf[200]; + sprintf(buf, "DeregisterEventSource failed with code %d", errCode); + throwMsg(env, "java/lang/Exception", buf); + } + } +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.java b/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.java new file mode 100644 index 000000000..006dbf9c5 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/NTEventLogger.java @@ -0,0 +1,196 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +/** + * This class provides an interface to Windows NT event logging. + * + * @version $Revision: 14579 $, $Date: 2007-05-01 13:07:48 -0700 (Tue, 01 May 2007) $ + */ +public class NTEventLogger { + + private byte[] handle; // Must be non-null. Should be non-empty. + private boolean open; // true if this log is open for writing. + + // The Windows NT event ID. The actual event ID is 1001, but we also + // need to set bit 29 to indicate that we are not Microsoft. + // See _Windows NT Event Logging_ (O'Reilly), page 128, for an explanation. + public static final int EVENT_ID = 0x20000000 | 1001; + + private NTEventLogger() { + } + + // Load native library. This is the same library used by OsSubsystem. + // loadLibrary() is idempotent, so don't worry about calling it multiple + // times. + static { + try { + System.loadLibrary("osutil"); + } catch (Throwable t) { + // This is bad news, the program is doomed at this point + t.printStackTrace(); + } + } + + /** + * Creates an application or system NT Event log handle. + * + * @param eventSourceName The name of the source application. + * This should be a subkey of + * <code>HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog</code>. + * If the given source does not exist, NT will automatically return + * a handle to the application log without complaining. + * The reason to use a real source, rather than just using the default + * application log, is that the registry key of a real source + * tells NT where to find the message resources for formatting + * the strings that are sent in <code>reportEvent</code>. + * If the default application log is used, NT will insert a lame + * message: "The description for Event ID ( ... ) in Source + * ( ... ) could not be found. It contains the following insertion + * string(s):". + * @throws Exception If an error occurs in the native NT code. The + * exception message will contain more information. + */ + public NTEventLogger(String eventSourceName) throws Exception { + open = true; + handle = initNTLog(eventSourceName); + } + + /** + * Writes a string to the log. This is the simple way to write to the + * NT event log. + * <p>This method must not be called after the log is + * closed. + * + * @param type The type of the event that is logged. Pre-defined types + * are: + * <table border> + * <tr><th>Name</th><th>Description</th></tr> + * <tr><td>EVENTLOG_SUCCESS</td><td>Success</td></tr> + * <tr><td>EVENTLOG_ERROR_TYPE</td><td>Error</td></tr> + * <tr><td>EVENTLOG_WARNING_TYPE</td><td>Warning</td></tr> + * <tr><td>EVENTLOG_INFORMATION_TYPE</td><td>Informational</td></tr> + * <tr><td>EVENTLOG_AUDIT_SUCCESS</td><td>Success Audit</td></tr> + * <tr><td>EVENTLOG_AUDIT_FAILURE</td><td>Failure Audit</td></tr> + * </table> + * @param logMessage The string that will be written to the log. + * @exception Exception If an error occurs. The exception message will + * have more information. + */ + public void + reportEvent(int type, String logMessage) throws Exception { + if (!open) { + throw new IllegalArgumentException("Log has been closed"); + } + + reportEventNative(handle, (short) type, (short) 0, EVENT_ID, + new String[] {logMessage} + ); + } + + /** + * Writes an NT event to the log. See NT documentation for a description + * of the parameters. This is the complicated way to write to the log, + * to be used if you want to do something tricky. Normally you'll want + * to call reportEvent(int, String). + * <p>This method must not be called after the log is + * closed. + * + * @param type The type of the event that is logged. Pre-defined types + * are: + * <table border> + * <tr><th>Name</th><th>Description</th></tr> + * <tr><td>EVENTLOG_SUCCESS</td><td>Success</td></tr> + * <tr><td>EVENTLOG_ERROR_TYPE</td><td>Error</td></tr> + * <tr><td>EVENTLOG_WARNING_TYPE</td><td>Warning</td></tr> + * <tr><td>EVENTLOG_INFORMATION_TYPE</td><td>Informational</td></tr> + * <tr><td>EVENTLOG_AUDIT_SUCCESS</td><td>Success Audit</td></tr> + * <tr><td>EVENTLOG_AUDIT_FAILURE</td><td>Failure Audit</td></tr> + * </table> + * @param category An application-defined category for the event, which + * must be in the range 0-65535. A value of 0 indicates that there + * is not event category. + * @param eventID The application-specific event index. It must be in the + * range 0-65535. + * @param strings An array of description strings to be written to the log. + * @exception Exception If an error occurs. The exception message will + * have more information. + */ + public void + reportEvent(int type, int category, int eventID, + String[] strings) throws Exception { + if (!open) { + throw new IllegalArgumentException("Log has been closed"); + } + + /* check args */ + if (category < 0 || category > 65535) { + throw new IllegalArgumentException("category " + category + + " is outside the valid range"); + } + + reportEventNative(handle, (short) type, (short) category, + eventID, strings); + } + + private static native void + reportEventNative(byte[] handle, short type, short category, int eventID, + String[] strings) throws Exception; + + // Cleans up native resources when the Java object gets garbage collected + protected void finalize() throws Throwable { + close(); + } + + public void close() throws Exception { + if (open) { + shutdownNTLog(handle); + open = false; + } + } + + // creates the NT log in native code, returns a byte array containing + // the Windows log HANDLE. + private static native byte[] + initNTLog(String eventSourceName) throws Exception; + + // Closes the log pointed to by the given handle. + private static native void + shutdownNTLog(byte[] handle) throws Exception; + + public static void main(String args[]) { + try { + NTEventLogger h = new NTEventLogger("NTEventLogger test"); + + h.reportEvent(EVENTLOG_SUCCESS, "This is a test"); + h.reportEvent(EVENTLOG_ERROR_TYPE, + "SERVER MELTDOWN: Evacuate the building!!!"); + + }catch (Exception e) { + e.printStackTrace(); + } + } + + public static final short EVENTLOG_SUCCESS = 0; + public static final short EVENTLOG_ERROR_TYPE = 1; + public static final short EVENTLOG_WARNING_TYPE = 2; + public static final short EVENTLOG_INFORMATION_TYPE = 4; + public static final short EVENTLOG_AUDIT_SUCCESS = 8; + public static final short EVENTLOG_AUDIT_FAILURE = 16; +} diff --git a/pki/base/osutil/src/com/netscape/osutil/OSUtil.c b/pki/base/osutil/src/com/netscape/osutil/OSUtil.c new file mode 100644 index 000000000..6fed949cc --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/OSUtil.c @@ -0,0 +1,290 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +#include <jni.h> +#include <assert.h> +#include <string.h> +#include "com_netscape_osutil_OSUtil.h" + +#ifdef XP_PC +#include <process.h> +#else +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#endif + +#include "base64.h" + +JNIEXPORT jbyteArray JNICALL +Java_com_netscape_osutil_OSUtil_AtoB + (JNIEnv* env, jclass this, jstring data) +{ + jbyteArray handleBA=NULL; + jbyte *handleBytes=NULL; + const char *dataChars; + unsigned char *result=NULL; + unsigned int olenp; + + dataChars = (*env)->GetStringUTFChars(env, data, NULL); + if( dataChars == NULL ) { + goto finish; + } + + result = ATOB_AsciiToData(dataChars, &olenp); + if (result == NULL) { + goto finish; + } + + handleBA = (*env)->NewByteArray(env, olenp); + if(handleBA == NULL ) { + goto finish; + } + handleBytes = (*env)->GetByteArrayElements(env, handleBA, NULL); + if(handleBytes==NULL) { + goto finish; + } + memcpy(handleBytes, result, olenp); + +finish: + if (dataChars) { + (*env)->ReleaseStringUTFChars(env, data, dataChars); + } + if (result) { + free(result); + } + if(handleBytes) { + assert(handleBA); + (*env)->ReleaseByteArrayElements(env, handleBA, handleBytes, 0); + } + return handleBA; +} + +JNIEXPORT jstring JNICALL +Java_com_netscape_osutil_OSUtil_BtoA + (JNIEnv* env, jclass this, jbyteArray data) +{ + char *result=NULL; + jint len; + jbyte *bytes=NULL; + jstring retval = NULL; + + len = (*env)->GetArrayLength(env, data); + bytes = (*env)->GetByteArrayElements(env, data, NULL); + if( bytes == NULL ) { + goto finish; + } + + result = BTOA_DataToAscii(bytes, len); + if (result == NULL) { + goto finish; + } + + retval = (*env)->NewStringUTF(env, result); + +finish: + if (result) { + free(result); + } + if(bytes) { + (*env)->ReleaseByteArrayElements(env, data, bytes, JNI_ABORT); + } + return retval; +} + +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_OSUtil_getNTpid + (JNIEnv *env, jobject this) +{ +#ifdef XP_PC + return _getpid(); +#else + assert( 0 ); + return 0; +#endif +} + +JNIEXPORT jstring JNICALL +Java_com_netscape_osutil_OSUtil_getenv + (JNIEnv* env, jclass this, jstring envName) +{ + const char* envNameChars=NULL; + char *envValueChars; + jstring retval = NULL; + + /* convert Java String environment name to char* */ + envNameChars = (*env)->GetStringUTFChars(env, envName, NULL); + if( envNameChars == NULL ) { + goto finish; + } + + /* look up the environment variable. The returned pointer points into + * the environment table, so must not be freed by the caller. */ + envValueChars = (char *) getenv(envNameChars); + if( envValueChars == NULL ) { + goto finish; + } + + /* convert char* to Java string */ + retval = (*env)->NewStringUTF(env, envValueChars); + +finish: + if( envNameChars ) { + (*env)->ReleaseStringUTFChars(env, envName, envNameChars); + } + return retval; +} + +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_OSUtil_getFileReadLock +(JNIEnv *env, jclass this, jstring filename) +{ +#ifdef XP_PC + return(0); /* Do nothing on NT for now */ +#else + const char* filenameChars=NULL; + int value = 0; + + struct flock lock; + int fd; + + filenameChars = (*env)->GetStringUTFChars(env, filename, NULL); + if (filenameChars == NULL) { + value = -1; + goto finish; + } + + fd = open(filenameChars, O_RDONLY); + lock.l_type = F_RDLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 50; + if (fcntl(fd, F_SETLK, &lock) < 0) + { + value = -1; + goto finish; + /* printf("Cannot set read lock.\n"); + printf("File is write locked by %ld\n", lock.l_pid); + */ + } + fcntl(fd, F_GETLK, &lock); + switch (lock.l_type) + { + case F_RDLCK: + value = 1; + break; + case F_WRLCK: + value = -1; + break; + case F_UNLCK: + value = 0; + break; + } + finish: + if( filenameChars ) { + (*env)->ReleaseStringUTFChars(env, filename, filenameChars); + } + return value; +#endif +} + +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_OSUtil_getFileWriteLock +(JNIEnv *env, jclass this, jstring filename) +{ + const char* filenameChars=NULL; + int value = 0; +#ifdef XP_PC +#else + struct flock lock; + int fd; +#endif + + filenameChars = (*env)->GetStringUTFChars(env, filename, NULL); + if (filenameChars == NULL) { + value = -1; + goto finish; + } +#ifdef XP_PC +#else + + fd = open(filenameChars, O_RDWR); + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 50; + if (fcntl(fd, F_SETLK, &lock) < 0) { + value = -1; + goto finish; + /* printf("Cannot set write lock\n"); + */ + } + fcntl(fd, F_GETLK, &lock); + switch (lock.l_type) + { + case F_RDLCK: + value = 1; + break; + case F_WRLCK: + value = 2; + break; + case F_UNLCK: + value = 0; + break; + } +#endif + finish: + if( filenameChars ) { + (*env)->ReleaseStringUTFChars(env, filename, filenameChars); + } + return value; +} + + +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_OSUtil_putenv +(JNIEnv* env, jclass this, jstring envName) +{ + const char* envNameChars=NULL; + int value =0; + + envNameChars = (*env)->GetStringUTFChars(env, envName, NULL); + if (envNameChars == NULL) { + value = -1; + goto finish; + } + +#ifdef XP_PC + value = _putenv(envNameChars); +#else + /* Ross 1/26 Are we trashing memory here? Look at putenv implementation details */ + value = putenv (strdup(envNameChars)); +#endif + +finish: + if( envNameChars ) { + (*env)->ReleaseStringUTFChars(env, envName, envNameChars); + } + return value; +} + +JNIEXPORT void JNICALL +Java_com_netscape_osutil_OSUtil_nativeExit +(JNIEnv *env, jobject this, jint status) +{ + exit(status); +} diff --git a/pki/base/osutil/src/com/netscape/osutil/OSUtil.java b/pki/base/osutil/src/com/netscape/osutil/OSUtil.java new file mode 100644 index 000000000..c19b3be95 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/OSUtil.java @@ -0,0 +1,72 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + +import java.io.*; +import java.util.*; + + +public final class OSUtil { + /** + * Causes this process to die. Works more reliably than System.exit(). + */ + public static native void nativeExit( int status ); + + public static native String BtoA( byte data[] ); + + public static native byte[] AtoB( String data ); + + // Load native library + static { + System.loadLibrary( "osutil" ); + } + + public static native int getNTpid(); + + /** + * A routine to get the value of an system or environment variable. + * @param envName A string of the form <code> env_var=value </code> + * @return String value of the environemnt variable. + */ + public static native String getenv( String envName ); + + /** + * A routine to set an environment variable. + * @param envName A string of the form <code> env_var=value </code> + * @return Return 0 on success, non-zero on failure + */ + public static native int putenv( String envValue ); + + /** + * A routine to get a file system read lock. + * @param filename A file with relative or absolute path + * @return Return 0 on getting a unique read lock, + * Return 1 on getting non-unique read lock, -1 on failure + */ + public static native int getFileReadLock( String filename ); + + /** + * A routine to get a file system write lock. + * @param filename A file with relative or absolute path + * @return Return 0 on successfully getting a write lock, + * return 1 if the file is read locked, + * return 2 if the file is write locked, -1 on failure + */ + public static native int getFileWriteLock( String filename ); +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.c b/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.c new file mode 100644 index 000000000..2e4203281 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.c @@ -0,0 +1,68 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <jni.h> + +#include <sys/resource.h> + +/* + * Class: com_netscape_osutil_ResourceLimit + * Method: getHardLimit + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_netscape_osutil_ResourceLimit_getHardLimit + (JNIEnv *env, jclass myclass, jint resource) +{ + struct rlimit limit; + + getrlimit(resource,&limit); + return limit.rlim_max; +} + +/* + * Class: com_netscape_osutil_ResourceLimit + * Method: getSoftLimit + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_netscape_osutil_ResourceLimit_getSoftLimit + (JNIEnv *env, jclass myclass, jint resource) +{ + struct rlimit limit; + + getrlimit(resource,&limit); + return limit.rlim_cur; +} + + +/* + * Class: com_netscape_certsrv_unix_ResourceLimit + * Method: setLimits + * Signature: (III)I + */ +JNIEXPORT jint JNICALL Java_com_netscape_osutil_ResourceLimit_setLimits + (JNIEnv *env, jclass myclass, jint resource, jint soft, jint hard) +{ + int r; + struct rlimit limit; + + limit.rlim_cur = soft; + limit.rlim_max = hard; + r = setrlimit(resource,&limit); + return r; +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.java b/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.java new file mode 100644 index 000000000..d914759d6 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/ResourceLimit.java @@ -0,0 +1,108 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +import java.io.*; + + +/** + * This class is to enabled reading/setting of various resource limits + * on unix + */ +public class ResourceLimit { + + /** + * Return the current process id of the Java VM + */ + + /** + * See /usr/include/sys/resource.h + */ + public static int RLIMIT_CPU = 0; + public static int RLIMIT_FSIZE = 1; + public static int RLIMIT_DATA = 2; + public static int RLIMIT_STACK = 3; + public static int RLIMIT_CORE = 4; + public static int RLIMIT_NOFILE = 5; + public static int RLIMIT_VMEM = 6; + + /** + * Return the hard limit of the specified resource + */ + public static native int getHardLimit(int resource); + + /** + * Return the soft limit of the specified resource + */ + public static native int getSoftLimit(int resource); + + /** + * Set limits on the resource + */ + public static native int setLimits(int resource, int soft, int hard); + + static { + if (File.separatorChar == '/') + System.loadLibrary("osutil"); + } + + /* little test program here... */ + + public static void main(String args[]) { + try { + testFDlimit("64"); + printFDLimit(); + System.gc(); + System.out.println("Changing softlimit to be equal to hardlimit()"); + + setLimits(RLIMIT_NOFILE, + getHardLimit(RLIMIT_NOFILE), + getHardLimit(RLIMIT_NOFILE) + ); + + testFDlimit("1024"); + printFDLimit(); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private static void printFDLimit() { + System.out.println("Max filedescs (hardlimit) " + getHardLimit(RLIMIT_NOFILE)); + System.out.println("Max filedescs (softlimit) " + getSoftLimit(RLIMIT_NOFILE)); + } + + /* this creates as many files as it can. The files will be closed when this + function exits, as they will be garbage collected. */ + + private static void testFDlimit(String a) { + int count = 0; + FileOutputStream f[] = new FileOutputStream[1024]; + + try { + for (count = 0; count < 1024; count++) { + f[count] = new FileOutputStream("test_" + a + "_" + count); + } + } catch (Exception e) { + } + } + +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/Signal.c b/pki/base/osutil/src/com/netscape/osutil/Signal.c new file mode 100644 index 000000000..64bd28089 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/Signal.c @@ -0,0 +1,272 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +#include <jni.h> +#include "com_netscape_osutil_Signal.h" +#include "unixdefs.h" +#include <signal.h> +#include <errno.h> + +#ifndef MAXSIG +#define MAXSIG 33 +#endif + +/* + * These are declared as syncronized funtions in the Java code, + * so this isn't needed. + */ +#define ENTER_MONITOR /* (*env)->MonitorEnter(obj) */ +#define EXIT_MONITOR /* (*env)->MonitorExit(obj) */ + +typedef struct { + jobject listener; + JavaVM *vm; + int watched; + int count; + struct sigaction oact; +} SigWatch; + +/* Good thing there's only one signal handler per processes */ +static SigWatch sig_watch[MAXSIG]; + +static void +sig_count(int signo) +{ + JNIEnv *env = NULL; + jobject listener = NULL; + jclass listenerClass = NULL; + jmethodID methodId = NULL; + jint status; + JavaVM *vm; + void *penv; + + sig_watch[signo-1].count++; + listener = sig_watch[signo-1].listener; + vm = sig_watch[signo-1].vm; + + status = (*vm)->AttachCurrentThread(vm, &penv, NULL); + if (status != 0) { + printf("XXX bad attaching\n"); + } + env = (JNIEnv *)penv; + listenerClass = (*env)->GetObjectClass(env, listener); + if (listenerClass == NULL) { + printf("XXX null listener\n"); + } + methodId = (*env)->GetMethodID(env, listenerClass, + "process", "()V"); + if (methodId == NULL) { + printf("XXX null process\n"); + } + (*env)->CallVoidMethod(env, listener, methodId); +} + +/* + * Check for a valid signal number. Throw IllegalArgumentException if so. + * This really shouldn't happen since the Java code protects us. + */ +static int +valid_signo(JNIEnv *env, int signo) +{ + jclass illExc; + + if (signo <= MAXSIG && signo > 0) + return 1; + + illExc = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); + if (illExc == 0) /* Unable to find the new exception class, give up. */ + return 0; + (*env)->ThrowNew(env, illExc, "bad signal number"); + return 0; +} + +/** + * Associates callback with signal. This obsoletes all + * the functions below. + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_Signal_addSignalListener(JNIEnv *env, + jclass cls, jint signo, jobject listener) +{ + struct sigaction act; + SigWatch *sw; + JavaVM *vmBuf[1]; +#if 0 + jsize nVMs; +#endif + + + if (!valid_signo(env, signo)) + return; + + sw = &sig_watch[signo-1]; + + if (sw->watched) { + EXIT_MONITOR + return; /* Already being watched */ + } + + sw->watched = 1; + sw->listener = (*env)->NewGlobalRef(env, listener); +#if 0 + /* IBM JRE1.5 does not like this, and I dont think we + are using this file anyway. So I've commented this out */ + JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs); +#endif + sw->vm = vmBuf[0]; + + sw->count = 0; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + act.sa_handler = sig_count; + sigaction(signo, &act, &sw->oact); + + EXIT_MONITOR +} + +/* + * Class: com_netscape_osutil_Signal + * Method: watch + * Signature: (I)V + * + * Add a signal handler to count the number of signals recieved. + * + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_Signal_watch(JNIEnv *env, jclass cls, + jint signo) +{ + struct sigaction act; + SigWatch *sw; + + if (!valid_signo(env, signo)) + return; + + sw = &sig_watch[signo-1]; + + if (sw->watched) { + EXIT_MONITOR + return; /* Already being watched */ + } + + sw->watched = 1; + sw->listener = NULL; + sw->vm = NULL; + + sw->count = 0; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + act.sa_handler = sig_count; + sigaction(signo, &act, &sw->oact); + + EXIT_MONITOR + +} + + +/* + * Class: com_netscape_certsrv_unix_Signal + * Method: release + * Signature: (I)V + * + * Restore whatever signal handler was present before the watch call. + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_Signal_release(JNIEnv *env, jclass cls, + jint signo) +{ + SigWatch *sw; + + if (!valid_signo(env, signo)) + return; + + sw = &sig_watch[signo-1]; + + ENTER_MONITOR + + if (!sw->watched) { + EXIT_MONITOR + return; /* not being watched */ + } + + sw->watched = 0; + sw->count = 0; + sigaction(signo, &sw->oact, NULL); + + EXIT_MONITOR +} + +/* + * Class: com_netscape_certsrv_unix_Signal + * Method: caught + * Signature: (I)I + * + * Return the number of signals caught. Resets the count to 0 + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_Signal_caught(JNIEnv *env, jclass cls, + jint signo) +{ + int count; + SigWatch *sw; + + if (!valid_signo(env, signo)) + return 0; + + sw = &sig_watch[signo-1]; + + if (!sw->watched) { + return 0; /* not being watched */ + } + + /* + * The usefulness of multiple threads using this interface + * is questionable. This just guarantees some consistency + */ + ENTER_MONITOR + count = sw->count; + sw->count = 0; + EXIT_MONITOR + + return count; +} + +/* + * Class: com_netscape_certsrv_unix_Signal + * Method: send + * Signature: (II)I + * + * Send a signal to a process + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_Signal_send(JNIEnv *env, jclass cls, jint pid, + jint signo) +{ + valid_signo(env, signo); + if (kill(pid, signo) != 0) { + switch (errno) { + case EINVAL: + unix_throw_exception(env, ILLARG, "invalid signal"); + break; + case EPERM: + unix_throw_exception(env, SECURITY, "permission denied"); + break; + } + } +} + + diff --git a/pki/base/osutil/src/com/netscape/osutil/Signal.java b/pki/base/osutil/src/com/netscape/osutil/Signal.java new file mode 100644 index 000000000..9be3ecda5 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/Signal.java @@ -0,0 +1,219 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +import java.io.*; + + +/** + * This class is a very simpy Java wrapper around Posix/Unix signals. + * The interface allows the programmer to catch a signal and check to + * see how many times the signal has been recieved. + */ + +public class Signal { + + /** hangup */ + public static final SignalNo SIGHUP = new SignalNo(1); + + /** interrupt (rubout) */ + public static final SignalNo SIGINT = new SignalNo(2); + + /** quit (ASCII FS) */ + public static final SignalNo SIGQUIT = new SignalNo(3); + + /** illegal instruction (not reset when caught) */ + public static final SignalNo SIGILL = new SignalNo(4); + + /** trace trap (not reset when caught) */ + public static final SignalNo SIGTRAP = new SignalNo(5); + + /** IOT instruction */ + public static final SignalNo SIGIOT = new SignalNo(6); + + /** used by abort, replace SIGIOT in the future */ + public static final SignalNo SIGABRT = SIGIOT; + + /** EMT instruction */ + public static final SignalNo SIGEMT = new SignalNo(7); + + /** floating point exception */ + public static final SignalNo SIGFPE = new SignalNo(8); + + /** kill (cannot be caught or ignored) */ + public static final SignalNo SIGKILL = new SignalNo(9); + + /** bus error */ + public static final SignalNo SIGBUS = new SignalNo(10); + + /** segmentation violation */ + public static final SignalNo SIGSEGV = new SignalNo(11); + + /** bad argument to system call */ + public static final SignalNo SIGSYS = new SignalNo(12); + + /** write on a pipe with no one to read it */ + public static final SignalNo SIGPIPE = new SignalNo(13); + + /** alarm clock */ + public static final SignalNo SIGALRM = new SignalNo(14); + + /** software termination signal from kill */ + public static final SignalNo SIGTERM = new SignalNo(15); + + /** user defined signal 1 */ + public static final SignalNo SIGUSR1 = new SignalNo(16); + + /** user defined signal 2 */ + public static final SignalNo SIGUSR2 = new SignalNo(17); + + /** death of a child */ + public static final SignalNo SIGCLD = new SignalNo(18); + + /** compatibility */ + public static final SignalNo SIGCHLD = SIGCLD; + + /** power-fail restart */ + public static final SignalNo SIGPWR = new SignalNo(19); + + /** window change */ + public static final SignalNo SIGWINCH = new SignalNo(20); + + /** urgent socket condition */ + public static final SignalNo SIGURG = new SignalNo(21); + + /** pollable event occurred */ + public static final SignalNo SIGPOLL = new SignalNo(22); + + /** sendable stop signal not from tty */ + public static final SignalNo SIGSTOP = new SignalNo(23); + + /** stop signal from tty */ + public static final SignalNo SIGTSTP = new SignalNo(24); + + /** continue a stopped process */ + public static final SignalNo SIGCONT = new SignalNo(25); + + /** to readers pgrp upon background tty read */ + public static final SignalNo SIGTTIN = new SignalNo(26); + + /** like TTIN for output if tp->t_local&TOSTOP */ + public static final SignalNo SIGTTOU = new SignalNo(27); + + /** virtual timer alarm */ + public static final SignalNo SIGVTALRM = new SignalNo(28); + + /** profile alarm */ + public static final SignalNo SIGPROF = new SignalNo(29); + + /** CPU time limit exceeded */ + public static final SignalNo SIGXCPU = new SignalNo(30); + + /** File size limit exceeded */ + public static final SignalNo SIGXFSZ = new SignalNo(31); + + /** process's lwps are blocked */ + public static final SignalNo SIGWAITING = new SignalNo(32); + + /** special signal used by thread library */ + public static final SignalNo SIGLWP = new SignalNo(33); + // Once you get past SIGLWP, it's not portable between OS's + + /** + * Watch a specific signal + * + * @param signo The signal which you want to catch + */ + // catch is a reserved word! + public static void watch(SignalNo signo) { + // Passing ints makes JNI much easier + watch(signo.toInt()); + } + + synchronized private static native void watch(int signo); + + public static void addSignalListener(SignalNo signo, SignalListener l) { + addSignalListener(signo.toInt(), l); + } + + synchronized private static native void addSignalListener(int signo, + SignalListener l); + + /** + * Stop checking for a specific signal + * + * @param signo The signal which you no longer want to catch + */ + public static void release(SignalNo signo) { + release(signo.toInt()); + } + + synchronized private static native void release(int signo); + + /** + * See how many times a specific signal has be caught + * + * @param signo The signal which you are watching + */ + public static int caught(SignalNo signo) { + return caught(signo.toInt()); + } + + synchronized private static native int caught(int signo); + + /** + * Send a signal to a pid + * + * @param signo The signal which you are sending + */ + public static void send(int pid, SignalNo signo) { + send(pid, signo.toInt()); + } + + synchronized private static native void send(int pid, int signo); + + static { + if (File.separatorChar == '/') + System.loadLibrary("osutil"); + } + +} + + +/** + * This class implements an enumerated type for signal values. It's hidden + * from users who must use the static values defined in the Signal class. + */ +class SignalNo { + private int mSignalNumber = 0; + + /** + * Construct a SignalNo from an integer + */ + public SignalNo(int signo) { + mSignalNumber = signo; + } + + /** + * Return the integer equivalent of a signal + */ + public int toInt() { + return mSignalNumber; + } +} diff --git a/pki/base/osutil/src/com/netscape/osutil/SignalListener.java b/pki/base/osutil/src/com/netscape/osutil/SignalListener.java new file mode 100644 index 000000000..c13cdfd06 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/SignalListener.java @@ -0,0 +1,30 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +/** + * This class is a very simpy Java wrapper around Posix/Unix signals. + * The interface allows the programmer to catch a signal and check to + * see how many times the signal has been received. + */ +public class SignalListener { + public void process() { + } +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/UserID.c b/pki/base/osutil/src/com/netscape/osutil/UserID.c new file mode 100644 index 000000000..a48e8eb8b --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/UserID.c @@ -0,0 +1,166 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/* + * Native wrappers for setuid/getuid + */ + +#include <jni.h> +#include "com_netscape_osutil_UserID.h" +#include "unixdefs.h" +#include <unistd.h> +#include <sys/types.h> +#include <pwd.h> +#include <errno.h> +#include <stdlib.h> + +/* + * Throw an IllegalArgumentException + */ +void +unix_throw_exception(JNIEnv *env, char *exception, char *reason) +{ + jclass exc; + + exc = (*env)->FindClass(env, exception); + if (exc) /* If unable to find the new exception class, give up. */ + (*env)->ThrowNew(env, exc, reason); +} + +/* + * Convert a jstring name into a uid_t value + */ +static uid_t +name_to_uid(JNIEnv *env, jstring name) +{ + const char *username = (*env)->GetStringUTFChars(env, name, 0); + struct passwd *pw; + int ret; + + if (NULL == username) { + unix_throw_exception(env, ILLARG, "can't convert username"); + return -1; + } + + pw = getpwnam(username); + + if (NULL == pw) { + /* XXX I suppose the failed user name would be useful here */ + unix_throw_exception(env, ILLARG, "no such user"); + return -1; + } + + ret = pw->pw_uid; + free(pw); + return ret; +} + +/* + * Class: com_netscape_osutil_UserID + * Method: get + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_UserID_get(JNIEnv *env, jclass cls) +{ + return getuid(); +} + +/* + * Class: com_netscape_certsrv_unix_UserID + * Method: getEffective + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_com_netscape_osutil_UserID_getEffective(JNIEnv *env, jclass cls) +{ + return geteuid(); +} + +/* + * Class: com_netscape_certsrv_unix_UserID + * Method: set + * Signature: (I)Z + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_UserID_set__I(JNIEnv *env, jclass cls, jint id) +{ + int status = setuid(id); + + if (status != 0) { + switch (errno) { + case EINVAL: + unix_throw_exception(env, ILLARG, "bad uid value"); + break; + case EPERM: + unix_throw_exception(env, SECURITY, "permission denied"); + break; + } + } +} + +/* + * Class: com_netscape_certsrv_unix_UserID + * Method: set + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_UserID_set__Ljava_lang_String_2(JNIEnv *env, jclass cls, jstring name) +{ + int id = name_to_uid(env, name); + + if (id >= 0) + Java_com_netscape_osutil_UserID_set__I(env, cls, id); +} + +/* + * Class: com_netscape_certsrv_unix_UserID + * Method: setEffective + * Signature: (I)Z + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_UserID_setEffective__I(JNIEnv *env, jclass cls, jint id) +{ + int status = seteuid(id); + + if (status != 0) { + switch (errno) { + case EINVAL: + unix_throw_exception(env, ILLARG, "bad uid value"); + break; + case EPERM: + unix_throw_exception(env, SECURITY, "permission denied"); + break; + } + } +} + +/* + * Class: com_netscape_certsrv_unix_UserID + * Method: setEffective + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT void JNICALL +Java_com_netscape_osutil_UserID_setEffective__Ljava_lang_String_2(JNIEnv *env, jclass cls, jstring name) +{ + int id = name_to_uid(env, name); + + if (id >= 0) + Java_com_netscape_osutil_UserID_setEffective__I(env, cls, id); +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/UserID.java b/pki/base/osutil/src/com/netscape/osutil/UserID.java new file mode 100644 index 000000000..b1842500d --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/UserID.java @@ -0,0 +1,73 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.osutil; + + +import java.io.*; + + +/** + * This class is a simple reflection of the Unix getuid/setuid + * functionality + */ +public class UserID { + + /** + * Return the current real user ID of the JavaVM + */ + public static native int get(); + + /** + * Return the current effective user ID of the JavaVM + */ + public static native int getEffective(); + + /** + * Set the current real user ID of the JavaVM + * + * @param id the user id + */ + public static native void set(int id); + + /** + * Set the current real user ID of the JavaVM + * + * @param user the user name + */ + public static native void set(String user); + + /** + * Set the current effective user ID of the JavaVM + * + * @param id the user id + */ + public static native void setEffective(int id); + + /** + * Set the current effective user ID of the JavaVM + * + * @param user the user name + */ + public static native void setEffective(String user); + + static { + if (File.separatorChar == '/') + System.loadLibrary("osutil"); + } +} + diff --git a/pki/base/osutil/src/com/netscape/osutil/unixdefs.h b/pki/base/osutil/src/com/netscape/osutil/unixdefs.h new file mode 100644 index 000000000..35e3e2bd7 --- /dev/null +++ b/pki/base/osutil/src/com/netscape/osutil/unixdefs.h @@ -0,0 +1,14 @@ +/* ====================================================== +* Copyright (c) 1997 Netscape Communications Corporation +* This file contains proprietary information of Netscape Communications. +* Copying or reproduction without prior written approval is prohibited. +* ====================================================== */ + +/* Handy shared values */ + +#define ILLARG "java/lang/IllegalArgumentException" +#define SECURITY "java/lang/SecurityException" +#define RUNTIME "java/lang/Runtime" + +void unix_throw_exception(JNIEnv *env, char *exception, char *reason); + |