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 19fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <dirent.h> 20fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <errno.h> 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <fcntl.h> 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h> 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h> 24fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <sys/resource.h> 25fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <sys/types.h> 26fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <sys/wait.h> 27fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include <unistd.h> 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 29fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#include "cutils/log.h" 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "jni.h" 31ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes#include "ExecStrings.h" 32ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes#include "JNIHelp.h" 33a9f5c16a864ff63ba63f810410f8a27c086d5d52Elliott Hughes#include "JniConstants.h" 346c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h" 35e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes#include "ScopedLocalRef.h" 36798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich#include "toStringArray.h" 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 38fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesstatic void CloseNonStandardFds(int status_pipe_fd) { 39fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // On Cygwin, Linux, and Solaris, the best way to close iterates over "/proc/self/fd/". 40fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes const char* fd_path = "/proc/self/fd"; 41fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#ifdef __APPLE__ 42fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // On Mac OS, there's "/dev/fd/" which Linux seems to link to "/proc/self/fd/", 43fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // but which on Solaris appears to be something quite different. 44fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes fd_path = "/dev/fd"; 45fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#endif 46fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 47fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Keep track of the system properties fd so we don't close it. 48fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int properties_fd = -1; 49fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes char* properties_fd_string = getenv("ANDROID_PROPERTY_WORKSPACE"); 50fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (properties_fd_string != NULL) { 51fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes properties_fd = atoi(properties_fd_string); 52fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 53fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 54fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes DIR* d = opendir(fd_path); 55fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int dir_fd = dirfd(d); 56fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes dirent* e; 57fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes while ((e = readdir(d)) != NULL) { 58fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes char* end; 59fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int fd = strtol(e->d_name, &end, 10); 60fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (!*end) { 61fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (fd > STDERR_FILENO && fd != dir_fd && fd != status_pipe_fd && fd != properties_fd) { 62fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(fd); 63fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 66fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes closedir(d); 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 69fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes#define PIPE_COUNT 4 // Number of pipes used to communicate with child. 70fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 71fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesstatic void ClosePipes(int pipes[], int skip_fd) { 72fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes for (int i = 0; i < PIPE_COUNT * 2; i++) { 73fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int fd = pipes[i]; 74fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (fd != -1 && fd != skip_fd) { 75fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(pipes[i]); 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 77fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 80fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesstatic void AbortChild(int status_pipe_fd) { 81fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int error = errno; 82fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes TEMP_FAILURE_RETRY(write(status_pipe_fd, &error, sizeof(int))); 83fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(status_pipe_fd); 84fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes _exit(127); 85fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes} 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 87fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes/** Executes a command in a child process. */ 88fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesstatic pid_t ExecuteProcess(JNIEnv* env, char** commands, char** environment, 89fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes const char* workingDirectory, jobject inDescriptor, 90fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jobject outDescriptor, jobject errDescriptor, 91fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jboolean redirectErrorStream) { 92fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 93fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe. 94fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 95fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes for (int i = 0; i < PIPE_COUNT; i++) { 96fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (pipe(pipes + i * 2) == -1) { 97fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniThrowIOException(env, errno); 98fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes ClosePipes(pipes, -1); 99fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes return -1; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 102fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stdinIn = pipes[0]; 103fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stdinOut = pipes[1]; 104fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stdoutIn = pipes[2]; 105fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stdoutOut = pipes[3]; 106fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stderrIn = pipes[4]; 107fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int stderrOut = pipes[5]; 108fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int statusIn = pipes[6]; 109fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int statusOut = pipes[7]; 110fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 111fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes pid_t childPid = fork(); 112fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 113fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // If fork() failed... 114fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (childPid == -1) { 115fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniThrowIOException(env, errno); 116fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes ClosePipes(pipes, -1); 117fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes return -1; 118fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 119fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 120fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // If this is the child process... 121fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (childPid == 0) { 122fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Note: We cannot malloc(3) or free(3) after this point! 123fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // A thread in the parent that no longer exists in the child may have held the heap lock 124fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // when we forked, so an attempt to malloc(3) or free(3) would result in deadlock. 125fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 126fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Replace stdin, out, and err with pipes. 127fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes dup2(stdinIn, 0); 128fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes dup2(stdoutOut, 1); 129fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (redirectErrorStream) { 130fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes dup2(stdoutOut, 2); 131fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } else { 132fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes dup2(stderrOut, 2); 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 135fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Close all but statusOut. This saves some work in the next step. 136fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes ClosePipes(pipes, statusOut); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 138fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Make statusOut automatically close if execvp() succeeds. 139fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes fcntl(statusOut, F_SETFD, FD_CLOEXEC); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 141fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Close remaining unwanted open fds. 142fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes CloseNonStandardFds(statusOut); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 144fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Switch to working directory. 145fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (workingDirectory != NULL) { 146fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (chdir(workingDirectory) == -1) { 147fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes AbortChild(statusOut); 148fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 149fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 151fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Set up environment. 152fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (environment != NULL) { 153fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes extern char** environ; // Standard, but not in any header file. 154fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes environ = environment; 155fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 157fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Execute process. By convention, the first argument in the arg array 158fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // should be the command itself. 159fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes execvp(commands[0], commands); 160fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes AbortChild(statusOut); 161fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 162fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 163fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // This is the parent process. 164fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 165fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Close child's pipe ends. 166fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stdinIn); 167fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stdoutOut); 168fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stderrOut); 169fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(statusOut); 170fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 171fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Check status pipe for an error code. If execvp(2) succeeds, the other 172fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // end of the pipe should automatically close, in which case, we'll read 173fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // nothing. 174fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int child_errno; 175fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes ssize_t count = TEMP_FAILURE_RETRY(read(statusIn, &child_errno, sizeof(int))); 176fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(statusIn); 177fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (count > 0) { 178fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // chdir(2) or execvp(2) in the child failed. 179fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // TODO: track which so we can be more specific in the detail message. 180fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniThrowIOException(env, child_errno); 181fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 182fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stdoutIn); 183fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stdinOut); 184fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes close(stderrIn); 185fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 186fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Reap our zombie child right away. 187fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int status; 188fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes int rc = TEMP_FAILURE_RETRY(waitpid(childPid, &status, 0)); 189fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (rc == -1) { 190fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes ALOGW("waitpid on failed exec failed: %s", strerror(errno)); 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 193fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes return -1; 194fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 195fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes 196fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Fill in file descriptor wrappers. 197fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn); 198fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut); 199fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn); 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 201fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes return childPid; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 205fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes * Converts Java String[] to char** and delegates to ExecuteProcess(). 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 207a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands, 208fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jobjectArray javaEnvironment, jstring javaWorkingDirectory, 209fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jobject inDescriptor, jobject outDescriptor, jobject errDescriptor, 210fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jboolean redirectErrorStream) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 212ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes ExecStrings commands(env, javaCommands); 213ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes ExecStrings environment(env, javaEnvironment); 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 215fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Extract working directory string. 216fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes const char* workingDirectory = NULL; 217fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (javaWorkingDirectory != NULL) { 218fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL); 219fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 221ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes pid_t result = ExecuteProcess(env, commands.get(), environment.get(), workingDirectory, 222fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes inDescriptor, outDescriptor, errDescriptor, redirectErrorStream); 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 224fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes // Clean up working directory string. 225fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes if (javaWorkingDirectory != NULL) { 226fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory); 227fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 229fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes return result; 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 232fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughesstatic JNINativeMethod gMethods[] = { 233fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott 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"), 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 2357cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_lang_ProcessManager(JNIEnv* env) { 236fd6fca42f9be9cf158cd6dd2e4c426f20d0e426fElliott Hughes jniRegisterNativeMethods(env, "java/lang/ProcessManager", gMethods, NELEM(gMethods)); 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 238