blob: 503130dd4ea1875d09aa0d073cc8150a91827fdd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2002, 2010 QNX Software Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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 <org_eclipse_cdt_utils_spawner_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) {
for (char **p = c_array; *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(char *));
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) {
for (char **p = c_array; *p; p++) {
free(*p);
}
free(c_array);
}
}
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec2(JNIEnv *env, jobject jobj, jobjectArray jcmd,
jobjectArray jenv, jstring jdir,
jobjectArray jchannels, jstring jslaveName,
jint masterFD, jboolean console) {
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 (jchannels == 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;
}
jobject cls = (*env)->FindClass(env, "org/eclipse/cdt/utils/spawner/Spawner$UnixChannel");
jmethodID constructor = (*env)->GetMethodID(env, cls, "<init>", "(I)V");
for (jsize i = 0; i < 3; i++) {
jobject chan = (*env)->NewObject(env, cls, constructor, fd[i]);
(*env)->SetObjectArrayElement(env, jchannels, i, chan);
}
bail_out:
(*env)->ReleaseStringUTFChars(env, jdir, dirpath);
(*env)->ReleaseStringUTFChars(env, jslaveName, pts_name);
free_c_array(cmd);
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);
free_c_array(cmd);
free_c_array(envp);
return pid;
}
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0(JNIEnv *env, jobject jobj, jobjectArray jcmd,
jobjectArray jenv, jstring jdir,
jobjectArray jchannels) {
const char *dirpath = (*env)->GetStringUTFChars(env, jdir, NULL);
char **cmd = NULL;
char **envp = NULL;
int fd[3];
pid_t pid = -1;
jclass channelClass = NULL;
jmethodID channelConstructor = NULL;
if (jchannels == NULL) {
goto bail_out;
}
channelClass = (*env)->FindClass(env, "org/eclipse/cdt/utils/spawner/Spawner$UnixChannel");
if (channelClass == 0) {
goto bail_out;
}
channelConstructor = (*env)->GetMethodID(env, channelClass, "<init>", "(I)V");
if (channelConstructor == 0) {
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;
}
for (jsize i = 0; i < 3; i++) {
jobject chan = (*env)->NewObject(env, channelClass, channelConstructor, fd[i]);
(*env)->SetObjectArrayElement(env, jchannels, i, chan);
}
bail_out:
(*env)->ReleaseStringUTFChars(env, jdir, dirpath);
free_c_array(cmd);
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);
}