mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-09 12:04:03 +08:00
Added: Write termux shell environment to /data/data/com.termux/files/usr/etc/termux/termux.env
on app startup and package changes
The `termux.env` can be sourced by shells to set termux environment normally exported. This can be useful for users starting termux shells with `adb` `run-as` or `root`. The file will not contain `SHELL_CMD__` variables since those are shell command specific. The items in the `termux.env` file have the format `export name="value"`. The `"`\$` characters will be escaped with `a backslash `\`, like `\"` if characters are for literal value. Note that if `$` is escaped and if its part of variable, then variable expansion will not happen if `.env` file is sourced. The `\` at the end of a value line means line continuation. Value can contain newline characters. The `termux.env` file should be sourceable by `POSIX` compliant shells like `bash`, `zsh`, `sh`, android's `mksh`, etc. Other shells with require manual parsing of the file to export variables. Related discussion #2565
This commit is contained in:
@@ -12,6 +12,7 @@ import com.termux.shared.termux.crash.TermuxCrashUtils;
|
|||||||
import com.termux.shared.termux.file.TermuxFileUtils;
|
import com.termux.shared.termux.file.TermuxFileUtils;
|
||||||
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences;
|
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences;
|
||||||
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
|
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
|
||||||
|
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment;
|
||||||
import com.termux.shared.termux.shell.am.TermuxAmSocketServer;
|
import com.termux.shared.termux.shell.am.TermuxAmSocketServer;
|
||||||
import com.termux.shared.termux.shell.TermuxShellManager;
|
import com.termux.shared.termux.shell.TermuxShellManager;
|
||||||
import com.termux.shared.termux.theme.TermuxThemeUtils;
|
import com.termux.shared.termux.theme.TermuxThemeUtils;
|
||||||
@@ -48,9 +49,8 @@ public class TermuxApplication extends Application {
|
|||||||
// Check and create termux files directory. If failed to access it like in case of secondary
|
// Check and create termux files directory. If failed to access it like in case of secondary
|
||||||
// user or external sd card installation, then don't run files directory related code
|
// user or external sd card installation, then don't run files directory related code
|
||||||
Error error = TermuxFileUtils.isTermuxFilesDirectoryAccessible(this, true, true);
|
Error error = TermuxFileUtils.isTermuxFilesDirectoryAccessible(this, true, true);
|
||||||
if (error != null) {
|
boolean isTermuxFilesDirectoryAccessible = error == null;
|
||||||
Logger.logErrorExtended(LOG_TAG, "Termux files directory is not accessible\n" + error);
|
if (isTermuxFilesDirectoryAccessible) {
|
||||||
} else {
|
|
||||||
Logger.logInfo(LOG_TAG, "Termux files directory is accessible");
|
Logger.logInfo(LOG_TAG, "Termux files directory is accessible");
|
||||||
|
|
||||||
error = TermuxFileUtils.isAppsTermuxAppDirectoryAccessible(true, true);
|
error = TermuxFileUtils.isAppsTermuxAppDirectoryAccessible(true, true);
|
||||||
@@ -59,10 +59,17 @@ public class TermuxApplication extends Application {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup termux-am-socket server
|
||||||
TermuxAmSocketServer.setupTermuxAmSocketServer(context);
|
TermuxAmSocketServer.setupTermuxAmSocketServer(context);
|
||||||
|
} else {
|
||||||
|
Logger.logErrorExtended(LOG_TAG, "Termux files directory is not accessible\n" + error);
|
||||||
|
}
|
||||||
|
|
||||||
// Init TermuxShellEnvironment constants and caches after everything has been setup including termux-am-socket server
|
// Init TermuxShellEnvironment constants and caches after everything has been setup including termux-am-socket server
|
||||||
TermuxShellEnvironment.init(this);
|
TermuxShellEnvironment.init(this);
|
||||||
|
|
||||||
|
if (isTermuxFilesDirectoryAccessible) {
|
||||||
|
TermuxShellEnvironment.writeEnvironmentToFile(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.termux.R;
|
import com.termux.R;
|
||||||
|
import com.termux.app.event.SystemEventReceiver;
|
||||||
import com.termux.app.terminal.TermuxTerminalSessionClient;
|
import com.termux.app.terminal.TermuxTerminalSessionClient;
|
||||||
import com.termux.shared.termux.plugins.TermuxPluginUtils;
|
import com.termux.shared.termux.plugins.TermuxPluginUtils;
|
||||||
import com.termux.shared.data.IntentUtils;
|
import com.termux.shared.data.IntentUtils;
|
||||||
@@ -116,6 +117,8 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
|
|||||||
mShellManager = TermuxShellManager.getShellManager();
|
mShellManager = TermuxShellManager.getShellManager();
|
||||||
|
|
||||||
runStartForeground();
|
runStartForeground();
|
||||||
|
|
||||||
|
SystemEventReceiver.registerPackageUpdateEvents(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("Wakelock")
|
@SuppressLint("Wakelock")
|
||||||
@@ -172,6 +175,9 @@ public final class TermuxService extends Service implements AppShell.AppShellCli
|
|||||||
killAllTermuxExecutionCommands();
|
killAllTermuxExecutionCommands();
|
||||||
|
|
||||||
TermuxShellManager.onAppExit(this);
|
TermuxShellManager.onAppExit(this);
|
||||||
|
|
||||||
|
SystemEventReceiver.unregisterPackageUpdateEvents(this);
|
||||||
|
|
||||||
runStopForeground();
|
runStopForeground();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,12 +2,18 @@ package com.termux.app.event;
|
|||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.termux.shared.data.IntentUtils;
|
import com.termux.shared.data.IntentUtils;
|
||||||
import com.termux.shared.logger.Logger;
|
import com.termux.shared.logger.Logger;
|
||||||
|
import com.termux.shared.termux.TermuxUtils;
|
||||||
|
import com.termux.shared.termux.file.TermuxFileUtils;
|
||||||
|
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment;
|
||||||
import com.termux.shared.termux.shell.TermuxShellManager;
|
import com.termux.shared.termux.shell.TermuxShellManager;
|
||||||
|
|
||||||
public class SystemEventReceiver extends BroadcastReceiver {
|
public class SystemEventReceiver extends BroadcastReceiver {
|
||||||
@@ -35,6 +41,11 @@ public class SystemEventReceiver extends BroadcastReceiver {
|
|||||||
case Intent.ACTION_BOOT_COMPLETED:
|
case Intent.ACTION_BOOT_COMPLETED:
|
||||||
onActionBootCompleted(context, intent);
|
onActionBootCompleted(context, intent);
|
||||||
break;
|
break;
|
||||||
|
case Intent.ACTION_PACKAGE_ADDED:
|
||||||
|
case Intent.ACTION_PACKAGE_REMOVED:
|
||||||
|
case Intent.ACTION_PACKAGE_REPLACED:
|
||||||
|
onActionPackageUpdated(context, intent);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Logger.logError(LOG_TAG, "Invalid action \"" + action + "\" passed to " + LOG_TAG);
|
Logger.logError(LOG_TAG, "Invalid action \"" + action + "\" passed to " + LOG_TAG);
|
||||||
}
|
}
|
||||||
@@ -44,4 +55,37 @@ public class SystemEventReceiver extends BroadcastReceiver {
|
|||||||
TermuxShellManager.onActionBootCompleted(context, intent);
|
TermuxShellManager.onActionBootCompleted(context, intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void onActionPackageUpdated(@NonNull Context context, @NonNull Intent intent) {
|
||||||
|
Uri data = intent.getData();
|
||||||
|
if (data != null && TermuxUtils.isUriDataForTermuxPluginPackage(data)) {
|
||||||
|
Logger.logDebug(LOG_TAG, intent.getAction().replaceAll("^android.intent.action.", "") +
|
||||||
|
" event received for \"" + data.toString().replaceAll("^package:", "") + "\"");
|
||||||
|
if (TermuxFileUtils.isTermuxFilesDirectoryAccessible(context, false, false) == null)
|
||||||
|
TermuxShellEnvironment.writeEnvironmentToFile(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register {@link SystemEventReceiver} to listen to {@link Intent#ACTION_PACKAGE_ADDED},
|
||||||
|
* {@link Intent#ACTION_PACKAGE_REMOVED} and {@link Intent#ACTION_PACKAGE_REPLACED} broadcasts.
|
||||||
|
* They must be registered dynamically and cannot be registered implicitly in
|
||||||
|
* the AndroidManifest.xml due to Android 8+ restrictions.
|
||||||
|
*
|
||||||
|
* https://developer.android.com/guide/components/broadcast-exceptions
|
||||||
|
*/
|
||||||
|
public synchronized static void registerPackageUpdateEvents(@NonNull Context context) {
|
||||||
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||||
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||||
|
intentFilter.addDataScheme("package");
|
||||||
|
context.registerReceiver(getInstance(), intentFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized static void unregisterPackageUpdateEvents(@NonNull Context context) {
|
||||||
|
context.unregisterReceiver(getInstance());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,60 @@ public class ShellEnvironmentUtils {
|
|||||||
return environmentList;
|
return environmentList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert environment {@link HashMap} to {@link String} where each item equals "key=value".
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String convertEnvironmentToDotEnvFile(@NonNull HashMap<String, String> environmentMap) {
|
||||||
|
return convertEnvironmentToDotEnvFile(convertEnvironmentMapToEnvironmentVariableList(environmentMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert environment {@link HashMap} to `.env` file {@link String}.
|
||||||
|
*
|
||||||
|
* The items in the `.env` file have the format `export name="value"`.
|
||||||
|
*
|
||||||
|
* If the {@link ShellEnvironmentVariable#escaped} is set to {@code true}, then
|
||||||
|
* {@link ShellEnvironmentVariable#value} will be considered to be a literal value that has
|
||||||
|
* already been escaped by the caller, otherwise all the `"`\$` in the value will be escaped
|
||||||
|
* with `a backslash `\`, like `\"`. Note that if `$` is escaped and if its part of variable,
|
||||||
|
* then variable expansion will not happen if `.env` file is sourced.
|
||||||
|
*
|
||||||
|
* The `\` at the end of a value line means line continuation. Value can contain newline characters.
|
||||||
|
*
|
||||||
|
* Check {@link #isValidEnvironmentVariableName(String)} and {@link #isValidEnvironmentVariableValue(String)}
|
||||||
|
* for valid variable names and values.
|
||||||
|
*
|
||||||
|
* https://github.com/ko1nksm/shdotenv#env-file-syntax
|
||||||
|
* https://github.com/ko1nksm/shdotenv/blob/main/docs/specification.md
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static String convertEnvironmentToDotEnvFile(@NonNull List<ShellEnvironmentVariable> environmentList) {
|
||||||
|
StringBuilder environment = new StringBuilder();
|
||||||
|
Collections.sort(environmentList);
|
||||||
|
for (ShellEnvironmentVariable variable : environmentList) {
|
||||||
|
if (isValidEnvironmentVariableNameValuePair(variable.name, variable.value, true) && variable.value != null) {
|
||||||
|
environment.append("export ").append(variable.name).append("=\"")
|
||||||
|
.append(variable.escaped ? variable.value : variable.value.replaceAll("([\"`\\\\$])", "\\\\$1"))
|
||||||
|
.append("\"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return environment.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert environment {@link HashMap} to {@link List< ShellEnvironmentVariable >}. Each item
|
||||||
|
* will have its {@link ShellEnvironmentVariable#escaped} set to {@code false}.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static List<ShellEnvironmentVariable> convertEnvironmentMapToEnvironmentVariableList(@NonNull HashMap<String, String> environmentMap) {
|
||||||
|
List<ShellEnvironmentVariable> environmentList = new ArrayList<>();
|
||||||
|
for (String name :environmentMap.keySet()) {
|
||||||
|
environmentList.add(new ShellEnvironmentVariable(name, environmentMap.get(name), false));
|
||||||
|
}
|
||||||
|
return environmentList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if environment variable name and value pair is valid. Errors will be logged if
|
* Check if environment variable name and value pair is valid. Errors will be logged if
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
package com.termux.shared.shell.command.environment;
|
||||||
|
|
||||||
|
public class ShellEnvironmentVariable implements Comparable<ShellEnvironmentVariable> {
|
||||||
|
|
||||||
|
/** The name for environment variable */
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
/** The value for environment variable */
|
||||||
|
public String value;
|
||||||
|
|
||||||
|
/** If environment variable {@link #value} is already escaped. */
|
||||||
|
public boolean escaped;
|
||||||
|
|
||||||
|
public ShellEnvironmentVariable(String name, String value) {
|
||||||
|
this(name, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShellEnvironmentVariable(String name, String value, boolean escaped) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
this.escaped = escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(ShellEnvironmentVariable other) {
|
||||||
|
return this.name.compareTo(other.name);
|
||||||
|
}
|
||||||
|
}
|
@@ -11,7 +11,7 @@ import java.util.Formatter;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version: v0.49.0
|
* Version: v0.50.0
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
* Changelog
|
* Changelog
|
||||||
@@ -266,8 +266,11 @@ import java.util.List;
|
|||||||
* - Removed `TERMUX_GAME_PACKAGES_GITHUB_*`, `TERMUX_SCIENCE_PACKAGES_GITHUB_*`,
|
* - Removed `TERMUX_GAME_PACKAGES_GITHUB_*`, `TERMUX_SCIENCE_PACKAGES_GITHUB_*`,
|
||||||
* `TERMUX_ROOT_PACKAGES_GITHUB_*`, `TERMUX_UNSTABLE_PACKAGES_GITHUB_*`
|
* `TERMUX_ROOT_PACKAGES_GITHUB_*`, `TERMUX_UNSTABLE_PACKAGES_GITHUB_*`
|
||||||
*
|
*
|
||||||
* - 0.49.0 (2022-06-10)
|
* - 0.49.0 (2022-06-11)
|
||||||
* - Added `TERMUX_ENV_PREFIX_ROOT`.
|
* - Added `TERMUX_ENV_PREFIX_ROOT`.
|
||||||
|
*
|
||||||
|
* - 0.50.0 (2022-06-11)
|
||||||
|
* - Added `TERMUX_CONFIG_PREFIX_DIR_PATH`, `TERMUX_ENV_FILE_PATH` and `TERMUX_ENV_TEMP_FILE_PATH`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -650,6 +653,11 @@ public final class TermuxConstants {
|
|||||||
/** Termux app config home directory */
|
/** Termux app config home directory */
|
||||||
public static final File TERMUX_CONFIG_HOME_DIR = new File(TERMUX_CONFIG_HOME_DIR_PATH);
|
public static final File TERMUX_CONFIG_HOME_DIR = new File(TERMUX_CONFIG_HOME_DIR_PATH);
|
||||||
|
|
||||||
|
/** Termux app config $PREFIX directory path */
|
||||||
|
public static final String TERMUX_CONFIG_PREFIX_DIR_PATH = TERMUX_ETC_PREFIX_DIR_PATH + "/termux"; // Default: "/data/data/com.termux/files/usr/etc/termux"
|
||||||
|
/** Termux app config $PREFIX directory */
|
||||||
|
public static final File TERMUX_CONFIG_PREFIX_DIR = new File(TERMUX_CONFIG_PREFIX_DIR_PATH);
|
||||||
|
|
||||||
|
|
||||||
/** Termux app data home directory path */
|
/** Termux app data home directory path */
|
||||||
public static final String TERMUX_DATA_HOME_DIR_PATH = TERMUX_HOME_DIR_PATH + "/.termux"; // Default: "/data/data/com.termux/files/home/.termux"
|
public static final String TERMUX_DATA_HOME_DIR_PATH = TERMUX_HOME_DIR_PATH + "/.termux"; // Default: "/data/data/com.termux/files/home/.termux"
|
||||||
@@ -756,6 +764,12 @@ public final class TermuxConstants {
|
|||||||
public static final String TERMUX_CRASH_LOG_BACKUP_FILE_PATH = TERMUX_HOME_DIR_PATH + "/crash_log_backup.md"; // Default: "/data/data/com.termux/files/home/crash_log_backup.md"
|
public static final String TERMUX_CRASH_LOG_BACKUP_FILE_PATH = TERMUX_HOME_DIR_PATH + "/crash_log_backup.md"; // Default: "/data/data/com.termux/files/home/crash_log_backup.md"
|
||||||
|
|
||||||
|
|
||||||
|
/** Termux app environment file path */
|
||||||
|
public static final String TERMUX_ENV_FILE_PATH = TERMUX_CONFIG_PREFIX_DIR_PATH + "/termux.env"; // Default: "/data/data/com.termux/files/usr/etc/termux/termux.env"
|
||||||
|
|
||||||
|
/** Termux app environment temp file path */
|
||||||
|
public static final String TERMUX_ENV_TEMP_FILE_PATH = TERMUX_CONFIG_PREFIX_DIR_PATH + "/termux.env.tmp"; // Default: "/data/data/com.termux/files/usr/etc/termux/termux.env.tmp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import android.content.Intent;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -273,6 +274,17 @@ public class TermuxUtils {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns {@code true} if {@link Uri} has `package:` scheme for {@link TermuxConstants#TERMUX_PACKAGE_NAME} or its sub plugin package. */
|
||||||
|
public static boolean isUriDataForTermuxOrPluginPackage(@NonNull Uri data) {
|
||||||
|
return data.toString().equals("package:" + TermuxConstants.TERMUX_PACKAGE_NAME) ||
|
||||||
|
data.toString().startsWith("package:" + TermuxConstants.TERMUX_PACKAGE_NAME + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns {@code true} if {@link Uri} has `package:` scheme for {@link TermuxConstants#TERMUX_PACKAGE_NAME} sub plugin package. */
|
||||||
|
public static boolean isUriDataForTermuxPluginPackage(@NonNull Uri data) {
|
||||||
|
return data.toString().startsWith("package:" + TermuxConstants.TERMUX_PACKAGE_NAME + ".");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux
|
* Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux
|
||||||
* app has been opened.
|
* app has been opened.
|
||||||
|
@@ -4,8 +4,13 @@ import android.content.Context;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.termux.shared.errors.Error;
|
||||||
|
import com.termux.shared.file.FileUtils;
|
||||||
|
import com.termux.shared.logger.Logger;
|
||||||
import com.termux.shared.shell.command.ExecutionCommand;
|
import com.termux.shared.shell.command.ExecutionCommand;
|
||||||
import com.termux.shared.shell.command.environment.AndroidShellEnvironment;
|
import com.termux.shared.shell.command.environment.AndroidShellEnvironment;
|
||||||
|
import com.termux.shared.shell.command.environment.ShellEnvironmentUtils;
|
||||||
|
import com.termux.shared.shell.command.environment.ShellCommandShellEnvironment;
|
||||||
import com.termux.shared.termux.TermuxBootstrap;
|
import com.termux.shared.termux.TermuxBootstrap;
|
||||||
import com.termux.shared.termux.TermuxConstants;
|
import com.termux.shared.termux.TermuxConstants;
|
||||||
import com.termux.shared.termux.shell.TermuxShellUtils;
|
import com.termux.shared.termux.shell.TermuxShellUtils;
|
||||||
@@ -28,11 +33,32 @@ public class TermuxShellEnvironment extends AndroidShellEnvironment {
|
|||||||
shellCommandShellEnvironment = new TermuxShellCommandShellEnvironment();
|
shellCommandShellEnvironment = new TermuxShellCommandShellEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Init {@link TermuxShellEnvironment} constants and caches. */
|
/** Init {@link TermuxShellEnvironment} constants and caches. */
|
||||||
public synchronized static void init(@NonNull Context currentPackageContext) {
|
public synchronized static void init(@NonNull Context currentPackageContext) {
|
||||||
TermuxAppShellEnvironment.setTermuxAppEnvironment(currentPackageContext);
|
TermuxAppShellEnvironment.setTermuxAppEnvironment(currentPackageContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Init {@link TermuxShellEnvironment} constants and caches. */
|
||||||
|
public synchronized static void writeEnvironmentToFile(@NonNull Context currentPackageContext) {
|
||||||
|
HashMap<String, String> environmentMap = new TermuxShellEnvironment().getEnvironment(currentPackageContext, false);
|
||||||
|
String environmentString = ShellEnvironmentUtils.convertEnvironmentToDotEnvFile(environmentMap);
|
||||||
|
|
||||||
|
// Write environment string to temp file and then move to final location since otherwise
|
||||||
|
// writing may happen while file is being sourced/read
|
||||||
|
Error error = FileUtils.writeTextToFile("termux.env.tmp", TermuxConstants.TERMUX_ENV_TEMP_FILE_PATH,
|
||||||
|
Charset.defaultCharset(), environmentString, false);
|
||||||
|
if (error != null) {
|
||||||
|
Logger.logErrorExtended(LOG_TAG, error.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = FileUtils.moveRegularFile("termux.env.tmp", TermuxConstants.TERMUX_ENV_TEMP_FILE_PATH, TermuxConstants.TERMUX_ENV_FILE_PATH, true);
|
||||||
|
if (error != null) {
|
||||||
|
Logger.logErrorExtended(LOG_TAG, error.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Get shell environment for Termux. */
|
/** Get shell environment for Termux. */
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
|
Reference in New Issue
Block a user