From 08a27094d94bec29a4dfa1fd9acfedebc80e4600 Mon Sep 17 00:00:00 2001 From: David Pursell Date: Tue, 20 Oct 2015 14:19:36 -0700 Subject: [PATCH] adb: fix -Tt options to match ssh. ssh has slightly more sophisticated -Tt options that we want to match. This CL changes -Tt behavior to match ssh so that we allocate a remote PTY in these cases: -T: never. : if stdin is a terminal and user wants an interactive shell. -t: if stdin is a terminal (otherwise print a warning message). -t -t: always. Now this will work as expected: $ adb shell < my_script.sh Also corrects a small unrelated bug with escape sequences so that only a single tilde is accepted for the disconnect sequence. Bug: http://b/24565284 Change-Id: Idab57ac98d81233b45c2613fe64ceb4398add961 --- adb/commandline.cpp | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/adb/commandline.cpp b/adb/commandline.cpp index a915a3359..2632b1f31 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -487,7 +487,11 @@ static void* stdin_read_thread(void* x) { state = 1; break; case '~': - if(state == 1) state++; + if(state == 1) { + state++; + } else { + state = 0; + } break; case '.': if(state == 2) { @@ -1351,15 +1355,20 @@ int adb_commandline(int argc, const char **argv) { // argv[0] is always "shell". --argc; ++argv; - std::string shell_type_arg; + int t_arg_count = 0; while (argc) { if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) { if (!CanUseFeature(features, kFeatureShell2)) { fprintf(stderr, "error: target doesn't support PTY args -Tt\n"); return 1; } - shell_type_arg = (argv[0][1] == 'T') ? kShellServiceArgRaw - : kShellServiceArgPty; + // Like ssh, -t arguments are cumulative so that multiple -t's + // are needed to force a PTY. + if (argv[0][1] == 't') { + ++t_arg_count; + } else { + t_arg_count = -1; + } --argc; ++argv; } else if (!strcmp(argv[0], "-x")) { @@ -1371,6 +1380,33 @@ int adb_commandline(int argc, const char **argv) { } } + std::string shell_type_arg; + if (CanUseFeature(features, kFeatureShell2)) { + if (t_arg_count < 0) { + shell_type_arg = kShellServiceArgRaw; + } else if (t_arg_count == 0) { + // If stdin isn't a TTY, default to a raw shell; this lets + // things like `adb shell < my_script.sh` work as expected. + // Otherwise leave |shell_type_arg| blank which uses PTY for + // interactive shells and raw for non-interactive. + if (!isatty(STDIN_FILENO)) { + shell_type_arg = kShellServiceArgRaw; + } + } else if (t_arg_count == 1) { + // A single -t arg isn't enough to override implicit -T. + if (!isatty(STDIN_FILENO)) { + fprintf(stderr, + "Remote PTY will not be allocated because stdin is not a terminal.\n" + "Use multiple -t options to force remote PTY allocation.\n"); + shell_type_arg = kShellServiceArgRaw; + } else { + shell_type_arg = kShellServiceArgPty; + } + } else { + shell_type_arg = kShellServiceArgPty; + } + } + std::string command; if (argc) { // We don't escape here, just like ssh(1). http://b/20564385.