/*
* Copyright (C) 2011 asksven
*
* 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.asksven.android.common.shellutils;
import java.io.*;
import android.util.Log;
/** A class that eases the pain of running external processes
* from applications. Lets you run a program three ways:
* <OL>
* <LI><B>exec</B>: Execute the command, returning
* immediately even if the command is still running.
* This would be appropriate for printing a file.
* <LI><B>execWait</B>: Execute the command, but dont
* return until the command finishes. This would be
* appropriate for sequential commands where the first
* depends on the second having finished (e.g.,
* <CODE>javac</CODE> followed by <CODE>java</CODE>).
* <LI><B>execPrint</B>: Execute the command and print the
* output. This would be appropriate for the Unix
* command <CODE>ls</CODE>.
* </OL>
* Note that the PATH is not taken into account, so you must
* specify the <B>full</B> pathname to the command, and shell
* built-in commands will not work. For instance, on Unix the
* above three examples might look like:
* <OL>
* <LI><PRE>Exec.exec("/usr/ucb/lpr Some-File");</PRE>
* <LI><PRE>Exec.execWait("/usr/local/bin/javac Foo.java");
* Exec.execWait("/usr/local/bin/java Foo");</PRE>
* <LI><PRE>Exec.execPrint("/usr/bin/ls -al");</PRE>
* </OL>
*
* Adapted from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* http://www.corewebprogramming.com/.
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class Exec
{
/** Starts a process to execute the command. Returns
* immediately, even if the new process is still running.
*
* @param command The <B>full</B> pathname of the command to
* be executed. No shell built-ins (e.g., "cd") or shell
* meta-chars (e.g. ">") are allowed.
* @return false if a problem is known to occur, but since
* this returns immediately, problems arent usually found
* in time. Returns true otherwise.
*/
public static ExecResult exec(String[] command)
{
return(exec(command, false, false));
}
/** Starts a process to execute the command. Waits for the
* process to finish before returning.
*
* @param command The <B>full</B> pathname of the command to
* be executed. No shell built-ins or shell metachars are
* allowed.
* @return false if a problem is known to occur, either due
* to an exception or from the subprocess returning a
* nonzero value. Returns true otherwise.
*/
public static ExecResult execWait(String[] command)
{
return(exec(command, false, true));
}
/** Starts a process to execute the command. Prints any output
* the command produces.
*
* @param command The <B>full</B> pathname of the command to
* be executed. No shell built-ins or shell meta-chars are
* allowed.
* @return false if a problem is known to occur, either due
* to an exception or from the subprocess returning a
* nonzero value. Returns true otherwise.
*/
public static ExecResult execPrint(String[] command)
{
return(exec(command, true, false));
}
/** This creates a Process object via Runtime.getRuntime.exec()
* Depending on the flags, it may call waitFor on the process
* to avoid continuing until the process terminates, and open
* an input stream from the process to read the results.
*/
private static ExecResult exec(String[] command,
boolean printResults,
boolean wait)
{
ExecResult oRet = new ExecResult();
try
{
// Start running command, returning immediately.
Log.d("Exec.exec", "Executing command " + command);
Process p = Runtime.getRuntime().exec(command);
// Print the output. Since we read until there is no more
// input, this causes us to wait until the process is
// completed.
if(printResults)
{
BufferedReader buffer = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String s = null;
try
{
while ((s = buffer.readLine()) != null)
{
oRet.m_oResult.add(s);
}
buffer.close();
if (p.exitValue() != 0)
{
oRet.m_bSuccess=false;
return(oRet);
}
}
catch (Exception e)
{
// Ignore read errors; they mean the process is done.
}
// If not printing the results, then we should call waitFor
// to stop until the process is completed.
}
else if (wait)
{
try
{
int returnVal = p.waitFor();
if (returnVal != 0)
{
oRet.m_bSuccess=false;
return oRet;
}
}
catch (Exception e)
{
oRet.m_oError.add(e.getMessage());
oRet.m_bSuccess=false;
return oRet;
}
}
}
catch (Exception e)
{
oRet.m_oError.add(e.getMessage());
oRet.m_bSuccess=false;
return oRet;
}
oRet.m_bSuccess=true;
return oRet;
}
public static void suExec(String strCommand)
{
try
{
// dirty hack: http://code.google.com/p/market-enabler/wiki/ShellCommands
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
Log.d("Exec.exec", "Executing command " + strCommand);
os.writeBytes(strCommand + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void shExec(String strCommand)
{
try
{
// dirty hack: http://code.google.com/p/market-enabler/wiki/ShellCommands
Process process = Runtime.getRuntime().exec("sh");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
Log.d("Exec.exec", "Executing command " + strCommand);
os.writeBytes(strCommand + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}