Skip to content

Commit

Permalink
improve terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
DerGoogler committed Sep 4, 2024
1 parent 378adea commit 468fc5c
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 29 deletions.
67 changes: 44 additions & 23 deletions app/src/main/java/com/dergoogler/plugin/TerminalPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.util.Log;

import com.dergoogler.util.Json;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.io.SuFile;

import org.apache.cordova.CallbackContext;
Expand All @@ -14,12 +15,14 @@

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class TerminalPlugin extends CordovaPlugin {
private static final String TAG = "TerminalPlugin";
Expand All @@ -34,7 +37,6 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
String cmd = data.getString(0);
JSONObject envp = data.getJSONObject(1);
String cwd = data.getString(2);
boolean printError = data.getBoolean(3);

this.terminalCallbackContext = callbackContext;
String[] commands = {"su", "-c", cmd};
Expand All @@ -44,11 +46,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
try {
run(envp, cwd, commands);
} catch (IOException | JSONException e) {
Log.e(TAG, e.toString());
if (printError) {
updateTerminalLine(e.toString());
}
//updateTerminalExit(500);
Log.e(TAG + ":execute", e.toString());
}
});
return true;
Expand All @@ -64,7 +62,7 @@ public boolean execute(String action, JSONArray data, CallbackContext callbackCo
}

public void run(JSONObject envp, String cwd, String... command) throws IOException, JSONException {
ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
ProcessBuilder pb = new ProcessBuilder(command);

if (envp != null) {
Map<String, String> m = pb.environment();
Expand All @@ -73,30 +71,53 @@ public void run(JSONObject envp, String cwd, String... command) throws IOExcepti

pb.directory(new SuFile(cwd));
Process process = pb.start();
try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
while (true) {
String line = in.readLine();
if (line == null)
break;
updateTerminalLine(line);

try (BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = stdoutReader.readLine()) != null) {
JSONObject progressObj = new JSONObject();
progressObj.put("stdout", line);
progressObj.put("stderr", null);
updateTerminalOutput(progressObj);
}
} catch (Exception e) {
Log.e(TAG, e.toString());
Log.e(TAG + ":run -> stdout", e.toString());
}

try (BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = stderrReader.readLine()) != null) {
JSONObject progressObj = new JSONObject();
progressObj.put("stdout", null);
progressObj.put("stderr", line);
updateTerminalOutput(progressObj);
}
} catch (Exception e) {
Log.e(TAG + ":run -> stderr", e.toString());
}

int exitCode;
try {
exitCode = process.waitFor();
updateTerminalExit(exitCode);
process.destroy();
} catch (InterruptedException e) {
Log.e(TAG + ":run -> exit", e.toString());
updateTerminalExit(500);
process.destroy();
}
updateTerminalExit(process);
}

