diff --git a/adb/services.c b/adb/services.c index 0a5edcf4b..78d092b83 100644 --- a/adb/services.c +++ b/adb/services.c @@ -31,6 +31,8 @@ # include # include # endif +#else +#include #endif typedef struct stinfo stinfo; @@ -196,12 +198,9 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) 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 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 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 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 } 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 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 #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 @@ int service_to_fd(const char *name) 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)) {