package fq.router2.utils;
import java.io.*;
import java.util.*;
public class ShellUtils {
private final static String[] BINARY_PLACES = {"/data/bin/", "/system/bin/", "/system/xbin/", "/sbin/",
"/data/local/xbin/", "/data/local/bin/", "/system/sd/xbin/", "/system/bin/failsafe/",
"/data/local/"};
private final static String PYTHON_HOME = "/data/data/fq.router2/python";
public static File DATA_DIR = new File("/data/data/fq.router2");
public static File BUSYBOX_FILE = new File(DATA_DIR, "busybox");
private static Boolean IS_ROOTED = null;
public static String execute(String... command) throws Exception {
Process process = executeNoWait(new HashMap<String, String>(), command);
return waitFor(Arrays.toString(command), process);
}
public static String execute(Map<String, String> env, String... command) throws Exception {
return waitFor(Arrays.toString(command), executeNoWait(env, command));
}
public static Process executeNoWait(Map<String, String> env, String... command) throws IOException {
LogUtils.i("command: " + Arrays.toString(command));
List<String> envp = new ArrayList<String>();
for (Map.Entry<String, String> entry : env.entrySet()) {
envp.add(entry.getKey() + "=" + entry.getValue());
}
return Runtime.getRuntime().exec(command, envp.toArray(new String[envp.size()]));
}
public static String sudo(Map<String, String> env, String... command) throws Exception {
if (Boolean.FALSE.equals(IS_ROOTED)) {
if (BUSYBOX_FILE.exists()) {
Process process = ShellUtils.executeNoWait(env, BUSYBOX_FILE.getCanonicalPath(), "sh");
OutputStreamWriter stdin = new OutputStreamWriter(process.getOutputStream());
try {
LogUtils.i("write to stdin: " + Arrays.toString(command));
for (String c : command) {
stdin.write(c);
stdin.write(" ");
}
stdin.write("\nexit\n");
} finally {
stdin.close();
}
return waitFor(Arrays.toString(command), process);
} else {
return waitFor(Arrays.toString(command), executeNoWait(env, command));
}
} else {
Process process = sudoNoWait(env, command);
return waitFor(Arrays.toString(command), process);
}
}
public static String sudo(String... command) throws Exception {
return sudo(new HashMap<String, String>(), command);
}
public static Process sudoNoWait(Map<String, String> env, String... command) throws Exception {
if (Boolean.FALSE.equals(IS_ROOTED)) {
return executeNoWait(env, command);
}
LogUtils.i("sudo: " + Arrays.toString(command));
ProcessBuilder processBuilder = new ProcessBuilder();
Process process = processBuilder
.command(findCommand("su"))
.redirectErrorStream(true)
.start();
OutputStreamWriter stdin = new OutputStreamWriter(process.getOutputStream());
try {
for (Map.Entry<String, String> entry : env.entrySet()) {
stdin.write(entry.getKey());
stdin.write("=");
stdin.write(entry.getValue());
stdin.write(" ");
}
for (String c : command) {
stdin.write(c);
stdin.write(" ");
}
stdin.write("\nexit\n");
} finally {
stdin.close();
}
return process;
}
public static String findCommand(String command) {
for (String binaryPlace : BINARY_PLACES) {
String path = binaryPlace + command;
if (new File(path).exists()) {
return path;
}
}
return command;
}
public static String waitFor(String command, Process process) throws Exception {
BufferedReader stdout = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output = new StringBuilder();
try {
String line;
while (null != (line = stdout.readLine())) {
output.append(line);
output.append("\n");
}
} finally {
stdout.close();
}
process.waitFor();
int exitValue = process.exitValue();
if (0 != exitValue) {
throw new Exception("failed to execute: " + command + ", exit value: " + exitValue + ", output: " + output);
}
return output.toString();
}
public static Map<String, String> pythonEnv() {
return new HashMap<String, String>() {{
put("PYTHONHOME", PYTHON_HOME);
put("PYTHONPATH", PYTHON_HOME + "/lib/python2.7/lib-dynload:" + PYTHON_HOME + "/lib/python2.7");
put("PATH", PYTHON_HOME + "/bin:" + System.getenv("PATH"));
put("LD_LIBRARY_PATH", System.getenv("LD_LIBRARY_PATH") + ":" + PYTHON_HOME + "/lib:" + PYTHON_HOME + "/lib/python2.7/lib-dynload");
}};
}
public static boolean checkRooted() {
IS_ROOTED = null;
try {
IS_ROOTED = sudo("echo", "hello").contains("hello");
} catch (Exception e) {
IS_ROOTED = false;
}
return IS_ROOTED;
}
public static boolean isRooted() {
return Boolean.TRUE.equals(IS_ROOTED);
}
}