mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 10:45:23 +08:00
Make TermuxTask and TermuxSession agnostic to termux environment
Those classes shouldn't be tied to termux environment like variables, interpreters and working directory since commands may need to be executed with a different environment like android's or with a different logic. Now both classes use the ShellEnvironmentClient interface to dynamically get the environment to be used which currently for Termux's case is implemented by TermuxShellEnvironmentClient which is just a wrapper for TermuxShellUtils since later implements static functions.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package com.termux.shared.shell;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public interface ShellEnvironmentClient {
|
||||
|
||||
/**
|
||||
* Get the default working directory path for the environment in case the path that was passed
|
||||
* was {@code null} or empty.
|
||||
*
|
||||
* @return Should return the default working directory path.
|
||||
*/
|
||||
@NonNull
|
||||
String getDefaultWorkingDirectoryPath();
|
||||
|
||||
/**
|
||||
* Get the default "/bin" path, likely $PREFIX/bin.
|
||||
*
|
||||
* @return Should return the "/bin" path.
|
||||
*/
|
||||
@NonNull
|
||||
String getDefaultBinPath();
|
||||
|
||||
/**
|
||||
* Build the shell environment to be used for commands.
|
||||
*
|
||||
* @param currentPackageContext The {@link Context} for the current package.
|
||||
* @param isFailSafe If running a failsafe session.
|
||||
* @param workingDirectory The working directory for the environment.
|
||||
* @return Should return the build environment.
|
||||
*/
|
||||
@NonNull
|
||||
String[] buildEnvironment(Context currentPackageContext, boolean isFailSafe, String workingDirectory);
|
||||
|
||||
/**
|
||||
* Setup process arguments for the file to execute, like interpreter, etc.
|
||||
*
|
||||
* @param fileToExecute The file to execute.
|
||||
* @param arguments The arguments to pass to the executable.
|
||||
* @return Should return the final process arguments.
|
||||
*/
|
||||
@NonNull
|
||||
String[] setupProcessArgs(@NonNull String fileToExecute, String[] arguments);
|
||||
|
||||
}
|
@@ -1,82 +1,13 @@
|
||||
package com.termux.shared.shell;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.termux.shared.models.errors.Error;
|
||||
import com.termux.shared.termux.TermuxConstants;
|
||||
import com.termux.shared.file.FileUtils;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.packages.PackageUtils;
|
||||
import com.termux.shared.termux.TermuxUtils;
|
||||
import com.termux.terminal.TerminalBuffer;
|
||||
import com.termux.terminal.TerminalEmulator;
|
||||
import com.termux.terminal.TerminalSession;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ShellUtils {
|
||||
|
||||
public static String[] buildEnvironment(Context currentPackageContext, boolean isFailSafe, String workingDirectory) {
|
||||
TermuxConstants.TERMUX_HOME_DIR.mkdirs();
|
||||
|
||||
if (workingDirectory == null || workingDirectory.isEmpty()) workingDirectory = TermuxConstants.TERMUX_HOME_DIR_PATH;
|
||||
|
||||
List<String> environment = new ArrayList<>();
|
||||
|
||||
// This function may be called by a different package like a plugin, so we get version for Termux package via its context
|
||||
Context termuxPackageContext = TermuxUtils.getTermuxPackageContext(currentPackageContext);
|
||||
if (termuxPackageContext != null) {
|
||||
String termuxVersionName = PackageUtils.getVersionNameForPackage(termuxPackageContext);
|
||||
if (termuxVersionName != null)
|
||||
environment.add("TERMUX_VERSION=" + termuxVersionName);
|
||||
}
|
||||
|
||||
environment.add("TERM=xterm-256color");
|
||||
environment.add("COLORTERM=truecolor");
|
||||
environment.add("HOME=" + TermuxConstants.TERMUX_HOME_DIR_PATH);
|
||||
environment.add("PREFIX=" + TermuxConstants.TERMUX_PREFIX_DIR_PATH);
|
||||
environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH"));
|
||||
environment.add("ANDROID_ROOT=" + System.getenv("ANDROID_ROOT"));
|
||||
environment.add("ANDROID_DATA=" + System.getenv("ANDROID_DATA"));
|
||||
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
||||
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
||||
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
||||
|
||||
// These variables are needed if running on Android 10 and higher.
|
||||
addToEnvIfPresent(environment, "ANDROID_ART_ROOT");
|
||||
addToEnvIfPresent(environment, "DEX2OATBOOTCLASSPATH");
|
||||
addToEnvIfPresent(environment, "ANDROID_I18N_ROOT");
|
||||
addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT");
|
||||
addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT");
|
||||
|
||||
if (isFailSafe) {
|
||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||
environment.add("PATH= " + System.getenv("PATH"));
|
||||
} else {
|
||||
environment.add("LANG=en_US.UTF-8");
|
||||
environment.add("PATH=" + TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH);
|
||||
environment.add("PWD=" + workingDirectory);
|
||||
environment.add("TMPDIR=" + TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH);
|
||||
}
|
||||
|
||||
return environment.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public static void addToEnvIfPresent(List<String> environment, String name) {
|
||||
String value = System.getenv(name);
|
||||
if (value != null) {
|
||||
environment.add(name + "=" + value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getPid(Process p) {
|
||||
try {
|
||||
Field f = p.getClass().getDeclaredField("pid");
|
||||
@@ -91,77 +22,12 @@ public class ShellUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] setupProcessArgs(@NonNull String fileToExecute, String[] arguments) {
|
||||
// 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.
|
||||
} 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 = TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/" + binary;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No shebang and no ELF, use standard shell.
|
||||
interpreter = TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/sh";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
if (interpreter != null) result.add(interpreter);
|
||||
result.add(fileToExecute);
|
||||
if (arguments != null) Collections.addAll(result, arguments);
|
||||
return result.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public static String getExecutableBasename(String executable) {
|
||||
if (executable == null) return null;
|
||||
int lastSlash = executable.lastIndexOf('/');
|
||||
return (lastSlash == -1) ? executable : executable.substring(lastSlash + 1);
|
||||
}
|
||||
|
||||
public static void clearTermuxTMPDIR(boolean onlyIfExists) {
|
||||
if(onlyIfExists && !FileUtils.directoryFileExists(TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH, false))
|
||||
return;
|
||||
|
||||
Error error;
|
||||
error = FileUtils.clearDirectory("$TMPDIR", FileUtils.getCanonicalPath(TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH, null));
|
||||
if (error != null) {
|
||||
Logger.logErrorExtended(error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTerminalSessionTranscriptText(TerminalSession terminalSession, boolean linesJoined, boolean trim) {
|
||||
if (terminalSession == null) return null;
|
||||
|
||||
|
@@ -9,7 +9,6 @@ import com.termux.shared.R;
|
||||
import com.termux.shared.models.ExecutionCommand;
|
||||
import com.termux.shared.models.ResultData;
|
||||
import com.termux.shared.models.errors.Errno;
|
||||
import com.termux.shared.termux.TermuxConstants;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.terminal.TerminalSession;
|
||||
import com.termux.terminal.TerminalSessionClient;
|
||||
@@ -52,6 +51,7 @@ public class TermuxSession {
|
||||
* @param executionCommand The {@link ExecutionCommand} containing the information for execution command.
|
||||
* @param terminalSessionClient The {@link TerminalSessionClient} interface implementation.
|
||||
* @param termuxSessionClient The {@link TermuxSessionClient} interface implementation.
|
||||
* @param shellEnvironmentClient The {@link ShellEnvironmentClient} interface implementation.
|
||||
* @param sessionName The optional {@link TerminalSession} name.
|
||||
* @param setStdoutOnExit If set to {@code true}, then the {@link ResultData#stdout}
|
||||
* available in the {@link TermuxSessionClient#onTermuxSessionExited(TermuxSession)}
|
||||
@@ -64,16 +64,24 @@ public class TermuxSession {
|
||||
*/
|
||||
public static TermuxSession execute(@NonNull final Context context, @NonNull ExecutionCommand executionCommand,
|
||||
@NonNull final TerminalSessionClient terminalSessionClient, final TermuxSessionClient termuxSessionClient,
|
||||
@NonNull final ShellEnvironmentClient shellEnvironmentClient,
|
||||
final String sessionName, final boolean setStdoutOnExit) {
|
||||
if (executionCommand.workingDirectory == null || executionCommand.workingDirectory.isEmpty()) executionCommand.workingDirectory = TermuxConstants.TERMUX_HOME_DIR_PATH;
|
||||
if (executionCommand.workingDirectory == null || executionCommand.workingDirectory.isEmpty())
|
||||
executionCommand.workingDirectory = shellEnvironmentClient.getDefaultWorkingDirectoryPath();
|
||||
if (executionCommand.workingDirectory.isEmpty())
|
||||
executionCommand.workingDirectory = "/";
|
||||
|
||||
String[] environment = ShellUtils.buildEnvironment(context, executionCommand.isFailsafe, executionCommand.workingDirectory);
|
||||
String[] environment = shellEnvironmentClient.buildEnvironment(context, executionCommand.isFailsafe, executionCommand.workingDirectory);
|
||||
|
||||
String defaultBinPath = shellEnvironmentClient.getDefaultBinPath();
|
||||
if (defaultBinPath.isEmpty())
|
||||
defaultBinPath = "/system/bin";
|
||||
|
||||
boolean isLoginShell = false;
|
||||
if (executionCommand.executable == null) {
|
||||
if (!executionCommand.isFailsafe) {
|
||||
for (String shellBinary : new String[]{"login", "bash", "zsh"}) {
|
||||
File shellFile = new File(TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH, shellBinary);
|
||||
File shellFile = new File(defaultBinPath, shellBinary);
|
||||
if (shellFile.canExecute()) {
|
||||
executionCommand.executable = shellFile.getAbsolutePath();
|
||||
break;
|
||||
@@ -88,7 +96,7 @@ public class TermuxSession {
|
||||
isLoginShell = true;
|
||||
}
|
||||
|
||||
String[] processArgs = ShellUtils.setupProcessArgs(executionCommand.executable, executionCommand.arguments);
|
||||
String[] processArgs = shellEnvironmentClient.setupProcessArgs(executionCommand.executable, executionCommand.arguments);
|
||||
|
||||
executionCommand.executable = processArgs[0];
|
||||
String processName = (isLoginShell ? "-" : "") + ShellUtils.getExecutableBasename(executionCommand.executable);
|
||||
@@ -199,10 +207,10 @@ public class TermuxSession {
|
||||
* callback will be called.
|
||||
*
|
||||
* @param termuxSession The {@link TermuxSession}, which should be set if
|
||||
* {@link #execute(Context, ExecutionCommand, TerminalSessionClient, TermuxSessionClient, String, boolean)}
|
||||
* {@link #execute(Context, ExecutionCommand, TerminalSessionClient, TermuxSessionClient, ShellEnvironmentClient, String, boolean)}
|
||||
* successfully started the process.
|
||||
* @param executionCommand The {@link ExecutionCommand}, which should be set if
|
||||
* {@link #execute(Context, ExecutionCommand, TerminalSessionClient, TermuxSessionClient, String, boolean)}
|
||||
* {@link #execute(Context, ExecutionCommand, TerminalSessionClient, TermuxSessionClient, ShellEnvironmentClient, String, boolean)}
|
||||
* failed to start the process.
|
||||
*/
|
||||
private static void processTermuxSessionResult(final TermuxSession termuxSession, ExecutionCommand executionCommand) {
|
||||
|
@@ -0,0 +1,33 @@
|
||||
package com.termux.shared.shell;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class TermuxShellEnvironmentClient implements ShellEnvironmentClient {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultWorkingDirectoryPath() {
|
||||
return TermuxShellUtils.getDefaultWorkingDirectoryPath();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String getDefaultBinPath() {
|
||||
return TermuxShellUtils.getDefaultBinPath();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String[] buildEnvironment(Context currentPackageContext, boolean isFailSafe, String workingDirectory) {
|
||||
return TermuxShellUtils.buildEnvironment(currentPackageContext, isFailSafe, workingDirectory);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String[] setupProcessArgs(@NonNull String fileToExecute, String[] arguments) {
|
||||
return TermuxShellUtils.setupProcessArgs(fileToExecute, arguments);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
package com.termux.shared.shell;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.termux.shared.models.errors.Error;
|
||||
import com.termux.shared.termux.TermuxConstants;
|
||||
import com.termux.shared.file.FileUtils;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.packages.PackageUtils;
|
||||
import com.termux.shared.termux.TermuxUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TermuxShellUtils {
|
||||
|
||||
public static String getDefaultWorkingDirectoryPath() {
|
||||
return TermuxConstants.TERMUX_HOME_DIR_PATH;
|
||||
}
|
||||
|
||||
public static String getDefaultBinPath() {
|
||||
return TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH;
|
||||
}
|
||||
|
||||
public static String[] buildEnvironment(Context currentPackageContext, boolean isFailSafe, String workingDirectory) {
|
||||
TermuxConstants.TERMUX_HOME_DIR.mkdirs();
|
||||
|
||||
if (workingDirectory == null || workingDirectory.isEmpty())
|
||||
workingDirectory = getDefaultWorkingDirectoryPath();
|
||||
|
||||
List<String> environment = new ArrayList<>();
|
||||
|
||||
// This function may be called by a different package like a plugin, so we get version for Termux package via its context
|
||||
Context termuxPackageContext = TermuxUtils.getTermuxPackageContext(currentPackageContext);
|
||||
if (termuxPackageContext != null) {
|
||||
String termuxVersionName = PackageUtils.getVersionNameForPackage(termuxPackageContext);
|
||||
if (termuxVersionName != null)
|
||||
environment.add("TERMUX_VERSION=" + termuxVersionName);
|
||||
}
|
||||
|
||||
environment.add("TERM=xterm-256color");
|
||||
environment.add("COLORTERM=truecolor");
|
||||
environment.add("HOME=" + TermuxConstants.TERMUX_HOME_DIR_PATH);
|
||||
environment.add("PREFIX=" + TermuxConstants.TERMUX_PREFIX_DIR_PATH);
|
||||
environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH"));
|
||||
environment.add("ANDROID_ROOT=" + System.getenv("ANDROID_ROOT"));
|
||||
environment.add("ANDROID_DATA=" + System.getenv("ANDROID_DATA"));
|
||||
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
|
||||
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
|
||||
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
|
||||
|
||||
// These variables are needed if running on Android 10 and higher.
|
||||
addToEnvIfPresent(environment, "ANDROID_ART_ROOT");
|
||||
addToEnvIfPresent(environment, "DEX2OATBOOTCLASSPATH");
|
||||
addToEnvIfPresent(environment, "ANDROID_I18N_ROOT");
|
||||
addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT");
|
||||
addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT");
|
||||
|
||||
if (isFailSafe) {
|
||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||
environment.add("PATH= " + System.getenv("PATH"));
|
||||
} else {
|
||||
environment.add("LANG=en_US.UTF-8");
|
||||
environment.add("PATH=" + TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH);
|
||||
environment.add("PWD=" + workingDirectory);
|
||||
environment.add("TMPDIR=" + TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH);
|
||||
}
|
||||
|
||||
return environment.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public static void addToEnvIfPresent(List<String> environment, String name) {
|
||||
String value = System.getenv(name);
|
||||
if (value != null) {
|
||||
environment.add(name + "=" + value);
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] setupProcessArgs(@NonNull String fileToExecute, String[] arguments) {
|
||||
// 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.
|
||||
} 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 = TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/" + binary;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No shebang and no ELF, use standard shell.
|
||||
interpreter = TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/sh";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore.
|
||||
}
|
||||
|
||||
List<String> result = new ArrayList<>();
|
||||
if (interpreter != null) result.add(interpreter);
|
||||
result.add(fileToExecute);
|
||||
if (arguments != null) Collections.addAll(result, arguments);
|
||||
return result.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public static void clearTermuxTMPDIR(boolean onlyIfExists) {
|
||||
if(onlyIfExists && !FileUtils.directoryFileExists(TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH, false))
|
||||
return;
|
||||
|
||||
Error error;
|
||||
error = FileUtils.clearDirectory("$TMPDIR", FileUtils.getCanonicalPath(TermuxConstants.TERMUX_TMP_PREFIX_DIR_PATH, null));
|
||||
if (error != null) {
|
||||
Logger.logErrorExtended(error.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -11,7 +11,6 @@ import com.termux.shared.R;
|
||||
import com.termux.shared.models.ExecutionCommand;
|
||||
import com.termux.shared.models.ResultData;
|
||||
import com.termux.shared.models.errors.Errno;
|
||||
import com.termux.shared.termux.TermuxConstants;
|
||||
import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.models.ExecutionCommand.ExecutionState;
|
||||
|
||||
@@ -54,6 +53,7 @@ public final class TermuxTask {
|
||||
* be called regardless of {@code isSynchronous} value but not if
|
||||
* {@code null} is returned by this method. This can
|
||||
* optionally be {@code null}.
|
||||
* @param shellEnvironmentClient The {@link ShellEnvironmentClient} interface implementation.
|
||||
* @param isSynchronous If set to {@code true}, then the command will be executed in the
|
||||
* caller thread and results returned synchronously in the {@link ExecutionCommand}
|
||||
* sub object of the {@link TermuxTask} returned.
|
||||
@@ -62,12 +62,17 @@ public final class TermuxTask {
|
||||
* @return Returns the {@link TermuxTask}. This will be {@code null} if failed to start the execution command.
|
||||
*/
|
||||
public static TermuxTask execute(@NonNull final Context context, @NonNull ExecutionCommand executionCommand,
|
||||
final TermuxTaskClient termuxTaskClient, final boolean isSynchronous) {
|
||||
if (executionCommand.workingDirectory == null || executionCommand.workingDirectory.isEmpty()) executionCommand.workingDirectory = TermuxConstants.TERMUX_HOME_DIR_PATH;
|
||||
final TermuxTaskClient termuxTaskClient,
|
||||
@NonNull final ShellEnvironmentClient shellEnvironmentClient,
|
||||
final boolean isSynchronous) {
|
||||
if (executionCommand.workingDirectory == null || executionCommand.workingDirectory.isEmpty())
|
||||
executionCommand.workingDirectory = shellEnvironmentClient.getDefaultWorkingDirectoryPath();
|
||||
if (executionCommand.workingDirectory.isEmpty())
|
||||
executionCommand.workingDirectory = "/";
|
||||
|
||||
String[] env = ShellUtils.buildEnvironment(context, false, executionCommand.workingDirectory);
|
||||
String[] env = shellEnvironmentClient.buildEnvironment(context, false, executionCommand.workingDirectory);
|
||||
|
||||
final String[] commandArray = ShellUtils.setupProcessArgs(executionCommand.executable, executionCommand.arguments);
|
||||
final String[] commandArray = shellEnvironmentClient.setupProcessArgs(executionCommand.executable, executionCommand.arguments);
|
||||
|
||||
if (!executionCommand.setState(ExecutionState.EXECUTING)) {
|
||||
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), context.getString(R.string.error_failed_to_execute_termux_task_command, executionCommand.getCommandIdAndLabelLogString()));
|
||||
@@ -254,10 +259,10 @@ public final class TermuxTask {
|
||||
* then the {@link TermuxTaskClient#onTermuxTaskExited(TermuxTask)} callback will be called.
|
||||
*
|
||||
* @param termuxTask The {@link TermuxTask}, which should be set if
|
||||
* {@link #execute(Context, ExecutionCommand, TermuxTaskClient, boolean)}
|
||||
* {@link #execute(Context, ExecutionCommand, TermuxTaskClient, ShellEnvironmentClient, boolean)}
|
||||
* successfully started the process.
|
||||
* @param executionCommand The {@link ExecutionCommand}, which should be set if
|
||||
* {@link #execute(Context, ExecutionCommand, TermuxTaskClient, boolean)}
|
||||
* {@link #execute(Context, ExecutionCommand, TermuxTaskClient, ShellEnvironmentClient, boolean)}
|
||||
* failed to start the process.
|
||||
*/
|
||||
private static void processTermuxTaskResult(final TermuxTask termuxTask, ExecutionCommand executionCommand) {
|
||||
|
@@ -16,6 +16,7 @@ import com.termux.shared.logger.Logger;
|
||||
import com.termux.shared.markdown.MarkdownUtils;
|
||||
import com.termux.shared.models.ExecutionCommand;
|
||||
import com.termux.shared.packages.PackageUtils;
|
||||
import com.termux.shared.shell.TermuxShellEnvironmentClient;
|
||||
import com.termux.shared.shell.TermuxTask;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -399,7 +400,7 @@ public class TermuxUtils {
|
||||
aptInfoScript = aptInfoScript.replaceAll(Pattern.quote("@TERMUX_PREFIX@"), TermuxConstants.TERMUX_PREFIX_DIR_PATH);
|
||||
|
||||
ExecutionCommand executionCommand = new ExecutionCommand(1, TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/bash", null, aptInfoScript, null, true, false);
|
||||
TermuxTask termuxTask = TermuxTask.execute(context, executionCommand, null, true);
|
||||
TermuxTask termuxTask = TermuxTask.execute(context, executionCommand, null, new TermuxShellEnvironmentClient(), true);
|
||||
if (termuxTask == null || !executionCommand.isSuccessful() || executionCommand.resultData.exitCode != 0) {
|
||||
Logger.logError(LOG_TAG, executionCommand.toString());
|
||||
return null;
|
||||
|
Reference in New Issue
Block a user