mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-07 03:05:18 +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.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A background job launched by Termux.
|
||||
@@ -24,16 +27,7 @@ public final class BackgroundJob {
|
||||
String[] env = buildEnvironment(false, cwd);
|
||||
if (cwd == null) cwd = TermuxService.HOME_PATH;
|
||||
|
||||
String[] modifiedArgs;
|
||||
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[] progArray = setupProcessArgs(fileToExecute, args);
|
||||
final String processDescription = Arrays.toString(progArray);
|
||||
|
||||
Process process;
|
||||
@@ -45,6 +39,7 @@ public final class BackgroundJob {
|
||||
Log.e(LOG_TAG, "Failed running background job: " + processDescription, e);
|
||||
return;
|
||||
}
|
||||
|
||||
mProcess = process;
|
||||
final int pid = getPid(mProcess);
|
||||
|
||||
@@ -126,17 +121,74 @@ public final class BackgroundJob {
|
||||
}
|
||||
|
||||
public static int getPid(Process p) {
|
||||
int pid = -1;
|
||||
|
||||
try {
|
||||
Field f = p.getClass().getDeclaredField("pid");
|
||||
f.setAccessible(true);
|
||||
pid = f.getInt(p);
|
||||
f.setAccessible(false);
|
||||
try {
|
||||
return f.getInt(p);
|
||||
} finally {
|
||||
f.setAccessible(false);
|
||||
}
|
||||
} 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