Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read command output inside su process

Tags:

android

root

su

firstly I will present my situation. I need to execute "su" command in my android app and it works well. Then I need to execute "ls" command and read the output. I'm doing it by getting the output stream from the "su" process and writing my command into it.

And here goes the question. How to read the output of the "ls" process? All I have is the "su" Process object. Getting the input stream from it gives nothing, because "su" doesn't write anything. But "ls" does and I don't know how to access its output messages.

I have searched many sites but I didn't find any solution. Maybe someone will help me:)

Regards

like image 813
glodos Avatar asked Aug 01 '11 09:08

glodos


2 Answers

Ok, I've found a solution. It should look like this:

Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
DataOutputStream stdin = new DataOutputStream(p.getOutputStream());
//from here all commands are executed with su permissions
stdin.writeBytes("ls /data\n"); // \n executes the command
InputStream stdout = p.getInputStream();
byte[] buffer = new byte[BUFF_LEN];
int read;
String out = new String();
//read method will wait forever if there is nothing in the stream
//so we need to read it in another way than while((read=stdout.read(buffer))>0)
while(true){
    read = stdout.read(buffer);
    out += new String(buffer, 0, read);
    if(read<BUFF_LEN){
        //we have read everything
        break;
    }
}
//do something with the output

Hope it will be helpful for someone

like image 118
glodos Avatar answered Sep 30 '22 06:09

glodos


I modified accepted answer by @glodos for following problems:

  1. the streams are closed, otherwise the exec process hangs forever, on the opened stream. If you execute ps in shell (ie adb shell) after several executions then you'll see several su processes alive. They needs to be properly terminated.
  2. added waitFor() to make sure the process is terminated.
  3. Added handling for read=-1, now commands with empty stdout can be executed. Previously they crashed on new String(buffer, 0, read)
  4. Using StringBuffer for more efficient strings handling.

    private String execCommand(String cmd) throws IOException, InterruptedException {
        Process p = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"});
        DataOutputStream stdout = new DataOutputStream(p.getOutputStream());
    
        stdout.writeBytes(cmd);
        stdout.writeByte('\n');
        stdout.flush();
        stdout.close();
    
        BufferedReader stdin = new BufferedReader(new InputStreamReader(p.getInputStream()));
        char[] buffer = new char[1024];
        int read;
        StringBuffer out = new StringBuffer();
    
        while((read = stdin.read(buffer)) > 0) {
            out.append(buffer, 0, read);
        }
        stdin.close();
        p.waitFor();
        return out.toString();
    }
    

Some credits go to @Sherif elKhatib ))

like image 27
Mixaz Avatar answered Sep 30 '22 07:09

Mixaz