java_lang_ProcessManager.cpp revision 6c1e5f4ad36c1f51687aa2b059e998a7c2db2e36
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define LOG_TAG "ProcessManager" 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob#include <sys/resource.h> 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/types.h> 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <unistd.h> 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <fcntl.h> 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <errno.h> 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "jni.h" 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h" 29a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 306c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h" 31e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes#include "ScopedLocalRef.h" 328545b837c61c3eaea2b8433b6791aa401f37e5f7Elliott Hughes#include "cutils/log.h" 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */ 35a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic void closeNonStandardFds(int skipFd1, int skipFd2) { 3694367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes // TODO: rather than close all these non-open files, we could look in /proc/self/fd. 37e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes rlimit rlimit; 38410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob getrlimit(RLIMIT_NOFILE, &rlimit); 3994367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes const int max_fd = rlimit.rlim_max; 4094367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes for (int fd = 3; fd < max_fd; ++fd) { 41a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fd != skipFd1 && fd != skipFd2) { 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(fd); 43410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob } 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define PIPE_COUNT (4) // number of pipes used to communicate with child proc 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes all pipes in the given array. */ 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closePipes(int pipes[], int skipFd) { 51a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT * 2; i++) { 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int fd = pipes[i]; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd == -1) { 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd != skipFd) { 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(pipes[i]); 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Executes a command in a child process. */ 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t executeProcess(JNIEnv* env, char** commands, char** environment, 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory, jobject inDescriptor, 651805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject outDescriptor, jobject errDescriptor, 661805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 67a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes 68a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Keep track of the system properties fd so we don't close it. 69a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int androidSystemPropertiesFd = -1; 70a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE"); 71a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes if (fdString) { 72a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes androidSystemPropertiesFd = atoi(fdString); 73a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes } 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe. 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 77a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes for (int i = 0; i < PIPE_COUNT; i++) { 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (pipe(pipes + i * 2) == -1) { 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinIn = pipes[0]; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdinOut = pipes[1]; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutIn = pipes[2]; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stdoutOut = pipes[3]; 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrIn = pipes[4]; 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int stderrOut = pipes[5]; 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusIn = pipes[6]; 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int statusOut = pipes[7]; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project pid_t childPid = fork(); 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If fork() failed... 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == -1) { 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, errno); 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, -1); 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If this is the child process... 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (childPid == 0) { 104410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob /* 1056c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * Note: We cannot malloc(3) or free(3) after this point! 1066c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * A thread in the parent that no longer exists in the child may have held the heap lock 1076c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes * when we forked, so an attempt to malloc(3) or free(3) would result in deadlock. 108410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob */ 109410530d90797fd49ad34c76a05a2c8f5147f88e1crazybob 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Replace stdin, out, and err with pipes. 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdinIn, 0); 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project dup2(stdoutOut, 1); 1131805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes if (redirectErrorStream) { 1141805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stdoutOut, 2); 1151805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } else { 1161805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes dup2(stderrOut, 2); 1171805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close all but statusOut. This saves some work in the next step. 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project closePipes(pipes, statusOut); 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Make statusOut automatically close if execvp() succeeds. 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project fcntl(statusOut, F_SETFD, FD_CLOEXEC); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 125a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes // Close remaining unwanted open fds. 126a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes closeNonStandardFds(statusOut, androidSystemPropertiesFd); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Switch to working directory. 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (workingDirectory != NULL) { 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (chdir(workingDirectory) == -1) { 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project goto execFailed; 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Set up environment. 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (environment != NULL) { 137a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes extern char** environ; // Standard, but not in any header file. 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project environ = environment; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Execute process. By convention, the first argument in the arg array 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should be the command itself. In fact, I get segfaults when this 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // isn't the case. 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project execvp(commands[0], commands); 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // If we got here, execvp() failed or the working dir was invalid. 1476c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott HughesexecFailed: 1486c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes int error = errno; 1496c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes write(statusOut, &error, sizeof(int)); 1506c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes close(statusOut); 1516c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes exit(error); 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // This is the parent process. 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Close child's pipe ends. 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinIn); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutOut); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrOut); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusOut); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Check status pipe for an error code. If execvp() succeeds, the other 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // end of the pipe should automatically close, in which case, we'll read 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing. 165a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes int result; 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int count = read(statusIn, &result, sizeof(int)); 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(statusIn); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (count > 0) { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniThrowIOException(env, result); 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdoutIn); 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stdinOut); 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project close(stderrIn); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return -1; 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Fill in file descriptor wrappers. 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn); 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut); 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn); 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return childPid; 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Converts a Java String[] to a 0-terminated char**. */ 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char** convertStrings(JNIEnv* env, jobjectArray javaArray) { 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return NULL; 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19294367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jsize length = env->GetArrayLength(javaArray); 193583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes char** array = new char*[length + 1]; 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project array[length] = 0; 195e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes for (jsize i = 0; i < length; ++i) { 196e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i))); 197583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes // We need to pass these strings to const-unfriendly code. 198e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes char* entry = const_cast<char*>(env->GetStringUTFChars(javaEntry.get(), NULL)); 199e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes array[i] = entry; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return array; 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Frees a char** which was converted from a Java String[]. */ 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) { 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaArray == NULL) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 21194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jsize length = env->GetArrayLength(javaArray); 212e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes for (jsize i = 0; i < length; ++i) { 213e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i))); 214e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes env->ReleaseStringUTFChars(javaEntry.get(), array[i]); 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 217583ce47780cae3a014ca46534e08f5c2adc8fa88Elliott Hughes delete[] array; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts Java String[] to char** and delegates to executeProcess(). 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 223a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands, 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project jobjectArray javaEnvironment, jstring javaWorkingDirectory, 2251805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jobject inDescriptor, jobject outDescriptor, jobject errDescriptor, 2261805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes jboolean redirectErrorStream) { 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Copy commands into char*[]. 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** commands = convertStrings(env, javaCommands); 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Extract working directory string. 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project const char* workingDirectory = NULL; 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 23494367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL); 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Convert environment array. 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char** environment = convertStrings(env, javaEnvironment); 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes pid_t result = executeProcess(env, commands, environment, workingDirectory, 2411805727c24b2b80161fef93c4b7742cf2322bdeaElliott Hughes inDescriptor, outDescriptor, errDescriptor, redirectErrorStream); 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Temporarily clear exception so we can clean up. 24494367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes jthrowable exception = env->ExceptionOccurred(); 24594367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ExceptionClear(); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaEnvironment, environment); 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Clean up working directory string. 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (javaWorkingDirectory != NULL) { 25194367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory); 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project freeStrings(env, javaCommands, commands); 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Re-throw exception if present. 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (exception != NULL) { 25894367e0ead84fc2228799a78ec207ea52e203f1aElliott Hughes if (env->Throw(exception) < 0) { 259679cf68b607e9b4a3beb8bcdee06868ae583386fSteve Block ALOGE("Error rethrowing exception!"); 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return result; 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod methods[] = { 267e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"), 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 2697cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_lang_ProcessManager(JNIEnv* env) { 2707cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods)); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 272