mirror of
https://github.com/topjohnwu/libsu.git
synced 2024-11-23 12:09:42 +00:00
Make sure resources are closed
This commit is contained in:
parent
1559d3eb9f
commit
c5ddd26bf4
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 John "topjohnwu" Wu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.topjohnwu.superuser.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import static com.topjohnwu.superuser.internal.Utils.UTF_8;
|
||||
|
||||
interface InputHandler {
|
||||
|
||||
String TAG = "SHELL_IN";
|
||||
|
||||
void handleInput(OutputStream in) throws IOException;
|
||||
|
||||
static InputHandler newInstance(String... cmd) {
|
||||
return in -> {
|
||||
for (String command : cmd) {
|
||||
in.write(command.getBytes(UTF_8));
|
||||
in.write('\n');
|
||||
Utils.log(TAG, command);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static InputHandler newInstance(InputStream is) {
|
||||
return in -> {
|
||||
Utils.log(TAG, "<InputStream>");
|
||||
Utils.pump(is, in);
|
||||
is.close();
|
||||
// Make sure it ends properly
|
||||
in.write('\n');
|
||||
};
|
||||
}
|
||||
}
|
@ -21,21 +21,22 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
class JobImpl extends Shell.Job {
|
||||
class JobImpl extends Shell.Job implements Closeable {
|
||||
|
||||
protected List<String> out, err;
|
||||
private final List<InputHandler> handlers;
|
||||
private final List<ShellInputSource> sources;
|
||||
protected ShellImpl shell;
|
||||
private boolean stderrSet = false;
|
||||
|
||||
JobImpl() {
|
||||
handlers = new ArrayList<>();
|
||||
sources = new ArrayList<>();
|
||||
}
|
||||
|
||||
JobImpl(ShellImpl s) {
|
||||
@ -48,7 +49,7 @@ class JobImpl extends Shell.Job {
|
||||
boolean redirect = !stderrSet && shell.redirect;
|
||||
result.out = out;
|
||||
result.err = redirect ? out : err;
|
||||
Shell.Task task = shell.newTask(handlers, result);
|
||||
Shell.Task task = shell.newTask(sources, result);
|
||||
try {
|
||||
shell.execTask(task);
|
||||
} catch (IOException e) {
|
||||
@ -58,6 +59,8 @@ class JobImpl extends Shell.Job {
|
||||
Utils.err(e);
|
||||
return ResultImpl.INSTANCE;
|
||||
}
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
if (redirect)
|
||||
result.err = null;
|
||||
@ -97,7 +100,7 @@ class JobImpl extends Shell.Job {
|
||||
@Override
|
||||
public Shell.Job add(@NonNull InputStream in) {
|
||||
if (in != null)
|
||||
handlers.add(InputHandler.newInstance(in));
|
||||
sources.add(new InputStreamSource(in));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -105,8 +108,13 @@ class JobImpl extends Shell.Job {
|
||||
@Override
|
||||
public Shell.Job add(@NonNull String... cmds) {
|
||||
if (cmds != null && cmds.length > 0)
|
||||
handlers.add(InputHandler.newInstance(cmds));
|
||||
sources.add(new CommandSource(cmds));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
for (ShellInputSource src : sources)
|
||||
src.close();
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,11 @@ import java.util.concurrent.Executor;
|
||||
class PendingJob extends JobImpl {
|
||||
|
||||
private final boolean isSU;
|
||||
private boolean retried;
|
||||
private boolean retry;
|
||||
|
||||
PendingJob(boolean su) {
|
||||
isSU = su;
|
||||
retried = false;
|
||||
retry = true;
|
||||
to(NOPList.getInstance());
|
||||
}
|
||||
|
||||
@ -42,16 +42,19 @@ class PendingJob extends JobImpl {
|
||||
try {
|
||||
shell = MainShell.get();
|
||||
} catch (NoShellException e) {
|
||||
close();
|
||||
return ResultImpl.INSTANCE;
|
||||
}
|
||||
if (isSU && !shell.isRoot())
|
||||
if (isSU && !shell.isRoot()) {
|
||||
close();
|
||||
return ResultImpl.INSTANCE;
|
||||
}
|
||||
if (out instanceof NOPList)
|
||||
out = new ArrayList<>();
|
||||
Shell.Result res = super.exec();
|
||||
if (!retried && res == ResultImpl.SHELL_ERR) {
|
||||
if (retry && res == ResultImpl.SHELL_ERR) {
|
||||
// The cached shell is terminated, try to re-run this task
|
||||
retried = true;
|
||||
retry = false;
|
||||
return exec();
|
||||
}
|
||||
return res;
|
||||
@ -61,6 +64,7 @@ class PendingJob extends JobImpl {
|
||||
public void submit(@Nullable Executor executor, @Nullable Shell.ResultCallback cb) {
|
||||
MainShell.get(null, s -> {
|
||||
if (isSU && !s.isRoot()) {
|
||||
close();
|
||||
ResultImpl.INSTANCE.callback(executor, cb);
|
||||
return;
|
||||
}
|
||||
@ -68,9 +72,9 @@ class PendingJob extends JobImpl {
|
||||
out = (cb == null) ? null : new ArrayList<>();
|
||||
shell = (ShellImpl) s;
|
||||
super.submit(executor, res -> {
|
||||
if (!retried && res == ResultImpl.SHELL_ERR) {
|
||||
if (retry && res == ResultImpl.SHELL_ERR) {
|
||||
// The cached shell is terminated, try to re-schedule this task
|
||||
retried = true;
|
||||
retry = false;
|
||||
submit(executor, cb);
|
||||
} else if (cb != null) {
|
||||
cb.onResult(res);
|
||||
|
@ -43,6 +43,13 @@ import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static com.topjohnwu.superuser.internal.Utils.UTF_8;
|
||||
|
||||
class ShellTerminatedException extends IOException {
|
||||
|
||||
ShellTerminatedException() {
|
||||
super("Shell terminated unexpectedly");
|
||||
}
|
||||
}
|
||||
|
||||
class ShellImpl extends Shell {
|
||||
private static final String TAG = "SHELLIMPL";
|
||||
|
||||
@ -241,17 +248,17 @@ class ShellImpl extends Shell {
|
||||
return new JobImpl(this);
|
||||
}
|
||||
|
||||
Task newTask(List<InputHandler> handlers, ResultImpl res) {
|
||||
return new DefaultTask(handlers, res);
|
||||
Task newTask(List<ShellInputSource> sources, ResultImpl res) {
|
||||
return new DefaultTask(sources, res);
|
||||
}
|
||||
|
||||
private class DefaultTask implements Task {
|
||||
|
||||
private final ResultImpl res;
|
||||
private final List<InputHandler> handlers;
|
||||
private final List<ShellInputSource> sources;
|
||||
|
||||
DefaultTask(List<InputHandler> h, ResultImpl r) {
|
||||
handlers = h;
|
||||
DefaultTask(List<ShellInputSource> s, ResultImpl r) {
|
||||
sources = s;
|
||||
res = r;
|
||||
}
|
||||
|
||||
@ -271,8 +278,8 @@ class ShellImpl extends Shell {
|
||||
err = EXECUTOR.submit(errGobbler.set(stderr, res.err));
|
||||
}
|
||||
|
||||
for (InputHandler handler : handlers)
|
||||
handler.handleInput(stdin);
|
||||
for (ShellInputSource src : sources)
|
||||
src.serve(stdin);
|
||||
stdin.write(endCmd);
|
||||
stdin.flush();
|
||||
try {
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2021 John "topjohnwu" Wu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.topjohnwu.superuser.internal;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import static com.topjohnwu.superuser.internal.Utils.UTF_8;
|
||||
|
||||
interface ShellInputSource extends Closeable {
|
||||
String TAG = "SHELL_IN";
|
||||
|
||||
void serve(OutputStream out) throws IOException;
|
||||
|
||||
@Override
|
||||
default void close() {}
|
||||
}
|
||||
|
||||
class InputStreamSource implements ShellInputSource {
|
||||
|
||||
private final InputStream in;
|
||||
InputStreamSource(InputStream in) { this.in = in; }
|
||||
|
||||
@Override
|
||||
public void serve(OutputStream out) throws IOException {
|
||||
Utils.pump(in, out);
|
||||
in.close();
|
||||
out.write('\n');
|
||||
Utils.log(TAG, "<InputStream>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
class CommandSource implements ShellInputSource {
|
||||
|
||||
private final String[] cmd;
|
||||
CommandSource(String[] cmd) { this.cmd = cmd; }
|
||||
|
||||
@Override
|
||||
public void serve(OutputStream out) throws IOException {
|
||||
for (String command : cmd) {
|
||||
out.write(command.getBytes(UTF_8));
|
||||
out.write('\n');
|
||||
Utils.log(TAG, command);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 John "topjohnwu" Wu
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.topjohnwu.superuser.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class ShellTerminatedException extends IOException {
|
||||
|
||||
ShellTerminatedException() {
|
||||
super("Shell terminated unexpectedly");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user