private void updateTerminalLine(String line) {

private void updateTerminalOutput(JSONObject line) {
sendUpdate(PluginResult.Status.OK, line);
}

private void updateTerminalExit(Process process) {
if (!process.isAlive()) {
sendUpdate(PluginResult.Status.ERROR, process.exitValue());
process.destroy();
}
private void updateTerminalExit(int code) {
sendUpdate(PluginResult.Status.ERROR, code);
}


private void sendUpdate(PluginResult.Status status, int line) {
if (this.terminalCallbackContext != null) {
PluginResult result = new PluginResult(status, line);
Expand All @@ -106,9 +127,9 @@ private void sendUpdate(PluginResult.Status status, int line) {
}


private void sendUpdate(PluginResult.Status status, String line) {
private void sendUpdate(PluginResult.Status status, JSONObject obj) {
if (this.terminalCallbackContext != null) {
PluginResult result = new PluginResult(status, line);
PluginResult result = new PluginResult(status, obj);
result.setKeepCallback(true);
this.terminalCallbackContext.sendPluginResult(result);
}
Expand Down
66 changes: 66 additions & 0 deletions src/native/Log.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Native } from "./Native";

type AllowedLogTypes = Pick<Console, "info" | "warn" | "error" | "debug">;

class Log extends Native {
private _tag: string;

public static VERBOSE: number = 2;
public static DEBUG: number = 3;
public static INFO: number = 4;
public static WARN: number = 5;
public static ERROR: number = 6;

public constructor(tag: string) {
super(window.__log__);
this._tag = tag;
}

public v(message: string) {
this._native_log(Log.INFO, "info", message);
}

public d(message: string) {
this._native_log(Log.DEBUG, "debug", message);
}
public i(message: string) {
this._native_log(Log.INFO, "info", message);
}

public w(message: string) {
this._native_log(Log.WARN, "warn", message);
}

public e(message: string) {
this._native_log(Log.ERROR, "error", message);
}

private _native_log(prio: number, bPrio: keyof AllowedLogTypes, message: string) {
if (this.isAndroid) {
this.interface.native_log(prio, String(this._tag), String(message));
} else {
console[bPrio](`[${this._tag}] -> ${message}`);
}
}

public static v(tag: string, message: string) {
new Log(tag).v(message);
}
public static d(tag: string, message: string) {
new Log(tag).d(message);
}

public static i(tag: string, message: string) {
new Log(tag).i(message);
}

public static w(tag: string, message: string) {
new Log(tag).w(message);
}

public static e(tag: string, message: string) {
new Log(tag).e(message);
}
}

export { Log };
2 changes: 2 additions & 0 deletions src/native/Native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export type NativeArgumentTypes<F extends Function> = F extends (...args: infer
*/
export class Native<I = any> implements INative<I> {
private _internal_interface: I;
public static static: Native;

/**
* This field is required, otherwise the comunacation between Android will not work
* @required true
*/
public constructor(i: I) {
this._internal_interface = i;
Native.static = this;
}

private static get userAgentRegex(): RegExp {
Expand Down
28 changes: 23 additions & 5 deletions src/native/Terminal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { Log } from "./Log";
import { Native } from "./Native";

type TerminalStream = {
stdout: string | null;
stderr: string | null;
};

interface TerminalExec {
command: string;
/**
Expand All @@ -15,7 +21,7 @@ interface TerminalExec {
* @default true
*/
printError?: boolean;
onLine: (line: string) => void;
onLine: (stream: TerminalStream) => void;
onExit?: ((code: number) => void) | null;
}

Expand All @@ -31,8 +37,9 @@ class Terminal extends Native<TerminalNative> {
private _env: TerminalEnv = {};
public cwd: string | undefined;
printErrors: boolean | undefined;
private _onLine: ((line: string) => void) | undefined;
private _onLine: ((stdout: string) => void) | undefined;
private _onExit: ((code: number) => void) | undefined | null;
private _onError: ((stderr: string) => void) | undefined | null;

public constructor(options?: TerminalOptions) {
super(window.__terminal__);
Expand All @@ -41,10 +48,14 @@ class Terminal extends Native<TerminalNative> {
this.printErrors = options?.printError;
}

public set onLine(func: TerminalExec["onLine"]) {
public set onLine(func: (stdout: string) => void) {
this._onLine = func;
}

public set onError(func: (stderr: string) => void) {
this._onError = func;
}

public set onExit(func: TerminalExec["onExit"]) {
this._onExit = func;
}
Expand All @@ -65,9 +76,16 @@ class Terminal extends Native<TerminalNative> {
command: command,
cwd: this.cwd,
env: this.env,
onLine: this._onLine,
onLine: (stream: TerminalStream) => {
if (stream.stdout && this._onLine) {
this._onLine(stream.stdout);
} else if (stream.stdout && this._onError) {
this._onError(stream.stdout);
} else {
Log.e("Terminal:exec", "Unable to find proper terminal stream");
}
},
onExit: this._onExit,
printError: this.printErrors,
});
}
}
Expand Down
1 change: 0 additions & 1 deletion web/cordova/plugins/terminal.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ cordova.define(
opt.command,
opt.env || { HOME: "/" },
opt.cwd || "/",
opt.printError || true,
]);
},
test: function (msg, successCallback, errorCallback) {
Expand Down

0 comments on commit 468fc5c

Please sign in to comment.