Support custom process

This commit is contained in:
vvb2060 2021-05-12 16:22:23 +08:00 committed by John Wu
parent 9f2fff6095
commit 25cf6df632
3 changed files with 42 additions and 15 deletions

View File

@ -465,6 +465,17 @@ public abstract class Shell implements Closeable {
*/
@NonNull
public abstract Shell build(String... commands);
/**
* Combine all of the options that have been set and build a new {@code Shell} instance
* with the provided process.
* @param process a shell {@link Process} that has already been created.
* @return the built {@code Shell} instance.
* @throws NoShellException the provided command cannot create a {@link Shell} instance, or
* initialization failed when using the configured {@link Initializer}.
*/
@NonNull
public abstract Shell build(Process process);
}
/**

View File

@ -17,6 +17,7 @@
package com.topjohnwu.superuser.internal;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
@ -34,6 +35,7 @@ import static com.topjohnwu.superuser.Shell.ROOT_SHELL;
@RestrictTo(RestrictTo.Scope.LIBRARY)
public class BuilderImpl extends Shell.Builder {
private static final String TAG = "SHELLIMPL";
boolean hasFlags(int flags) {
return (this.flags & flags) == flags;
@ -72,9 +74,22 @@ public class BuilderImpl extends Shell.Builder {
@NonNull
@Override
public ShellImpl build(String... commands) {
try {
Utils.log(TAG, "exec " + TextUtils.join(" ", commands));
Process process = Runtime.getRuntime().exec(commands);
return build(process);
} catch (IOException e) {
Utils.ex(e);
throw new NoShellException("Unable to create a shell!", e);
}
}
@NonNull
@Override
public ShellImpl build(Process process) {
ShellImpl shell;
try {
shell = new ShellImpl(timeout, hasFlags(FLAG_REDIRECT_STDERR), commands);
shell = new ShellImpl(timeout, hasFlags(FLAG_REDIRECT_STDERR), process);
} catch (IOException e) {
Utils.ex(e);
throw new NoShellException("Unable to create a shell!", e);

View File

@ -47,8 +47,6 @@ class ShellTerminatedException extends IOException {
}
class ShellImpl extends Shell {
private static final String TAG = "SHELLIMPL";
private int status;
final ExecutorService executor;
@ -93,20 +91,15 @@ class ShellImpl extends Shell {
}
}
ShellImpl(long timeout, boolean redirect, String... cmd) throws IOException {
ShellImpl(long timeout, boolean redirect, Process process) throws IOException {
status = UNKNOWN;
this.redirect = redirect;
Utils.log(TAG, "exec " + TextUtils.join(" ", cmd));
process = Runtime.getRuntime().exec(cmd);
STDIN = new NoCloseOutputStream(process.getOutputStream());
STDOUT = new NoCloseInputStream(process.getInputStream());
STDERR = new NoCloseInputStream(process.getErrorStream());
this.process = process;
STDIN = new NoCloseOutputStream(this.process.getOutputStream());
STDOUT = new NoCloseInputStream(this.process.getInputStream());
STDERR = new NoCloseInputStream(this.process.getErrorStream());
executor = new SerialExecutorService();
if (cmd.length >= 2 && TextUtils.equals(cmd[1], "--mount-master"))
status = ROOT_MOUNT_MASTER;
// Shell checks might get stuck indefinitely
Future<Void> check = executor.submit(this::shellCheck);
try {
@ -151,8 +144,16 @@ class ShellImpl extends Shell {
if (!TextUtils.isEmpty(s) && s.contains("uid=0"))
status = ROOT_SHELL;
if (status == ROOT_SHELL && this.status == ROOT_MOUNT_MASTER)
status = ROOT_MOUNT_MASTER;
if (status == ROOT_SHELL) {
STDIN.write(("readlink /proc/self/ns/mnt\n").getBytes(UTF_8));
STDIN.flush();
s = br.readLine();
STDIN.write(("readlink /proc/1/ns/mnt\n").getBytes(UTF_8));
STDIN.flush();
String s2 = br.readLine();
if (!TextUtils.isEmpty(s) && !TextUtils.isEmpty(s2) && TextUtils.equals(s, s2))
status = ROOT_MOUNT_MASTER;
}
this.status = status;
}