summaryrefslogtreecommitdiffstats
path: root/adb/services.cpp
diff options
context:
space:
mode:
authorDavid Pursell <dpursell@google.com>2015-08-10 12:52:16 -0700
committerDavid Pursell <dpursell@google.com>2015-08-12 14:16:22 -0700
commitd4093f191b3f23de30479c93be8c684b47505e44 (patch)
treeaf5f1a2181bcbc4ae2f6f23134d90540a88bbcbc /adb/services.cpp
parent317acfb88065f68bc3030a5624a63ba4cfaab414 (diff)
downloadcore-d4093f191b3f23de30479c93be8c684b47505e44.tar.gz
core-d4093f191b3f23de30479c93be8c684b47505e44.tar.bz2
core-d4093f191b3f23de30479c93be8c684b47505e44.zip
adb: Fix PTY logic for non-interactive shells.
Change `adb shell` so that interactive sessions use a PTY but non-interactive do not. This matches `ssh` functionality better and also enables future work to split stdout/stderr for non-interactive sessions. A test to verify this behavior is added to test_device.py with supporting modifications in device.py. Bug: http://b/21215503 Change-Id: Ib4ba40df85f82ddef4e0dd557952271c859d1c7b
Diffstat (limited to 'adb/services.cpp')
-rw-r--r--adb/services.cpp44
1 files changed, 34 insertions, 10 deletions
diff --git a/adb/services.cpp b/adb/services.cpp
index 68545d8bd..255be098b 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -59,6 +59,10 @@ struct stinfo {
void *cookie;
};
+enum class SubprocessType {
+ kPty,
+ kRaw,
+};
void *service_bootstrap_func(void *x)
{
@@ -389,17 +393,27 @@ static void subproc_waiter_service(int fd, void *cookie)
}
}
-static int create_subproc_thread(const char *name, bool pty = false) {
+// Starts a subprocess and spawns a thread to wait for the subprocess to finish
+// and trigger the necessary cleanup.
+//
+// |name| is the command to execute in the subprocess; empty string will start
+// an interactive session.
+// |type| selects between a PTY or raw subprocess.
+//
+// Returns an open file descriptor tied to the subprocess stdin/stdout/stderr.
+static int create_subproc_thread(const char *name, SubprocessType type) {
const char *arg0, *arg1;
- if (name == 0 || *name == 0) {
- arg0 = "-"; arg1 = 0;
+ if (*name == '\0') {
+ arg0 = "-";
+ arg1 = nullptr;
} else {
- arg0 = "-c"; arg1 = name;
+ arg0 = "-c";
+ arg1 = name;
}
pid_t pid = -1;
int ret_fd;
- if (pty) {
+ if (type == SubprocessType::kPty) {
ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
} else {
ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
@@ -466,9 +480,16 @@ int service_to_fd(const char *name)
} else if (!strncmp(name, "jdwp:", 5)) {
ret = create_jdwp_connection_fd(atoi(name+5));
} else if(!strncmp(name, "shell:", 6)) {
- ret = create_subproc_thread(name + 6, true);
+ const char* args = name + 6;
+ if (*args) {
+ // Non-interactive session uses a raw subprocess.
+ ret = create_subproc_thread(args, SubprocessType::kRaw);
+ } else {
+ // Interactive session uses a PTY subprocess.
+ ret = create_subproc_thread(args, SubprocessType::kPty);
+ }
} else if(!strncmp(name, "exec:", 5)) {
- ret = create_subproc_thread(name + 5);
+ ret = create_subproc_thread(name + 5, SubprocessType::kRaw);
} else if(!strncmp(name, "sync:", 5)) {
ret = create_service_thread(file_sync_service, NULL);
} else if(!strncmp(name, "remount:", 8)) {
@@ -482,10 +503,13 @@ int service_to_fd(const char *name)
} else if(!strncmp(name, "unroot:", 7)) {
ret = create_service_thread(restart_unroot_service, NULL);
} else if(!strncmp(name, "backup:", 7)) {
- ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
- (name + 7)).c_str());
+ ret = create_subproc_thread(
+ android::base::StringPrintf("/system/bin/bu backup %s",
+ (name + 7)).c_str(),
+ SubprocessType::kRaw);
} else if(!strncmp(name, "restore:", 8)) {
- ret = create_subproc_thread("/system/bin/bu restore");
+ ret = create_subproc_thread("/system/bin/bu restore",
+ SubprocessType::kRaw);
} else if(!strncmp(name, "tcpip:", 6)) {
int port;
if (sscanf(name + 6, "%d", &port) != 1) {