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
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index a915a33..2632b1f 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -487,7 +487,11 @@
                     state = 1;
                     break;
                 case '~':
-                    if(state == 1) state++;
+                    if(state == 1) {
+                        state++;
+                    } else {
+                        state = 0;
+                    }
                     break;
                 case '.':
                     if(state == 2) {
@@ -1351,15 +1355,20 @@
         // 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 @@
             }
         }
 
+        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.