Mercurial > 510Connectbot
comparison jni/Exec/com_google_ase_Exec.cpp @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0ce5cc452d02 |
---|---|
1 /* | |
2 * Copyright (C) 2007 The Android Open Source Project | |
3 * | |
4 * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 * you may not use this file except in compliance with the License. | |
6 * You may obtain a copy of the License at | |
7 * | |
8 * http://www.apache.org/licenses/LICENSE-2.0 | |
9 * | |
10 * Unless required by applicable law or agreed to in writing, software | |
11 * distributed under the License is distributed on an "AS IS" BASIS, | |
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 * See the License for the specific language governing permissions and | |
14 * limitations under the License. | |
15 */ | |
16 | |
17 #include "com_google_ase_Exec.h" | |
18 | |
19 #include <errno.h> | |
20 #include <fcntl.h> | |
21 #include <stdlib.h> | |
22 #include <sys/ioctl.h> | |
23 #include <sys/types.h> | |
24 #include <sys/wait.h> | |
25 #include <termios.h> | |
26 #include <unistd.h> | |
27 | |
28 #include "android/log.h" | |
29 | |
30 #define LOG_TAG "Exec" | |
31 #define LOG(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) | |
32 | |
33 void JNU_ThrowByName(JNIEnv * env, const char *name, const char *msg) { | |
34 jclass clazz = env->FindClass(name); | |
35 if (clazz != NULL) { | |
36 env->ThrowNew(clazz, msg); | |
37 } | |
38 env->DeleteLocalRef(clazz); | |
39 } | |
40 | |
41 char *JNU_GetStringNativeChars(JNIEnv * env, jstring jstr) { | |
42 if (jstr == NULL) { | |
43 return NULL; | |
44 } | |
45 jbyteArray bytes = 0; | |
46 jthrowable exc; | |
47 char *result = 0; | |
48 if (env->EnsureLocalCapacity(2) < 0) { | |
49 return 0; /* out of memory error */ | |
50 } | |
51 jclass Class_java_lang_String = env->FindClass("java/lang/String"); | |
52 jmethodID MID_String_getBytes = env->GetMethodID(Class_java_lang_String, "getBytes", "()[B"); | |
53 bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes); | |
54 exc = env->ExceptionOccurred(); | |
55 if (!exc) { | |
56 jint len = env->GetArrayLength(bytes); | |
57 result = (char *) malloc(len + 1); | |
58 if (result == 0) { | |
59 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); | |
60 env->DeleteLocalRef(bytes); | |
61 return 0; | |
62 } | |
63 env->GetByteArrayRegion(bytes, 0, len, (jbyte *) result); | |
64 result[len] = 0; /* NULL-terminate */ | |
65 } else { | |
66 env->DeleteLocalRef(exc); | |
67 } | |
68 env->DeleteLocalRef(bytes); | |
69 return result; | |
70 } | |
71 | |
72 int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) { | |
73 jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); | |
74 jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, | |
75 "descriptor", "I"); | |
76 return env->GetIntField(fileDescriptor, descriptor); | |
77 } | |
78 | |
79 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, int *pProcessId) { | |
80 char *devname; | |
81 int ptm; | |
82 pid_t pid; | |
83 | |
84 ptm = open("/dev/ptmx", O_RDWR); // | O_NOCTTY); | |
85 if (ptm < 0) { | |
86 LOG("[ cannot open /dev/ptmx - %s ]\n", strerror(errno)); | |
87 return -1; | |
88 } | |
89 fcntl(ptm, F_SETFD, FD_CLOEXEC); | |
90 | |
91 if (grantpt(ptm) || unlockpt(ptm) || ((devname = (char *) ptsname(ptm)) == 0)) { | |
92 LOG("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); | |
93 return -1; | |
94 } | |
95 | |
96 pid = fork(); | |
97 if (pid < 0) { | |
98 LOG("- fork failed: %s -\n", strerror(errno)); | |
99 return -1; | |
100 } | |
101 | |
102 if (pid == 0) { | |
103 int pts; | |
104 | |
105 setsid(); | |
106 | |
107 pts = open(devname, O_RDWR); | |
108 if (pts < 0) | |
109 exit(-1); | |
110 | |
111 dup2(pts, 0); | |
112 dup2(pts, 1); | |
113 dup2(pts, 2); | |
114 | |
115 close(ptm); | |
116 | |
117 execl(cmd, cmd, arg0, arg1, NULL); | |
118 exit(-1); | |
119 } else { | |
120 *pProcessId = (int) pid; | |
121 return ptm; | |
122 } | |
123 } | |
124 | |
125 JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(JNIEnv * env, jclass clazz, | |
126 jstring cmd, jstring arg0, | |
127 jstring arg1, | |
128 jintArray processIdArray) { | |
129 char *cmd_8 = JNU_GetStringNativeChars(env, cmd); | |
130 char *arg0_8 = JNU_GetStringNativeChars(env, arg0); | |
131 char *arg1_8 = JNU_GetStringNativeChars(env, arg1); | |
132 | |
133 int procId; | |
134 int ptm = create_subprocess(cmd_8, arg0_8, arg1_8, &procId); | |
135 | |
136 if (processIdArray) { | |
137 int procIdLen = env->GetArrayLength(processIdArray); | |
138 if (procIdLen > 0) { | |
139 jboolean isCopy; | |
140 int *pProcId = (int *) env->GetPrimitiveArrayCritical(processIdArray, &isCopy); | |
141 if (pProcId) { | |
142 *pProcId = procId; | |
143 env->ReleasePrimitiveArrayCritical(processIdArray, pProcId, 0); | |
144 } | |
145 } | |
146 } | |
147 | |
148 jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); | |
149 jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor, | |
150 "<init>", "()V"); | |
151 jobject result = env->NewObject(Class_java_io_FileDescriptor, init); | |
152 | |
153 if (!result) { | |
154 LOG("Couldn't create a FileDescriptor."); | |
155 } else { | |
156 jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, | |
157 "descriptor", "I"); | |
158 env->SetIntField(result, descriptor, ptm); | |
159 } | |
160 | |
161 return result; | |
162 } | |
163 | |
164 JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(JNIEnv * env, jclass clazz, | |
165 jobject fileDescriptor, jint row, jint col, | |
166 jint xpixel, jint ypixel) { | |
167 int fd; | |
168 struct winsize sz; | |
169 | |
170 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); | |
171 | |
172 if (env->ExceptionOccurred() != NULL) { | |
173 return; | |
174 } | |
175 | |
176 sz.ws_row = row; | |
177 sz.ws_col = col; | |
178 sz.ws_xpixel = xpixel; | |
179 sz.ws_ypixel = ypixel; | |
180 | |
181 ioctl(fd, TIOCSWINSZ, &sz); | |
182 } | |
183 | |
184 JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv * env, jclass clazz, jint procId) { | |
185 int status; | |
186 waitpid(procId, &status, 0); | |
187 int result = 0; | |
188 if (WIFEXITED(status)) { | |
189 result = WEXITSTATUS(status); | |
190 } | |
191 return result; | |
192 } |