refine libexec

This commit is contained in:
Max Lv
2012-12-19 15:32:31 +08:00
parent 5bb9ccd848
commit 89da9abda3
9 changed files with 103 additions and 110 deletions
+7 -5
View File
@@ -43,16 +43,18 @@ public class Exec {
* Callers are responsible for calling Exec.close() on the returned file
* descriptor.
*
* @param cmd The command to execute
* @param args An array of arguments to the command
* @param cmd The command to execute.
* @param args An array of arguments to the command.
* @param envVars An array of strings of the form "VAR=value" to be added to the
* environment of the process
* environment of the process.
* @param scripts The scripts to execute.
* @param processId A one-element array to which the process ID of the started
* process will be written.
* @return the file descriptor of the started process.
* @return File descriptor
*/
public static native FileDescriptor createSubprocess(String cmd,
String[] args, String[] envVars, int[] processId);
String[] args, String[] envVars,
String scripts, int[] processId);
/**
* Send SIGHUP to a process group.
View File
@@ -1,13 +1,21 @@
package com.github.shadowsocks;
import android.app.Application;
import android.content.Context;
import com.google.analytics.tracking.android.EasyTracker;
public class ShadowsocksApplication extends Application {
private static String sTmpDir;
public static String getTmpDir() {
return sTmpDir;
}
@Override
public void onCreate() {
EasyTracker.getInstance().setContext(this);
sTmpDir = getCacheDir().getAbsolutePath();
}
}
+46 -76
View File
@@ -8,7 +8,10 @@ import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.util.Log;
import java.io.*;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
public class Utils {
@@ -17,51 +20,32 @@ public class Utils {
* Internal thread used to execute scripts (as root or not).
*/
private static final class ScriptRunner extends Thread {
private final File file;
private final String script;
private final StringBuilder res;
private final String scripts;
private final StringBuilder result;
private final boolean asroot;
public int exitcode = -1;
// private Process exec;
private int mProcId;
private FileDescriptor mTermFd;
/**
* Creates a new script runner.
*
* @param file temporary script file
* @param script script to run
* @param res response output
* @param result result output
* @param asroot if true, executes the script as root
*/
public ScriptRunner(File file, String script, StringBuilder res,
public ScriptRunner(String script, StringBuilder result,
boolean asroot) {
this.file = file;
this.script = script;
this.res = res;
this.scripts = script;
this.result = result;
this.asroot = asroot;
}
private int createSubprocess(int[] processId, String cmd) {
private FileDescriptor createSubprocess(int[] processId, String cmd) {
ArrayList<String> argList = parse(cmd);
String arg0 = argList.get(0);
String[] args = argList.toArray(new String[1]);
mTermFd = Exec.createSubprocess(arg0, args, null, processId);
return processId[0];
}
/**
* Destroy this script runner
*/
@Override
public synchronized void destroy() {
try {
Exec.hangupProcessGroup(mProcId);
Exec.close(mTermFd);
} catch (NoClassDefFoundError ignore) {
// Nothing
}
return Exec.createSubprocess(arg0, args, null,
scripts + "\nexit\n", processId);
}
private ArrayList<String> parse(String cmd) {
@@ -114,61 +98,48 @@ public class Utils {
@Override
public void run() {
FileDescriptor pipe = null;
int pid[] = new int[1];
pid[0] = -1;
try {
new File(DEFOUT_FILE).createNewFile();
file.createNewFile();
final String abspath = file.getAbsolutePath();
// TODO: Rewrite this line
// make sure we have execution permission on the script file
// Runtime.getRuntime().exec("chmod 755 " + abspath).waitFor();
// Write the script to be executed
final OutputStreamWriter out = new OutputStreamWriter(
new FileOutputStream(file));
out.write("#!/system/bin/sh\n");
out.write(script);
if (!script.endsWith("\n"))
out.write("\n");
out.write("exit\n");
out.flush();
out.close();
if (this.asroot) {
// Create the "su" request to run the script
// exec = Runtime.getRuntime().exec(
// root_shell + " -c " + abspath);
int pid[] = new int[1];
mProcId = createSubprocess(pid, root_shell + " -c "
+ abspath);
pipe = createSubprocess(pid, root_shell);
} else {
// Create the "sh" request to run the script
// exec = Runtime.getRuntime().exec(getShell() + " " +
// abspath);
int pid[] = new int[1];
mProcId = createSubprocess(pid, getShell() + " " + abspath);
pipe = createSubprocess(pid, getShell());
}
final InputStream stdout = new FileInputStream(DEFOUT_FILE);
if (pipe == null) return;
if (pid[0] != -1) {
Exec.waitFor(pid[0]);
}
final InputStream stdout = new FileInputStream(pipe);
final byte buf[] = new byte[8192];
int read = 0;
exitcode = Exec.waitFor(mProcId);
// Read stdout
while (stdout.available() > 0) {
read = stdout.read(buf);
if (res != null)
res.append(new String(buf, 0, read));
if (result != null)
result.append(new String(buf, 0, read));
}
} catch (Exception ex) {
if (res != null)
res.append("\n" + ex);
Log.e(TAG, "Cannot execute command", ex);
if (result != null)
result.append("\n").append(ex);
} finally {
destroy();
if (pipe != null) {
Exec.close(pipe);
}
if (pid[0] != -1) {
Exec.hangupProcessGroup(pid[0]);
}
}
}
}
@@ -181,8 +152,6 @@ public class Utils {
public final static String ALTERNATIVE_ROOT = "/system/xbin/su";
public final static String DEFAULT_IPTABLES = "/data/data/com.github.shadowsocks/iptables";
public final static String ALTERNATIVE_IPTABLES = "/system/bin/iptables";
public final static String SCRIPT_FILE = "/data/data/com.github.shadowsocks/script";
public final static String DEFOUT_FILE = "/data/data/com.github.shadowsocks/defout";
public final static int TIME_OUT = -99;
private static boolean initialized = false;
@@ -281,7 +250,7 @@ public class Utils {
public static boolean getHasRedirectSupport() {
if (hasRedirectSupport == -1)
initHasRedirectSupported();
return hasRedirectSupport == 1 ? true : false;
return hasRedirectSupport == 1;
}
public static String getIptables() {
@@ -338,7 +307,7 @@ public class Utils {
public static boolean isRoot() {
if (isRoot != -1)
return isRoot == 1 ? true : false;
return isRoot == 1;
// switch between binaries
if (new File(DEFAULT_ROOT).exists()) {
@@ -352,7 +321,7 @@ public class Utils {
String lines = null;
StringBuilder sb = new StringBuilder();
String command = "ls /\n" + "exit\n";
String command = "ls /\n exit\n";
int exitcode = runScript(command, sb, 10 * 1000, true);
@@ -366,7 +335,7 @@ public class Utils {
isRoot = 1;
}
return isRoot == 1 ? true : false;
return isRoot == 1;
}
public static boolean runCommand(String command) {
@@ -392,8 +361,10 @@ public class Utils {
public static boolean runRootCommand(String command, int timeout) {
if (!isRoot())
if (!isRoot()) {
Log.e(TAG, "Cannot get ROOT permission: " + root_shell);
return false;
}
Log.d(TAG, command);
@@ -402,10 +373,9 @@ public class Utils {
return true;
}
private synchronized static int runScript(String script, StringBuilder res,
private synchronized static int runScript(String script, StringBuilder result,
long timeout, boolean asroot) {
final File file = new File(SCRIPT_FILE);
final ScriptRunner runner = new ScriptRunner(file, script, res, asroot);
final ScriptRunner runner = new ScriptRunner(script, result, asroot);
runner.start();
try {
if (timeout > 0) {