Separate STDOUT/STDERR impl

This commit is contained in:
topjohnwu 2020-07-18 00:30:50 -07:00
parent 902d97fb60
commit 9997e0f578
2 changed files with 53 additions and 31 deletions

View File

@ -20,7 +20,6 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.topjohnwu.superuser.CallbackList;
import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellUtils;
@ -54,8 +53,8 @@ class ShellImpl extends Shell {
private final NoCloseOutputStream STDIN;
private final NoCloseInputStream STDOUT;
private final NoCloseInputStream STDERR;
private final StreamGobbler outGobbler;
private final StreamGobbler errGobbler;
private final StreamGobbler.OUT outGobbler;
private final StreamGobbler.ERR errGobbler;
private final byte[] endCmd;
private static class NoCloseInputStream extends FilterInputStream {
@ -104,8 +103,8 @@ class ShellImpl extends Shell {
String uuid = UUID.randomUUID().toString();
InternalUtils.log(TAG, "UUID: " + uuid);
outGobbler = new StreamGobbler(uuid, true);
errGobbler = new StreamGobbler(uuid, false);
outGobbler = new StreamGobbler.OUT(uuid);
errGobbler = new StreamGobbler.ERR(uuid);
endCmd = String.format("__RET=$?;echo %s;echo %s >&2;echo $__RET;unset __RET\n", uuid, uuid).getBytes("UTF-8");
SERIAL_EXECUTOR = new SerialExecutorService();
@ -247,7 +246,7 @@ class ShellImpl extends Shell {
@Override
public void run(@NonNull OutputStream stdin, @NonNull InputStream stdout, @NonNull InputStream stderr) throws IOException {
Future<Integer> out;
Future<Integer> err;
Future<Void> err;
if (res.out != null && res.out == res.err &&
!synchronizedListClass.isInstance(res.out)) {
// Synchronize the list internally only if both lists are the same and are not

View File

@ -22,35 +22,33 @@ import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.Callable;
class StreamGobbler implements Callable<Integer> {
abstract class StreamGobbler<T> implements Callable<T> {
private static final String TAG = "SHELLOUT";
private final String delim;
private final boolean returnCode;
private final String eos;
private InputStream in;
private List<String> list;
protected InputStream in;
protected List<String> list;
StreamGobbler(String delim, boolean b) {
this.delim = delim;
returnCode = b;
StreamGobbler(String eos) {
this.eos = eos;
}
public Callable<Integer> set(InputStream in, List<String> list) {
public Callable<T> set(InputStream in, List<String> list) {
this.in = in;
this.list = list;
return this;
}
private boolean output(String line) {
protected boolean isEOS(String line) {
boolean eof = false;
int sl = line.length() - 1;
int tl = delim.length() - 1;
int tl = eos.length() - 1;
if (sl >= tl) {
eof = true;
for (; tl >= 0; --tl, --sl) {
if (delim.charAt(tl) != line.charAt(sl)) {
if (eos.charAt(tl) != line.charAt(sl)) {
eof = false;
break;
}
@ -65,19 +63,44 @@ class StreamGobbler implements Callable<Integer> {
return eof;
}
static class OUT extends StreamGobbler<Integer> {
OUT(String eos) {
super(eos);
}
@Override
public Integer call() throws Exception {
int code = 0;
int code;
try (BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"))) {
for (;;) {
if (output(br.readLine()))
if (isEOS(br.readLine()))
break;
}
if (returnCode)
code = Integer.parseInt(br.readLine());
}
in = null;
list = null;
return code;
}
}
static class ERR extends StreamGobbler<Void> {
ERR(String eos) {
super(eos);
}
@Override
public Void call() throws Exception {
try (BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"))) {
for (;;) {
if (isEOS(br.readLine()))
break;
}
}
in = null;
list = null;
return null;
}
}
}