| /******************************************************************************* | |
| * Copyright (c) 2002, 2010 QNX Software Systems and others. | |
| * All rights reserved. This program and the accompanying materials | |
| * are made available under the terms of the Eclipse Public License v1.0 | |
| * which accompanies this distribution, and is available at | |
| * http://www.eclipse.org/legal/epl-v10.html | |
| * | |
| * Contributors: | |
| * QNX Software Systems - initial API and implementation | |
| * Wind River Systems, Inc. | |
| * Mikhail Zabaluev (Nokia) - bug 82744 | |
| *******************************************************************************/ | |
| #include <unistd.h> | |
| #include <stdlib.h> | |
| #include <stdio.h> | |
| #include <signal.h> | |
| #include <string.h> | |
| #include <jni.h> | |
| #include "exec0.h" | |
| #include <Spawner.h> | |
| #define DEBUGIT 0 | |
| /* | |
| * Header for class org_eclipse_cdt_utils_spawner_Spawner | |
| */ | |
| #if DEBUGIT | |
| static void print_array(char **c_array) | |
| { | |
| if (c_array) { | |
| char **p = c_array; | |
| for (; *p; p++) { | |
| if (*p) { | |
| fprintf(stderr, " %s", *p); | |
| } | |
| } | |
| } else { | |
| fprintf(stderr, "null"); | |
| } | |
| fprintf(stderr, "\n"); | |
| } | |
| #endif | |
| static char **alloc_c_array(JNIEnv * env, jobjectArray j_array) | |
| { | |
| int i; | |
| jint c_array_size = (*env)->GetArrayLength(env, j_array); | |
| char **c_array = calloc(c_array_size + 1, sizeof(*c_array)); | |
| if (c_array == NULL) | |
| return NULL; | |
| for (i = 0; i < c_array_size; i++) { | |
| jstring j_str = | |
| (jstring) (*env)->GetObjectArrayElement(env, j_array, i); | |
| const char *c_str = (*env)->GetStringUTFChars(env, j_str, NULL); | |
| c_array[i] = (char *) strdup(c_str); | |
| (*env)->ReleaseStringUTFChars(env, j_str, c_str); | |
| (*env)->DeleteLocalRef(env, j_str); | |
| } | |
| return c_array; | |
| } | |
| static void free_c_array(char **c_array) | |
| { | |
| if (c_array) { | |
| char **p = c_array; | |
| for (; *p; p++) { | |
| if (*p) { | |
| free(*p); | |
| } | |
| } | |
| free(c_array); | |
| } | |
| } | |
| /* | |
| * Class: org_eclipse_cdt_utils_spawner_Spawner | |
| * Method: exec2 | |
| * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[ILorg/eclipse/cdt/utils/pty/PTY;)I | |
| */ | |
| JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2 | |
| (JNIEnv *env, jobject jobj, jobjectArray jcmd, jobjectArray jenv, jstring jdir, jintArray jchannels, | |
| jstring jslaveName, jint masterFD, jboolean console) | |
| { | |
| jint *channels = (*env)->GetIntArrayElements(env, jchannels, 0); | |
| const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL); | |
| const char *pts_name = (*env)->GetStringUTFChars(env, jslaveName, NULL); | |
| char **cmd = NULL; | |
| char **envp = NULL; | |
| int fd[3]; | |
| pid_t pid = -1; | |
| if (channels == NULL) | |
| goto bail_out; | |
| cmd = alloc_c_array(env, jcmd); | |
| if (cmd == NULL) | |
| goto bail_out; | |
| envp = alloc_c_array(env, jenv); | |
| if (envp == NULL) | |
| goto bail_out; | |
| #if DEBUGIT | |
| fprintf(stderr, "command:"); | |
| print_array(cmd); | |
| fprintf(stderr, "Envp:"); | |
| print_array(envp); | |
| fprintf(stderr, "dirpath: %s\n", dirpath); | |
| fprintf(stderr, "pts_name: %s\n", pts_name); | |
| #endif | |
| pid = exec_pty(cmd[0], cmd, envp, dirpath, fd, pts_name, masterFD, console); | |
| if (pid < 0) | |
| goto bail_out; | |
| channels[0] = fd[0]; | |
| channels[1] = fd[1]; | |
| channels[2] = fd[2]; | |
| bail_out: | |
| (*env)->ReleaseIntArrayElements(env, jchannels, channels, 0); | |
| (*env)->ReleaseStringUTFChars(env, jdir, dirpath); | |
| (*env)->ReleaseStringUTFChars(env, jslaveName, pts_name); | |
| if (cmd) | |
| free_c_array(cmd); | |
| if (envp) | |
| free_c_array(envp); | |
| return pid; | |
| } | |
| JNIEXPORT jint JNICALL | |
| Java_org_eclipse_cdt_utils_spawner_Spawner_exec1(JNIEnv * env, jobject jobj, | |
| jobjectArray jcmd, | |
| jobjectArray jenv, | |
| jstring jdir) | |
| { | |
| const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL); | |
| char **cmd = NULL; | |
| char **envp = NULL; | |
| pid_t pid = -1; | |
| cmd = alloc_c_array(env, jcmd); | |
| if (cmd == NULL) | |
| goto bail_out; | |
| envp = alloc_c_array(env, jenv); | |
| if (envp == NULL) | |
| goto bail_out; | |
| #if DEBUGIT | |
| fprintf(stderr, "command:"); | |
| print_array(cmd); | |
| fprintf(stderr, "Envp:"); | |
| print_array(envp); | |
| fprintf(stderr, "dirpath: %s\n", dirpath); | |
| #endif | |
| pid = exec0(cmd[0], cmd, envp, dirpath, NULL); | |
| if (pid < 0) | |
| goto bail_out; | |
| bail_out: | |
| (*env)->ReleaseStringUTFChars(env, jdir, dirpath); | |
| if (cmd) | |
| free_c_array(cmd); | |
| if (envp) | |
| free_c_array(envp); | |
| return pid; | |
| } | |
| /* | |
| * Class: org_eclipse_cdt_utils_spawner_Spawner | |
| * Method: exec0 | |
| * Signature: ([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[I)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv * env, jobject jobj, | |
| jobjectArray jcmd, | |
| jobjectArray jenv, | |
| jstring jdir, | |
| jintArray jchannels) | |
| { | |
| jint *channels = (*env)->GetIntArrayElements(env, jchannels, 0); | |
| const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL); | |
| char **cmd = NULL; | |
| char **envp = NULL; | |
| int fd[3]; | |
| pid_t pid = -1; | |
| if (channels == NULL) | |
| goto bail_out; | |
| cmd = alloc_c_array(env, jcmd); | |
| if (cmd == NULL) | |
| goto bail_out; | |
| envp = alloc_c_array(env, jenv); | |
| if (envp == NULL) | |
| goto bail_out; | |
| #if DEBUGIT | |
| fprintf(stderr, "command:"); | |
| print_array(cmd); | |
| fprintf(stderr, "Envp:"); | |
| print_array(envp); | |
| fprintf(stderr, "dirpath: %s\n", dirpath); | |
| #endif | |
| pid = exec0(cmd[0], cmd, envp, dirpath, fd); | |
| if (pid < 0) | |
| goto bail_out; | |
| channels[0] = fd[0]; | |
| channels[1] = fd[1]; | |
| channels[2] = fd[2]; | |
| bail_out: | |
| (*env)->ReleaseIntArrayElements(env, jchannels, channels, 0); | |
| (*env)->ReleaseStringUTFChars(env, jdir, dirpath); | |
| if (cmd) | |
| free_c_array(cmd); | |
| if (envp) | |
| free_c_array(envp); | |
| return pid; | |
| } | |
| /* | |
| * Class: org_eclipse_cdt_utils_spawner_Spawner | |
| * Method: raise | |
| * Signature: (II)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_org_eclipse_cdt_utils_spawner_Spawner_raise(JNIEnv * env, jobject jobj, | |
| jint pid, jint sig) | |
| { | |
| int status = -1; | |
| switch (sig) { | |
| case 0: /* NOOP */ | |
| status = killpg(pid, 0); | |
| if(status == -1) { | |
| status = kill(pid, 0); | |
| } | |
| break; | |
| case 2: /* INTERRUPT */ | |
| status = killpg(pid, SIGINT); | |
| if(status == -1) { | |
| status = kill(pid, SIGINT); | |
| } | |
| break; | |
| case 9: /* KILL */ | |
| status = killpg(pid, SIGKILL); | |
| if(status == -1) { | |
| status = kill(pid, SIGKILL); | |
| } | |
| break; | |
| case 15: /* TERM */ | |
| status = killpg(pid, SIGTERM); | |
| if(status == -1) { | |
| status = kill(pid, SIGTERM); | |
| } | |
| break; | |
| default: | |
| status = killpg(pid, sig); /* WHAT ?? */ | |
| if(status == -1) { | |
| status = kill(pid, sig); /* WHAT ?? */ | |
| } | |
| break; | |
| } | |
| return status; | |
| } | |
| /* | |
| * Class: org_eclipse_cdt_utils_spawner_Spawner | |
| * Method: waitFor | |
| * Signature: (I)I | |
| */ | |
| JNIEXPORT jint JNICALL | |
| Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor(JNIEnv * env, | |
| jobject jobj, jint pid) | |
| { | |
| return wait0(pid); | |
| } |