package com.ghostsq.commander.root;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.regex.Matcher;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import com.ghostsq.commander.adapters.Engine;;
public class ExecEngine extends Engine {
protected String sh;
protected Context context;
private String bb = "";
private String where, command;
private boolean use_busybox = false;
private int wait_timeout = 500;
private StringBuilder result;
private boolean done = false;
private OutputStreamWriter os = null;
private BufferedReader is = null;
private BufferedReader es = null;
protected ExecEngine( Context context_ ) {
context = context_;
sh = getSuPath();
where = null;
command = null;
result = null;
}
public ExecEngine( Context context_, String where_, String command_, boolean use_bb, int timeout ) {
context = context_;
sh = getSuPath();
where = where_;
command = command_;
use_busybox = use_bb;
wait_timeout = timeout;
result = new StringBuilder( 1024 );
}
protected String getSuPath() {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences( context );
return sharedPref.getString( "su_path", "su" );
}
@Override
public void run() {
try {
if( command == null ) return;
execute();
} catch( Exception e ) {
error( "Exception: " + e );
}
synchronized( this ) {
done = true;
notify();
}
if( thread_handler != null )
sendResult( result != null && result.length() > 0 ? result.toString() :
( errMsg != null ? "\nFailed to execute \"" + command + "\"" : null ) );
}
protected boolean execute( String cmd, boolean use_bb ) {
command = cmd;
use_busybox = use_bb;
return execute();
}
protected boolean execute( String cmd, boolean use_bb, int timeout ) {
command = cmd;
use_busybox = use_bb;
wait_timeout = timeout;
return execute();
}
protected boolean execute() {
os = null;
is = null;
es = null;
try {
setEngineName( null );
if( context != null ) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences( context );
bb = sharedPref.getString( "busybox_path", "busybox" ) + " ";
}
else
bb = "busybox ";
Process p = Runtime.getRuntime().exec( sh );
os = new OutputStreamWriter( p.getOutputStream() );
is = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
es = new BufferedReader( new InputStreamReader( p.getErrorStream() ) );
if( where != null )
outCmd( false, "cd '" + where + "'", os );
boolean ok = cmdDialog( os, is, es );
os.write( "exit\n" );
os.flush();
p.waitFor();
int ev = p.exitValue();
if( ev != 0 ) {
Log.e( TAG, "Exit code " + ev );
procError( es );
if( errMsg == null || errMsg.length() == 0 )
error( "Exit code " + ev );
return false;
}
return ok;
}
catch( Exception e ) {
error( "Exception: " + e );
}
finally {
try {
if( os != null ) os.close();
if( is != null ) is.close();
if( es != null ) es.close();
} catch( IOException e ) {
e.printStackTrace();
}
}
return false;
}
protected void outCmd( boolean use_bb, String cmd, OutputStreamWriter os )
throws IOException, InterruptedException {
String to_exec = ( use_bb ? bb : "" ) + cmd + "\n";
Log.v( TAG, "executing: " + to_exec );
os.write( to_exec ); // execute the command
os.flush();
boolean ready = false;
final int swait = 10;
final int tries = wait_timeout / swait;
for( int i = 0; i < tries; i++ ) {
if( is.ready() ) {
ready = true;
break;
}
Thread.sleep( swait );
}
if( ready )
Log.d( TAG, "After cmd execution the input stream is ready" );
else
Log.w( TAG, "After " + wait_timeout + "ms the input stream is NOT yet ready!" );
}
// to override by a derived class which wants something more complex
protected boolean cmdDialog( OutputStreamWriter os, BufferedReader is, BufferedReader es ) {
try {
if( command != null )
outCmd( use_busybox, command, os );
boolean err = procError( es );
if( !is.ready() ) // may be an error may be not
Log.w( TAG, "No output from the executed command " + command );
procInput( is );
return !err;
} catch( Exception e ) {
error( e.getMessage() );
if( command != null )
Log.e( TAG, "Exception '" + e.getMessage() + "' nn execution '" + command + "'" );
}
return false;
}
// to override by derived classes
protected void procInput( BufferedReader br )
throws IOException, Exception {
if( br != null && result != null )
while( br.ready() ) {
Thread.sleep( 10 );
if( isStopReq() )
throw new Exception();
String ln = br.readLine();
if( ln == null ) break;
result.append( ln ).append( "\n" );
}
}
protected boolean procError( BufferedReader es ) throws IOException {
while( es.ready() ) {
String err_str = es.readLine();
if( err_str.trim().length() > 0 ) {
error( err_str );
return true;
}
}
if( isStopReq() ) {
error( "Canceled" );
return true;
}
return false;
}
public synchronized StringBuilder getResult() {
try {
wait( 500 );
} catch( InterruptedException e ) {}
return done ? result : null;
}
static String prepFileName( String fn ) {
return "'" + fn.replaceAll( "'", Matcher.quoteReplacement("'\\''") ) + "'";
}
}