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__ */