diff options
Diffstat (limited to 'adb/services.c')
-rw-r--r-- | adb/services.c | 207 |
1 files changed, 139 insertions, 68 deletions
diff --git a/adb/services.c b/adb/services.c index 5b63a43..bcfc163 100644 --- a/adb/services.c +++ b/adb/services.c @@ -116,23 +116,10 @@ void reboot_service(int fd, void *arg) { char buf[100]; char property_val[PROPERTY_VALUE_MAX]; - int pid, ret; + int ret; sync(); - /* Attempt to unmount the SD card first. - * No need to bother checking for errors. - */ - pid = fork(); - if (pid == 0) { - /* ask vdc to unmount it */ - execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount", - getenv("EXTERNAL_STORAGE"), "force", NULL); - } else if (pid > 0) { - /* wait until vdc succeeds or fails */ - waitpid(pid, &ret, 0); - } - ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg); if (ret >= (int) sizeof(property_val)) { snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret); @@ -154,6 +141,17 @@ cleanup: adb_close(fd); } +void reverse_service(int fd, void* arg) +{ + const char* command = arg; + + if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) { + sendfailmsg(fd, "not a reverse forwarding command"); + } + free(arg); + adb_close(fd); +} + #endif static int create_service_thread(void (*func)(int, void *), void *cookie) @@ -186,25 +184,38 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) } #if !ADB_HOST -static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) + +static void init_subproc_child() +{ + setsid(); + + // Set OOM score adjustment to prevent killing + int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC); + if (fd >= 0) { + adb_write(fd, "0", 1); + adb_close(fd); + } else { + D("adb: unable to update oom_score_adj\n"); + } +} + +static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) { -#ifdef HAVE_WIN32_PROC - D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); - fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); + D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); +#if defined(_WIN32) + fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); return -1; -#else /* !HAVE_WIN32_PROC */ - char *devname; +#else int ptm; - ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); + ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY); if(ptm < 0){ printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); return -1; } - fcntl(ptm, F_SETFD, FD_CLOEXEC); - if(grantpt(ptm) || unlockpt(ptm) || - ((devname = (char*) ptsname(ptm)) == 0)){ + char devname[64]; + if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) { printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); adb_close(ptm); return -1; @@ -217,46 +228,74 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 return -1; } - if(*pid == 0){ - int pts; + if (*pid == 0) { + init_subproc_child(); - setsid(); - - pts = unix_open(devname, O_RDWR); - if(pts < 0) { + int pts = unix_open(devname, O_RDWR | O_CLOEXEC); + if (pts < 0) { fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); exit(-1); } - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); + dup2(pts, STDIN_FILENO); + dup2(pts, STDOUT_FILENO); + dup2(pts, STDERR_FILENO); adb_close(pts); adb_close(ptm); - // set OOM adjustment to zero - char text[64]; - snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); - int fd = adb_open(text, O_WRONLY); - if (fd >= 0) { - adb_write(fd, "0", 1); - adb_close(fd); - } else { - D("adb: unable to open %s\n", text); - } execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { - // Don't set child's OOM adjustment to zero. - // Let the child do it itself, as sometimes the parent starts - // running before the child has a /proc/pid/oom_adj. - // """adb: unable to open /proc/644/oom_adj""" seen in some logs. return ptm; } -#endif /* !HAVE_WIN32_PROC */ +#endif /* !defined(_WIN32) */ +} + +static int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) +{ + D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); +#if defined(_WIN32) + fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); + return -1; +#else + + // 0 is parent socket, 1 is child socket + int sv[2]; + if (unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { + printf("[ cannot create socket pair - %s ]\n", strerror(errno)); + return -1; + } + + *pid = fork(); + if (*pid < 0) { + printf("- fork failed: %s -\n", strerror(errno)); + adb_close(sv[0]); + adb_close(sv[1]); + return -1; + } + + if (*pid == 0) { + adb_close(sv[0]); + init_subproc_child(); + + dup2(sv[1], STDIN_FILENO); + dup2(sv[1], STDOUT_FILENO); + dup2(sv[1], STDERR_FILENO); + + adb_close(sv[1]); + + execl(cmd, cmd, arg0, arg1, NULL); + fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", + cmd, strerror(errno), errno); + exit(-1); + } else { + adb_close(sv[1]); + return sv[0]; + } +#endif /* !defined(_WIN32) */ } #endif /* !ABD_HOST */ @@ -298,18 +337,32 @@ static void subproc_waiter_service(int fd, void *cookie) } } -static int create_subproc_thread(const char *name) +static int create_subproc_thread(const char *name, const subproc_mode mode) { stinfo *sti; adb_thread_t t; int ret_fd; - pid_t pid; - if(name) { - ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid); + pid_t pid = -1; + + const char *arg0, *arg1; + if (name == 0 || *name == 0) { + arg0 = "-"; arg1 = 0; } else { - ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid); + arg0 = "-c"; arg1 = name; + } + + switch (mode) { + case SUBPROC_PTY: + ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid); + break; + case SUBPROC_RAW: + ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid); + break; + default: + fprintf(stderr, "invalid subproc_mode %d\n", mode); + return -1; } - D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); + D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid); sti = malloc(sizeof(stinfo)); if(sti == 0) fatal("cannot allocate stinfo"); @@ -317,14 +370,14 @@ static int create_subproc_thread(const char *name) sti->cookie = (void*) (uintptr_t) pid; sti->fd = ret_fd; - if(adb_thread_create( &t, service_bootstrap_func, sti)){ + if (adb_thread_create(&t, service_bootstrap_func, sti)) { free(sti); adb_close(ret_fd); - printf("cannot create service thread\n"); + fprintf(stderr, "cannot create service thread\n"); return -1; } - D("service thread started, fd=%d pid=%d\n",ret_fd, pid); + D("service thread started, fd=%d pid=%d\n", ret_fd, pid); return ret_fd; } #endif @@ -363,33 +416,41 @@ int service_to_fd(const char *name) #endif #if !ADB_HOST } else if(!strncmp("dev:", name, 4)) { - ret = unix_open(name + 4, O_RDWR); + ret = unix_open(name + 4, O_RDWR | O_CLOEXEC); } else if(!strncmp(name, "framebuffer:", 12)) { ret = create_service_thread(framebuffer_service, 0); } else if (!strncmp(name, "jdwp:", 5)) { ret = create_jdwp_connection_fd(atoi(name+5)); } else if(!HOST && !strncmp(name, "shell:", 6)) { - if(name[6]) { - ret = create_subproc_thread(name + 6); - } else { - ret = create_subproc_thread(0); - } + ret = create_subproc_thread(name + 6, SUBPROC_PTY); + } else if(!HOST && !strncmp(name, "exec:", 5)) { + ret = create_subproc_thread(name + 5, SUBPROC_RAW); } else if(!strncmp(name, "sync:", 5)) { ret = create_service_thread(file_sync_service, NULL); } else if(!strncmp(name, "remount:", 8)) { ret = create_service_thread(remount_service, NULL); } else if(!strncmp(name, "reboot:", 7)) { void* arg = strdup(name + 7); - if(arg == 0) return -1; + if (arg == NULL) return -1; ret = create_service_thread(reboot_service, arg); } else if(!strncmp(name, "root:", 5)) { ret = create_service_thread(restart_root_service, NULL); } else if(!strncmp(name, "backup:", 7)) { - char* arg = strdup(name+7); + char* arg = strdup(name + 7); if (arg == NULL) return -1; - ret = backup_service(BACKUP, arg); + char* c = arg; + for (; *c != '\0'; c++) { + if (*c == ':') + *c = ' '; + } + char* cmd; + if (asprintf(&cmd, "/system/bin/bu backup %s", arg) != -1) { + ret = create_subproc_thread(cmd, SUBPROC_RAW); + free(cmd); + } + free(arg); } else if(!strncmp(name, "restore:", 8)) { - ret = backup_service(RESTORE, NULL); + ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW); } else if(!strncmp(name, "tcpip:", 6)) { int port; if (sscanf(name + 6, "%d", &port) == 0) { @@ -398,6 +459,16 @@ int service_to_fd(const char *name) ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port); } else if(!strncmp(name, "usb:", 4)) { ret = create_service_thread(restart_usb_service, NULL); + } else if (!strncmp(name, "reverse:", 8)) { + char* cookie = strdup(name + 8); + if (cookie == NULL) { + ret = -1; + } else { + ret = create_service_thread(reverse_service, cookie); + if (ret < 0) { + free(cookie); + } + } #endif } if (ret >= 0) { @@ -460,7 +531,7 @@ static void connect_device(char* host, char* buffer, int buffer_size) snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); - fd = socket_network_client(hostbuf, port, SOCK_STREAM); + fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10); if (fd < 0) { snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); return; |