Merge "Pass $TERM to the device."
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 5113eb8..c13872a 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -595,6 +595,10 @@
     if (!type_arg.empty()) {
         args.push_back(type_arg);
     }
+    const char* terminal_type = getenv("TERM");
+    if (terminal_type != nullptr) {
+        args.push_back(std::string("TERM=") + terminal_type);
+    }
 
     // Shell service string can look like: shell[,arg1,arg2,...]:[command].
     return android::base::StringPrintf("shell%s%s:%s",
@@ -1029,8 +1033,7 @@
         use_shell_protocol = CanUseFeature(features, kFeatureShell2);
     }
 
-    std::string service_string = ShellServiceString(use_shell_protocol, "",
-                                                    command);
+    std::string service_string = ShellServiceString(use_shell_protocol, "", command);
 
     int fd;
     while (true) {
diff --git a/adb/services.cpp b/adb/services.cpp
index 19a6726..41da4b8 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -213,9 +213,11 @@
     // Defaults:
     //   PTY for interactive, raw for non-interactive.
     //   No protocol.
+    //   $TERM set to "dumb".
     SubprocessType type(command.empty() ? SubprocessType::kPty
                                         : SubprocessType::kRaw);
     SubprocessProtocol protocol = SubprocessProtocol::kNone;
+    std::string terminal_type = "dumb";
 
     for (const std::string& arg : android::base::Split(service_args, ",")) {
         if (arg == kShellServiceArgRaw) {
@@ -224,14 +226,15 @@
             type = SubprocessType::kPty;
         } else if (arg == kShellServiceArgShellProtocol) {
             protocol = SubprocessProtocol::kShell;
-        }
-        else if (!arg.empty()) {
-            LOG(ERROR) << "Unsupported shell service arguments: " << args;
-            return -1;
+        } else if (android::base::StartsWith(arg, "TERM=")) {
+            terminal_type = arg.substr(5);
+        } else if (!arg.empty()) {
+            // This is not an error to allow for future expansion.
+            LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
         }
     }
 
-    return StartSubprocess(command.c_str(), type, protocol);
+    return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
 }
 
 #endif  // !ADB_HOST
@@ -308,8 +311,7 @@
     } else if(!strncmp(name, "shell", 5)) {
         ret = ShellService(name + 5, transport);
     } else if(!strncmp(name, "exec:", 5)) {
-        ret = StartSubprocess(name + 5, SubprocessType::kRaw,
-                              SubprocessProtocol::kNone);
+        ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {
@@ -325,9 +327,9 @@
     } else if(!strncmp(name, "backup:", 7)) {
         ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",
                                                           (name + 7)).c_str(),
-                              SubprocessType::kRaw, SubprocessProtocol::kNone);
+                              nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
     } else if(!strncmp(name, "restore:", 8)) {
-        ret = StartSubprocess("/system/bin/bu restore", SubprocessType::kRaw,
+        ret = StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
     } else if(!strncmp(name, "tcpip:", 6)) {
         int port;
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index e3fde26..2e41fe6 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -175,8 +175,8 @@
 
 class Subprocess {
   public:
-    Subprocess(const std::string& command, SubprocessType type,
-               SubprocessProtocol protocol);
+    Subprocess(const std::string& command, const char* terminal_type,
+               SubprocessType type, SubprocessProtocol protocol);
     ~Subprocess();
 
     const std::string& command() const { return command_; }
@@ -207,6 +207,7 @@
     ScopedFd* PassOutput(ScopedFd* sfd, ShellProtocol::Id id);
 
     const std::string command_;
+    const std::string terminal_type_;
     SubprocessType type_;
     SubprocessProtocol protocol_;
     pid_t pid_ = -1;
@@ -220,9 +221,12 @@
     DISALLOW_COPY_AND_ASSIGN(Subprocess);
 };
 
-Subprocess::Subprocess(const std::string& command, SubprocessType type,
-                       SubprocessProtocol protocol)
-        : command_(command), type_(type), protocol_(protocol) {
+Subprocess::Subprocess(const std::string& command, const char* terminal_type,
+                       SubprocessType type, SubprocessProtocol protocol)
+    : command_(command),
+      terminal_type_(terminal_type ? terminal_type : ""),
+      type_(type),
+      protocol_(protocol) {
 }
 
 Subprocess::~Subprocess() {
@@ -290,6 +294,9 @@
             setenv("SHELL", pw->pw_shell, 1);
             setenv("USER", pw->pw_name, 1);
         }
+        if (!terminal_type_.empty()) {
+            setenv("TERM", terminal_type_.c_str(), 1);
+        }
 
         if (is_interactive()) {
             execl(_PATH_BSHELL, _PATH_BSHELL, "-", nullptr);
@@ -644,13 +651,14 @@
 
 }  // namespace
 
-int StartSubprocess(const char *name, SubprocessType type,
-                    SubprocessProtocol protocol) {
-    D("starting %s subprocess (protocol=%s): '%s'",
+int StartSubprocess(const char* name, const char* terminal_type,
+                    SubprocessType type, SubprocessProtocol protocol) {
+    D("starting %s subprocess (protocol=%s, TERM=%s): '%s'",
       type == SubprocessType::kRaw ? "raw" : "PTY",
-      protocol == SubprocessProtocol::kNone ? "none" : "shell", name);
+      protocol == SubprocessProtocol::kNone ? "none" : "shell",
+      terminal_type, name);
 
-    Subprocess* subprocess = new Subprocess(name, type, protocol);
+    Subprocess* subprocess = new Subprocess(name, terminal_type, type, protocol);
     if (!subprocess) {
         LOG(ERROR) << "failed to allocate new subprocess";
         return -1;
diff --git a/adb/shell_service.h b/adb/shell_service.h
index 63c00da..6f8ea9b 100644
--- a/adb/shell_service.h
+++ b/adb/shell_service.h
@@ -141,8 +141,8 @@
 // shell is started, otherwise |name| is executed non-interactively.
 //
 // Returns an open FD connected to the subprocess or -1 on failure.
-int StartSubprocess(const char* name, SubprocessType type,
-                    SubprocessProtocol protocol);
+int StartSubprocess(const char* name, const char* terminal_type,
+                    SubprocessType type, SubprocessProtocol protocol);
 
 #endif  // !ADB_HOST
 
diff --git a/adb/shell_service_test.cpp b/adb/shell_service_test.cpp
index e18f905..a012f3e 100644
--- a/adb/shell_service_test.cpp
+++ b/adb/shell_service_test.cpp
@@ -69,7 +69,7 @@
     SHELL_EXIT_NOTIFY_FD = fd[0];
     shell_exit_receiver_fd_ = fd[1];
 
-    subprocess_fd_ = StartSubprocess(command, type, protocol);
+    subprocess_fd_ = StartSubprocess(command, nullptr, type, protocol);
     ASSERT_TRUE(subprocess_fd_ >= 0);
 }