/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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.
 */

#define LOG_TAG "ProcessManager"

#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "jni.h"
#include "JNIHelp.h"
#include "utils/Log.h"

/** Environment variables. */
extern char **environ;

static jmethodID onExitMethod = NULL;
static jfieldID descriptorField = NULL;

#ifdef ANDROID
// Keeps track of the system properties fd so we don't close it.
static int androidSystemPropertiesFd = -1;
#endif

/*
 * These are constants shared with the higher level code in
 * ProcessManager.java.
 */
#define WAIT_STATUS_UNKNOWN (-1)       // unknown child status
#define WAIT_STATUS_NO_CHILDREN (-2)   // no children to wait for
#define WAIT_STATUS_STRANGE_ERRNO (-3) // observed an undocumented errno

/** Closes a file descriptor. */
static void java_lang_ProcessManager_close(JNIEnv* env,
        jclass, jobject javaDescriptor) {
    int fd = env->GetIntField(javaDescriptor, descriptorField);
    if (TEMP_FAILURE_RETRY(close(fd)) == -1) {
        jniThrowIOException(env, errno);
    }
}

/**
 * Kills process with the given ID.
 */
static void java_lang_ProcessManager_kill(JNIEnv* env, jclass, jint pid) {
    int result = kill((pid_t) pid, SIGKILL);
    if (result == -1) {
        jniThrowIOException(env, errno);
    }
}

/**
 * Loops indefinitely and calls ProcessManager.onExit() when children exit.
 */
static void java_lang_ProcessManager_watchChildren(JNIEnv* env, jobject o) {
    if (onExitMethod == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "staticInitialize() must run first.");
    }

    while (1) {
        int status;

        /* wait for children in our process group */
        pid_t pid = waitpid(0, &status, 0);

        if (pid >= 0) {
            // Extract real status.
            if (WIFEXITED(status)) {
                status = WEXITSTATUS(status);
            } else if (WIFSIGNALED(status)) {
                status = WTERMSIG(status);
            } else if (WIFSTOPPED(status)) {
                status = WSTOPSIG(status);
            } else {
                status = WAIT_STATUS_UNKNOWN;
            }
        } else {
            /*
             * The pid should be -1 already, but force it here just in case
             * we somehow end up with some other negative value.
             */
            pid = -1;

            switch (errno) {
                case ECHILD: {
                    /*
                     * Expected errno: There are no children to wait()
                     * for. The callback will sleep until it is
                     * informed of another child coming to life.
                     */
                    status = WAIT_STATUS_NO_CHILDREN;
                    break;
                }
                case EINTR: {
                    /*
                     * An unblocked signal came in while waiting; just
                     * retry the wait().
                     */
                    continue;
                }
                default: {
                    /*
                     * Unexpected errno, so squawk! Note: Per the
                     * Linux docs, there are no errnos defined for
                     * wait() other than the two that are handled
                     * immediately above.
                     */
                    LOGE("Error %d calling wait(): %s", errno,
                            strerror(errno));
                    status = WAIT_STATUS_STRANGE_ERRNO;
                    break;
                }
            }
        }

        env->CallVoidMethod(o, onExitMethod, pid, status);
        if (env->ExceptionOccurred()) {
            /*
             * The callback threw, so break out of the loop and return,
             * letting the exception percolate up.
             */
            break;
        }
    }
}

/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */
static void closeNonStandardFds(int skipFd) {
    // TODO: rather than close all these non-open files, we could look in /proc/self/fd.
    struct rlimit rlimit;
    getrlimit(RLIMIT_NOFILE, &rlimit);
    const int max_fd = rlimit.rlim_max;
    for (int fd = 3; fd < max_fd; ++fd) {
        if (fd != skipFd
#ifdef ANDROID
                && fd != androidSystemPropertiesFd
#endif
                ) {
            close(fd);
        }
    }
}

#define PIPE_COUNT (4) // number of pipes used to communicate with child proc

/** Closes all pipes in the given array. */
static void closePipes(int pipes[], int skipFd) {
    int i;
    for (i = 0; i < PIPE_COUNT * 2; i++) {
        int fd = pipes[i];
        if (fd == -1) {
            return;
        }
        if (fd != skipFd) {
            close(pipes[i]);
        }
    }
}

