diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 93a20c0..c22d68a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -134,21 +134,11 @@
android:exported="false"
android:label="@string/error"
android:theme="@style/AppTheme.NoActionBar.Dark"/>
-
-
static const char *rewrite_executable(const char *filename, char *buffer, int buffer_len) {
- strcpy(buffer, "/data/data/io.neoterm/files/usr/bin/");
char *bin_match = strstr(filename, "/bin/");
if (bin_match == filename || bin_match == (filename + 4)) {
// We have either found "/bin/" at the start of the string or at
// "/xxx/bin/". Take the path after that.
- strncpy(buffer + 36, bin_match + 5, (size_t) (buffer_len - 37));
+ strncpy(buffer, bin_match + 5, (size_t) (buffer_len - 1));
filename = buffer;
}
return filename;
diff --git a/app/src/main/cpp/neoterm.cpp b/app/src/main/cpp/neoterm.cpp
index fc00e85..9a63af8 100755
--- a/app/src/main/cpp/neoterm.cpp
+++ b/app/src/main/cpp/neoterm.cpp
@@ -108,7 +108,7 @@ static int create_subprocess(JNIEnv *env,
// Show terminal output about failing exec() call:
char *error_message;
if (asprintf(&error_message, "exec(\"%s\")", cmd) == -1)
- error_message = const_cast("exec()");;
+ error_message = const_cast("exec()");
perror(error_message);
_exit(1);
}
diff --git a/app/src/main/java/io/neoterm/component/comp.kt b/app/src/main/java/io/neoterm/component/comp.kt
index be1541a..1ec3ea6 100644
--- a/app/src/main/java/io/neoterm/component/comp.kt
+++ b/app/src/main/java/io/neoterm/component/comp.kt
@@ -7,7 +7,6 @@ import io.neoterm.component.completion.CompletionComponent
import io.neoterm.component.config.ConfigureComponent
import io.neoterm.component.extrakey.ExtraKeyComponent
import io.neoterm.component.font.FontComponent
-import io.neoterm.component.pm.PackageComponent
import io.neoterm.component.profile.ProfileComponent
import io.neoterm.component.session.SessionComponent
import io.neoterm.component.session.ShellProfile
@@ -80,7 +79,6 @@ object NeoInitializer {
ComponentManager.registerComponent(UserScriptComponent::class.java)
ComponentManager.registerComponent(ExtraKeyComponent::class.java)
ComponentManager.registerComponent(CompletionComponent::class.java)
- ComponentManager.registerComponent(PackageComponent::class.java)
ComponentManager.registerComponent(SessionComponent::class.java)
ComponentManager.registerComponent(ProfileComponent::class.java)
diff --git a/app/src/main/java/io/neoterm/component/config/comp.kt b/app/src/main/java/io/neoterm/component/config/comp.kt
index af7c1d3..e732aad 100644
--- a/app/src/main/java/io/neoterm/component/config/comp.kt
+++ b/app/src/main/java/io/neoterm/component/config/comp.kt
@@ -84,18 +84,6 @@ object NeoPreference {
val dipInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, context.resources.displayMetrics)
MIN_FONT_SIZE = (4f * dipInPixels).toInt()
MAX_FONT_SIZE = 256
-
- // load apt source
- val sourceFile = File(NeoTermPath.SOURCE_FILE)
- kotlin.runCatching {
- Files.readAllBytes(sourceFile.toPath())?.let {
- val source = String(it).trim().trimEnd()
- val array = source.split(" ")
- if (array.size >= 2 && array[0] == "deb") {
- store(R.string.key_package_source, array[1])
- }
- }
- }
}
fun store(key: Int, value: Any) {
@@ -156,7 +144,6 @@ object NeoPreference {
val loginProgramPath = findLoginProgram(loginProgramName) ?: return false
store(R.string.key_general_shell, loginProgramName)
- symlinkLoginShell(loginProgramPath)
return true
}
@@ -167,39 +154,17 @@ object NeoPreference {
fun getLoginShellPath(): String {
val loginProgramName = getLoginShellName()
- // Some programs like ssh needs it
- val shell = File(NeoTermPath.NEOTERM_LOGIN_SHELL_PATH)
val loginProgramPath = findLoginProgram(loginProgramName) ?: {
setLoginShellName(DefaultValues.loginShell)
- "${NeoTermPath.USR_PATH}/bin/${DefaultValues.loginShell}"
+ loadString(R.string.key_general_shell,DefaultValues.loginShell)
}()
- if (!shell.exists()) {
- symlinkLoginShell(loginProgramPath)
- }
-
return loginProgramPath
}
fun validateFontSize(fontSize: Int): Int {
return Math.max(MIN_FONT_SIZE, Math.min(fontSize, MAX_FONT_SIZE))
}
-
- private fun symlinkLoginShell(loginProgramPath: String) {
- File(NeoTermPath.CUSTOM_PATH).mkdirs()
- try {
- val shellSymlink = File(NeoTermPath.NEOTERM_LOGIN_SHELL_PATH)
- if (shellSymlink.exists()) {
- shellSymlink.delete()
- }
- Os.symlink(loginProgramPath, NeoTermPath.NEOTERM_LOGIN_SHELL_PATH)
- Os.chmod(NeoTermPath.NEOTERM_LOGIN_SHELL_PATH, 448 /* Decimal of 0700 */)
- } catch (e: ErrnoException) {
- NLog.e("Preference", "Failed to symlink login shell: ${e.localizedMessage}")
- e.printStackTrace()
- }
- }
-
fun findLoginProgram(loginProgramName: String): String? {
val file = File("${NeoTermPath.USR_PATH}/bin", loginProgramName)
return if (file.canExecute()) file.absolutePath else null
diff --git a/app/src/main/java/io/neoterm/component/config/defaults.kt b/app/src/main/java/io/neoterm/component/config/defaults.kt
index eaf2d34..82e8085 100644
--- a/app/src/main/java/io/neoterm/component/config/defaults.kt
+++ b/app/src/main/java/io/neoterm/component/config/defaults.kt
@@ -18,7 +18,7 @@ object DefaultValues {
const val enableSpecialVolumeKeys = false
const val enableWordBasedIme = false
- const val loginShell = "bash"
+ const val loginShell = "sh"
const val initialCommand = ""
const val defaultFont = "SourceCodePro"
}
@@ -28,7 +28,6 @@ object NeoTermPath {
const val ROOT_PATH = "/data/data/io.neoterm/files"
const val USR_PATH = "$ROOT_PATH/usr"
const val HOME_PATH = "$ROOT_PATH/home"
- const val APT_BIN_PATH = "$USR_PATH/bin/apt"
const val LIB_PATH = "$USR_PATH/lib"
const val CUSTOM_PATH = "$HOME_PATH/.neoterm"
@@ -40,14 +39,4 @@ object NeoTermPath {
const val USER_SCRIPT_PATH = "$CUSTOM_PATH/script"
const val PROFILE_PATH = "$CUSTOM_PATH/profile"
- const val SOURCE_FILE = "$USR_PATH/etc/apt/sources.list"
- const val PACKAGE_LIST_DIR = "$USR_PATH/var/lib/apt/lists"
-
- private const val SOURCE = "https://raw.githubusercontent.com/NeoTerm/NeoTerm-repo/main"
-
- val DEFAULT_MAIN_PACKAGE_SOURCE: String
-
- init {
- DEFAULT_MAIN_PACKAGE_SOURCE = SOURCE
- }
}
diff --git a/app/src/main/java/io/neoterm/component/pm/NeoPackageParser.java b/app/src/main/java/io/neoterm/component/pm/NeoPackageParser.java
deleted file mode 100644
index 2c5d816..0000000
--- a/app/src/main/java/io/neoterm/component/pm/NeoPackageParser.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package io.neoterm.component.pm;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-
-/**
- * @author kiva
- */
-
-public class NeoPackageParser {
- public interface ParseStateListener {
- void onStartState();
-
- void onEndState();
-
- NeoPackageInfo onCreatePackageInfo();
-
- void onStartParsePackage(String name, NeoPackageInfo packageInfo);
-
- void onEndParsePackage(NeoPackageInfo packageInfo);
- }
-
- private static final String
- KEY_PACKAGE_NAME = "Package",
- KEY_VERSION = "Version",
- KEY_ESSENTIAL = "Essential",
- KEY_ARCH = "Architecture",
- KEY_MAINTAINER = "Maintainer",
- KEY_INSTALLED_SIZE = "Installed-Size",
- KEY_DEPENDS = "Depends",
- KEY_FILENAME = "Filename",
- KEY_SIZE = "Size",
- KEY_MD5 = "MD5sum",
- KEY_SHA1 = "SHA1",
- KEY_SHA256 = "SHA256",
- KEY_HOMEPAGE = "Homepage",
- KEY_DESC = "Description";
-
- private BufferedReader reader;
- private ParseStateListener stateListener;
-
- NeoPackageParser(InputStream inputStream) {
- reader = new BufferedReader(new InputStreamReader(inputStream));
- }
-
- void setStateListener(ParseStateListener stateListener) {
- this.stateListener = stateListener;
- }
-
- public void parse() throws IOException {
- if (stateListener == null) {
- return;
- }
-
- String line;
- String[] splits = new String[2];
- String key = null;
- String value = null;
- boolean appendMode = false;
-
- NeoPackageInfo packageInfo = null;
-
- stateListener.onStartState();
- while ((line = reader.readLine()) != null) {
- if (line.isEmpty()) {
- continue;
- }
-
- if (splitKeyAndValue(line, splits)) {
- key = splits[0];
- value = splits[1];
- appendMode = false;
- } else {
- if (key == null) {
- // no key provided, we don't know where the value should be appended to
- continue;
- }
- // the rest value to previous key
- value = line.trim();
- appendMode = true;
- }
-
- if (key.equals(KEY_PACKAGE_NAME)) {
- if (packageInfo != null) {
- stateListener.onEndParsePackage(packageInfo);
- }
- packageInfo = stateListener.onCreatePackageInfo();
- packageInfo.setPackageName(value);
- stateListener.onStartParsePackage(value, packageInfo);
- }
-
- if (packageInfo == null) {
- continue;
- }
-
- if (appendMode) {
- value = appendToLastValue(packageInfo, key, value);
- }
-
- switch (key) {
- case KEY_ARCH:
- packageInfo.setArchitecture(Architecture.Companion.parse(value));
- break;
- case KEY_DEPENDS:
- packageInfo.setDependenciesString(value);
- break;
- case KEY_DESC:
- packageInfo.setDescription(value);
- break;
- case KEY_ESSENTIAL:
- packageInfo.setEssential(value.equals("yes"));
- break;
- case KEY_FILENAME:
- packageInfo.setFileName(value);
- break;
- case KEY_HOMEPAGE:
- packageInfo.setHomePage(value);
- break;
- case KEY_INSTALLED_SIZE:
- packageInfo.setInstalledSizeInBytes(Long.parseLong(value));
- break;
- case KEY_MAINTAINER:
- packageInfo.setMaintainer(value);
- break;
- case KEY_MD5:
- packageInfo.setMd5(value);
- break;
- case KEY_SHA1:
- packageInfo.setSha1(value);
- break;
- case KEY_SHA256:
- packageInfo.setSha256(value);
- break;
- case KEY_SIZE:
- packageInfo.setSizeInBytes(Long.parseLong(value));
- break;
- case KEY_VERSION:
- packageInfo.setVersion(value);
- break;
- }
- }
- if (packageInfo != null) {
- stateListener.onEndParsePackage(packageInfo);
- }
- stateListener.onEndState();
- }
-
- private String appendToLastValue(NeoPackageInfo packageInfo, String key, String value) {
- // Currently, only descriptions can be multiline
- switch (key) {
- case KEY_DESC:
- return packageInfo.getDescription() + " " + value;
- default:
- return value;
- }
- }
-
- private boolean splitKeyAndValue(String line, String[] splits) {
- int valueIndex = line.indexOf(':');
- if (valueIndex < 0) {
- return false;
- }
-
- splits[0] = line.substring(0, valueIndex).trim();
- splits[1] = line.substring(valueIndex == line.length() ? valueIndex : valueIndex + 1).trim();
- return true;
- }
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/PackageComponent.java b/app/src/main/java/io/neoterm/component/pm/PackageComponent.java
deleted file mode 100644
index 56099bd..0000000
--- a/app/src/main/java/io/neoterm/component/pm/PackageComponent.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package io.neoterm.component.pm;
-
-import io.neoterm.component.NeoComponent;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.HashMap;
-
-/**
- * @author kiva
- */
-
-public class PackageComponent implements NeoComponent {
- private final Object lock = new Object();
- private boolean isRefreshing = false;
- private boolean queryEnabled = true;
- private HashMap neoPackages;
-
- private NeoPackageInfo getPackageInfo(String packageName) {
- return queryEnabled ? neoPackages.get(packageName) : null;
- }
-
- public HashMap getPackages() {
- return queryEnabled ? neoPackages : new HashMap<>();
- }
-
- public int getPackageCount() {
- return queryEnabled ? neoPackages.size() : -1;
- }
-
- public SourceManager getSourceManager() {
- return new SourceManager();
- }
-
- public void reloadPackages(File packageListFile, boolean clearPrevious) throws IOException {
- synchronized (lock) {
- if (isRefreshing) {
- return;
- }
- isRefreshing = true;
- }
- tryParsePackages(packageListFile, clearPrevious);
- synchronized (lock) {
- isRefreshing = false;
- }
- }
-
- public void clearPackages() {
- if (isRefreshing) {
- return;
- }
- neoPackages.clear();
- }
-
- private void tryParsePackages(File packageListFile, final boolean clearPrevious) throws IOException {
- NeoPackageParser packageParser = new NeoPackageParser(new FileInputStream(packageListFile));
- packageParser.setStateListener(new NeoPackageParser.ParseStateListener() {
- @Override
- public void onStartState() {
- queryEnabled = false;
- if (clearPrevious) {
- neoPackages.clear();
- }
- }
-
- @Override
- public void onEndState() {
- queryEnabled = true;
- for (NeoPackageInfo info : neoPackages.values()) {
- resolveDepends(info);
- }
- }
-
- @Override
- public NeoPackageInfo onCreatePackageInfo() {
- return new NeoPackageInfo();
- }
-
- @Override
- public void onStartParsePackage(String name, NeoPackageInfo packageInfo) {
- }
-
- @Override
- public void onEndParsePackage(NeoPackageInfo packageInfo) {
- neoPackages.put(packageInfo.getPackageName(), packageInfo);
- }
- });
- packageParser.parse();
- }
-
- private void resolveDepends(NeoPackageInfo info) {
- String dep = info.getDependenciesString();
- if (dep == null) {
- return;
- }
-
- String[] splits = dep.split(",");
- NeoPackageInfo[] depends = new NeoPackageInfo[splits.length];
- info.setDependencies(depends);
-
- for (int i = 0; i < splits.length; ++i) {
- String item = splits[i].trim();
- depends[i] = getPackageInfo(item);
- }
- }
-
- @Override
- public void onServiceInit() {
- neoPackages = new HashMap<>();
- }
-
- @Override
- public void onServiceDestroy() {
- }
-
- @Override
- public void onServiceObtained() {
- }
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/Source.java b/app/src/main/java/io/neoterm/component/pm/Source.java
deleted file mode 100644
index e88f960..0000000
--- a/app/src/main/java/io/neoterm/component/pm/Source.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.neoterm.component.pm;
-
-import io.neoterm.framework.database.annotation.ID;
-import io.neoterm.framework.database.annotation.Table;
-
-/**
- * @author kiva
- */
-@Table
-public class Source {
- @ID(autoIncrement = true)
- private int id;
-
- public String url;
-
- public String repo;
-
- public boolean enabled;
-
- public Source() {
- // for Database
- }
-
- public Source(String url, String repo, boolean enabled) {
- this.url = url;
- this.repo = repo;
- this.enabled = enabled;
- }
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/data.kt b/app/src/main/java/io/neoterm/component/pm/data.kt
deleted file mode 100644
index c7029c8..0000000
--- a/app/src/main/java/io/neoterm/component/pm/data.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.neoterm.component.pm
-
-enum class Architecture {
- ALL, ARM, AARCH64, X86, X86_64;
-
- companion object {
- fun parse(arch: String): Architecture {
- return when (arch) {
- "arm" -> ARM
- "aarch64" -> AARCH64
- "x86" -> X86
- "x86_64" -> X86_64
- else -> ALL
- }
- }
- }
-}
-
-class NeoPackageInfo {
- var packageName: String? = null
- var isEssential: Boolean = false
- var version: String? = null
- var architecture: Architecture = Architecture.ALL
- var maintainer: String? = null
- var installedSizeInBytes: Long = 0L
- var fileName: String? = null
- var dependenciesString: String? = null
- var dependencies: Array? = null
- var sizeInBytes: Long = 0L
- var md5: String? = null
- var sha1: String? = null
- var sha256: String? = null
- var homePage: String? = null
- var description: String? = null
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/helper.kt b/app/src/main/java/io/neoterm/component/pm/helper.kt
deleted file mode 100644
index 2b7ed9a..0000000
--- a/app/src/main/java/io/neoterm/component/pm/helper.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-package io.neoterm.component.pm
-
-import io.neoterm.App
-import io.neoterm.R
-import io.neoterm.component.ComponentManager
-import io.neoterm.component.config.NeoTermPath
-import io.neoterm.framework.NeoTermDatabase
-import io.neoterm.utils.NLog
-import java.io.File
-import java.net.URL
-import java.nio.file.Files
-import java.nio.file.Paths
-
-object SourceHelper {
- fun syncSource() {
- val sourceManager = ComponentManager.getComponent().sourceManager
- syncSource(sourceManager)
- }
-
- fun syncSource(sourceManager: SourceManager) {
- val content = buildString {
- this.append("# Generated by NeoTerm-Preference\n")
- sourceManager.getEnabledSources()
- .joinTo(this, "\n") { "deb [trusted=yes] ${it.url} ${it.repo}\n" }
- }
- kotlin.runCatching {
- Files.write(Paths.get(NeoTermPath.SOURCE_FILE), content.toByteArray())
- }
- }
-
- fun detectSourceFiles(): List {
- val sourceManager = ComponentManager.getComponent().sourceManager
- val sourceFiles = ArrayList()
- try {
- val prefixes = sourceManager.getEnabledSources()
- .map { detectSourceFilePrefix(it) }
- .filter { it.isNotEmpty() }
-
- File(NeoTermPath.PACKAGE_LIST_DIR)
- .listFiles()
- .filterTo(sourceFiles) { file ->
- prefixes.filter { file.name.startsWith(it) }
- .count() > 0
- }
- } catch (e: Exception) {
- sourceFiles.clear()
- NLog.e("PM", "Failed to detect source files: ${e.localizedMessage}")
- }
-
- return sourceFiles
- }
-
- fun detectSourceFilePrefix(source: Source): String {
- try {
- val url = URL(source.url)
- val builder = StringBuilder(url.host)
- if (url.port != -1) {
- builder.append(":${url.port}")
- }
-
- val path = url.path
- if (path != null && path.isNotEmpty()) {
- builder.append("_")
- val fixedPath = path.replace("/", "_").substring(1) // skip the last '/'
- builder.append(fixedPath)
- }
- builder.append("_dists_${source.repo.replace(" ".toRegex(), "_")}_binary-")
- return builder.toString()
- } catch (e: Exception) {
- NLog.e("PM", "Failed to detect source file prefix: ${e.localizedMessage}")
- return ""
- }
- }
-}
-
-class SourceManager internal constructor() {
- private val database = NeoTermDatabase.instance("sources")
-
- init {
- if (database.findAll(Source::class.java).isEmpty()) {
- App.get().resources.getStringArray(R.array.pref_package_source_values)
- .forEach {
- database.saveBean(Source(it, "stable main", true))
- }
- }
- }
-
- fun addSource(sourceUrl: String, repo: String, enabled: Boolean) {
- database.saveBean(Source(sourceUrl, repo, enabled))
- }
-
- fun removeSource(sourceUrl: String) {
- database.deleteBeanByWhere(Source::class.java, "url == '$sourceUrl'")
- }
-
- fun updateAll(sources: List) {
- database.dropAllTable()
- database.saveBeans(sources)
- }
-
- fun getAllSources(): List {
- return database.findAll(Source::class.java)
- }
-
- fun getEnabledSources(): List {
- return getAllSources().filter { it.enabled }
- }
-
- fun getMainPackageSource(): String {
- return getEnabledSources()
- .map { it.repo }
- .singleOrNull { it.trim() == "stable main" }
- ?: NeoTermPath.DEFAULT_MAIN_PACKAGE_SOURCE
- }
-
- fun applyChanges() {
- database.vacuum()
- }
-}
-
diff --git a/app/src/main/java/io/neoterm/component/session/comp.kt b/app/src/main/java/io/neoterm/component/session/comp.kt
index 9b08c38..6b25f8c 100644
--- a/app/src/main/java/io/neoterm/component/session/comp.kt
+++ b/app/src/main/java/io/neoterm/component/session/comp.kt
@@ -94,7 +94,6 @@ class SessionComponent : NeoComponent {
.executablePath(parameter.executablePath)
.currentWorkingDirectory(parameter.cwd)
.callback(parameter.sessionCallback)
- .systemShell(parameter.systemShell)
.envArray(parameter.env)
.argArray(parameter.arguments)
.initialCommand(parameter.initialCommand)
diff --git a/app/src/main/java/io/neoterm/component/session/shell.kt b/app/src/main/java/io/neoterm/component/session/shell.kt
index 1ffd10c..798b56a 100644
--- a/app/src/main/java/io/neoterm/component/session/shell.kt
+++ b/app/src/main/java/io/neoterm/component/session/shell.kt
@@ -27,7 +27,6 @@ class ShellParameter {
var initialCommand: String? = null
var env: Array>? = null
var sessionCallback: TerminalSession.SessionChangedCallback? = null
- var systemShell: Boolean = false
var shellProfile: ShellProfile? = null
fun executablePath(executablePath: String?): ShellParameter {
@@ -60,11 +59,6 @@ class ShellParameter {
return this
}
- fun systemShell(systemShell: Boolean): ShellParameter {
- this.systemShell = systemShell
- return this
- }
-
fun profile(shellProfile: ShellProfile): ShellParameter {
this.shellProfile = shellProfile
return this
@@ -291,21 +285,14 @@ open class ShellTermSession private constructor(
return this
}
- fun systemShell(systemShell: Boolean): Builder {
- this.systemShell = systemShell
- return this
- }
fun create(context: Context): ShellTermSession {
val cwd = this.cwd ?: NeoTermPath.HOME_PATH
- val shell = this.executablePath ?: if (systemShell)
- "/system/bin/sh"
- else
- shellProfile.loginShell
+ val shell = shellProfile.loginShell
val args = this.args ?: mutableListOf(shell)
- val env = transformEnvironment(this.env) ?: buildEnvironment(cwd, systemShell)
+ val env = transformEnvironment(this.env) ?: buildEnvironment(cwd)
val callback = changeCallback ?: TermSessionCallback()
return ShellTermSession(
shell, cwd, args.toTypedArray(), env, callback,
@@ -324,7 +311,7 @@ open class ShellTermSession private constructor(
}
- private fun buildEnvironment(cwd: String?, systemShell: Boolean): Array {
+ private fun buildEnvironment(cwd: String?): Array {
val selectedCwd = cwd ?: NeoTermPath.HOME_PATH
File(NeoTermPath.HOME_PATH).mkdirs()
@@ -336,62 +323,11 @@ open class ShellTermSession private constructor(
val externalStorageEnv = "EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE")
val colorterm = "COLORTERM=truecolor"
- // PY Trade: Some programs support NeoTerm in a special way.
- val neotermIdEnv = "__NEOTERM=1"
- val originPathEnv = "__NEOTERM_ORIGIN_PATH=" + buildOriginPathEnv()
- val originLdEnv = "__NEOTERM_ORIGIN_LD_LIBRARY_PATH=" + buildOriginLdLibEnv()
-
- return if (systemShell) {
- val pathEnv = "PATH=" + System.getenv("PATH")
- arrayOf(
- termEnv, homeEnv, androidRootEnv, androidDataEnv,
- externalStorageEnv, pathEnv, neotermIdEnv, prefixEnv,
- originLdEnv, originPathEnv, colorterm
- )
-
- } else {
- val ps1Env = "PS1=$ "
- val langEnv = "LANG=en_US.UTF-8"
- val pathEnv = "PATH=" + buildPathEnv()
- val ldEnv = "LD_LIBRARY_PATH=" + buildLdLibraryEnv()
- val pwdEnv = "PWD=$selectedCwd"
- val tmpdirEnv = "TMPDIR=${NeoTermPath.USR_PATH}/tmp"
-
-
- // execve(2) wrapper to avoid incorrect shebang
- val ldPreloadEnv = if (shellProfile.enableExecveWrapper) {
- "LD_PRELOAD=${App.get().applicationInfo.nativeLibraryDir}/libnexec.so"
- } else {
- ""
- }
-
- arrayOf(
- termEnv, homeEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv,
- androidRootEnv, androidDataEnv, externalStorageEnv,
- tmpdirEnv, neotermIdEnv, originPathEnv, originLdEnv,
- ldPreloadEnv, prefixEnv, colorterm
- )
- }
- .filter { it.isNotEmpty() }
- .toTypedArray()
- }
-
- private fun buildOriginPathEnv(): String {
- val path = System.getenv("PATH")
- return path ?: ""
- }
-
- private fun buildOriginLdLibEnv(): String {
- val path = System.getenv("LD_LIBRARY_PATH")
- return path ?: ""
- }
-
- private fun buildLdLibraryEnv(): String {
- return "${NeoTermPath.USR_PATH}/lib"
- }
-
- private fun buildPathEnv(): String {
- return "${NeoTermPath.USR_PATH}/bin:${NeoTermPath.USR_PATH}/bin/applets"
+ val pathEnv = "PATH=" + System.getenv("PATH")
+ return arrayOf(
+ termEnv, homeEnv, androidRootEnv, androidDataEnv,
+ externalStorageEnv, pathEnv, prefixEnv, colorterm
+ ).filter { it.isNotEmpty() }.toTypedArray()
}
}
}
diff --git a/app/src/main/java/io/neoterm/frontend/floating/dialog.kt b/app/src/main/java/io/neoterm/frontend/floating/dialog.kt
index 864ad30..c010ecb 100644
--- a/app/src/main/java/io/neoterm/frontend/floating/dialog.kt
+++ b/app/src/main/java/io/neoterm/frontend/floating/dialog.kt
@@ -53,7 +53,6 @@ class TerminalDialog(val context: Context) {
.executablePath(executablePath)
.arguments(arguments)
.callback(terminalSessionCallback)
- .systemShell(false)
terminalSession = Terminals.createSession(context, parameter)
if (terminalSession is ShellTermSession) {
(terminalSession as ShellTermSession).exitPrompt = context.getString(R.string.process_exit_prompt_press_back)
diff --git a/app/src/main/java/io/neoterm/setup/SetupThread.java b/app/src/main/java/io/neoterm/setup/SetupThread.java
deleted file mode 100644
index 42e5103..0000000
--- a/app/src/main/java/io/neoterm/setup/SetupThread.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package io.neoterm.setup;
-
-import android.app.ProgressDialog;
-import android.system.Os;
-import android.util.Pair;
-import androidx.appcompat.app.AppCompatActivity;
-import io.neoterm.backend.EmulatorDebug;
-import io.neoterm.component.config.NeoTermPath;
-import io.neoterm.utils.NLog;
-
-import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-/**
- * @author kiva
- */
-
-final class SetupThread extends Thread {
- private final SourceConnection sourceConnection;
- private final File prefixPath;
- private final AppCompatActivity activity;
- private final ResultListener resultListener;
- private final ProgressDialog progressDialog;
-
- public SetupThread(AppCompatActivity activity, SourceConnection sourceConnection,
- File prefixPath, ResultListener resultListener,
- ProgressDialog progressDialog) {
- this.activity = activity;
- this.sourceConnection = sourceConnection;
- this.prefixPath = prefixPath;
- this.resultListener = resultListener;
- this.progressDialog = progressDialog;
- }
-
- @Override
- public void run() {
- try {
- final String stagingPrefixPath = NeoTermPath.ROOT_PATH + "/usr-staging";
- final File stagingPrefixFile = new File(stagingPrefixPath);
-
- if (stagingPrefixFile.exists()) {
- deleteFolder(stagingPrefixFile);
- }
-
- int totalReadBytes = 0;
- final byte[] buffer = new byte[8096];
- final List> symlinks = new ArrayList<>(50);
-
-
- try (ZipInputStream zipInput = new ZipInputStream(sourceConnection.getInputStream())) {
- ZipEntry zipEntry;
-
- int totalBytes = sourceConnection.getSize();
-
- while ((zipEntry = zipInput.getNextEntry()) != null) {
- totalReadBytes += zipEntry.getCompressedSize();
-
- final int totalReadBytesFinal = totalReadBytes;
- final int totalBytesFinal = totalBytes;
-
- activity.runOnUiThread(() -> {
- try {
- double progressFloat = ((double) totalReadBytesFinal) / ((double) totalBytesFinal) * 100.0;
- progressDialog.setProgress((int) progressFloat);
- } catch (RuntimeException ignore) {
- // activity dismissed
- }
- });
-
- if (zipEntry.getName().contains("SYMLINKS.txt")) {
- BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
- String line;
- while ((line = symlinksReader.readLine()) != null) {
- if (line.isEmpty()) {
- continue;
- }
- String[] parts = line.split("←");
- if (parts.length != 2)
- throw new RuntimeException("Malformed symlink line: " + line);
- String oldPath = parts[0];
- String newPath = stagingPrefixPath + "/" + parts[1];
- symlinks.add(Pair.create(oldPath, newPath));
- }
- } else {
- String zipEntryName = zipEntry.getName();
- File targetFile = new File(stagingPrefixPath, zipEntryName);
- if (zipEntry.isDirectory()) {
- if (!targetFile.mkdirs())
- throw new RuntimeException("Failed to create directory: " + targetFile.getAbsolutePath());
- } else {
- try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
- int readBytes;
- while ((readBytes = zipInput.read(buffer)) != -1) {
- outStream.write(buffer, 0, readBytes);
- }
- }
- if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") || zipEntryName.startsWith("lib/apt/methods")) {
- //noinspection OctalInteger
- Os.chmod(targetFile.getAbsolutePath(), 0700);
- }
- }
- }
- }
- }
-
- sourceConnection.close();
-
- if (symlinks.isEmpty())
- throw new RuntimeException("No SYMLINKS.txt encountered");
- for (Pair symlink : symlinks) {
- NLog.INSTANCE.e("Setup", "Linking " + symlink.first + " to " + symlink.second);
- Os.symlink(symlink.first, symlink.second);
- }
-
- if (!stagingPrefixFile.renameTo(prefixPath)) {
- throw new RuntimeException("Unable to rename staging folder");
- }
-
- activity.runOnUiThread(() -> resultListener.onResult(null));
- } catch (final Exception e) {
- NLog.INSTANCE.e(EmulatorDebug.LOG_TAG, "Bootstrap error", e);
- activity.runOnUiThread(() -> {
- try {
- resultListener.onResult(e);
- } catch (RuntimeException e1) {
- // Activity already dismissed - ignore.
- }
- });
- } finally {
- activity.runOnUiThread(() -> {
- try {
- progressDialog.dismiss();
- } catch (RuntimeException e) {
- // Activity already dismissed - ignore.
- }
- });
- }
- }
-
- private static void deleteFolder(File fileOrDirectory) throws IOException {
- if (fileOrDirectory.getCanonicalPath().equals(fileOrDirectory.getAbsolutePath()) && fileOrDirectory.isDirectory()) {
- File[] children = fileOrDirectory.listFiles();
-
- if (children != null) {
- for (File child : children) {
- deleteFolder(child);
- }
- }
- }
-
- if (!fileOrDirectory.delete()) {
- throw new RuntimeException("Unable to delete "
- + (fileOrDirectory.isDirectory() ? "directory " : "file ")
- + fileOrDirectory.getAbsolutePath());
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/setup/SourceConnection.java b/app/src/main/java/io/neoterm/setup/SourceConnection.java
deleted file mode 100644
index 0fe8f89..0000000
--- a/app/src/main/java/io/neoterm/setup/SourceConnection.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package io.neoterm.setup;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * @author kiva
- */
-public interface SourceConnection {
- InputStream getInputStream() throws IOException;
- int getSize();
- void close();
-}
diff --git a/app/src/main/java/io/neoterm/setup/connections.kt b/app/src/main/java/io/neoterm/setup/connections.kt
deleted file mode 100644
index 8ba120a..0000000
--- a/app/src/main/java/io/neoterm/setup/connections.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-package io.neoterm.setup
-
-import android.content.Context
-import android.net.Uri
-import java.io.IOException
-import java.io.InputStream
-import java.net.HttpURLConnection
-import java.net.URL
-
-/**
- * @author kiva
- */
-
-class BackupFileConnection(context: Context, uri: Uri) : LocalFileConnection(context, uri)
-
-/**
- * @author kiva
- */
-
-open class LocalFileConnection(context: Context, uri: Uri) : OfflineUriConnection(context, uri)
-
-/**
- * @author kiva
- */
-
-class NetworkConnection(private val sourceUrl: String) : SourceConnection {
- private var connection: HttpURLConnection? = null
-
- @Throws(IOException::class)
- override fun getInputStream(): InputStream {
- if (connection == null) {
- connection = openHttpConnection()
- connection!!.connectTimeout = 8000
- connection!!.readTimeout = 8000
- }
- return connection!!.inputStream
- }
-
- override fun getSize(): Int {
- return if (connection != null) {
- connection!!.contentLength
- } else 0
-
- }
-
- override fun close() {
- if (connection != null) {
- connection!!.disconnect()
- }
- }
-
- @Throws(IOException::class)
- private fun openHttpConnection(): HttpURLConnection {
- val arch = SetupHelper.determineArchName()
-
- return URL("$sourceUrl/boot/$arch.zip").openConnection() as HttpURLConnection
- }
-}
-
-/**
- * @author kiva
- */
-
-abstract class OfflineConnection : SourceConnection {
- private var inputStream: InputStream? = null
-
- @Throws(IOException::class)
- protected abstract fun openInputStream(): InputStream
-
- @Throws(IOException::class)
- override fun getInputStream(): InputStream {
- if (inputStream == null) {
- inputStream = openInputStream()
- }
- return inputStream!!
- }
-
- override fun getSize(): Int {
- if (inputStream != null) {
- return try {
- inputStream!!.available()
- } catch (e: IOException) {
- e.printStackTrace()
- 0
- }
-
- }
- return 0
- }
-
- override fun close() {
- if (inputStream != null) {
- try {
- inputStream!!.close()
- } catch (ignore: IOException) {
- ignore.printStackTrace()
- }
-
- }
- }
-}
-
-/**
- * @author kiva
- */
-
-open class OfflineUriConnection(private val context: Context, private val uri: Uri) : OfflineConnection() {
-
- @Throws(IOException::class)
- override fun openInputStream(): InputStream {
- return context.contentResolver.openInputStream(uri)
- }
-}
diff --git a/app/src/main/java/io/neoterm/setup/setup.kt b/app/src/main/java/io/neoterm/setup/setup.kt
deleted file mode 100644
index 1bfca1a..0000000
--- a/app/src/main/java/io/neoterm/setup/setup.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package io.neoterm.setup
-
-import android.app.ProgressDialog
-import android.content.Context
-import android.os.Build
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import io.neoterm.App
-import io.neoterm.R
-import io.neoterm.component.config.NeoTermPath
-import java.io.File
-import java.util.*
-
-/**
- * @author kiva
- */
-interface ResultListener {
- fun onResult(error: Exception?)
-}
-
-/**
- * @author kiva
- */
-object SetupHelper {
- fun needSetup(): Boolean {
- val PREFIX_FILE = File(NeoTermPath.USR_PATH)
- return !PREFIX_FILE.isDirectory
- }
-
- fun setup(
- activity: AppCompatActivity, connection: SourceConnection,
- resultListener: ResultListener
- ) {
- if (!needSetup()) {
- resultListener.onResult(null)
- return
- }
-
- val prefixFile = File(NeoTermPath.USR_PATH)
-
- val progress = makeProgressDialog(activity)
- progress.max = 100
- progress.show()
-
- SetupThread(activity, connection, prefixFile, resultListener, progress).start()
- }
-
- private fun makeProgressDialog(context: Context): ProgressDialog {
- return makeProgressDialog(context, context.getString(R.string.installer_message))
- }
-
- fun makeProgressDialog(context: Context, message: String): ProgressDialog {
- val dialog = ProgressDialog(context)
- dialog.setMessage(message)
- dialog.isIndeterminate = false
- dialog.setCancelable(false)
- dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
- return dialog
- }
-
- fun makeErrorDialog(context: Context, messageId: Int): AlertDialog {
- return makeErrorDialog(context, context.getString(messageId))
- }
-
- fun makeErrorDialog(context: Context, message: String): AlertDialog {
- return AlertDialog.Builder(context)
- .setTitle(R.string.error)
- .setMessage(message)
- .setPositiveButton(android.R.string.yes, null)
- .setNeutralButton(R.string.show_help) { _, _ -> App.get().openHelpLink() }
- .create()
- }
-
- fun determineArchName(): String {
- for (androidArch in Build.SUPPORTED_ABIS) {
- when (androidArch) {
- "arm64-v8a" -> return "aarch64"
- "armeabi-v7a" -> return "arm"
- "x86_64" -> return "x86_64"
- }
- }
- throw RuntimeException(
- "Unable to determine arch from Build.SUPPORTED_ABIS = "
- + Arrays.toString(Build.SUPPORTED_ABIS)
- )
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt b/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
index ef60883..eb017cc 100644
--- a/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
@@ -44,7 +44,6 @@ open class BaseCustomizeActivity : AppCompatActivity() {
.executablePath("${NeoTermPath.USR_PATH}/bin/echo")
.arguments(arrayOf("echo", "-e", *script))
.callback(sessionCallback)
- .systemShell(false)
session = Terminals.createSession(this, parameter)
terminalView.attachSession(session)
diff --git a/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt b/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
index fd6db93..97b6548 100644
--- a/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
@@ -131,20 +131,6 @@ class AboutActivity : AppCompatActivity() {
findViewById(R.id.about_source_code_view).setOnClickListener {
openUrl("https://github.com/NeoTerm/NeoTerm")
}
-
- findViewById(R.id.about_reset_app_view).setOnClickListener {
- AlertDialog.Builder(this)
- .setMessage(R.string.reset_app_warning)
- .setPositiveButton(R.string.yes) { _, _ ->
- resetApp()
- }
- .setNegativeButton(android.R.string.no, null)
- .show()
- }
- }
-
- private fun resetApp() {
- startActivity(Intent(this, SetupActivity::class.java))
}
private fun openUrl(url: String) {
diff --git a/app/src/main/java/io/neoterm/ui/other/SetupActivity.kt b/app/src/main/java/io/neoterm/ui/other/SetupActivity.kt
deleted file mode 100644
index 7981aa0..0000000
--- a/app/src/main/java/io/neoterm/ui/other/SetupActivity.kt
+++ /dev/null
@@ -1,238 +0,0 @@
-package io.neoterm.ui.other
-
-import android.content.ActivityNotFoundException
-import android.content.Intent
-import android.net.Uri
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.widget.*
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import io.neoterm.App
-import io.neoterm.R
-import io.neoterm.component.config.NeoTermPath
-import io.neoterm.component.pm.SourceHelper
-import io.neoterm.setup.*
-import io.neoterm.utils.getPathOfMediaUri
-import io.neoterm.utils.runApt
-import java.io.File
-
-
-/**
- * @author kiva
- */
-class SetupActivity : AppCompatActivity(), View.OnClickListener, ResultListener {
- companion object {
- private const val REQUEST_SELECT_PARAMETER = 520;
- }
-
- private var setupParameter = ""
- private var setupParameterUri: Uri? = null
-
- private val hintMapping = arrayOf(
- R.id.setup_method_online, R.string.setup_hint_online,
- R.id.setup_method_local, R.string.setup_hint_local,
- R.id.setup_method_backup, R.string.setup_hint_backup
- )
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.ui_setup)
-
- val parameterEditor = findViewById(R.id.setup_source_parameter)
-
- val tipText = findViewById(R.id.setup_url_tip_text)
-
- val onCheckedChangeListener = CompoundButton.OnCheckedChangeListener { button, checked ->
- if (checked) {
- val id = button.id
- val index = hintMapping.indexOf(id)
- if (index < 0 || index % 2 != 0) {
- parameterEditor.setHint(R.string.setup_input_source_parameter)
- return@OnCheckedChangeListener
- }
- parameterEditor.setHint(hintMapping[index + 1])
- tipText.setText(hintMapping[index + 1])
- setDefaultValue(parameterEditor, id)
- }
- }
-
- findViewById(R.id.setup_method_online).setOnCheckedChangeListener(onCheckedChangeListener)
- findViewById(R.id.setup_method_local).setOnCheckedChangeListener(onCheckedChangeListener)
- findViewById(R.id.setup_method_backup).setOnCheckedChangeListener(onCheckedChangeListener)
-
- findViewById