0

I want to execute multiple commands from Java Process but I don't want to spawn a new process for executing every command. So I made an Object called Shell that holds InputStream and OutputStream for Process. The problem is that if I don't terminate a process by appending

"exit\n"

I can't tell where is the end of the InputStream and the InputStream gets into waiting state when I've read the whole output so I need to know when to stop doing next read. Is there some kind of a standard symbol at the end of the output? Because what I came up with is

final String outputTerminationSignal = checksum(command);
command += ";echo \"" + outputTerminationSignal + "\";echo $?\n"

This way when I get the outputTerminationSignal line I can get the exit code and stop reading.

final String line = bufferedReader.readLine();
if (line != null && line.equals(outputTerminationSignal)) {
    final String exitCode = bufferedReader.readLine();
}

Of course this is exploitable and error-prone because the real output in some case may match my generated outputTerminationSignal and the app will stop reading when it shouldn't. I wonder if there is some standard so called "outputTerminationSignal" comming from the output I am not aware of.

Yaroslav Mytkalyk
  • 16,950
  • 10
  • 72
  • 99

2 Answers2

1

Unix doesn't use a special character or symbol to indicate the end of a stream. In java, if you try to read from a stream that's at end-of-file, then you'll get an EOFException.

Having said that, if you're reading from a stream connected to a running program, then you won't get an EOFException just because the other program is idle. You would only get an EOFException if the other program has exited, or if it explicitly closes its output stream (that you are reading from). The situation you describe sounds like the shell is just idle waiting for another command. You won't get an EOF indication from the stream in this case.

You could try getting the shell to print a command prompt when it's waiting for a command, then look for the command prompt as an "end of command" indicator. Shells normally print command prompts only when they're interactive, but you might be able to find a way around that.

If you want to make the shell process exit without sending it the "exit" command, you could try closing the stream that you're using to write to the shell process. The shell should see that as an end-of-file and exit.

Kenster
  • 23,465
  • 21
  • 80
  • 106
  • Printing a command prompt can be mixed with the actual output, if the stdout prints something that has exactly the same chars as the command prompt It can missinterpret the output with the command prompt. Well anyway I got your point. I should print something anyway so I guess the approach I used in a question is the best one you can get for this particular case. The chance of coincidence is very low if I expect md5sum of command plus application name. – Yaroslav Mytkalyk Jan 02 '14 at 14:46
0

You could ask the shell for the PID of the spawned child, and monitor its state

miniBill
  • 1,743
  • 17
  • 41
  • Please provide an example. – Yaroslav Mytkalyk Jan 02 '14 at 12:47
  • http://stackoverflow.com/questions/1908610/how-to-get-pid-of-background-process actually, why do you want to avoid spawning a single process per command? the shell will do that anyway – miniBill Jan 02 '14 at 13:10
  • actually in Android there is a difference because the app will have to query superuser access every time it does something. Plus it's kinda faster to avoid creating new Java Process and opening streams. – Yaroslav Mytkalyk Jan 02 '14 at 13:15
  • ok so I know the PID but now how do I know when it exits in Java? I should start a background thread with monitoring or something? It's a bad idea. – Yaroslav Mytkalyk Jan 02 '14 at 13:21
  • yes, if your objective is doing things as root on android it makes sense to use only one shell. If you had started the subprocesses you could have used `Process.waitFor()`, but since you didn't... http://stackoverflow.com/questions/3991819/java-get-a-process-given-a-pid – miniBill Jan 02 '14 at 18:44