mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 10:45:23 +08:00
Use $PREFIX/bin/sh for script file without shebang
Also try to handle #!(/usr)/bin/foo shebangs.
This commit is contained in:
@@ -4,12 +4,15 @@ import android.util.Log;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A background job launched by Termux.
|
* A background job launched by Termux.
|
||||||
@@ -24,16 +27,7 @@ public final class BackgroundJob {
|
|||||||
String[] env = buildEnvironment(false, cwd);
|
String[] env = buildEnvironment(false, cwd);
|
||||||
if (cwd == null) cwd = TermuxService.HOME_PATH;
|
if (cwd == null) cwd = TermuxService.HOME_PATH;
|
||||||
|
|
||||||
String[] modifiedArgs;
|
final String[] progArray = setupProcessArgs(fileToExecute, args);
|
||||||
if (args == null) {
|
|
||||||
modifiedArgs = new String[]{fileToExecute};
|
|
||||||
} else {
|
|
||||||
modifiedArgs = new String[args.length + 1];
|
|
||||||
modifiedArgs[0] = fileToExecute;
|
|
||||||
System.arraycopy(args, 0, modifiedArgs, 1, args.length);
|
|
||||||
}
|
|
||||||
final String[] progArray = modifiedArgs;
|
|
||||||
|
|
||||||
final String processDescription = Arrays.toString(progArray);
|
final String processDescription = Arrays.toString(progArray);
|
||||||
|
|
||||||
Process process;
|
Process process;
|
||||||
@@ -45,6 +39,7 @@ public final class BackgroundJob {
|
|||||||
Log.e(LOG_TAG, "Failed running background job: " + processDescription, e);
|
Log.e(LOG_TAG, "Failed running background job: " + processDescription, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mProcess = process;
|
mProcess = process;
|
||||||
final int pid = getPid(mProcess);
|
final int pid = getPid(mProcess);
|
||||||
|
|
||||||
@@ -126,17 +121,74 @@ public final class BackgroundJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int getPid(Process p) {
|
public static int getPid(Process p) {
|
||||||
int pid = -1;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Field f = p.getClass().getDeclaredField("pid");
|
Field f = p.getClass().getDeclaredField("pid");
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
pid = f.getInt(p);
|
try {
|
||||||
f.setAccessible(false);
|
return f.getInt(p);
|
||||||
|
} finally {
|
||||||
|
f.setAccessible(false);
|
||||||
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
pid = -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return pid;
|
}
|
||||||
|
|
||||||
|
static String[] setupProcessArgs(String fileToExecute, String[] args) {
|
||||||
|
// The file to execute may either be:
|
||||||
|
// - An elf file, in which we execute it directly.
|
||||||
|
// - A script file without shebang, which we execute with our standard shell $PREFIX/bin/sh instead of the
|
||||||
|
// system /system/bin/sh. The system shell may vary and may not work at all due to LD_LIBRARY_PATH.
|
||||||
|
// - A file with shebang, which we try to handle with e.g. /bin/foo -> $PREFIX/bin/foo.
|
||||||
|
String interpreter = null;
|
||||||
|
try {
|
||||||
|
File file = new File(fileToExecute);
|
||||||
|
try (FileInputStream in = new FileInputStream(file)) {
|
||||||
|
byte[] buffer = new byte[256];
|
||||||
|
int bytesRead = in.read(buffer);
|
||||||
|
if (bytesRead > 4) {
|
||||||
|
if (buffer[0] == 0x7F && buffer[1] == 'E' && buffer[2] == 'L' && buffer[3] == 'F') {
|
||||||
|
// Elf file, do nothing.
|
||||||
|
} else if (buffer[0] == '#' && buffer[1] == '!') {
|
||||||
|
// Try to parse shebang.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (int i = 2; i < bytesRead; i++) {
|
||||||
|
char c = (char) buffer[i];
|
||||||
|
if (c == ' ' || c == '\n') {
|
||||||
|
if (builder.length() == 0) {
|
||||||
|
// Skip whitespace after shebang.
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// End of shebang.
|
||||||
|
String executable = builder.toString();
|
||||||
|
if (executable.startsWith("/usr") || executable.startsWith("/bin")) {
|
||||||
|
String[] parts = executable.split("/");
|
||||||
|
String binary = parts[parts.length - 1];
|
||||||
|
interpreter = TermuxService.PREFIX_PATH + "/bin/" + binary;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No shebang and no ELF, use standard shell.
|
||||||
|
interpreter = TermuxService.PREFIX_PATH + "/bin/sh";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
if (interpreter != null) result.add(interpreter);
|
||||||
|
result.add(fileToExecute);
|
||||||
|
if (args != null) {
|
||||||
|
for (String arg : args) result.add(arg);
|
||||||
|
}
|
||||||
|
return result.toArray(new String[result.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user