diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4a2bc2f8..6a9ac9ff 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,6 +34,7 @@ + + + + + + + diff --git a/app/src/main/java/com/termux/app/TermuxService.java b/app/src/main/java/com/termux/app/TermuxService.java index 902aa1b1..4e947916 100644 --- a/app/src/main/java/com/termux/app/TermuxService.java +++ b/app/src/main/java/com/termux/app/TermuxService.java @@ -170,6 +170,8 @@ public final class TermuxService extends Service implements AppShell.AppShellCli actionReleaseWakeLock(false); if (!mWantsToStop) killAllTermuxExecutionCommands(); + + TermuxShellManager.onAppExit(this); runStopForeground(); } @@ -463,6 +465,8 @@ public final class TermuxService extends Service implements AppShell.AppShellCli return null; } + executionCommand.setShellCommandShellEnvironment = true; + if (Logger.getLogLevel() >= Logger.LOG_LEVEL_VERBOSE) Logger.logVerboseExtended(LOG_TAG, executionCommand.toString()); @@ -571,13 +575,15 @@ public final class TermuxService extends Service implements AppShell.AppShellCli return null; } + executionCommand.setShellCommandShellEnvironment = true; + executionCommand.terminalTranscriptRows = mProperties.getTerminalTranscriptRows(); + if (Logger.getLogLevel() >= Logger.LOG_LEVEL_VERBOSE) Logger.logVerboseExtended(LOG_TAG, executionCommand.toString()); // If the execution command was started for a plugin, only then will the stdout be set // Otherwise if command was manually started by the user like by adding a new terminal session, // then no need to set stdout - executionCommand.terminalTranscriptRows = mProperties.getTerminalTranscriptRows(); TermuxSession newTermuxSession = TermuxSession.execute(this, executionCommand, getTermuxTerminalSessionClient(), this, new TermuxShellEnvironment(), null, executionCommand.isPluginExecutionCommand); if (newTermuxSession == null) { diff --git a/app/src/main/java/com/termux/app/event/SystemEventReceiver.java b/app/src/main/java/com/termux/app/event/SystemEventReceiver.java new file mode 100644 index 00000000..49a3c172 --- /dev/null +++ b/app/src/main/java/com/termux/app/event/SystemEventReceiver.java @@ -0,0 +1,47 @@ +package com.termux.app.event; + +import android.content.BroadcastReceiver; +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.termux.shared.data.IntentUtils; +import com.termux.shared.logger.Logger; +import com.termux.shared.termux.shell.TermuxShellManager; + +public class SystemEventReceiver extends BroadcastReceiver { + + private static SystemEventReceiver mInstance; + + private static final String LOG_TAG = "SystemEventReceiver"; + + public static synchronized SystemEventReceiver getInstance() { + if (mInstance == null) { + mInstance = new SystemEventReceiver(); + } + return mInstance; + } + + @Override + public void onReceive(@NonNull Context context, @Nullable Intent intent) { + if (intent == null) return; + Logger.logDebug(LOG_TAG, "Intent Received:\n" + IntentUtils.getIntentString(intent)); + + String action = intent.getAction(); + if (action == null) return; + + switch (action) { + case Intent.ACTION_BOOT_COMPLETED: + onActionBootCompleted(context, intent); + break; + default: + Logger.logError(LOG_TAG, "Invalid action \"" + action + "\" passed to " + LOG_TAG); + } + } + + public synchronized void onActionBootCompleted(@NonNull Context context, @NonNull Intent intent) { + TermuxShellManager.onActionBootCompleted(context, intent); + } + +} diff --git a/termux-shared/src/main/java/com/termux/shared/settings/preferences/SharedPreferenceUtils.java b/termux-shared/src/main/java/com/termux/shared/settings/preferences/SharedPreferenceUtils.java index 8f7a420a..68bd7c3e 100644 --- a/termux-shared/src/main/java/com/termux/shared/settings/preferences/SharedPreferenceUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/settings/preferences/SharedPreferenceUtils.java @@ -188,6 +188,38 @@ public class SharedPreferenceUtils { sharedPreferences.edit().putInt(key, value).apply(); } + /** + * Set an {@code int} in {@link SharedPreferences}. + * + * @param sharedPreferences The {@link SharedPreferences} to set the value in. + * @param key The key for the value. + * @param def The default value if failed to read a valid value. + * @param commitToFile If set to {@code true}, then value will be set to shared preferences + * in-memory cache and the file synchronously. Ideally, only to be used for + * multi-process use-cases. + * @param resetValue The value if not {@code null} that should be set if current or incremented + * value is less than 0. + * @return Returns the {@code int} value stored in {@link SharedPreferences} before increment, + * otherwise returns default if failed to read a valid value, like in case of an exception. + */ + @SuppressLint("ApplySharedPref") + public static int getAndIncrementInt(SharedPreferences sharedPreferences, String key, int def, + boolean commitToFile, Integer resetValue) { + if (sharedPreferences == null) { + Logger.logError(LOG_TAG, "Ignoring incrementing int value for the \"" + key + "\" key into null shared preferences."); + return def; + } + + int curValue = getInt(sharedPreferences, key, def); + if (resetValue != null && (curValue < 0)) curValue = resetValue; + + int newValue = curValue + 1; + if (resetValue != null && newValue < 0) newValue = resetValue; + + setInt(sharedPreferences, key, newValue, commitToFile); + return curValue; + } + /** diff --git a/termux-shared/src/main/java/com/termux/shared/shell/command/ExecutionCommand.java b/termux-shared/src/main/java/com/termux/shared/shell/command/ExecutionCommand.java index d68c628c..5a97f966 100644 --- a/termux-shared/src/main/java/com/termux/shared/shell/command/ExecutionCommand.java +++ b/termux-shared/src/main/java/com/termux/shared/shell/command/ExecutionCommand.java @@ -195,6 +195,10 @@ public class ExecutionCommand { /** The {@link ShellCreateMode} of commands. */ public String shellCreateMode; + /** Whether to set {@link ExecutionCommand} shell environment. */ + public boolean setShellCommandShellEnvironment; + + /** The command label for the {@link ExecutionCommand}. */ @@ -396,6 +400,8 @@ public class ExecutionCommand { logString.append("\n").append(executionCommand.getShellCreateModeLogString()); } + logString.append("\n").append(executionCommand.getSetRunnerShellEnvironmentLogString()); + if (!ignoreNull || executionCommand.commandIntent != null) logString.append("\n").append(executionCommand.getCommandIntentLogString()); @@ -490,7 +496,7 @@ public class ExecutionCommand { markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Shell Name", executionCommand.shellName, "-")); markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Shell Create Mode", executionCommand.shellCreateMode, "-")); - + markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Set Shell Command Shell Environment", executionCommand.setShellCommandShellEnvironment, "-")); markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("isPluginExecutionCommand", executionCommand.isPluginExecutionCommand, "-")); @@ -588,6 +594,10 @@ public class ExecutionCommand { return Logger.getSingleLineLogStringEntry("Shell Create Mode", shellCreateMode, "-"); } + public String getSetRunnerShellEnvironmentLogString() { + return "Set Shell Command Shell Environment: `" + setShellCommandShellEnvironment + "`"; + } + public String getCommandDescriptionLogString() { return Logger.getSingleLineLogStringEntry("Command Description", commandDescription, "-"); } diff --git a/termux-shared/src/main/java/com/termux/shared/shell/command/environment/AndroidShellEnvironment.java b/termux-shared/src/main/java/com/termux/shared/shell/command/environment/AndroidShellEnvironment.java index f87c1438..91a8652e 100644 --- a/termux-shared/src/main/java/com/termux/shared/shell/command/environment/AndroidShellEnvironment.java +++ b/termux-shared/src/main/java/com/termux/shared/shell/command/environment/AndroidShellEnvironment.java @@ -20,6 +20,12 @@ import java.util.HashMap; */ public class AndroidShellEnvironment extends UnixShellEnvironment { + protected ShellCommandShellEnvironment shellCommandShellEnvironment; + + public AndroidShellEnvironment() { + shellCommandShellEnvironment = new ShellCommandShellEnvironment(); + } + /** Get shell environment for Android. */ @NonNull @Override @@ -85,6 +91,9 @@ public class AndroidShellEnvironment extends UnixShellEnvironment { getDefaultWorkingDirectoryPath()); ShellEnvironmentUtils.createHomeDir(environment); + if (executionCommand.setShellCommandShellEnvironment && shellCommandShellEnvironment != null) + environment.putAll(shellCommandShellEnvironment.getEnvironment(currentPackageContext, executionCommand)); + return environment; } diff --git a/termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellCommandShellEnvironment.java b/termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellCommandShellEnvironment.java new file mode 100644 index 00000000..a898dec9 --- /dev/null +++ b/termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellCommandShellEnvironment.java @@ -0,0 +1,62 @@ +package com.termux.shared.shell.command.environment; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.termux.shared.shell.command.ExecutionCommand; + +import java.util.HashMap; + +/** + * Environment for {@link ExecutionCommand}. + */ +public class ShellCommandShellEnvironment { + + /** Environment variable prefix for the {@link ExecutionCommand}. */ + public static final String SHELL_CMD_ENV_PREFIX = "SHELL_CMD__"; + + /** Environment variable for the {@link ExecutionCommand.Runner} name. */ + public static final String ENV_SHELL_CMD__RUNNER_NAME = SHELL_CMD_ENV_PREFIX + "RUNNER_NAME"; + + /** Environment variable for the package name running the {@link ExecutionCommand}. */ + public static final String ENV_SHELL_CMD__PACKAGE_NAME = SHELL_CMD_ENV_PREFIX + "PACKAGE_NAME"; + + /** Environment variable for the {@link ExecutionCommand#id}/TermuxShellManager.SHELL_ID name. + * This will be common for all runners. */ + public static final String ENV_SHELL_CMD__SHELL_ID = SHELL_CMD_ENV_PREFIX + "SHELL_ID"; + + /** Environment variable for the {@link ExecutionCommand#shellName} name. */ + public static final String ENV_SHELL_CMD__SHELL_NAME = SHELL_CMD_ENV_PREFIX + "SHELL_NAME"; + + /** Environment variable for the {@link ExecutionCommand.Runner#APP_SHELL} number since boot. */ + public static final String ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_BOOT = SHELL_CMD_ENV_PREFIX + "APP_SHELL_NUMBER_SINCE_BOOT"; + + /** Environment variable for the {{@link ExecutionCommand.Runner#TERMINAL_SESSION} number since boot. */ + public static final String ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_BOOT = SHELL_CMD_ENV_PREFIX + "TERMINAL_SESSION_NUMBER_SINCE_BOOT"; + + /** Environment variable for the {@link ExecutionCommand.Runner#APP_SHELL} number since app start. */ + public static final String ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_APP_START = SHELL_CMD_ENV_PREFIX + "APP_SHELL_NUMBER_SINCE_APP_START"; + + /** Environment variable for the {@link ExecutionCommand.Runner#TERMINAL_SESSION} number since app start. */ + public static final String ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_APP_START = SHELL_CMD_ENV_PREFIX + "TERMINAL_SESSION_NUMBER_SINCE_APP_START"; + + + /** Get shell environment containing info for {@link ExecutionCommand}. */ + @NonNull + public HashMap getEnvironment(@NonNull Context currentPackageContext, + @NonNull ExecutionCommand executionCommand) { + HashMap environment = new HashMap<>(); + + ExecutionCommand.Runner runner = ExecutionCommand.Runner.runnerOf(executionCommand.runner); + if (runner == null) return environment; + + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__RUNNER_NAME, runner.getName()); + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__PACKAGE_NAME, currentPackageContext.getPackageName()); + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__SHELL_ID, String.valueOf(executionCommand.id)); + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__SHELL_NAME, executionCommand.shellName); + + return environment; + } + +} diff --git a/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxAppSharedPreferences.java b/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxAppSharedPreferences.java index f0f3eba1..a33be8e6 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxAppSharedPreferences.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxAppSharedPreferences.java @@ -215,6 +215,28 @@ public class TermuxAppSharedPreferences { } + public synchronized int getAndIncrementAppShellNumberSinceBoot() { + // Keep value at MAX_VALUE on integer overflow and not 0, since not first shell + return SharedPreferenceUtils.getAndIncrementInt(mSharedPreferences, TERMUX_APP.KEY_APP_SHELL_NUMBER_SINCE_BOOT, + TERMUX_APP.DEFAULT_VALUE_APP_SHELL_NUMBER_SINCE_BOOT, true, Integer.MAX_VALUE); + } + + public synchronized void resetAppShellNumberSinceBoot() { + SharedPreferenceUtils.setInt(mSharedPreferences, TERMUX_APP.KEY_APP_SHELL_NUMBER_SINCE_BOOT, + TERMUX_APP.DEFAULT_VALUE_APP_SHELL_NUMBER_SINCE_BOOT, true); + } + + public synchronized int getAndIncrementTerminalSessionNumberSinceBoot() { + // Keep value at MAX_VALUE on integer overflow and not 0, since not first shell + return SharedPreferenceUtils.getAndIncrementInt(mSharedPreferences, TERMUX_APP.KEY_TERMINAL_SESSION_NUMBER_SINCE_BOOT, + TERMUX_APP.DEFAULT_VALUE_TERMINAL_SESSION_NUMBER_SINCE_BOOT, true, Integer.MAX_VALUE); + } + + public synchronized void resetTerminalSessionNumberSinceBoot() { + SharedPreferenceUtils.setInt(mSharedPreferences, TERMUX_APP.KEY_TERMINAL_SESSION_NUMBER_SINCE_BOOT, + TERMUX_APP.DEFAULT_VALUE_TERMINAL_SESSION_NUMBER_SINCE_BOOT, true); + } + public boolean isTerminalViewKeyLoggingEnabled() { return SharedPreferenceUtils.getBoolean(mSharedPreferences, TERMUX_APP.KEY_TERMINAL_VIEW_KEY_LOGGING_ENABLED, TERMUX_APP.DEFAULT_VALUE_TERMINAL_VIEW_KEY_LOGGING_ENABLED); diff --git a/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxPreferenceConstants.java b/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxPreferenceConstants.java index b03f19d0..80226914 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxPreferenceConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxPreferenceConstants.java @@ -1,7 +1,7 @@ package com.termux.shared.termux.settings.preferences; /* - * Version: v0.15.0 + * Version: v0.16.0 * * Changelog * @@ -65,8 +65,14 @@ package com.termux.shared.termux.settings.preferences; * - 0.15.0 (2021-09-05) * - Added following to `TERMUX_TASKER_APP`: * `KEY_LAST_PENDING_INTENT_REQUEST_CODE` and `DEFAULT_VALUE_KEY_LAST_PENDING_INTENT_REQUEST_CODE`. + * + * - 0.16.0 (2022-06-11) + * - Added following to `TERMUX_APP`: + * `KEY_APP_SHELL_NUMBER_SINCE_BOOT` and `KEY_TERMINAL_SESSION_NUMBER_SINCE_BOOT`. */ +import com.termux.shared.shell.command.ExecutionCommand; + /** * A class that defines shared constants of the SharedPreferences used by Termux app and its plugins. * This class will be hosted by termux-shared lib and should be imported by other termux plugin @@ -143,6 +149,18 @@ public final class TermuxPreferenceConstants { public static final String KEY_LAST_NOTIFICATION_ID = "last_notification_id"; public static final int DEFAULT_VALUE_KEY_LAST_NOTIFICATION_ID = 0; + /** + * The {@link ExecutionCommand.Runner#APP_SHELL} number after termux app process since boot. + */ + public static final String KEY_APP_SHELL_NUMBER_SINCE_BOOT = "app_shell_number_since_boot"; + public static final int DEFAULT_VALUE_APP_SHELL_NUMBER_SINCE_BOOT = 0; + + /** + * The {@link ExecutionCommand.Runner#TERMINAL_SESSION} number after termux app process since boot. + */ + public static final String KEY_TERMINAL_SESSION_NUMBER_SINCE_BOOT = "terminal_session_number_since_boot"; + public static final int DEFAULT_VALUE_TERMINAL_SESSION_NUMBER_SINCE_BOOT = 0; + /** * Defines the key for whether termux terminal view key logging is enabled or not diff --git a/termux-shared/src/main/java/com/termux/shared/termux/shell/TermuxShellManager.java b/termux-shared/src/main/java/com/termux/shared/termux/shell/TermuxShellManager.java index 1cc52e65..b5477b99 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/shell/TermuxShellManager.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/shell/TermuxShellManager.java @@ -40,6 +40,16 @@ public class TermuxShellManager { */ public final List mPendingPluginExecutionCommands = new ArrayList<>(); + /** + * The {@link ExecutionCommand.Runner#APP_SHELL} number after app process was started/restarted. + */ + public static int APP_SHELL_NUMBER_SINCE_APP_START; + + /** + * The {@link ExecutionCommand.Runner#TERMINAL_SESSION} number after app process was started/restarted. + */ + public static int TERMINAL_SESSION_NUMBER_SINCE_APP_START; + public TermuxShellManager(@NonNull Context context) { @@ -69,8 +79,45 @@ public class TermuxShellManager { } + public synchronized static void onActionBootCompleted(@NonNull Context context, @NonNull Intent intent) { + TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(context); + if (preferences == null) return; + + // Ensure any shells started after boot have valid ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_BOOT and + // ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_BOOT exported + preferences.resetAppShellNumberSinceBoot(); + preferences.resetTerminalSessionNumberSinceBoot(); + } + + public static void onAppExit(@NonNull Context context) { + // Ensure any shells started after boot have valid ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_APP_START and + // ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_APP_START exported + APP_SHELL_NUMBER_SINCE_APP_START = 0; + TERMINAL_SESSION_NUMBER_SINCE_APP_START = 0; + } + public static synchronized int getNextShellId() { return SHELL_ID++; } + public static synchronized int getAndIncrementAppShellNumberSinceAppStart() { + // Keep value at MAX_VALUE on integer overflow and not 0, since not first shell + int curValue = APP_SHELL_NUMBER_SINCE_APP_START; + if (curValue < 0) curValue = Integer.MAX_VALUE; + + APP_SHELL_NUMBER_SINCE_APP_START = curValue + 1; + if (APP_SHELL_NUMBER_SINCE_APP_START < 0) APP_SHELL_NUMBER_SINCE_APP_START = Integer.MAX_VALUE; + return curValue; + } + + public static synchronized int getAndIncrementTerminalSessionNumberSinceAppStart() { + // Keep value at MAX_VALUE on integer overflow and not 0, since not first shell + int curValue = TERMINAL_SESSION_NUMBER_SINCE_APP_START; + if (curValue < 0) curValue = Integer.MAX_VALUE; + + TERMINAL_SESSION_NUMBER_SINCE_APP_START = curValue + 1; + if (TERMINAL_SESSION_NUMBER_SINCE_APP_START < 0) TERMINAL_SESSION_NUMBER_SINCE_APP_START = Integer.MAX_VALUE; + return curValue; + } + } diff --git a/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellCommandShellEnvironment.java b/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellCommandShellEnvironment.java new file mode 100644 index 00000000..421d94b5 --- /dev/null +++ b/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellCommandShellEnvironment.java @@ -0,0 +1,48 @@ +package com.termux.shared.termux.shell.command.environment; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import com.termux.shared.shell.command.ExecutionCommand; +import com.termux.shared.shell.command.environment.ShellCommandShellEnvironment; +import com.termux.shared.shell.command.environment.ShellEnvironmentUtils; +import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences; +import com.termux.shared.termux.shell.TermuxShellManager; + +import java.util.HashMap; + +/** + * Environment for Termux {@link ExecutionCommand}. + */ +public class TermuxShellCommandShellEnvironment extends ShellCommandShellEnvironment { + + /** Get shell environment containing info for Termux {@link ExecutionCommand}. */ + @NonNull + @Override + public HashMap getEnvironment(@NonNull Context currentPackageContext, + @NonNull ExecutionCommand executionCommand) { + HashMap environment = super.getEnvironment(currentPackageContext, executionCommand); + + TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(currentPackageContext); + if (preferences == null) return environment; + + if (ExecutionCommand.Runner.APP_SHELL.equalsRunner(executionCommand.runner)) { + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_BOOT, + String.valueOf(preferences.getAndIncrementAppShellNumberSinceBoot())); + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__APP_SHELL_NUMBER_SINCE_APP_START, + String.valueOf(TermuxShellManager.getAndIncrementAppShellNumberSinceAppStart())); + + } else if (ExecutionCommand.Runner.TERMINAL_SESSION.equalsRunner(executionCommand.runner)) { + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_BOOT, + String.valueOf(preferences.getAndIncrementTerminalSessionNumberSinceBoot())); + ShellEnvironmentUtils.putToEnvIfSet(environment, ENV_SHELL_CMD__TERMINAL_SESSION_NUMBER_SINCE_APP_START, + String.valueOf(TermuxShellManager.getAndIncrementTerminalSessionNumberSinceAppStart())); + } else { + return environment; + } + + return environment; + } + +} diff --git a/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellEnvironment.java b/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellEnvironment.java index 0677c20f..dce3c534 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellEnvironment.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/shell/command/environment/TermuxShellEnvironment.java @@ -23,6 +23,10 @@ public class TermuxShellEnvironment extends AndroidShellEnvironment { /** Environment variable for the termux {@link TermuxConstants#TERMUX_PREFIX_DIR_PATH}. */ public static final String ENV_PREFIX = "PREFIX"; + public TermuxShellEnvironment() { + super(); + shellCommandShellEnvironment = new TermuxShellCommandShellEnvironment(); + } /** Get shell environment for Termux. */ @NonNull