Mercurial > 510Connectbot
annotate app/src/main/jni/Exec/com_google_ase_Exec.cpp @ 513:13a922d1fc5c
update docs
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 10 Feb 2023 17:16:47 -0700 |
parents | 105815cce146 |
children |
rev | line source |
---|---|
0 | 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> | |
457
105815cce146
minimum version android 5, target and compile version api 28
Carl Byington <carl@five-ten-sg.com>
parents:
438
diff
changeset
|
27 #include <string.h> |
0 | 28 |
29 #include "android/log.h" | |
30 | |
31 #define LOG_TAG "Exec" | |
32 #define LOG(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) | |
33 | |
34 void JNU_ThrowByName(JNIEnv * env, const char *name, const char *msg) { | |
35 jclass clazz = env->FindClass(name); | |
36 if (clazz != NULL) { | |
37 env->ThrowNew(clazz, msg); | |
38 } | |
39 env->DeleteLocalRef(clazz); | |
40 } | |
41 | |
42 char *JNU_GetStringNativeChars(JNIEnv * env, jstring jstr) { | |
43 if (jstr == NULL) { | |
44 return NULL; | |
45 } | |
46 jbyteArray bytes = 0; | |
47 jthrowable exc; | |
48 char *result = 0; | |
49 if (env->EnsureLocalCapacity(2) < 0) { | |
50 return 0; /* out of memory error */ | |
51 } | |
52 jclass Class_java_lang_String = env->FindClass("java/lang/String"); | |
53 jmethodID MID_String_getBytes = env->GetMethodID(Class_java_lang_String, "getBytes", "()[B"); | |
54 bytes = (jbyteArray) env->CallObjectMethod(jstr, MID_String_getBytes); | |
55 exc = env->ExceptionOccurred(); | |
56 if (!exc) { | |
57 jint len = env->GetArrayLength(bytes); | |
58 result = (char *) malloc(len + 1); | |
59 if (result == 0) { | |
60 JNU_ThrowByName(env, "java/lang/OutOfMemoryError", 0); | |
61 env->DeleteLocalRef(bytes); | |
62 return 0; | |
63 } | |
64 env->GetByteArrayRegion(bytes, 0, len, (jbyte *) result); | |
65 result[len] = 0; /* NULL-terminate */ | |
66 } else { | |
67 env->DeleteLocalRef(exc); | |
68 } | |
69 env->DeleteLocalRef(bytes); | |
70 return result; | |
71 } | |
72 | |
73 int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) { | |
74 jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); | |
75 jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, | |
76 "descriptor", "I"); | |
77 return env->GetIntField(fileDescriptor, descriptor); | |
78 } | |
79 | |
80 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, int *pProcessId) { | |
81 char *devname; | |
82 int ptm; | |
83 pid_t pid; | |
84 | |
85 ptm = open("/dev/ptmx", O_RDWR); // | O_NOCTTY); | |
86 if (ptm < 0) { | |
87 LOG("[ cannot open /dev/ptmx - %s ]\n", strerror(errno)); | |
88 return -1; | |
89 } | |
90 fcntl(ptm, F_SETFD, FD_CLOEXEC); | |
91 | |
92 if (grantpt(ptm) || unlockpt(ptm) || ((devname = (char *) ptsname(ptm)) == 0)) { | |
93 LOG("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); | |
94 return -1; | |
95 } | |
96 | |
97 pid = fork(); | |
98 if (pid < 0) { | |
99 LOG("- fork failed: %s -\n", strerror(errno)); | |
100 return -1; | |
101 } | |
102 | |
103 if (pid == 0) { | |
104 int pts; | |
105 | |
106 setsid(); | |
107 | |
108 pts = open(devname, O_RDWR); | |
109 if (pts < 0) | |
110 exit(-1); | |
111 | |
112 dup2(pts, 0); | |
113 dup2(pts, 1); | |
114 dup2(pts, 2); | |
115 | |
116 close(ptm); | |
117 | |
118 execl(cmd, cmd, arg0, arg1, NULL); | |
119 exit(-1); | |
120 } else { | |
121 *pProcessId = (int) pid; | |
122 return ptm; | |
123 } | |
124 } | |
125 | |
126 JNIEXPORT jobject JNICALL Java_com_google_ase_Exec_createSubprocess(JNIEnv * env, jclass clazz, | |
127 jstring cmd, jstring arg0, | |
128 jstring arg1, | |
129 jintArray processIdArray) { | |
130 char *cmd_8 = JNU_GetStringNativeChars(env, cmd); | |
131 char *arg0_8 = JNU_GetStringNativeChars(env, arg0); | |
132 char *arg1_8 = JNU_GetStringNativeChars(env, arg1); | |
133 | |
134 int procId; | |
135 int ptm = create_subprocess(cmd_8, arg0_8, arg1_8, &procId); | |
136 | |
137 if (processIdArray) { | |
138 int procIdLen = env->GetArrayLength(processIdArray); | |
139 if (procIdLen > 0) { | |
140 jboolean isCopy; | |
141 int *pProcId = (int *) env->GetPrimitiveArrayCritical(processIdArray, &isCopy); | |
142 if (pProcId) { | |
143 *pProcId = procId; | |
144 env->ReleasePrimitiveArrayCritical(processIdArray, pProcId, 0); | |
145 } | |
146 } | |
147 } | |
148 | |
149 jclass Class_java_io_FileDescriptor = env->FindClass("java/io/FileDescriptor"); | |
150 jmethodID init = env->GetMethodID(Class_java_io_FileDescriptor, | |
151 "<init>", "()V"); | |
152 jobject result = env->NewObject(Class_java_io_FileDescriptor, init); | |
153 | |
154 if (!result) { | |
155 LOG("Couldn't create a FileDescriptor."); | |
156 } else { | |
157 jfieldID descriptor = env->GetFieldID(Class_java_io_FileDescriptor, | |
158 "descriptor", "I"); | |
159 env->SetIntField(result, descriptor, ptm); | |
160 } | |
161 | |
162 return result; | |
163 } | |
164 | |
165 JNIEXPORT void Java_com_google_ase_Exec_setPtyWindowSize(JNIEnv * env, jclass clazz, | |
166 jobject fileDescriptor, jint row, jint col, | |
167 jint xpixel, jint ypixel) { | |
168 int fd; | |
169 struct winsize sz; | |
170 | |
171 fd = jniGetFDFromFileDescriptor(env, fileDescriptor); | |
172 | |
173 if (env->ExceptionOccurred() != NULL) { | |
174 return; | |
175 } | |
176 | |
177 sz.ws_row = row; | |
178 sz.ws_col = col; | |
179 sz.ws_xpixel = xpixel; | |
180 sz.ws_ypixel = ypixel; | |
181 | |
182 ioctl(fd, TIOCSWINSZ, &sz); | |
183 } | |
184 | |
185 JNIEXPORT jint Java_com_google_ase_Exec_waitFor(JNIEnv * env, jclass clazz, jint procId) { | |
186 int status; | |
187 waitpid(procId, &status, 0); | |
188 int result = 0; | |
189 if (WIFEXITED(status)) { | |
190 result = WEXITSTATUS(status); | |
191 } | |
192 return result; | |
193 } |