/** Executes a command in a child process. */
static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
        const char* workingDirectory, jobject inDescriptor,
        jobject outDescriptor, jobject errDescriptor,
        jboolean redirectErrorStream) {
    int i, result, error;

    // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
    int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
    for (i = 0; i < PIPE_COUNT; i++) {
        if (pipe(pipes + i * 2) == -1) {
            jniThrowIOException(env, errno);
            closePipes(pipes, -1);
            return -1;
        }
    }
    int stdinIn = pipes[0];
    int stdinOut = pipes[1];
    int stdoutIn = pipes[2];
    int stdoutOut = pipes[3];
    int stderrIn = pipes[4];
    int stderrOut = pipes[5];
    int statusIn = pipes[6];
    int statusOut = pipes[7];

    pid_t childPid = fork();

    // If fork() failed...
    if (childPid == -1) {
        jniThrowIOException(env, errno);
        closePipes(pipes, -1);
        return -1;
    }

    // If this is the child process...
    if (childPid == 0) {
        /*
         * Note: We cannot malloc() or free() after this point!
         * A no-longer-running thread may be holding on to the heap lock, and
         * an attempt to malloc() or free() would result in deadlock.
         */

        // Replace stdin, out, and err with pipes.
        dup2(stdinIn, 0);
        dup2(stdoutOut, 1);
        if (redirectErrorStream) {
            dup2(stdoutOut, 2);
        } else {
            dup2(stderrOut, 2);
        }

        // Close all but statusOut. This saves some work in the next step.
        closePipes(pipes, statusOut);

        // Make statusOut automatically close if execvp() succeeds.
        fcntl(statusOut, F_SETFD, FD_CLOEXEC);

        // Close remaining open fds with the exception of statusOut.
        closeNonStandardFds(statusOut);

        // Switch to working directory.
        if (workingDirectory != NULL) {
            if (chdir(workingDirectory) == -1) {
                goto execFailed;
            }
        }

        // Set up environment.
        if (environment != NULL) {
            environ = environment;
        }

        // Execute process. By convention, the first argument in the arg array
        // should be the command itself. In fact, I get segfaults when this
        // isn't the case.
        execvp(commands[0], commands);

        // If we got here, execvp() failed or the working dir was invalid.
        execFailed:
            error = errno;
            write(statusOut, &error, sizeof(int));
            close(statusOut);
            exit(error);
    }

    // This is the parent process.

    // Close child's pipe ends.
    close(stdinIn);
    close(stdoutOut);
    close(stderrOut);
    close(statusOut);

    // Check status pipe for an error code. If execvp() succeeds, the other
    // end of the pipe should automatically close, in which case, we'll read
    // nothing.
    int count = read(statusIn, &result, sizeof(int));
    close(statusIn);
    if (count > 0) {
        jniThrowIOException(env, result);

        close(stdoutIn);
        close(stdinOut);
        close(stderrIn);

        return -1;
    }

    // Fill in file descriptor wrappers.
    jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
    jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
    jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);

    return childPid;
}

/** Converts a Java String[] to a 0-terminated char**. */
static char** convertStrings(JNIEnv* env, jobjectArray javaArray) {
    if (javaArray == NULL) {
        return NULL;
    }

    char** array = NULL;
    jsize length = env->GetArrayLength(javaArray);
    array = (char**) malloc(sizeof(char*) * (length + 1));
    array[length] = 0;
    jsize index;
    for (index = 0; index < length; index++) {
        jstring javaEntry =
                (jstring) env->GetObjectArrayElement(javaArray, index);
        char* entry = (char*) env->GetStringUTFChars(javaEntry, NULL);
        array[index] = entry;
    }

    return array;
}

/** Frees a char** which was converted from a Java String[]. */
static void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) {
    if (javaArray == NULL) {
        return;
    }

    jsize length = env->GetArrayLength(javaArray);
    jsize index;
    for (index = 0; index < length; index++) {
        jstring javaEntry =
                (jstring) env->GetObjectArrayElement(javaArray, index);
        env->ReleaseStringUTFChars(javaEntry, array[index]);
    }

    free(array);
}

/**
 * Converts Java String[] to char** and delegates to executeProcess().
 */
static pid_t java_lang_ProcessManager_exec(
        JNIEnv* env, jclass, jobjectArray javaCommands,
        jobjectArray javaEnvironment, jstring javaWorkingDirectory,
        jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
        jboolean redirectErrorStream) {

    // Copy commands into char*[].
    char** commands = convertStrings(env, javaCommands);

    // Extract working directory string.
    const char* workingDirectory = NULL;
    if (javaWorkingDirectory != NULL) {
        workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
    }

    // Convert environment array.
    char** environment = convertStrings(env, javaEnvironment);

    pid_t result = executeProcess(
            env, commands, environment, workingDirectory, 
            inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);

    // Temporarily clear exception so we can clean up.
    jthrowable exception = env->ExceptionOccurred();
    env->ExceptionClear();

    freeStrings(env, javaEnvironment, environment);

    // Clean up working directory string.
    if (javaWorkingDirectory != NULL) {
        env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
    }

    freeStrings(env, javaCommands, commands);

    // Re-throw exception if present.
    if (exception != NULL) {
        if (env->Throw(exception) < 0) {
            LOGE("Error rethrowing exception!");
        }
    }

    return result;
}

/**
 * Looks up Java members.
 */
static void java_lang_ProcessManager_staticInitialize(JNIEnv* env,
        jclass clazz) {
#ifdef ANDROID
    char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE");
    if (fdString) {
        androidSystemPropertiesFd = atoi(fdString);
    }
#endif

    onExitMethod = env->GetMethodID(clazz, "onExit", "(II)V");
    if (onExitMethod == NULL) {
        return;
    }

    jclass fileDescriptorClass = env->FindClass("java/io/FileDescriptor");
    if (fileDescriptorClass == NULL) {
        return;
    }
    descriptorField = env->GetFieldID(fileDescriptorClass, "descriptor", "I");
    if (descriptorField == NULL) {
        return;
    }
}

static JNINativeMethod methods[] = {
    { "close",            "(Ljava/io/FileDescriptor;)V", (void*) java_lang_ProcessManager_close },
    { "kill",             "(I)V",                        (void*) java_lang_ProcessManager_kill },
    { "staticInitialize", "()V",                         (void*) java_lang_ProcessManager_staticInitialize },
    { "watchChildren",    "()V",                         (void*) java_lang_ProcessManager_watchChildren },
    { "exec",             "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I",
                                                         (void*) java_lang_ProcessManager_exec },
};
int register_java_lang_ProcessManager(JNIEnv* env) {
    return jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods));
}
