You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2019/05/28 09:46:55 UTC
svn commit: r1860225 [4/16] - in /tomee/deps/branches/commons-daemon: ./
src/ src/assembly/ src/changes/ src/docs/ src/main/ src/main/java/
src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/commons/ src/main/java/org/apache/commons/...
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/java.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/java.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/java.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/java.c Tue May 28 09:46:53 2019
@@ -0,0 +1,604 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jsvc.h"
+
+#ifdef OS_CYGWIN
+typedef long long __int64;
+#endif
+#include <unistd.h>
+#include <jni.h>
+
+#ifdef CHARSET_EBCDIC
+#ifdef OSD_POSIX
+#include <ascii_ebcdic.h>
+#define jsvc_xlate_to_ascii(b) _e2a(b)
+#define jsvc_xlate_from_ascii(b) _a2e(b)
+#endif
+#else
+#define jsvc_xlate_to_ascii(b) /* NOOP */
+#define jsvc_xlate_from_ascii(b) /* NOOP */
+#endif
+
+static JavaVM *jvm = NULL;
+static JNIEnv *env = NULL;
+static jclass cls = NULL;
+
+#define FALSE 0
+#define TRUE !FALSE
+
+static void shutdown(JNIEnv *env, jobject source, jboolean reload)
+{
+ log_debug("Shutdown requested (reload is %d)", reload);
+ if (reload == TRUE)
+ main_reload();
+ else
+ main_shutdown();
+}
+
+static void failed(JNIEnv *env, jobject source, jstring message)
+{
+ if (message) {
+ const char *msg = (*env)->GetStringUTFChars(env, message, NULL);
+ log_error("Failed %s", msg ? msg : "(null)");
+ if (msg)
+ (*env)->ReleaseStringUTFChars(env, message, msg);
+ }
+ else
+ log_error("Failed requested");
+ main_shutdown();
+}
+
+/* Automatically restart when the JVM crashes */
+static void java_abort123(void)
+{
+ exit(123);
+}
+
+char *java_library(arg_data *args, home_data *data)
+{
+ char *libf = NULL;
+
+ /* Did we find ANY virtual machine? */
+ if (data->jnum == 0) {
+ log_error("Cannot find any VM in Java Home %s", data->path);
+ return NULL;
+ }
+
+ /* Select the VM */
+ if (args->name == NULL) {
+ libf = data->jvms[0]->libr;
+ log_debug("Using default JVM in %s", libf);
+ }
+ else {
+ int x;
+ for (x = 0; x < data->jnum; x++) {
+ if (data->jvms[x]->name == NULL)
+ continue;
+ if (strcmp(args->name, data->jvms[x]->name) == 0) {
+ libf = data->jvms[x]->libr;
+ log_debug("Using specific JVM in %s", libf);
+ break;
+ }
+ }
+ if (libf == NULL) {
+ log_error("Invalid JVM name specified %s", args->name);
+ return NULL;
+ }
+ }
+ return libf;
+}
+
+typedef jint (*jvm_create_t)(JavaVM **, JNIEnv **, JavaVMInitArgs *);
+
+bool java_signal(void)
+{
+ jmethodID method;
+ jboolean ret;
+ char start[] = "signal";
+ char startparams[] = "()Z";
+
+ jsvc_xlate_to_ascii(start);
+ jsvc_xlate_to_ascii(startparams);
+ method = (*env)->GetStaticMethodID(env, cls, start, startparams);
+ if (method == NULL) {
+ (*env)->ExceptionClear(env);
+ log_error("Cannot find DaemonLoader \"signal\" method");
+ return false;
+ }
+
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method);
+ /* Clear any pending exception
+ * so we can continue calling native methods
+ */
+ (*env)->ExceptionClear(env);
+ log_debug("Daemon signal method returned %s", ret ? "true" : "false");
+ return ret;
+}
+
+/* Initialize the JVM and its environment, loading libraries and all */
+bool java_init(arg_data *args, home_data *data)
+{
+#ifdef OS_DARWIN
+ dso_handle apph = NULL;
+ char appf[1024];
+ struct stat sb;
+#endif /* ifdef OS_DARWIN */
+ jvm_create_t symb = NULL;
+ JNINativeMethod nativemethods[2];
+ JavaVMOption *opt = NULL;
+ dso_handle libh = NULL;
+ JavaVMInitArgs arg;
+ char *libf = NULL;
+ jint ret;
+ int x;
+ char loaderclass[] = LOADER;
+ char shutdownmethod[] = "shutdown";
+ char shutdownparams[] = "(Z)V";
+ char failedmethod[] = "failed";
+ char failedparams[] = "(Ljava/lang/String;)V";
+ char daemonprocid[64];
+ /* Decide WHAT virtual machine we need to use */
+ libf = java_library(args, data);
+ if (libf == NULL) {
+ log_error("Cannot locate JVM library file");
+ return false;
+ }
+
+ /* Initialize the DSO library */
+ if (dso_init() != true) {
+ log_error("Cannot initialize the dynamic library loader");
+ return false;
+ }
+
+ /* Load the JVM library */
+#if !defined(OSD_POSIX)
+ libh = dso_link(libf);
+ if (libh == NULL) {
+ log_error("Cannot dynamically link to %s", libf);
+ log_error("%s", dso_error());
+ return false;
+ }
+ log_debug("JVM library %s loaded", libf);
+#endif
+
+#ifdef OS_DARWIN
+ /*
+ MacOS/X actually has two libraries, one with the REAL vm, and one for
+ the VM startup.
+ - JVM 1.6, the library name is libverify.dylib
+ - JVM 1.7 onwards, the library name is libjli.dylib
+ */
+ if (replace(appf, 1024, "$JAVA_HOME/../Libraries/libverify.dylib",
+ "$JAVA_HOME", data->path) != 0) {
+ log_error("Cannot replace values in loader library");
+ return false;
+ }
+ if (stat(appf, &sb)) {
+ if (replace(appf, 1024, "$JAVA_HOME/../MacOS/libjli.dylib",
+ "$JAVA_HOME", data->path) != 0) {
+ log_error("Cannot replace values in loader library");
+ return false;
+ }
+ }
+ apph = dso_link(appf);
+ if (apph == NULL) {
+ log_error("Cannot load required shell library %s", appf);
+ return false;
+ }
+ log_debug("Shell library %s loaded", appf);
+#endif /* ifdef OS_DARWIN */
+#if defined(OSD_POSIX)
+ /* BS2000 does not allow to call JNI_CreateJavaVM indirectly */
+#else
+ symb = (jvm_create_t)dso_symbol(libh, "JNI_CreateJavaVM");
+ if (symb == NULL) {
+#ifdef OS_DARWIN
+ symb = (jvm_create_t)dso_symbol(apph, "JNI_CreateJavaVM");
+ if (symb == NULL) {
+#endif /* ifdef OS_DARWIN */
+ log_error("Cannot find JVM library entry point");
+ return false;
+#ifdef OS_DARWIN
+ }
+#endif /* ifdef OS_DARWIN */
+ }
+ log_debug("JVM library entry point found (0x%08X)", symb);
+#endif
+
+ /* Prepare the VM initialization arguments */
+
+ /* Minimum Java version is Java 6 */
+ arg.version = JNI_VERSION_1_6;
+
+#if defined(OSD_POSIX)
+ if (JNI_GetDefaultJavaVMInitArgs(&arg) < 0) {
+ log_error("Cannot init default JVM default args");
+ return false;
+ }
+#endif
+ arg.ignoreUnrecognized = FALSE;
+ arg.nOptions = args->onum + 5; /* pid, ppid, version, class and abort */
+ opt = (JavaVMOption *) malloc(arg.nOptions * sizeof(JavaVMOption));
+ for (x = 0; x < args->onum; x++) {
+ opt[x].optionString = strdup(args->opts[x]);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x].extraInfo = NULL;
+ }
+ /* Add our daemon process id */
+ snprintf(daemonprocid, sizeof(daemonprocid),
+ "-Dcommons.daemon.process.id=%d", (int)getpid());
+ opt[x].optionString = strdup(daemonprocid);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x++].extraInfo = NULL;
+
+ snprintf(daemonprocid, sizeof(daemonprocid),
+ "-Dcommons.daemon.process.parent=%d", (int)getppid());
+ opt[x].optionString = strdup(daemonprocid);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x++].extraInfo = NULL;
+
+ snprintf(daemonprocid, sizeof(daemonprocid),
+ "-Dcommons.daemon.version=%s", JSVC_VERSION_STRING);
+ opt[x].optionString = strdup(daemonprocid);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x++].extraInfo = NULL;
+
+ /* DBCP-388. For the benefit of jconsole. */
+ snprintf(daemonprocid, sizeof(daemonprocid),
+ "-Dsun.java.command=%s", args->clas);
+ opt[x].optionString = strdup(daemonprocid);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x++].extraInfo = NULL;
+
+ opt[x].optionString = strdup("abort");
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ opt[x].extraInfo = (void *)java_abort123;
+
+ arg.options = opt;
+
+ /* Do some debugging */
+ if (log_debug_flag == true) {
+ log_debug("+-- DUMPING JAVA VM CREATION ARGUMENTS -----------------");
+ log_debug("| Version: %#08x", arg.version);
+ log_debug("| Ignore Unrecognized Arguments: %s",
+ arg.ignoreUnrecognized == TRUE ? "True" : "False");
+ log_debug("| Extra options: %d", args->onum);
+
+ for (x = 0; x < args->onum; x++) {
+ jsvc_xlate_from_ascii(opt[x].optionString);
+ log_debug("| \"%s\" (0x%08x)", opt[x].optionString,
+ opt[x].extraInfo);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ }
+ log_debug("+-------------------------------------------------------");
+ log_debug("| Internal options: %d", arg.nOptions - args->onum);
+
+ for (; x < arg.nOptions; x++) {
+ jsvc_xlate_from_ascii(opt[x].optionString);
+ log_debug("| \"%s\" (0x%08x)", opt[x].optionString,
+ opt[x].extraInfo);
+ jsvc_xlate_to_ascii(opt[x].optionString);
+ }
+ log_debug("+-------------------------------------------------------");
+ }
+
+ /* And finally create the Java VM */
+#if defined(OSD_POSIX)
+ ret = JNI_CreateJavaVM(&jvm, &env, &arg);
+#else
+ ret = (*symb) (&jvm, &env, &arg);
+#endif
+ if (ret < 0) {
+ log_error("Cannot create Java VM");
+ return false;
+ }
+ log_debug("Java VM created successfully");
+
+ jsvc_xlate_to_ascii(loaderclass);
+ cls = (*env)->FindClass(env, loaderclass);
+ jsvc_xlate_from_ascii(loaderclass);
+ if (cls == NULL) {
+ log_error("Cannot find daemon loader %s", loaderclass);
+ return false;
+ }
+ log_debug("Class %s found", loaderclass);
+
+ jsvc_xlate_to_ascii(shutdownmethod);
+ nativemethods[0].name = shutdownmethod;
+ jsvc_xlate_to_ascii(shutdownparams);
+ nativemethods[0].signature = shutdownparams;
+ nativemethods[0].fnPtr = (void *)shutdown;
+ jsvc_xlate_to_ascii(failedmethod);
+ nativemethods[1].name = failedmethod;
+ jsvc_xlate_to_ascii(failedparams);
+ nativemethods[1].signature = failedparams;
+ nativemethods[1].fnPtr = (void *)failed;
+
+ if ((*env)->RegisterNatives(env, cls, nativemethods, 2) != 0) {
+ log_error("Cannot register native methods");
+ return false;
+ }
+ log_debug("Native methods registered");
+
+ return true;
+}
+
+/* Destroy the Java VM */
+bool JVM_destroy(int exit)
+{
+ jclass system = NULL;
+ jmethodID method;
+ char System[] = "java/lang/System";
+ char exitclass[] = "exit";
+ char exitparams[] = "(I)V";
+
+ jsvc_xlate_to_ascii(System);
+ system = (*env)->FindClass(env, System);
+ jsvc_xlate_from_ascii(System);
+ if (system == NULL) {
+ log_error("Cannot find class %s", System);
+ return false;
+ }
+
+ jsvc_xlate_to_ascii(exitclass);
+ jsvc_xlate_to_ascii(exitparams);
+ method = (*env)->GetStaticMethodID(env, system, exitclass, exitparams);
+ if (method == NULL) {
+ log_error("Cannot find \"System.exit(int)\" entry point");
+ return false;
+ }
+
+ log_debug("Calling System.exit(%d)", exit);
+ (*env)->CallStaticVoidMethod(env, system, method, (jint) exit);
+
+ /* We shouldn't get here, but just in case... */
+ log_debug("Destroying the Java VM");
+ if ((*jvm)->DestroyJavaVM(jvm) != 0)
+ return false;
+ log_debug("Java VM destroyed");
+ return true;
+}
+
+/* Call the load method in our DaemonLoader class */
+bool java_load(arg_data *args)
+{
+ jclass stringClass = NULL;
+ jstring className = NULL;
+ jstring currentArgument = NULL;
+ jobjectArray stringArray = NULL;
+ jmethodID method = NULL;
+ jboolean ret = FALSE;
+ int x;
+ char lang[] = "java/lang/String";
+ char load[] = "load";
+ char loadparams[] = "(Ljava/lang/String;[Ljava/lang/String;)Z";
+
+ jsvc_xlate_to_ascii(args->clas);
+ className = (*env)->NewStringUTF(env, args->clas);
+ jsvc_xlate_from_ascii(args->clas);
+ if (className == NULL) {
+ log_error("Cannot create string for class name");
+ return false;
+ }
+
+ jsvc_xlate_to_ascii(lang);
+ stringClass = (*env)->FindClass(env, lang);
+ if (stringClass == NULL) {
+ log_error("Cannot find class java/lang/String");
+ return false;
+ }
+
+ stringArray = (*env)->NewObjectArray(env, args->anum, stringClass, NULL);
+ if (stringArray == NULL) {
+ log_error("Cannot create arguments array");
+ return false;
+ }
+
+ for (x = 0; x < args->anum; x++) {
+ jsvc_xlate_to_ascii(args->args[x]);
+ currentArgument = (*env)->NewStringUTF(env, args->args[x]);
+ if (currentArgument == NULL) {
+ jsvc_xlate_from_ascii(args->args[x]);
+ log_error("Cannot create string for argument %s", args->args[x]);
+ return false;
+ }
+ (*env)->SetObjectArrayElement(env, stringArray, x, currentArgument);
+ }
+
+ jsvc_xlate_to_ascii(load);
+ jsvc_xlate_to_ascii(loadparams);
+ method = (*env)->GetStaticMethodID(env, cls, load, loadparams);
+ if (method == NULL) {
+ log_error("Cannot find Daemon Loader \"load\" entry point");
+ return false;
+ }
+
+ log_debug("Daemon loading...");
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method, className,
+ stringArray);
+ if (ret == FALSE) {
+ log_error("Cannot load daemon");
+ return false;
+ }
+
+ log_debug("Daemon loaded successfully");
+ return true;
+}
+
+/* Call the start method in our daemon loader */
+bool java_start(void)
+{
+ jmethodID method;
+ jboolean ret;
+ char start[] = "start";
+ char startparams[] = "()Z";
+
+ jsvc_xlate_to_ascii(start);
+ jsvc_xlate_to_ascii(startparams);
+ method = (*env)->GetStaticMethodID(env, cls, start, startparams);
+ if (method == NULL) {
+ log_error("Cannot find Daemon Loader \"start\" entry point");
+ return false;
+ }
+
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method);
+ if (ret == FALSE) {
+ log_error("Cannot start daemon");
+ return false;
+ }
+
+ log_debug("Daemon started successfully");
+ return true;
+}
+
+/*
+ * call the java sleep to prevent problems with threads
+ */
+void java_sleep(int wait)
+{
+ jclass clsThread;
+ jmethodID method;
+ char jsleep[] = "sleep";
+ char jsleepparams[] = "(J)V";
+ char jthread[] = "java/lang/Thread";
+
+ jsvc_xlate_to_ascii(jsleep);
+ jsvc_xlate_to_ascii(jsleepparams);
+ jsvc_xlate_to_ascii(jthread);
+
+ clsThread = (*env)->FindClass(env, jthread);
+ if (clsThread == NULL) {
+ log_error("Cannot find java/lang/Thread class");
+ return;
+ }
+ method = (*env)->GetStaticMethodID(env, clsThread, jsleep, jsleepparams);
+ if (method == NULL) {
+ log_error("Cannot found the sleep entry point");
+ return;
+ }
+
+ (*env)->CallStaticVoidMethod(env, clsThread, method, (jlong) wait * 1000);
+}
+
+/* Call the stop method in our daemon loader */
+bool java_stop(void)
+{
+ jmethodID method;
+ jboolean ret;
+ char stop[] = "stop";
+ char stopparams[] = "()Z";
+
+ jsvc_xlate_to_ascii(stop);
+ jsvc_xlate_to_ascii(stopparams);
+ method = (*env)->GetStaticMethodID(env, cls, stop, stopparams);
+ if (method == NULL) {
+ log_error("Cannot found Daemon Loader \"stop\" entry point");
+ return false;
+ }
+
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method);
+ if (ret == FALSE) {
+ log_error("Cannot stop daemon");
+ return false;
+ }
+
+ log_debug("Daemon stopped successfully");
+ return true;
+}
+
+/* Call the version method in our daemon loader */
+bool java_version(void)
+{
+ jmethodID method;
+ char version[] = "version";
+ char versionparams[] = "()V";
+
+ jsvc_xlate_to_ascii(version);
+ jsvc_xlate_to_ascii(versionparams);
+ method = (*env)->GetStaticMethodID(env, cls, version, versionparams);
+ if (method == NULL) {
+ log_error("Cannot found Daemon Loader \"version\" entry point");
+ return false;
+ }
+
+ (*env)->CallStaticVoidMethod(env, cls, method);
+ return true;
+}
+
+/* Call the check method in our DaemonLoader class */
+bool java_check(arg_data *args)
+{
+ jstring className = NULL;
+ jmethodID method = NULL;
+ jboolean ret = FALSE;
+ char check[] = "check";
+ char checkparams[] = "(Ljava/lang/String;)Z";
+
+ log_debug("Checking daemon");
+
+ jsvc_xlate_to_ascii(args->clas);
+ className = (*env)->NewStringUTF(env, args->clas);
+ jsvc_xlate_from_ascii(args->clas);
+ if (className == NULL) {
+ log_error("Cannot create string for class name");
+ return false;
+ }
+
+ jsvc_xlate_to_ascii(check);
+ jsvc_xlate_to_ascii(checkparams);
+ method = (*env)->GetStaticMethodID(env, cls, check, checkparams);
+ if (method == NULL) {
+ log_error("Cannot found Daemon Loader \"check\" entry point");
+ return false;
+ }
+
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method, className);
+ if (ret == FALSE) {
+ log_error("An error was detected checking the %s daemon", args->clas);
+ return false;
+ }
+
+ log_debug("Daemon checked successfully");
+ return true;
+}
+
+/* Call the destroy method in our daemon loader */
+bool java_destroy(void)
+{
+ jmethodID method;
+ jboolean ret;
+ char destroy[] = "destroy";
+ char destroyparams[] = "()Z";
+
+ jsvc_xlate_to_ascii(destroy);
+ jsvc_xlate_to_ascii(destroyparams);
+ method = (*env)->GetStaticMethodID(env, cls, destroy, destroyparams);
+ if (method == NULL) {
+ log_error("Cannot found Daemon Loader \"destroy\" entry point");
+ return false;
+ }
+
+ ret = (*env)->CallStaticBooleanMethod(env, cls, method);
+ if (ret == FALSE) {
+ log_error("Cannot destroy daemon");
+ return false;
+ }
+
+ log_debug("Daemon destroyed successfully");
+ return true;
+}
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/java.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/java.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/java.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/java.h Tue May 28 09:46:53 2019
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __JSVC_JAVA_H__
+#define __JSVC_JAVA_H__
+
+#define LOADER "org/apache/commons/daemon/support/DaemonLoader"
+
+char *java_library(arg_data *args, home_data *data);
+bool java_init(arg_data *args, home_data *data);
+bool java_destroy(void);
+bool java_load(arg_data *args);
+bool java_signal(void);
+bool java_start(void);
+bool java_stop(void);
+bool java_version(void);
+bool java_check(arg_data *args);
+bool JVM_destroy(int exit);
+
+#endif /* __JSVC_JAVA_H__ */
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc-unix.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc-unix.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc-unix.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc-unix.c Tue May 28 09:46:53 2019
@@ -0,0 +1,1411 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jsvc.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <errno.h>
+#ifdef OS_LINUX
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#define _LINUX_FS_H
+#include <linux/capability.h>
+#ifdef HAVE_LIBCAP
+#include <sys/capability.h>
+#endif
+#endif
+#include <time.h>
+
+#ifdef OS_CYGWIN
+#include <sys/fcntl.h>
+#define F_ULOCK 0 /* Unlock a previously locked region */
+#define F_LOCK 1 /* Lock a region for exclusive use */
+#endif
+extern char **environ;
+
+static mode_t envmask; /* mask to create the files */
+
+pid_t controller_pid = 0; /* The parent process pid */
+pid_t controlled = 0; /* the child process pid */
+pid_t logger_pid = 0; /* the logger process pid */
+static volatile bool stopping = false;
+static volatile bool doreload = false;
+static bool doreopen = false;
+static bool dosignal = false;
+
+static int run_controller(arg_data *args, home_data *data, uid_t uid,
+ gid_t gid);
+static void set_output(char *outfile, char *errfile, bool redirectstdin,
+ char *procname);
+
+#ifdef OS_CYGWIN
+/*
+ * File locking routine
+ */
+static int lockf(int fildes, int function, off_t size)
+{
+ struct flock buf;
+
+ switch (function) {
+ case F_LOCK:
+ buf.l_type = F_WRLCK;
+ break;
+ case F_ULOCK:
+ buf.l_type = F_UNLCK;
+ break;
+ default:
+ return -1;
+ }
+ buf.l_whence = 0;
+ buf.l_start = 0;
+ buf.l_len = size;
+
+ return fcntl(fildes, F_SETLK, &buf);
+}
+
+#endif
+
+static void handler(int sig)
+{
+ switch (sig) {
+ case SIGTERM:
+ log_debug("Caught SIGTERM: Scheduling a shutdown");
+ if (stopping == true) {
+ log_error("Shutdown or reload already scheduled");
+ }
+ else {
+ stopping = true;
+ /* Ensure the controller knows a shutdown was requested. */
+ kill(controller_pid,sig);
+ }
+ break;
+ case SIGINT:
+ log_debug("Caught SIGINT: Scheduling a shutdown");
+ if (stopping == true) {
+ log_error("Shutdown or reload already scheduled");
+ }
+ else {
+ stopping = true;
+ /* Ensure the controller knows a shutdown was requested. */
+ kill(controller_pid,sig);
+ }
+ break;
+ case SIGHUP:
+ log_debug("Caught SIGHUP: Scheduling a reload");
+ if (stopping == true) {
+ log_error("Shutdown or reload already scheduled");
+ }
+ else {
+ stopping = true;
+ doreload = true;
+ }
+ break;
+ case SIGUSR1:
+ log_debug("Caught SIGUSR1: Reopening logs");
+ doreopen = true;
+ break;
+ case SIGUSR2:
+ log_debug("Caught SIGUSR2: Scheduling a custom signal");
+ dosignal = true;
+ break;
+ default:
+ log_debug("Caught unknown signal %d", sig);
+ break;
+ }
+}
+
+/* user and group */
+static int set_user_group(const char *user, int uid, int gid)
+{
+ if (user != NULL) {
+ if (setgid(gid) != 0) {
+ log_error("Cannot set group id for user '%s'", user);
+ return -1;
+ }
+ if (initgroups(user, gid) != 0) {
+ if (getuid() != uid) {
+ log_error("Cannot set supplement group list for user '%s'",
+ user);
+ return -1;
+ }
+ else
+ log_debug("Cannot set supplement group list for user '%s'",
+ user);
+ }
+ if (getuid() == uid) {
+ log_debug("No need to change user to '%s'!", user);
+ return 0;
+ }
+ if (setuid(uid) != 0) {
+ log_error("Cannot set user id for user '%s'", user);
+ return -1;
+ }
+ log_debug("user changed to '%s'", user);
+ }
+ return 0;
+}
+
+/* Set linux capability, user and group */
+#ifdef OS_LINUX
+/* CAPSALL is to allow to read/write at any location */
+#define LEGACY_CAPSALL (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_SETUID) + \
+ (1 << CAP_SETGID) + \
+ (1 << CAP_DAC_READ_SEARCH) + \
+ (1 << CAP_DAC_OVERRIDE)
+
+#define LEGACY_CAPSMAX (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_DAC_READ_SEARCH) + \
+ (1 << CAP_DAC_OVERRIDE)
+
+/* That a more reasonable configuration */
+#define LEGACY_CAPS (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_DAC_READ_SEARCH) + \
+ (1 << CAP_SETUID) + \
+ (1 << CAP_SETGID)
+
+/* probably the only one Java could use */
+#define LEGACY_CAPSMIN (1 << CAP_NET_BIND_SERVICE) + \
+ (1 << CAP_DAC_READ_SEARCH)
+
+#define LEGACY_CAP_VERSION 0x19980330
+static int set_legacy_caps(int caps)
+{
+ struct __user_cap_header_struct caphead;
+ struct __user_cap_data_struct cap;
+
+ memset(&caphead, 0, sizeof caphead);
+ caphead.version = LEGACY_CAP_VERSION;
+ caphead.pid = 0;
+ memset(&cap, 0, sizeof cap);
+ cap.effective = caps;
+ cap.permitted = caps;
+ cap.inheritable = caps;
+ if (syscall(__NR_capset, &caphead, &cap) < 0) {
+ log_error("set_caps: failed to set capabilities");
+ log_error("check that your kernel supports capabilities");
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef HAVE_LIBCAP
+static cap_value_t caps_std[] = {
+ CAP_NET_BIND_SERVICE,
+ CAP_SETUID,
+ CAP_SETGID,
+ CAP_DAC_READ_SEARCH
+};
+
+static cap_value_t caps_min[] = {
+ CAP_NET_BIND_SERVICE,
+ CAP_DAC_READ_SEARCH
+};
+
+#define CAPS 1
+#define CAPSMIN 2
+
+
+typedef int (*fd_cap_free)(void *);
+typedef cap_t (*fd_cap_init)(void);
+typedef int (*fd_cap_clear)(cap_t);
+typedef int (*fd_cap_get_flag)(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *);
+typedef int (*fd_cap_set_flag)(cap_t, cap_flag_t, int, const cap_value_t *, cap_flag_value_t);
+typedef int (*fd_cap_set_proc)(cap_t);
+
+static dso_handle hlibcap = NULL;
+static fd_cap_free fp_cap_free;
+static fd_cap_init fp_cap_init;
+static fd_cap_clear fp_cap_clear;
+static fd_cap_get_flag fp_cap_get_flag;
+static fd_cap_set_flag fp_cap_set_flag;
+static fd_cap_set_proc fp_cap_set_proc;
+
+static const char *libcap_locs[] = {
+#ifdef __LP64__
+ "/lib64/libcap.so.2",
+ "/lib64/libcap.so.1",
+ "/lib64/libcap.so",
+ "/usr/lib64/libcap.so.2",
+ "/usr/lib64/libcap.so.1",
+ "/usr/lib64/libcap.so",
+#endif
+ "/lib/libcap.so.2",
+ "/lib/libcap.so.1",
+ "/lib/libcap.so",
+ "/usr/lib/libcap.so.2",
+ "/usr/lib/libcap.so.1",
+ "/usr/lib/libcap.so",
+ "libcap.so.2",
+ "libcap.so.1",
+ "libcap.so",
+ NULL
+};
+
+static int ld_libcap(void)
+{
+ int i = 0;
+ dso_handle dso = NULL;
+#define CAP_LDD(name) \
+ if ((fp_##name = dso_symbol(dso, #name)) == NULL) { \
+ log_error("cannot locate " #name " in libcap.so -- %s", dso_error()); \
+ dso_unlink(dso); \
+ return -1; \
+ } else log_debug("loaded " #name " from libcap.")
+
+ if (hlibcap != NULL)
+ return 0;
+ while (libcap_locs[i] && dso == NULL) {
+ if ((dso = dso_link(libcap_locs[i++])))
+ break;
+ };
+ if (dso == NULL) {
+ log_error("failed loading capabilities library -- %s.", dso_error());
+ return -1;
+ }
+ CAP_LDD(cap_free);
+ CAP_LDD(cap_init);
+ CAP_LDD(cap_clear);
+
+ CAP_LDD(cap_get_flag);
+ CAP_LDD(cap_set_flag);
+ CAP_LDD(cap_set_proc);
+ hlibcap = dso;
+#undef CAP_LDD
+ return 0;
+}
+
+
+static int set_caps(int cap_type)
+{
+ cap_t c;
+ int ncap;
+ int flag = CAP_SET;
+ cap_value_t *caps;
+ const char *type;
+
+ if (ld_libcap()) {
+ return set_legacy_caps(cap_type);
+ }
+ if (cap_type == CAPS) {
+ ncap = sizeof(caps_std)/sizeof(cap_value_t);
+ caps = caps_std;
+ type = "default";
+ }
+ else if (cap_type == CAPSMIN) {
+ ncap = sizeof(caps_min)/sizeof(cap_value_t);
+ caps = caps_min;
+ type = "min";
+ }
+ else {
+ ncap = sizeof(caps_min)/sizeof(cap_value_t);
+ caps = caps_min;
+ type = "null";
+ flag = CAP_CLEAR;
+ }
+ c = (*fp_cap_init)();
+ (*fp_cap_clear)(c);
+ (*fp_cap_set_flag)(c, CAP_EFFECTIVE, ncap, caps, flag);
+ (*fp_cap_set_flag)(c, CAP_INHERITABLE, ncap, caps, flag);
+ (*fp_cap_set_flag)(c, CAP_PERMITTED, ncap, caps, flag);
+ if ((*fp_cap_set_proc)(c) != 0) {
+ log_error("failed setting %s capabilities.", type);
+ return -1;
+ }
+ (*fp_cap_free)(c);
+ if (cap_type == CAPS)
+ log_debug("increased capability set.");
+ else if (cap_type == CAPSMIN)
+ log_debug("decreased capability set to min required.");
+ else
+ log_debug("dropped capabilities.");
+ return 0;
+}
+
+#else /* !HAVE_LIBCAP */
+/* CAPSALL is to allow to read/write at any location */
+#define CAPSALL LEGACY_CAPSALL
+#define CAPSMAX LEGACY_CAPSMAX
+#define CAPS LEGACY_CAPS
+#define CAPSMIN LEGACY_CAPSMIN
+static int set_caps(int caps)
+{
+ return set_legacy_caps(caps);
+}
+#endif
+
+static int linuxset_user_group(const char *user, int uid, int gid)
+{
+ int caps_set = 0;
+
+ if (user == NULL)
+ return 0;
+ /* set capabilities enough for binding port 80 setuid/getuid */
+ if (getuid() == 0) {
+ if (set_caps(CAPS) != 0) {
+ if (getuid() != uid) {
+ log_error("set_caps(CAPS) failed for user '%s'", user);
+ return -1;
+ }
+ log_debug("set_caps(CAPS) failed for user '%s'", user);
+ }
+ /* make sure they are kept after setuid */
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
+ log_error("prctl failed in for user '%s'", user);
+ return -1;
+ }
+ caps_set = 1;
+ }
+
+ /* set setuid/getuid */
+ if (set_user_group(user, uid, gid) != 0) {
+ log_error("set_user_group failed for user '%s'", user);
+ return -1;
+ }
+
+ if (caps_set) {
+ /* set capability to binding port 80 read conf */
+ if (set_caps(CAPSMIN) != 0) {
+ if (getuid() != uid) {
+ log_error("set_caps(CAPSMIN) failed for user '%s'", user);
+ return -1;
+ }
+ log_debug("set_caps(CAPSMIN) failed for user '%s'", user);
+ }
+ }
+
+ return 0;
+}
+#endif
+
+
+static bool checkuser(char *user, uid_t * uid, gid_t * gid)
+{
+ struct passwd *pwds = NULL;
+ int status = 0;
+ pid_t pid = 0;
+
+ /* Do we actually _have_ to switch user? */
+ if (user == NULL)
+ return true;
+
+ pwds = getpwnam(user);
+ if (pwds == NULL) {
+ log_error("Invalid user name '%s' specified", user);
+ return false;
+ }
+
+ *uid = pwds->pw_uid;
+ *gid = pwds->pw_gid;
+
+ /* Validate the user name in another process */
+ pid = fork();
+ if (pid == -1) {
+ log_error("Cannot validate user name");
+ return false;
+ }
+
+ /* If we're in the child process, let's validate */
+ if (pid == 0) {
+ if (set_user_group(user, *uid, *gid) != 0)
+ exit(1);
+ /* If we got here we switched user/group */
+ exit(0);
+ }
+
+ while (waitpid(pid, &status, 0) != pid) {
+ /* Just wait */
+ }
+
+ /* The child must have exited cleanly */
+ if (WIFEXITED(status)) {
+ status = WEXITSTATUS(status);
+
+ /* If the child got out with 0 the user is ok */
+ if (status == 0) {
+ log_debug("User '%s' validated", user);
+ return true;
+ }
+ }
+
+ log_error("Error validating user '%s'", user);
+ return false;
+}
+
+#ifdef OS_CYGWIN
+static void cygwincontroller(void)
+{
+ raise(SIGTERM);
+}
+#endif
+static void controller(int sig, siginfo_t *sip, void *ucp)
+{
+ switch (sig) {
+ case SIGTERM:
+ case SIGINT:
+ if (!stopping) {
+ /*
+ * Only forward a signal that requests shutdown once (the
+ * issue being that the child also forwards the signal to
+ * the parent and we need to avoid loops).
+ *
+ * Note that there are * two * instances of the stopping
+ * variable ... one in the parent and the second in the
+ * child.
+ */
+ stopping = true;
+ if (sip == NULL
+ || !(sip->si_code <= 0 && sip->si_pid == controlled)) {
+ log_debug("Forwarding signal %d to process %d", sig,
+ controlled);
+ kill(controlled, sig);
+ }
+ }
+ break;
+ case SIGHUP:
+ case SIGUSR1:
+ case SIGUSR2:
+ log_debug("Forwarding signal %d to process %d", sig, controlled);
+ kill(controlled, sig);
+ break;
+ default:
+ log_debug("Caught unknown signal %d", sig);
+ break;
+ }
+}
+
+static int mkdir0(const char *name, int perms)
+{
+ if (mkdir(name, perms) == 0)
+ return 0;
+ else
+ return errno;
+}
+
+static int mkdir1(char *name, int perms)
+{
+ int rc;
+
+ rc = mkdir0(name, perms);
+ if (rc == EEXIST)
+ return 0;
+ if (rc == ENOENT) { /* Missing an intermediate dir */
+ char *pos;
+ if ((pos = strrchr(name, '/'))) {
+ *pos = '\0';
+ if (*name) {
+ if (!(rc = mkdir1(name, perms))) {
+ /* Try again, now with parents created
+ */
+ *pos = '/';
+ rc = mkdir0(name, perms);
+ }
+ }
+ *pos = '/';
+ }
+ }
+ return rc;
+}
+
+static int mkdir2(const char *name, int perms)
+{
+ int rc = 0;
+ char *pos;
+ char *dir = strdup(name);
+
+ if (!dir)
+ return ENOMEM;
+ if ((pos = strrchr(dir, '/'))) {
+ *pos = '\0';
+ if (*dir)
+ rc = mkdir1(dir, perms);
+ }
+ free(dir);
+ return rc;
+}
+
+/*
+ * Check pid and if still running
+ */
+
+static int check_pid(arg_data *args)
+{
+ int fd;
+ FILE *pidf;
+ char buff[80];
+ pid_t pidn = getpid();
+ int i, pid;
+ int once = 0;
+
+ /* skip writing the pid file if version or check */
+ if (args->vers || args->chck) {
+ return 0;
+ }
+
+retry:
+ fd = open(args->pidf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (fd < 0) {
+ if (once == 0 && (errno == ENOTDIR || errno == ENOENT)) {
+ once = 1;
+ if (mkdir2(args->pidf, S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH) == 0)
+ goto retry;
+ }
+ log_error("Cannot open PID file %s, PID is %d", args->pidf, pidn);
+ return -1;
+ }
+ else {
+ lockf(fd, F_LOCK, 0);
+ i = read(fd, buff, sizeof(buff));
+ if (i > 0) {
+ buff[i] = '\0';
+ pid = atoi(buff);
+ if (kill(pid, 0) == 0) {
+ log_error("Still running according to PID file %s, PID is %d",
+ args->pidf, pid);
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+ return 122;
+ }
+ }
+ lseek(fd, SEEK_SET, 0);
+ pidf = fdopen(fd, "r+");
+ fprintf(pidf, "%d\n", (int)getpid());
+ fflush(pidf);
+ fclose(pidf);
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+ }
+ return 0;
+}
+
+/*
+ * Delete the pid file
+ */
+static void remove_pid_file(arg_data *args, int pidn)
+{
+ char buff[80];
+ int fd, i, pid;
+
+ fd = open(args->pidf, O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ log_debug("remove_pid_file: open %s: fd=%d", args->pidf, fd);
+ if (fd < 0) {
+ return;
+ }
+ lockf(fd, F_LOCK, 0);
+ i = read(fd, buff, sizeof(buff));
+ if (i > 0) {
+ buff[i] = '\0';
+ pid = atoi(buff);
+ } else {
+ pid = -1;
+ }
+ if (pid == pidn) {
+ /* delete the file while it's still locked */
+ unlink(args->pidf);
+ } else {
+ log_debug("remove_pid_file: pid changed (%d->%d), not removing pid file %s",
+ pidn, pid, args->pidf);
+ }
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+}
+
+/*
+ * read the pid from the pidfile
+ */
+static int get_pidf(arg_data *args, bool quiet)
+{
+ int fd;
+ int i;
+ char buff[80];
+
+ fd = open(args->pidf, O_RDONLY, 0);
+ if (!quiet)
+ log_debug("get_pidf: %d in %s", fd, args->pidf);
+ if (fd < 0) {
+ /* something has gone wrong the JVM has stopped */
+ return -1;
+ }
+ lockf(fd, F_LOCK, 0);
+ i = read(fd, buff, sizeof(buff));
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+ if (i > 0) {
+ buff[i] = '\0';
+ i = atoi(buff);
+ if (!quiet)
+ log_debug("get_pidf: pid %d", i);
+ if (kill(i, 0) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
+ * Check temporatory file created by controller
+ * /tmp/pid.jsvc_up
+ * Notes:
+ * we fork several times
+ * 1 - to be a daemon before the setsid(), the child is the controler process.
+ * 2 - to start the JVM in the child process. (whose pid is stored in pidfile).
+ */
+static int check_tmp_file(arg_data *args)
+{
+ int pid;
+ char buff[80];
+ int fd;
+
+ pid = get_pidf(args, false);
+ if (pid < 0)
+ return -1;
+ sprintf(buff, "/tmp/%d.jsvc_up", pid);
+ log_debug("check_tmp_file: %s", buff);
+ fd = open(buff, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ close(fd);
+ return 0;
+}
+
+static void create_tmp_file(arg_data *args)
+{
+ char buff[80];
+ int fd;
+
+ sprintf(buff, "/tmp/%d.jsvc_up", (int)getpid());
+ log_debug("create_tmp_file: %s", buff);
+ fd = open(buff, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd != -1)
+ close(fd);
+}
+
+static void remove_tmp_file(arg_data *args)
+{
+ char buff[80];
+
+ sprintf(buff, "/tmp/%d.jsvc_up", (int)getpid());
+ log_debug("remove_tmp_file: %s", buff);
+ unlink(buff);
+}
+
+/*
+ * wait until jsvc create the I am ready file
+ * pid is the controller and args->pidf the JVM itself.
+ */
+static int wait_child(arg_data *args, int pid)
+{
+ int count = 10;
+ bool havejvm = false;
+ int fd;
+ char buff[80];
+ int i, status, waittime;
+
+ log_debug("wait_child %d", pid);
+ waittime = args->wait / 10;
+ if (waittime > 10) {
+ count = waittime;
+ waittime = 10;
+ }
+ while (count > 0) {
+ sleep(1);
+ /* check if the controler is still running */
+ if (waitpid(pid, &status, WNOHANG) == pid) {
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ else
+ return 1;
+ }
+
+ /* check if the pid file process exists */
+ fd = open(args->pidf, O_RDONLY);
+ if (fd < 0 && havejvm) {
+ /* something has gone wrong the JVM has stopped */
+ return 1;
+ }
+ lockf(fd, F_LOCK, 0);
+ i = read(fd, buff, sizeof(buff));
+ lockf(fd, F_ULOCK, 0);
+ close(fd);
+ if (i > 0) {
+ buff[i] = '\0';
+ i = atoi(buff);
+ if (kill(i, 0) == 0) {
+ /* the JVM process has started */
+ havejvm = true;
+ if (check_tmp_file(args) == 0) {
+ /* the JVM is started */
+ if (waitpid(pid, &status, WNOHANG) == pid) {
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ else
+ return 1;
+ }
+ return 0; /* ready JVM started */
+ }
+ }
+ }
+ sleep(waittime);
+ count--;
+ }
+ /* It takes more than the wait time to start,
+ * something must be wrong
+ */
+ return 1;
+}
+
+/*
+ * stop the running jsvc
+ */
+static int stop_child(arg_data *args)
+{
+ int pid = get_pidf(args, false);
+ int count = 60;
+
+ if (pid > 0) {
+ /* kill the process and wait until the pidfile has been
+ * removed by the controler
+ */
+ kill(pid, SIGTERM);
+ while (count > 0) {
+ sleep(1);
+ pid = get_pidf(args, true);
+ if (pid <= 0) {
+ /* JVM has stopped */
+ return 0;
+ }
+ count--;
+ }
+ }
+ return -1;
+}
+
+/*
+ * child process logic.
+ */
+
+static int child(arg_data *args, home_data *data, uid_t uid, gid_t gid)
+{
+ int ret = 0;
+ struct sigaction act;
+
+ /* check the pid file */
+ ret = check_pid(args);
+ if (args->vers != true && args->chck != true) {
+ if (ret == 122)
+ return ret;
+ if (ret < 0)
+ return ret;
+ }
+
+#ifdef OS_LINUX
+ /* setuid()/setgid() only apply the current thread so we must do it now */
+ if (linuxset_user_group(args->user, uid, gid) != 0)
+ return 4;
+#endif
+ /* Initialize the Java VM */
+ if (java_init(args, data) != true) {
+ log_debug("java_init failed");
+ return 1;
+ }
+ else
+ log_debug("java_init done");
+
+ /* Check wether we need to dump the VM version */
+ if (args->vers == true) {
+ log_error("jsvc (Apache Commons Daemon) " JSVC_VERSION_STRING);
+ log_error("Copyright (c) 1999-2011 Apache Software Foundation.");
+ if (java_version() != true) {
+ return -1;
+ }
+ else
+ return 0;
+ }
+ /* Check wether we need to dump the VM version */
+ else if (args->vershow == true) {
+ if (java_version() != true) {
+ return 7;
+ }
+ }
+
+ /* Do we have to do a "check-only" initialization? */
+ if (args->chck == true) {
+ if (java_check(args) != true)
+ return 2;
+ printf("Service \"%s\" checked successfully\n", args->clas);
+ return 0;
+ }
+
+ /* Load the service */
+ if (java_load(args) != true) {
+ log_debug("java_load failed");
+ return 3;
+ }
+ else
+ log_debug("java_load done");
+
+ /* Downgrade user */
+#ifdef OS_LINUX
+ if (args->user && set_caps(0) != 0) {
+ log_debug("set_caps (0) failed");
+ return 4;
+ }
+#else
+ if (set_user_group(args->user, uid, gid) != 0)
+ return 4;
+#endif
+
+ /* Start the service */
+ if (java_start() != true) {
+ log_debug("java_start failed");
+ return 5;
+ }
+ else
+ log_debug("java_start done");
+
+ /* Install signal handlers */
+ memset(&act, '\0', sizeof(act));
+ act.sa_handler = handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
+ sigaction(SIGUSR2, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
+
+ log_debug("Waiting for a signal to be delivered");
+ create_tmp_file(args);
+ while (!stopping) {
+#if defined(OSD_POSIX)
+ java_sleep(60);
+ /* pause(); */
+#else
+ /* pause() is not threadsafe */
+ sleep(60);
+#endif
+ if(doreopen) {
+ doreopen = false;
+ set_output(args->outfile, args->errfile, args->redirectstdin, args->procname);
+ }
+ if(dosignal) {
+ dosignal = false;
+ java_signal();
+ }
+ }
+ remove_tmp_file(args);
+ log_debug("Shutdown or reload requested: exiting");
+
+ /* Stop the service */
+ if (java_stop() != true)
+ return 6;
+
+ if (doreload == true)
+ ret = 123;
+ else
+ ret = 0;
+
+ /* Destroy the service */
+ java_destroy();
+
+ /* Destroy the Java VM */
+ if (JVM_destroy(ret) != true)
+ return 7;
+
+ return ret;
+}
+
+/*
+ * freopen close the file first and then open the new file
+ * that is not very good if we are try to trace the output
+ * note the code assumes that the errors are configuration errors.
+ */
+static FILE *loc_freopen(char *outfile, char *mode, FILE * stream)
+{
+ FILE *ftest;
+
+ mkdir2(outfile, S_IRWXU);
+ ftest = fopen(outfile, mode);
+ if (ftest == NULL) {
+ fprintf(stderr, "Unable to redirect to %s\n", outfile);
+ return stream;
+ }
+ fclose(ftest);
+ return freopen(outfile, mode, stream);
+}
+
+#define LOGBUF_SIZE 1024
+
+/* Read from file descriptors. Log to syslog. */
+static int logger_child(int out_fd, int err_fd, char *procname)
+{
+ fd_set rfds;
+ struct timeval tv;
+ int retval, nfd = -1, rc = 0;
+ ssize_t n;
+ char buf[LOGBUF_SIZE];
+
+ if (out_fd == -1 && err_fd == -1)
+ return EINVAL;
+ if (out_fd == -1)
+ nfd = err_fd;
+ else if (err_fd == -1)
+ nfd = out_fd;
+ else
+ nfd = out_fd > err_fd ? out_fd : err_fd;
+ ++nfd;
+
+ openlog(procname, LOG_PID, LOG_DAEMON);
+
+ while (out_fd != -1 || err_fd != -1) {
+ FD_ZERO(&rfds);
+ if (out_fd != -1) {
+ FD_SET(out_fd, &rfds);
+ }
+ if (err_fd != -1) {
+ FD_SET(err_fd, &rfds);
+ }
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ retval = select(nfd, &rfds, NULL, NULL, &tv);
+ if (retval == -1) {
+ rc = errno;
+ syslog(LOG_ERR, "select: %s", strerror(errno));
+ /* If select failed no point to continue */
+ break;
+ }
+ else if (retval) {
+ if (out_fd != -1 && FD_ISSET(out_fd, &rfds)) {
+ do {
+ n = read(out_fd, buf, LOGBUF_SIZE-1);
+ } while (n == -1 && errno == EINTR);
+ if (n == -1) {
+ syslog(LOG_ERR, "read: %s", strerror(errno));
+ close(out_fd);
+ if (err_fd == -1)
+ break;
+ nfd = err_fd + 1;
+ out_fd = -1;
+ }
+ else if (n > 0 && buf[0] != '\n') {
+ buf[n] = 0;
+ syslog(LOG_INFO, "%s", buf);
+ }
+ }
+ if (err_fd != -1 && FD_ISSET(err_fd, &rfds)) {
+ do {
+ n = read(err_fd, buf, LOGBUF_SIZE-1);
+ } while (n == -1 && errno == EINTR);
+ if (n == -1) {
+ syslog(LOG_ERR, "read: %s", strerror(errno));
+ close(err_fd);
+ if (out_fd == -1)
+ break;
+ nfd = out_fd + 1;
+ err_fd = -1;
+ }
+ else if (n > 0 && buf[0] != '\n') {
+ buf[n] = 0;
+ syslog(LOG_ERR, "%s", buf);
+ }
+ }
+ }
+ }
+ return rc;
+}
+
+/**
+ * Redirect stdin, stdout, stderr.
+ */
+static void set_output(char *outfile, char *errfile, bool redirectstdin, char *procname)
+{
+ int out_pipe[2] = {-1, -1};
+ int err_pipe[2] = {-1, -1};
+ int fork_needed = 0;
+
+ if (redirectstdin == true) {
+ freopen("/dev/null", "r", stdin);
+ }
+
+ log_debug("redirecting stdout to %s and stderr to %s", outfile, errfile);
+
+ /* make sure the debug goes out */
+ if (log_debug_flag == true && strcmp(errfile, "/dev/null") == 0)
+ return;
+ if (strcmp(outfile, "&1") == 0 && strcmp(errfile, "&2") == 0)
+ return;
+ if (strcmp(outfile, "SYSLOG") == 0) {
+ freopen("/dev/null", "a", stdout);
+ /* Send stdout to syslog through a logger process */
+ if (pipe(out_pipe) == -1) {
+ log_error("cannot create stdout pipe: %s",
+ strerror(errno));
+ }
+ else {
+ fork_needed = 1;
+ log_stdout_syslog_flag = true;
+ }
+ }
+ else if (strcmp(outfile, "&2")) {
+ if (strcmp(outfile, "&1")) {
+ /* Redirect stdout to a file */
+ loc_freopen(outfile, "a", stdout);
+ }
+ }
+
+ if (strcmp(errfile, "SYSLOG") == 0) {
+ freopen("/dev/null", "a", stderr);
+ /* Send stderr to syslog through a logger process */
+ if (pipe(err_pipe) == -1) {
+ log_error("cannot create stderr pipe: %s",
+ strerror(errno));
+ }
+ else {
+ fork_needed = 1;
+ log_stderr_syslog_flag = true;
+ }
+ }
+ else if (strcmp(errfile, "&1")) {
+ if (strcmp(errfile, "&2")) {
+ /* Redirect stderr to a file */
+ loc_freopen(errfile, "a", stderr);
+ }
+ }
+ if (strcmp(errfile, "&1") == 0 && strcmp(outfile, "&1")) {
+ /*
+ * -errfile &1 -outfile foo
+ * Redirect stderr to stdout
+ */
+ close(2);
+ dup2(1, 2);
+ }
+ if (strcmp(outfile, "&2") == 0 && strcmp(errfile, "&2")) {
+ /*
+ * -outfile &2 -errfile foo
+ * Redirect stdout to stderr
+ */
+ close(1);
+ dup2(2, 1);
+ }
+
+ if (fork_needed) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ log_error("cannot create logger process: %s", strerror(errno));
+ }
+ else {
+ if (pid != 0) {
+ /* Parent process.
+ * Close child pipe endpoints.
+ */
+ logger_pid = pid;
+ if (out_pipe[0] != -1) {
+ close(out_pipe[0]);
+ if (dup2(out_pipe[1], 1) == -1) {
+ log_error("cannot redirect stdout to pipe for syslog: %s",
+ strerror(errno));
+ }
+ }
+ if (err_pipe[0] != -1) {
+ close(err_pipe[0]);
+ if (dup2(err_pipe[1], 2) == -1) {
+ log_error("cannot redirect stderr to pipe for syslog: %s",
+ strerror(errno));
+ }
+ }
+ }
+ else {
+ exit(logger_child(out_pipe[0], err_pipe[0], procname));
+ }
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ arg_data *args = NULL;
+ home_data *data = NULL;
+ pid_t pid = 0;
+ uid_t uid = 0;
+ gid_t gid = 0;
+ int res;
+
+ /* Parse command line arguments */
+ args = arguments(argc, argv);
+ if (args == NULL)
+ return 1;
+
+ /* Stop running jsvc if required */
+ if (args->stop == true)
+ return (stop_child(args));
+
+ /* Let's check if we can switch user/group IDs */
+ if (checkuser(args->user, &uid, &gid) == false)
+ return 1;
+
+ /* Retrieve JAVA_HOME layout */
+ data = home(args->home);
+ if (data == NULL)
+ return 1;
+
+ /* Check for help */
+ if (args->help == true) {
+ help(data);
+ return 0;
+ }
+
+#ifdef OS_LINUX
+ /* On some UNIX operating systems, we need to REPLACE this current
+ process image with another one (thru execve) to allow the correct
+ loading of VMs (notably this is for Linux). Set, replace, and go. */
+ if (strcmp(argv[0], args->procname) != 0) {
+ char *oldpath = getenv("LD_LIBRARY_PATH");
+ char *libf = java_library(args, data);
+ char *filename;
+ char buf[2048];
+ int ret;
+ char *tmp = NULL;
+ char *p1 = NULL;
+ char *p2 = NULL;
+
+ /* We don't want to use a form of exec() that searches the
+ * PATH, so require that argv[0] be either an absolute or
+ * relative path. Error out if this isn't the case.
+ */
+ tmp = strchr(argv[0], '/');
+ if (tmp == NULL) {
+ log_error("JSVC re-exec requires execution with an absolute or relative path");
+ return 1;
+ }
+
+ /*
+ * There is no need to change LD_LIBRARY_PATH
+ * if we were not able to find a path to libjvm.so
+ * (additionaly a strdup(NULL) cores dump on my machine).
+ */
+ if (libf != NULL) {
+ p1 = strdup(libf);
+ tmp = strrchr(p1, '/');
+ if (tmp != NULL)
+ tmp[0] = '\0';
+
+ p2 = strdup(p1);
+ tmp = strrchr(p2, '/');
+ if (tmp != NULL)
+ tmp[0] = '\0';
+
+ if (oldpath == NULL)
+ snprintf(buf, 2048, "%s:%s", p1, p2);
+ else
+ snprintf(buf, 2048, "%s:%s:%s", oldpath, p1, p2);
+
+ tmp = strdup(buf);
+ setenv("LD_LIBRARY_PATH", tmp, 1);
+
+ log_debug("Invoking w/ LD_LIBRARY_PATH=%s",
+ getenv("LD_LIBRARY_PATH"));
+ }
+
+ /* execve needs a full path */
+ ret = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (ret <= 0)
+ strcpy(buf, argv[0]);
+ else
+ buf[ret] = '\0';
+
+ filename = buf;
+
+ argv[0] = args->procname;
+ execve(filename, argv, environ);
+ log_error("Cannot execute JSVC executor process (%s)", filename);
+ return 1;
+ }
+ log_debug("Running w/ LD_LIBRARY_PATH=%s", getenv("LD_LIBRARY_PATH"));
+#endif /* ifdef OS_LINUX */
+
+ /* If we have to detach, let's do it now */
+ if (args->dtch == true) {
+ pid = fork();
+ if (pid == -1) {
+ log_error("Cannot detach from parent process");
+ return 1;
+ }
+ /* If we're in the parent process */
+ if (pid != 0) {
+ if (args->wait >= 10)
+ return wait_child(args, pid);
+ else
+ return 0;
+ }
+#ifndef NO_SETSID
+ setsid();
+#endif
+ }
+
+ if (chdir(args->cwd)) {
+ log_error("ERROR: jsvc was unable to "
+ "change directory to: %s", args->cwd);
+ }
+ /*
+ * umask() uses inverse logic; bits are CLEAR for allowed access.
+ */
+ if (~args->umask & 0022) {
+ log_error("NOTICE: jsvc umask of %03o allows "
+ "write permission to group and/or other", args->umask);
+ }
+ envmask = umask(args->umask);
+ set_output(args->outfile, args->errfile, args->redirectstdin, args->procname);
+ log_debug("Switching umask back to %03o from %03o", envmask, args->umask);
+ res = run_controller(args, data, uid, gid);
+ if (logger_pid != 0) {
+ kill(logger_pid, SIGTERM);
+ }
+
+ return res;
+}
+
+static int run_controller(arg_data *args, home_data *data, uid_t uid,
+ gid_t gid)
+{
+ pid_t pid = 0;
+ int restarts = 0;
+ struct sigaction act;
+
+ controller_pid = getpid();
+
+ /*
+ * Install signal handlers for the parent process.
+ * These will be replaced in the child process.
+ */
+ memset(&act, '\0', sizeof(act));
+ act.sa_handler = controller;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART | SA_NOCLDSTOP | SA_SIGINFO;
+
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGUSR1, &act, NULL);
+ sigaction(SIGUSR2, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
+
+ /* We have to fork: this process will become the controller and the other
+ will be the child */
+ while ((pid = fork()) != -1) {
+ time_t laststart;
+ int status = 0;
+ /* We forked (again), if this is the child, we go on normally */
+ if (pid == 0)
+ exit(child(args, data, uid, gid));
+ laststart = time(NULL);
+
+ /* We are in the controller, we have to forward all interesting signals
+ to the child, and wait for it to die */
+ controlled = pid;
+
+#ifdef OS_CYGWIN
+ SetTerm(cygwincontroller);
+#endif
+
+ while (waitpid(pid, &status, 0) != pid) {
+ /* Wait for process */
+ }
+
+ /* The child must have exited cleanly */
+ if (WIFEXITED(status)) {
+ status = WEXITSTATUS(status);
+
+ /* Delete the pid file */
+ if (args->vers != true && args->chck != true && status != 122)
+ remove_pid_file(args, pid);
+
+ /* If the child got out with 123 he wants to be restarted */
+ /* See java_abort123 (we use this return code to restart when the JVM aborts) */
+ if (!stopping) {
+ if (status == 123) {
+ if (args->restarts == 0) {
+ log_debug("Service failure, restarts disabled");
+ return 1;
+ }
+ if (args->restarts != -1 && args->restarts <= restarts) {
+ log_debug("Service failure, restart limit reached, aborting");
+ return 1;
+ }
+ log_debug("Reloading service");
+ restarts++;
+ /* prevent looping */
+ if (laststart + 60 > time(NULL)) {
+ log_debug("Waiting 60 s to prevent looping");
+ sleep(60);
+ }
+ continue;
+ }
+ }
+ /* If the child got out with 0 he is shutting down */
+ if (status == 0) {
+ log_debug("Service shut down");
+ return 0;
+ }
+ /* Otherwise we don't rerun it */
+ log_error("Service exit with a return value of %d", status);
+ return 1;
+
+ }
+ else {
+ if (WIFSIGNALED(status)) {
+ log_error("Service killed by signal %d", WTERMSIG(status));
+ /* prevent looping */
+ if (!stopping) {
+ if (laststart + 60 > time(NULL)) {
+ log_debug("Waiting 60 s to prevent looping");
+ sleep(60);
+ }
+ /* Normal or user controlled termination, reset restart counter */
+ restarts = 0;
+ continue;
+ }
+ }
+ log_error("Service did not exit cleanly", status);
+ return 1;
+ }
+ }
+
+ /* Got out of the loop? A fork() failed then. */
+ log_error("Cannot decouple controller/child processes");
+ return 1;
+
+}
+
+void main_reload(void)
+{
+ log_debug("Killing self with HUP signal");
+ kill(controlled, SIGHUP);
+}
+
+void main_shutdown(void)
+{
+ log_debug("Killing self with TERM signal");
+ kill(controlled, SIGTERM);
+}
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/jsvc.h Tue May 28 09:46:53 2019
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __JSVC_H__
+#define __JSVC_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* Definitions for booleans */
+#ifdef OS_DARWIN
+#include <stdbool.h>
+#else
+typedef enum {
+ false,
+ true
+} bool;
+#endif
+
+#include "version.h"
+#include "debug.h"
+#include "arguments.h"
+#include "home.h"
+#include "location.h"
+#include "replace.h"
+#include "dso.h"
+#include "java.h"
+#include "help.h"
+#include "signals.h"
+#include "locks.h"
+
+int main(int argc, char *argv[]);
+void main_reload(void);
+void main_shutdown(void);
+
+#endif /* ifndef __JSVC_H__ */
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/location.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/location.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/location.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/location.c Tue May 28 09:46:53 2019
@@ -0,0 +1,173 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jsvc.h"
+
+/* Locations of various JVM files. We have to deal with all this madness since
+ * we're not distributed together (yet!) with an official VM distribution. All
+ * this CRAP needs improvement, and based on the observation of default
+ * distributions of VMs and OSes. If it doesn't work for you, please report
+ * your VM layout (ls -laR) and system details (build/config.guess) so that we
+ * can improve the search algorithms.
+ */
+
+/* If JAVA_HOME is not defined we search this list of paths (OS-dependent)
+ * to find the default location of the JVM.
+ */
+char *location_home[] = {
+#if defined(OS_DARWIN)
+ "/System/Library/Frameworks/JavaVM.framework/Home",
+ "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home/",
+#elif defined(OS_LINUX) || defined(OS_SOLARIS) || defined(OS_BSD) || defined(OS_AIX)
+ "/usr/java/default",
+ "/usr/java",
+ "/usr/local/java",
+ "/usr/lib/jvm/default-java",
+ "/usr/lib/jvm/java",
+ "/etc/alternatives/java_sdk",
+ "/etc/alternatives/java_sdk_openjdk",
+ "/etc/alternatives/jre",
+#if defined(__LP64__)
+ "/lib64/jvm/java",
+ "/lib64/jvm/java-openjdk",
+#endif
+ "/lib/jvm/java",
+ "/lib/jvm/java-openjdk",
+#elif defined(OS_CYGWIN)
+ "/cygdrive/c/WINNT/system32/java",
+#elif defined(OS_SYSV)
+ "/opt/java",
+ "/opt/java/jdk13",
+#elif defined(OS_TRU64)
+ "/usr/opt/java142",
+ "/usr/opt/java13",
+#elif defined(OS_HPUX)
+ "/opt/java6",
+ "/opt/java1.5",
+ "/opt/java1.4",
+ "/opt/java1.3",
+#endif
+ NULL,
+};
+
+/* The jvm.cfg file defines the VMs available for invocation. So far, on all
+ * all systems I've seen it's in $JAVA_HOME/lib. If this file is not found,
+ * then the "default" VMs (from location_jvm_default) is searched, otherwise,
+ * we're going to look thru the "configured" VMs (from lod_cfgvm) lying
+ * somewhere around JAVA_HOME. (Only two, I'm happy)
+ */
+char *location_jvm_cfg[] = {
+ "$JAVA_HOME/jre/lib/jvm.cfg", /* JDK */
+ "$JAVA_HOME/lib/jvm.cfg", /* JRE */
+ "$JAVA_HOME/jre/lib/" CPU "/jvm.cfg", /* JDK */
+ "$JAVA_HOME/lib/" CPU "/jvm.cfg", /* JRE */
+#if defined(OS_AIX)
+ "$JAVA_HOME/jre/lib/ppc/jvm.cfg", /* JDK */
+ "$JAVA_HOME/lib/ppc/jvm.cfg", /* JRE */
+#endif
+ NULL,
+};
+
+/* This is the list of "defaults" VM (searched when jvm.cfg is not found, as
+ * in the case of most JDKs 1.2.2
+ */
+char *location_jvm_default[] = {
+#if defined(OS_DARWIN)
+ "$JAVA_HOME/../Libraries/libjvm.dylib",
+ "$JAVA_HOME/jre/lib/server/libjvm.dylib",
+ "$JAVA_HOME/jre/lib/client/libjvm.dylib",
+#elif defined(OS_CYGWIN)
+ "$JAVA_HOME/jre/bin/classic/jvm.dll", /* Sun JDK 1.3 */
+ "$JAVA_HOME/jre/bin/client/jvm.dll", /* Sun JDK 1.4 */
+#elif defined(OS_LINUX) || defined(OS_SOLARIS) || defined(OS_BSD) || defined(OS_SYSV) || defined(OS_FREEBSD) || defined(OS_TRU64) || defined(OS_AIX)
+ "$JAVA_HOME/jre/lib/" CPU "/classic/libjvm.so", /* Sun JDK 1.2 */
+ "$JAVA_HOME/jre/lib/" CPU "/server/libjvm.so", /* Sun JDK 1.4 */
+ "$JAVA_HOME/jre/lib/" CPU "/client/libjvm.so", /* Sun JDK 1.3 */
+ "$JAVA_HOME/jre/lib/" CPU "/libjvm.so", /* Sun JDK */
+ "$JAVA_HOME/lib/" CPU "/classic/libjvm.so", /* Sun JRE 1.2 */
+ "$JAVA_HOME/lib/" CPU "/server/libjvm.so", /* Sun JRE 1.4 */
+ "$JAVA_HOME/lib/" CPU "/client/libjvm.so", /* Sun JRE 1.3 */
+ "$JAVA_HOME/lib/" CPU "/libjvm.so", /* Sun JRE */
+ "$JAVA_HOME/jre/bin/" CPU "/classic/libjvm.so", /* IBM JDK 1.3 */
+ "$JAVA_HOME/jre/bin/" CPU "/libjvm.so", /* IBM JDK */
+ "$JAVA_HOME/bin/" CPU "/classic/libjvm.so", /* IBM JRE 1.3 */
+ "$JAVA_HOME/bin/" CPU "/libjvm.so", /* IBM JRE */
+ /* Those are "weirdos: if we got here, we're probably in troubles and
+ * we're not going to find anything, but hope never dies...
+ */
+ "$JAVA_HOME/jre/lib/" CPU "/classic/green_threads/libjvm.so",
+#if defined(OSD_POSIX)
+ "$JAVA_HOME/lib/s390/client/green_threads/libjvm.so",
+ "$JAVA_HOME/lib/sparc/client/green_threads/libjvm.so",
+#endif
+ "$JAVA_HOME/jre/lib/classic/libjvm.so",
+ "$JAVA_HOME/jre/lib/client/libjvm.so",
+ "$JAVA_HOME/jre/lib/libjvm.so",
+ "$JAVA_HOME/lib/classic/libjvm.so",
+ "$JAVA_HOME/lib/client/libjvm.so",
+ "$JAVA_HOME/lib/libjvm.so",
+ "$JAVA_HOME/jre/bin/classic/libjvm.so",
+ "$JAVA_HOME/jre/bin/client/libjvm.so",
+ "$JAVA_HOME/jre/bin/libjvm.so",
+ "$JAVA_HOME/bin/classic/libjvm.so",
+ "$JAVA_HOME/bin/client/libjvm.so",
+ "$JAVA_HOME/bin/libjvm.so",
+ "$JAVA_HOME/jre/lib/" CPU "/fast64/libjvm.so",
+ "$JAVA_HOME/jre/lib/" CPU "/fast32/libjvm.so",
+ "$JAVA_HOME/lib/" CPU "/fast64/libjvm.so",
+ "$JAVA_HOME/lib/" CPU "/fast32/libjvm.so",
+#elif defined(OS_HPUX)
+ "$JAVA_HOME/jre/lib/" CPU "/server/libjvm." SO_EXT,
+ "$JAVA_HOME/jre/lib/" CPU "/client/libjvm." SO_EXT,
+ "$JAVA_HOME/jre/lib/" CPU "/hotspot/libjvm." SO_EXT,
+ "$JAVA_HOME/jre/lib/" CPU "/classic/libjvm." SO_EXT,
+#endif
+ "/usr/lib/libgcj.so.7", /* gcc java libraries */
+ "/usr/lib/libgcj.so.6",
+ NULL,
+};
+
+/* This is the list of "configured" VM (searched when jvm.cfg is found, as
+ * in the case of most JDKs 1.3 (not IBM, for example), way easier than
+ * before, and lovely, indeed...
+ */
+char *location_jvm_configured[] = {
+#if defined(OS_DARWIN)
+ "$JAVA_HOME/lib/$VM_NAME/libjvm.dylib", /* Java 9 */
+ "$JAVA_HOME/jre/lib/$VM_NAME/libjvm.dylib",
+ "$JAVA_HOME/../Libraries/lib$VM_NAME.dylib",
+#elif defined(OS_CYGWIN)
+ "$JAVA_HOME/jre/bin/$VM_NAME/jvm.dll", /* Sun JDK 1.3 */
+#elif defined(OS_LINUX) || defined(OS_SOLARIS) || defined(OS_BSD) || defined(OS_FREEBSD) || defined(OS_TRU64) || defined(OS_AIX)
+ "$JAVA_HOME/lib/$VM_NAME/libjvm.so", /* Java 9 */
+ "$JAVA_HOME/jre/lib/" CPU "/$VM_NAME/libjvm.so", /* Sun JDK 1.3 */
+ "$JAVA_HOME/lib/" CPU "/$VM_NAME/libjvm.so", /* Sun JRE 1.3 */
+#if defined(OS_AIX)
+ "$JAVA_HOME/jre/lib/ppc/$VM_NAME/libjvm.so", /* Sun JDK 1.3 */
+ "$JAVA_HOME/lib/ppc/$VM_NAME/libjvm.so", /* Sun JRE 1.3 */
+#endif
+#elif defined(OS_HPUX)
+ "$JAVA_HOME/jre/lib/" CPU "/$VM_NAME/libjvm." SO_EXT,
+ "$JAVA_HOME/lib/" CPU "/$VM_NAME/libjvm." SO_EXT,
+#elif defined(OS_SYSV)
+ "$JAVA_HOME/jre/lib/" CPU "/$VM_NAME/dce_threads/libjvm.so",
+ "$JAVA_HOME/jre/lib/" CPU "/$VM_NAME/green_threads/libjvm.so",
+ "$JAVA_HOME/lib/" CPU "/$VM_NAME/dce_threads/libjvm.so",
+ "$JAVA_HOME/lib/" CPU "/$VM_NAME/green_threads/libjvm.so",
+#endif
+ NULL,
+};
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/location.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/location.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/location.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/location.h Tue May 28 09:46:53 2019
@@ -0,0 +1,28 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __JSVC_LOCATION_H__
+#define __JSVC_LOCATION_H__
+
+#include "jsvc.h"
+
+extern char *location_home[];
+extern char *location_jvm_cfg[];
+extern char *location_jvm_default[];
+extern char *location_jvm_configured[];
+
+#endif /* __JSVC_LOCATION_H__ */
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/locks.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/locks.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/locks.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/locks.c Tue May 28 09:46:53 2019
@@ -0,0 +1,50 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * as Cygwin does not support lockf, jsvc uses fcntl to emulate it.
+ */
+#ifdef OS_CYGWIN
+#include "jsvc.h"
+#include <sys/fcntl.h>
+
+/*
+ * File locking routine
+ */
+int lockf(int fildes, int function, off_t size)
+{
+ struct flock buf;
+
+ switch (function) {
+ case F_LOCK:
+ buf.l_type = F_WRLCK;
+ break;
+ case F_ULOCK:
+ buf.l_type = F_UNLCK;
+ break;
+ default:
+ return -1;
+ }
+ buf.l_whence = 0;
+ buf.l_start = 0;
+ buf.l_len = size;
+
+ return fcntl(fildes, F_SETLK, &buf);
+}
+#else
+const char __unused_locks_c[] = __FILE__;
+#endif
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/locks.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/locks.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/locks.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/locks.h Tue May 28 09:46:53 2019
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __JSVC_LOCKS_H__
+#define __JSVC_LOCKS_H__
+
+/*
+ * as Cygwin does not support locks, jsvc use NT API to emulate them.
+ */
+#ifdef OS_CYGWIN
+
+#define F_ULOCK 0 /* Unlock a previously locked region */
+#define F_LOCK 1 /* Lock a region for exclusive use */
+
+/*
+ * allow a file to be locked
+ * @param fildes an open file descriptor
+ * @param function a control value that specifies the action to be taken
+ * @param size number of bytes to lock
+ * @return Zero on success, a value less than 0 if an error was encountered
+ */
+int lockf(int fildes, int function, off_t size);
+
+#endif
+#endif /* __JSVC_LOCKS_H__ */
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/replace.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/replace.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/replace.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/replace.c Tue May 28 09:46:53 2019
@@ -0,0 +1,120 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jsvc.h"
+
+/* Replace all occurrences of a string in another */
+int replace(char *new, int len, char *old, char *mch, char *rpl)
+{
+ char *tmp;
+ int count;
+ int shift;
+ int nlen;
+ int olen;
+ int mlen;
+ int rlen;
+ int x;
+
+ /* The new buffer is NULL, fail */
+ if (new == NULL)
+ return -1;
+ /* The length of the buffer is less than zero, fail */
+ if (len < 0)
+ return -2;
+ /* The old buffer is NULL, fail */
+ if (old == NULL)
+ return -3;
+
+ /* The string to be matched is NULL or empty, simply copy */
+ if ((mch == NULL) || (strlen(mch) == 0)) {
+ olen = strlen(old);
+ if (len <= olen)
+ return (olen + 1);
+ strcpy(new, old);
+ return 0;
+ }
+
+ /* The string to be replaced is NULL, assume it's an empty string */
+ if (rpl == NULL)
+ rpl = "";
+
+ /* Evaluate some lengths */
+ olen = strlen(old);
+ mlen = strlen(mch);
+ rlen = strlen(rpl);
+
+ /* Calculate how many times the mch string appears in old */
+ tmp = old;
+ count = 0;
+ while ((tmp = strstr(tmp, mch)) != NULL) {
+ count++;
+ tmp += mlen;
+ }
+
+ /* We have no matches, simply copy */
+ if (count == 0) {
+ olen = strlen(old);
+ if (len <= olen)
+ return (olen + 1);
+ strcpy(new, old);
+ return 0;
+ }
+
+ /* Calculate how big the buffer must be to hold the translation
+ * and of how many bytes we need to shift the data
+ */
+ shift = rlen - mlen;
+ nlen = olen + (shift * count);
+ /* printf("Count=%d Shift= %d OLen=%d NLen=%d\n",count,shift,olen,nlen); */
+
+ /* Check if we have enough size in the buffer */
+ if (nlen >= len)
+ return (nlen + 1);
+
+ /* Copy over the old buffer in the new one (save memory) */
+ strcpy(new, old);
+
+ /* Start replacing */
+ tmp = new;
+ while ((tmp = strstr(tmp, mch)) != NULL) {
+ /* If shift is > 0 we need to move data from right to left */
+ if (shift > 0) {
+ for (x = (strlen(tmp) + shift); x > shift; x--) {
+ /*
+ printf("src %c(%d) dst %c(%d)\n",
+ tmp[x-shift],tmp[x-shift],tmp[x],tmp[x]);
+ */
+ tmp[x] = tmp[x - shift];
+ }
+ /* If shift is < 0 we need to move data from left to right */
+ }
+ else if (shift < 0) {
+ for (x = mlen; x < strlen(tmp) - shift; x++) {
+ /*
+ printf("src %c(%d) dst %c(%d)\n",
+ tmp[x],tmp[x],tmp[x+shift],tmp[x+shift]);
+ */
+ tmp[x + shift] = tmp[x];
+ }
+ }
+ /* If shift is = 0 we don't have to shift data */
+ strncpy(tmp, rpl, rlen);
+ tmp += rlen;
+ /* printf("\"%s\"\n",tmp); */
+ }
+ return 0;
+}
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/replace.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/replace.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/replace.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/replace.h Tue May 28 09:46:53 2019
@@ -0,0 +1,38 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __JSVC_REPLACE_H__
+#define __JSVC_REPLACE_H__
+
+/**
+ * Replace all occurrences of mch in old with the new string rpl, and
+ * stores the result in new, provided that its length (specified in len)
+ * is enough.
+ *
+ * @param new The buffer where the result of the replace operation will be
+ * stored into.
+ * @param len The length of the previous buffer.
+ * @param old The string where occurrences of mtch must be searched.
+ * @param mch The characters to match in old (and to be replaced)
+ * @param rpl The characters that will be replaced in place of mch.
+ * @return Zero on success, a value less than 0 if an error was encountered
+ * or a value greater than zero (indicating the required storage size
+ * for new) if the buffer was too short to hold the new string.
+ */
+int replace(char *new, int len, char *old, char *mch, char *rpl);
+
+#endif /* ifndef __JSVC_REPLACE_H__ */
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/signals.c
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/signals.c?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/signals.c (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/signals.c Tue May 28 09:46:53 2019
@@ -0,0 +1,103 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * as Windows does not support signal, jsvc uses events to emulate them.
+ * The supported signal is SIGTERM.
+ * The kills.c contains the kill logic.
+ */
+#ifdef OS_CYGWIN
+#include <windows.h>
+#include <stdio.h>
+static void (*HandleTerm) (void) = NULL; /* address of the handler routine. */
+
+/*
+ * Event handling routine
+ */
+void v_difthf(LPVOID par)
+{
+ HANDLE hevint; /* make a local copy because the parameter is shared! */
+
+ hevint = (HANDLE) par;
+
+ for (;;) {
+ if (WaitForSingleObject(hevint, INFINITE) == WAIT_FAILED) {
+ /* something have gone wrong. */
+ return; /* may be something more is needed. */
+ }
+
+ /* call the interrupt handler. */
+ if (HandleTerm == NULL)
+ return;
+ HandleTerm();
+ }
+}
+
+/*
+ * set a routine handler for the signal
+ * note that it cannot be used to change the signal handler
+ */
+int SetTerm(void (*func) (void))
+{
+ char Name[256];
+ HANDLE hevint, hthread;
+ DWORD ThreadId;
+ SECURITY_ATTRIBUTES sa;
+ SECURITY_DESCRIPTOR sd;
+
+ sprintf(Name, "TERM%ld", GetCurrentProcessId());
+
+ /*
+ * event cannot be inherited.
+ * the event is reseted to nonsignaled after the waiting thread is released.
+ * the start state is resetted.
+ */
+
+ /* Initialize the new security descriptor. */
+ InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+
+ /* Add a NULL descriptor ACL to the security descriptor. */
+ SetSecurityDescriptorDacl(&sd, TRUE, (PACL) NULL, FALSE);
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = TRUE;
+
+
+ /* It works also with NULL instead &sa!! */
+ hevint = CreateEvent(&sa, FALSE, FALSE, Name);
+
+ HandleTerm = func;
+
+ if (hevint == NULL)
+ return -1; /* failed */
+
+ /* create the thread to wait for event */
+ hthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) v_difthf,
+ (LPVOID) hevint, 0, &ThreadId);
+ if (hthread == NULL) {
+ /* failed remove the event */
+ CloseHandle(hevint); /* windows will remove it. */
+ return -1;
+ }
+
+ CloseHandle(hthread); /* not needed */
+ return 0;
+}
+#else
+const char __unused_signals_c[] = __FILE__;
+#endif
+
Added: tomee/deps/branches/commons-daemon/src/native/unix/native/signals.h
URL: http://svn.apache.org/viewvc/tomee/deps/branches/commons-daemon/src/native/unix/native/signals.h?rev=1860225&view=auto
==============================================================================
--- tomee/deps/branches/commons-daemon/src/native/unix/native/signals.h (added)
+++ tomee/deps/branches/commons-daemon/src/native/unix/native/signals.h Tue May 28 09:46:53 2019
@@ -0,0 +1,33 @@
+/*
+ Copyright 2001-2004 The Apache Software Foundation.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+#ifndef __JSVC_SIGNALS_H__
+#define __JSVC_SIGNALS_H__
+
+/*
+ * as Windows does not support signal, jsvc use event to emulate them.
+ * The supported signal is SIGTERM.
+ */
+#ifdef OS_CYGWIN
+/*
+ * set a routine handler for the signal
+ * note that it cannot be used to change the signal handler
+ * @param func The function to call on termination
+ * @return Zero on success, a value less than 0 if an error was encountered
+ */
+int SetTerm(void (*func) (void));
+
+#endif
+#endif /* ifndef __JSVC_SIGNALS_H__ */