Merge change 9362

* changes:
  Change assignment code gen to use leaR0 .. storeR0ToTOS.
diff --git a/adb/services.c b/adb/services.c
index 0a5edcf..78d092b 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -31,6 +31,8 @@
 #    include <netinet/in.h>
 #    include <netdb.h>
 #  endif
+#else
+#include <sys/poll.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -196,12 +198,9 @@
     return s[0];
 }
 
+#if !ADB_HOST
 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
 {
-#ifdef HAVE_WIN32_PROC
-	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
-	return -1;
-#else /* !HAVE_WIN32_PROC */
     char *devname;
     int ptm;
     pid_t pid;
@@ -244,7 +243,6 @@
                 cmd, strerror(errno), errno);
         exit(-1);
     } else {
-#if !ADB_HOST
         // set child's OOM adjustment to zero
         char text[64];
         snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -255,11 +253,11 @@
         } else {
            D("adb: unable to open %s\n", text);
         }
-#endif
+
         return ptm;
     }
-#endif /* !HAVE_WIN32_PROC */
 }
+#endif /* !ADB_HOST */
 
 #if ADB_HOST
 #define SHELL_COMMAND "/bin/sh"
@@ -267,6 +265,76 @@
 #define SHELL_COMMAND "/system/bin/sh"
 #endif
 
+#if !ADB_HOST
+static void shell_service(int s, void *command)
+{
+    char    buffer[MAX_PAYLOAD];
+    char    buffer2[MAX_PAYLOAD];
+    struct pollfd ufds[2];
+    int     fd, ret = 0;
+    unsigned count = 0;
+    char** args = (char **)command;
+    fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);
+
+    while (1) {
+        while (count < sizeof(buffer)) {
+            ufds[0].fd = fd;
+            ufds[0].events = POLLIN | POLLHUP;
+            ufds[0].revents = 0;
+            ufds[1].fd = s;
+            ufds[1].events = POLLIN | POLLHUP;
+            ufds[1].revents = 0;
+            // use a 100ms timeout so we don't block indefinitely with our
+            // buffer partially filled.
+            ret = poll(ufds, 2, 100);
+            if (ret <= 0) {
+                D("poll returned %d\n", ret);
+                // file has closed or we timed out
+                // set ret to 1 so we don't exit the outer loop
+                ret = 1;
+                break;
+            }
+
+            if (ufds[0].revents & POLLIN) {
+                ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
+                D("read fd ret: %d, count: %d\n", ret, count);
+                if (ret > 0)
+                    count += ret;
+                else
+                    break;
+            }
+            if (ufds[1].revents & POLLIN) {
+                ret = adb_read(s, buffer2, sizeof(buffer2));
+                D("read s ret: %d\n", ret);
+                if (ret > 0)
+                    adb_write(fd, buffer2, ret);
+                else
+                    break;
+            }
+
+            if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
+                // set flag to exit after flushing the buffer
+                ret = -1;
+                break;
+            }
+        }
+
+        D("writing: %d\n", count);
+        if (count > 0) {
+            adb_write(s, buffer, count);
+            count = 0;
+        }
+        if (ret <= 0)
+            break;
+    }
+
+    D("shell_service done\n");
+
+    adb_close(fd);
+    adb_close(s);
+}
+#endif // !ADB_HOST
+
 int service_to_fd(const char *name)
 {
     int ret = -1;
@@ -317,14 +385,16 @@
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if (!strncmp(name, "log:", 4)) {
         ret = create_service_thread(log_service, get_log_file_path(name + 4));
-#endif
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
+        const char* args[2];
         if(name[6]) {
-            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
+            args[0] = "-c";
+            args[1] = name + 6;
         } else {
-            ret = create_subprocess(SHELL_COMMAND, "-", 0);
+            args[0] = "-";
+            args[1] = 0;
         }
-#if !ADB_HOST
+        ret = create_service_thread(shell_service, (void *)args);
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {