5
5
import android .content .Intent ;
6
6
import android .os .Bundle ;
7
7
8
- import com .termux .BuildConfig ;
9
8
import com .termux .app .utils .Logger ;
9
+ import com .termux .app .utils .ShellUtils ;
10
10
import com .termux .models .ExecutionCommand ;
11
11
import com .termux .models .ExecutionCommand .ExecutionState ;
12
12
13
13
import java .io .BufferedReader ;
14
14
import java .io .File ;
15
- import java .io .FileInputStream ;
16
15
import java .io .IOException ;
17
16
import java .io .InputStream ;
18
17
import java .io .InputStreamReader ;
19
- import java .lang .reflect .Field ;
20
18
import java .nio .charset .StandardCharsets ;
21
- import java .util .ArrayList ;
22
19
import java .util .Arrays ;
23
- import java .util .Collections ;
24
- import java .util .List ;
25
20
26
21
/**
27
22
* A background job launched by Termux.
@@ -37,12 +32,12 @@ public BackgroundJob(String executable, final String[] arguments, String working
37
32
}
38
33
39
34
public BackgroundJob (ExecutionCommand executionCommand , final TermuxService service ) {
40
- String [] env = buildEnvironment (false , executionCommand .workingDirectory );
35
+ String [] env = ShellUtils . buildEnvironment (false , executionCommand .workingDirectory );
41
36
42
37
if (executionCommand .workingDirectory == null || executionCommand .workingDirectory .isEmpty ())
43
38
executionCommand .workingDirectory = TermuxConstants .TERMUX_HOME_DIR_PATH ;
44
39
45
- final String [] commandArray = setupProcessArgs (executionCommand .executable , executionCommand .arguments );
40
+ final String [] commandArray = ShellUtils . setupProcessArgs (executionCommand .executable , executionCommand .arguments );
46
41
final String commandDescription = Arrays .toString (commandArray );
47
42
48
43
if (!executionCommand .setState (ExecutionState .EXECUTING ))
@@ -59,7 +54,7 @@ public BackgroundJob(ExecutionCommand executionCommand, final TermuxService serv
59
54
}
60
55
61
56
mProcess = process ;
62
- final int pid = getPid (mProcess );
57
+ final int pid = ShellUtils . getPid (mProcess );
63
58
final Bundle result = new Bundle ();
64
59
final StringBuilder outResult = new StringBuilder ();
65
60
final StringBuilder errResult = new StringBuilder ();
@@ -138,118 +133,4 @@ public void run() {
138
133
}.start ();
139
134
}
140
135
141
- private static void addToEnvIfPresent (List <String > environment , String name ) {
142
- String value = System .getenv (name );
143
- if (value != null ) {
144
- environment .add (name + "=" + value );
145
- }
146
- }
147
-
148
- static String [] buildEnvironment (boolean isFailSafe , String workingDirectory ) {
149
- TermuxConstants .TERMUX_HOME_DIR .mkdirs ();
150
-
151
- if (workingDirectory == null || workingDirectory .isEmpty ()) workingDirectory = TermuxConstants .TERMUX_HOME_DIR_PATH ;
152
-
153
- List <String > environment = new ArrayList <>();
154
-
155
- environment .add ("TERMUX_VERSION=" + BuildConfig .VERSION_NAME );
156
- environment .add ("TERM=xterm-256color" );
157
- environment .add ("COLORTERM=truecolor" );
158
- environment .add ("HOME=" + TermuxConstants .TERMUX_HOME_DIR_PATH );
159
- environment .add ("PREFIX=" + TermuxConstants .TERMUX_PREFIX_DIR_PATH );
160
- environment .add ("BOOTCLASSPATH=" + System .getenv ("BOOTCLASSPATH" ));
161
- environment .add ("ANDROID_ROOT=" + System .getenv ("ANDROID_ROOT" ));
162
- environment .add ("ANDROID_DATA=" + System .getenv ("ANDROID_DATA" ));
163
- // EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
164
- // Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
165
- environment .add ("EXTERNAL_STORAGE=" + System .getenv ("EXTERNAL_STORAGE" ));
166
-
167
- // These variables are needed if running on Android 10 and higher.
168
- addToEnvIfPresent (environment , "ANDROID_ART_ROOT" );
169
- addToEnvIfPresent (environment , "DEX2OATBOOTCLASSPATH" );
170
- addToEnvIfPresent (environment , "ANDROID_I18N_ROOT" );
171
- addToEnvIfPresent (environment , "ANDROID_RUNTIME_ROOT" );
172
- addToEnvIfPresent (environment , "ANDROID_TZDATA_ROOT" );
173
-
174
- if (isFailSafe ) {
175
- // Keep the default path so that system binaries can be used in the failsafe session.
176
- environment .add ("PATH= " + System .getenv ("PATH" ));
177
- } else {
178
- environment .add ("LANG=en_US.UTF-8" );
179
- environment .add ("PATH=" + TermuxConstants .TERMUX_BIN_PREFIX_DIR_PATH );
180
- environment .add ("PWD=" + workingDirectory );
181
- environment .add ("TMPDIR=" + TermuxConstants .TERMUX_TMP_PREFIX_DIR_PATH );
182
- }
183
-
184
- return environment .toArray (new String [0 ]);
185
- }
186
-
187
- public static int getPid (Process p ) {
188
- try {
189
- Field f = p .getClass ().getDeclaredField ("pid" );
190
- f .setAccessible (true );
191
- try {
192
- return f .getInt (p );
193
- } finally {
194
- f .setAccessible (false );
195
- }
196
- } catch (Throwable e ) {
197
- return -1 ;
198
- }
199
- }
200
-
201
- static String [] setupProcessArgs (String fileToExecute , String [] arguments ) {
202
- // The file to execute may either be:
203
- // - An elf file, in which we execute it directly.
204
- // - A script file without shebang, which we execute with our standard shell $PREFIX/bin/sh instead of the
205
- // system /system/bin/sh. The system shell may vary and may not work at all due to LD_LIBRARY_PATH.
206
- // - A file with shebang, which we try to handle with e.g. /bin/foo -> $PREFIX/bin/foo.
207
- String interpreter = null ;
208
- try {
209
- File file = new File (fileToExecute );
210
- try (FileInputStream in = new FileInputStream (file )) {
211
- byte [] buffer = new byte [256 ];
212
- int bytesRead = in .read (buffer );
213
- if (bytesRead > 4 ) {
214
- if (buffer [0 ] == 0x7F && buffer [1 ] == 'E' && buffer [2 ] == 'L' && buffer [3 ] == 'F' ) {
215
- // Elf file, do nothing.
216
- } else if (buffer [0 ] == '#' && buffer [1 ] == '!' ) {
217
- // Try to parse shebang.
218
- StringBuilder builder = new StringBuilder ();
219
- for (int i = 2 ; i < bytesRead ; i ++) {
220
- char c = (char ) buffer [i ];
221
- if (c == ' ' || c == '\n' ) {
222
- if (builder .length () == 0 ) {
223
- // Skip whitespace after shebang.
224
- } else {
225
- // End of shebang.
226
- String executable = builder .toString ();
227
- if (executable .startsWith ("/usr" ) || executable .startsWith ("/bin" )) {
228
- String [] parts = executable .split ("/" );
229
- String binary = parts [parts .length - 1 ];
230
- interpreter = TermuxConstants .TERMUX_BIN_PREFIX_DIR_PATH + "/" + binary ;
231
- }
232
- break ;
233
- }
234
- } else {
235
- builder .append (c );
236
- }
237
- }
238
- } else {
239
- // No shebang and no ELF, use standard shell.
240
- interpreter = TermuxConstants .TERMUX_BIN_PREFIX_DIR_PATH + "/sh" ;
241
- }
242
- }
243
- }
244
- } catch (IOException e ) {
245
- // Ignore.
246
- }
247
-
248
- List <String > result = new ArrayList <>();
249
- if (interpreter != null ) result .add (interpreter );
250
- result .add (fileToExecute );
251
- if (arguments != null ) Collections .addAll (result , arguments );
252
- return result .toArray (new String [0 ]);
253
- }
254
-
255
136
}
0 commit comments