New Shell.Builder and Shell.Interactive classes
waitForIdle() deadlock

waitForIdle() could be called synchronized, which would prevent the idle
state from occuring
Combine passed environment with system environment
Check some cases of shell termination
ShellOnMainThreadException no longer called if main thread has no Looper
Added ACCESS_SUPERUSER permission
Detect possible malfunction in Shell.SU.available()

It has been reported by a user of the library that in some odd cases the
id call may terminatue the shell. I'm not sure how or why, but this fix
does succesfully work around the problem
New ADT
Fix stackoverflow in backward-compatible Shell.run

It called itself instead of the new method
Fix comment re: usage of blocking calls

Signed-off-by: Jorrit Jongma <git@jongma.org>
Fix a couple of minor typos

Signed-off-by: Jorrit Jongma <git@jongma.org>
Interactive: Fix NPE on unsolicited stdout/stderr

If output is received while command == null (i.e. there is no outstanding
command), the app will crash.  One easy way to reproduce this is to
call Builder.open() and then deny the SU request through the GUI.  The su
UNIX command will print "Permission denied" to stderr and this generates
an exception.

So, let's just discard any output that is printed outside the context
of a valid command.

Signed-off-by: Jorrit Jongma <git@jongma.org>
Interactive: onLine() methods are not thread-safe

The onLine() methods operate on several members of the parent Interactive
class without locking.  The values of command, lastMarkerSTDOUT,
lastMarkerSTDERR, etc. can be changed from background threads and this
occasionally causes a NPE (especially when debugging).

Add locking to prevent this.

Signed-off-by: Jorrit Jongma <git@jongma.org>
Interactive: Add new watchdog timeout feature

Interactive sessions can fail in a number of different ways, including:

1) Superuser request is denied, times out, or fails; "su" exits without
starting our shell.  Maybe the user mis-clicked, or maybe he just didn't
notice the prompt until it was too late.

2) The shell crashes / terminates / runs out of memory / etc, e.g. the
caller sends an "exit" command and so libsuperuser never sees its markers
on stdout/stderr.

3) A legitimate command blocks or hangs ("cat", "sleep 10000"), or an
incomplete command gets the shell stuck ("if").

We can't detect or prevent most of these, but at least we can make sure
the client gets a callback after N seconds if his command gets stuck.  We
can also guarantee that he will either see a timeout callback OR a
"command finished" callback, not both.

Note that watchdogTimeout is not declared as final, because we may want
to use a longer timeout for the initial command (the only command that
can generate an interactive SU prompt).

Signed-off-by: Jorrit Jongma <git@jongma.org>
Move "check shell availability" code into a common function

Signed-off-by: Jorrit Jongma <git@jongma.org>
Interactive: Add new "open-with-callback" feature

This attempts to start a shell process in the background.  Within 60
seconds it will invoke the supplied callback to indicate one of the
following results:

SHELL_RUNNING: success; commands may now be queued
SHELL_EXEC_FAILED: couldn't start the shell (missing su binary?)
SHELL_WRONG_UID: shell is running, but does not report uid 0 (if root)
WATCHDOG_EXIT: timeout
SHELL_DIED: shell exited unexpectedly (user denied SU request?)

Signed-off-by: Jorrit Jongma <git@jongma.org>
Eliminate redundant BuildConfig checks

Debug.log() already checks BuildConfig.DEBUG, so the callers don't need to.

Signed-off-by: Jorrit Jongma <git@jongma.org>
Implement fine-grained logging

Some applications send a large number of commands to the shell in rapid
succession, and the default behavior of logging all commands + output in
debug mode can significantly affect performance and clutter up the logcat
output.  Provide a way for the application to disable the noisiest logs
(commands and output) while retaining sanity checks and error messages.

Signed-off-by: Jorrit Jongma <git@jongma.org>
Fix toUpperCase default locale warnings

toUpperCase() will use the default locale if not instructed otherwise.
This can result in unexpected behavior on non-US devices.

Signed-off-by: Jorrit Jongma <git@jongma.org>
example: Use a scrollable TextView instead of an EditText field

The EditText field pops up the keyboard at inopportune moments.  This
will become a usability problem when we add buttons to the interface.

Signed-off-by: Jorrit Jongma <git@jongma.org>