java_lang_ProcessManager.cpp revision adc854b798c1cfe3bfd4c27d68d5cee38ca617da
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
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/types.h>
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <sys/wait.h>
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <unistd.h>
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <fcntl.h>
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <signal.h>
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdlib.h>
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <string.h>
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <errno.h>
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <dirent.h>
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "jni.h"
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "JNIHelp.h"
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "utils/Log.h"
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include "AndroidSystemNatives.h"
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Environment variables. */
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectextern char **environ;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic jmethodID onExitMethod = NULL;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic jfieldID descriptorField = NULL;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project// Keeps track of the system properties fd so we don't close it.
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic int androidSystemPropertiesFd = -1;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * These are constants shared with the higher level code in
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * ProcessManager.java.
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_UNKNOWN (-1)       // unknown child status
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_NO_CHILDREN (-2)   // no children to wait for
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define WAIT_STATUS_STRANGE_ERRNO (-3) // observed an undocumented errno
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes a file descriptor. */
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic int closeNow(int fd) {
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int result;
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    do {
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        result = close(fd);
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    } while (result == -1 && errno == EINTR);
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return result;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes a file descriptor. */
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_close(JNIEnv* env,
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jclass clazz, jobject javaDescriptor) {
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int fd = (*env)->GetIntField(env, javaDescriptor, descriptorField);
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (closeNow(fd) == -1) {
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jclass ioException = (*env)->FindClass(env, "java/io/IOException");
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (*env)->ThrowNew(env, ioException, strerror(errno));
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Kills process with the given ID.
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_kill(JNIEnv* env, jclass clazz, jint pid) {
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int result = kill((pid_t) pid, SIGKILL);
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (result == -1) {
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jniThrowIOException(env, errno);
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Loops indefinitely and calls ProcessManager.onExit() when children exit.
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_watchChildren(JNIEnv* env, jobject o) {
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (onExitMethod == NULL) {
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jniThrowException(env, "java/lang/IllegalStateException",
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "staticInitialize() must run first.");
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    while (1) {
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int status;
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        pid_t pid = wait(&status);
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (pid >= 0) {
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Extract real status.
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (WIFEXITED(status)) {
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                status = WEXITSTATUS(status);
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (WIFSIGNALED(status)) {
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                status = WTERMSIG(status);
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (WIFSTOPPED(status)) {
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                status = WSTOPSIG(status);
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                status = WAIT_STATUS_UNKNOWN;
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * The pid should be -1 already, but force it here just in case
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * we somehow end up with some other negative value.
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            pid = -1;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (errno) {
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case ECHILD: {
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Expected errno: There are no children to wait()
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * for. The callback will sleep until it is
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * informed of another child coming to life.
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    status = WAIT_STATUS_NO_CHILDREN;
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case EINTR: {
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * An unblocked signal came in while waiting; just
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * retry the wait().
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                default: {
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Unexpected errno, so squawk! Note: Per the
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Linux docs, there are no errnos defined for
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * wait() other than the two that are handled
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * immediately above.
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    LOGE("Error %d calling wait(): %s", errno,
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            strerror(errno));
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    status = WAIT_STATUS_STRANGE_ERRNO;
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (*env)->CallVoidMethod(env, o, onExitMethod, pid, status);
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((*env)->ExceptionOccurred(env)) {
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * The callback threw, so break out of the loop and return,
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * letting the exception percolate up.
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            break;
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Close all open fds > 2 (i.e. everything but stdin/out/err). */
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closeNonStandardFds(int skipFd) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    DIR* dir = opendir("/proc/self/fd");
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (dir == NULL) {
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Print message to standard err. The parent process can read this
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // from Process.getErrorStream().
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        perror("opendir");
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    struct dirent* entry;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int dirFd = dirfd(dir);
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    while ((entry = readdir(dir)) != NULL) {
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int fd = atoi(entry->d_name);
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fd > 2 && fd != dirFd && fd != skipFd
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && fd != androidSystemPropertiesFd
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ) {
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            close(fd);
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    closedir(dir);
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#define PIPE_COUNT (4) // number of pipes used to communicate with child proc
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Closes all pipes in the given array. */
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void closePipes(int pipes[], int skipFd) {
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int i;
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    for (i = 0; i < PIPE_COUNT * 2; i++) {
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int fd = pipes[i];
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fd == -1) {
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fd != skipFd) {
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            close(pipes[i]);
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Executes a command in a child process. */
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        const char* workingDirectory, jobject inDescriptor,
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jobject outDescriptor, jobject errDescriptor) {
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int i, result, error;
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    for (i = 0; i < PIPE_COUNT; i++) {
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (pipe(pipes + i * 2) == -1) {
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            jniThrowIOException(env, errno);
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            closePipes(pipes, -1);
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return -1;
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stdinIn = pipes[0];
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stdinOut = pipes[1];
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stdoutIn = pipes[2];
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stdoutOut = pipes[3];
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stderrIn = pipes[4];
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int stderrOut = pipes[5];
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int statusIn = pipes[6];
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int statusOut = pipes[7];
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    pid_t childPid = fork();
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // If fork() failed...
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (childPid == -1) {
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jniThrowIOException(env, errno);
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        closePipes(pipes, -1);
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return -1;
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // If this is the child process...
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (childPid == 0) {
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Replace stdin, out, and err with pipes.
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        dup2(stdinIn, 0);
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        dup2(stdoutOut, 1);
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        dup2(stderrOut, 2);
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Close all but statusOut. This saves some work in the next step.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        closePipes(pipes, statusOut);
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Make statusOut automatically close if execvp() succeeds.
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        fcntl(statusOut, F_SETFD, FD_CLOEXEC);
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Close remaining open fds with the exception of statusOut.
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        closeNonStandardFds(statusOut);
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Switch to working directory.
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (workingDirectory != NULL) {
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (chdir(workingDirectory) == -1) {
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                goto execFailed;
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Set up environment.
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (environment != NULL) {
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            environ = environment;
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Execute process. By convention, the first argument in the arg array
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // should be the command itself. In fact, I get segfaults when this
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // isn't the case.
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        execvp(commands[0], commands);
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If we got here, execvp() failed or the working dir was invalid.
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        execFailed:
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            error = errno;
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            write(statusOut, &error, sizeof(int));
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            close(statusOut);
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            exit(error);
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // This is the parent process.
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Close child's pipe ends.
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    close(stdinIn);
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    close(stdoutOut);
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    close(stderrOut);
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    close(statusOut);
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Check status pipe for an error code. If execvp() succeeds, the other
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // end of the pipe should automatically close, in which case, we'll read
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // nothing.
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    int count = read(statusIn, &result, sizeof(int));
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    close(statusIn);
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (count > 0) {
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jniThrowIOException(env, result);
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        close(stdoutIn);
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        close(stdinOut);
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        close(stderrIn);
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return -1;
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Fill in file descriptor wrappers.
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return childPid;
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Converts a Java String[] to a 0-terminated char**. */
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char** convertStrings(JNIEnv* env, jobjectArray javaArray) {
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (javaArray == NULL) {
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return NULL;
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char** array = NULL;
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jsize length = (*env)->GetArrayLength(env, javaArray);
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    array = (char**) malloc(sizeof(char*) * (length + 1));
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    array[length] = 0;
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jsize index;
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    for (index = 0; index < length; index++) {
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jstring javaEntry = (jstring) (*env)->GetObjectArrayElement(
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                env, javaArray, index);
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        char* entry = (char*) (*env)->GetStringUTFChars(
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                env, javaEntry, NULL);
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        array[index] = entry;
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return array;
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** Frees a char** which was converted from a Java String[]. */
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) {
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (javaArray == NULL) {
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return;
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jsize length = (*env)->GetArrayLength(env, javaArray);
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jsize index;
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    for (index = 0; index < length; index++) {
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jstring javaEntry = (jstring) (*env)->GetObjectArrayElement(
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                env, javaArray, index);
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (*env)->ReleaseStringUTFChars(env, javaEntry, array[index]);
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    free(array);
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Converts Java String[] to char** and delegates to executeProcess().
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic pid_t java_lang_ProcessManager_exec(
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        JNIEnv* env, jclass clazz, jobjectArray javaCommands,
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jobjectArray javaEnvironment, jstring javaWorkingDirectory,
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jobject inDescriptor, jobject outDescriptor, jobject errDescriptor) {
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Copy commands into char*[].
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char** commands = convertStrings(env, javaCommands);
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Extract working directory string.
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    const char* workingDirectory = NULL;
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (javaWorkingDirectory != NULL) {
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        workingDirectory = (const char*) (*env)->GetStringUTFChars(
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                env, javaWorkingDirectory, NULL);
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Convert environment array.
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char** environment = convertStrings(env, javaEnvironment);
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    pid_t result = executeProcess(
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            env, commands, environment, workingDirectory,
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            inDescriptor, outDescriptor, errDescriptor);
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Temporarily clear exception so we can clean up.
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jthrowable exception = (*env)->ExceptionOccurred(env);
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    (*env)->ExceptionClear(env);
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    freeStrings(env, javaEnvironment, environment);
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Clean up working directory string.
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (javaWorkingDirectory != NULL) {
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (*env)->ReleaseStringUTFChars(
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                env, javaWorkingDirectory, workingDirectory);
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    freeStrings(env, javaCommands, commands);
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Re-throw exception if present.
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (exception != NULL) {
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((*env)->Throw(env, exception) < 0) {
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            LOGE("Error rethrowing exception!");
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return result;
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Looks up Java members.
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic void java_lang_ProcessManager_staticInitialize(JNIEnv* env,
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        jclass clazz) {
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#ifdef ANDROID
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE");
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (fdString) {
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        androidSystemPropertiesFd = atoi(fdString);
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#endif
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    onExitMethod = (*env)->GetMethodID(env, clazz, "onExit", "(II)V");
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (onExitMethod == NULL) {
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    jclass fileDescriptorClass
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            = (*env)->FindClass(env, "java/io/FileDescriptor");
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (fileDescriptorClass == NULL) {
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return;
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    descriptorField = (*env)->GetFieldID(env, fileDescriptorClass,
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "descriptor", "I");
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (descriptorField == NULL) {
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return;
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic JNINativeMethod methods[] = {
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    { "kill", "(I)V", (void*) java_lang_ProcessManager_kill },
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    { "watchChildren", "()V", (void*) java_lang_ProcessManager_watchChildren },
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    { "exec", "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;"
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        "Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        "Ljava/io/FileDescriptor;)I", (void*) java_lang_ProcessManager_exec },
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    { "staticInitialize", "()V",
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (void*) java_lang_ProcessManager_staticInitialize },
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    { "close", "(Ljava/io/FileDescriptor;)V",
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        (void*) java_lang_ProcessManager_close },
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project};
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectint register_java_lang_ProcessManager(JNIEnv* env) {
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return jniRegisterNativeMethods(
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            env, "java/lang/ProcessManager", methods, NELEM(methods));
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
439