Loading adb/Android.mk +0 −1 Original line number Diff line number Diff line Loading @@ -102,7 +102,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ adb.c \ backup_service.c \ fdevent.c \ transport.c \ transport_local.c \ Loading adb/adb.h +6 −6 Original line number Diff line number Diff line Loading @@ -326,11 +326,6 @@ int create_jdwp_connection_fd(int jdwp_pid); int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd); #if !ADB_HOST typedef enum { BACKUP, RESTORE } BackupOperation; int backup_service(BackupOperation operation, char* args); void framebuffer_service(int fd, void *cookie); void remount_service(int fd, void *cookie); #endif Loading Loading @@ -418,7 +413,7 @@ void adb_qemu_trace(const char* fmt, ...); # define D(...) ((void)0) # define DR(...) ((void)0) # define ADB_TRACING 0 #endif #endif /* ADB_TRACE */ #if !DEBUG_PACKETS Loading Loading @@ -476,6 +471,11 @@ int connection_state(atransport *t); extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; typedef enum { SUBPROC_PTY = 0, SUBPROC_RAW = 1, } subproc_mode; #define CHUNK_SIZE (64*1024) #if !ADB_HOST Loading adb/backup_service.cdeleted 100644 → 0 +0 −152 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <unistd.h> #include <stdio.h> #include "sysdeps.h" #define TRACE_TAG TRACE_ADB #include "adb.h" typedef struct { pid_t pid; int fd; } backup_harvest_params; // socketpair but do *not* mark as close_on_exec static int backup_socketpair(int sv[2]) { int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); if (rc < 0) return -1; return 0; } // harvest the child process then close the read end of the socketpair static void* backup_child_waiter(void* args) { int status; backup_harvest_params* params = (backup_harvest_params*) args; waitpid(params->pid, &status, 0); adb_close(params->fd); free(params); return NULL; } /* returns the data socket passing the backup data here for forwarding */ int backup_service(BackupOperation op, char* args) { pid_t pid; int s[2]; char* operation; // Command string depends on our invocation if (op == BACKUP) { operation = "backup"; } else { operation = "restore"; } D("backup_service(%s, %s)\n", operation, args); // set up the pipe from the subprocess to here // parent will read s[0]; child will write s[1] if (backup_socketpair(s)) { D("can't create backup/restore socketpair\n"); fprintf(stderr, "unable to create backup/restore socketpair\n"); return -1; } D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]); close_on_exec(s[0]); // only the side we hold on to // spin off the child process to run the backup command pid = fork(); if (pid < 0) { // failure D("can't fork for %s\n", operation); fprintf(stderr, "unable to fork for %s\n", operation); adb_close(s[0]); adb_close(s[1]); return -1; } // Great, we're off and running. if (pid == 0) { // child -- actually run the backup here char* p; int argc; char portnum[16]; char** bu_args; // fixed args: [0] is 'bu', [1] is the port number, [2] is the 'operation' string argc = 3; for (p = (char*)args; p && *p; ) { argc++; while (*p && *p != ':') p++; if (*p == ':') p++; } bu_args = (char**) alloca(argc*sizeof(char*) + 1); // run through again to build the argv array argc = 0; bu_args[argc++] = "bu"; snprintf(portnum, sizeof(portnum), "%d", s[1]); bu_args[argc++] = portnum; bu_args[argc++] = operation; for (p = (char*)args; p && *p; ) { bu_args[argc++] = p; while (*p && *p != ':') p++; if (*p == ':') { *p = 0; p++; } } bu_args[argc] = NULL; // Close the half of the socket that we don't care about, route 'bu's console // to the output socket, and off we go adb_close(s[0]); // off we go execvp("/system/bin/bu", (char * const *)bu_args); // oops error - close up shop and go home fprintf(stderr, "Unable to exec 'bu', bailing\n"); exit(-1); } else { adb_thread_t t; backup_harvest_params* params; // parent, i.e. adbd -- close the sending half of the socket D("fork() returned pid %d\n", pid); adb_close(s[1]); // spin a thread to harvest the child process params = (backup_harvest_params*) malloc(sizeof(backup_harvest_params)); params->pid = pid; params->fd = s[0]; if (adb_thread_create(&t, backup_child_waiter, params)) { adb_close(s[0]); free(params); D("Unable to create child harvester\n"); return -1; } } // we'll be reading from s[0] as the data is sent by the child process return s[0]; } adb/commandline.c +57 −15 Original line number Diff line number Diff line Loading @@ -287,8 +287,17 @@ static void copy_to_file(int inFd, int outFd) { long total = 0; D("copy_to_file(%d -> %d)\n", inFd, outFd); #ifdef HAVE_TERMIO_H if (inFd == STDIN_FILENO) { stdin_raw_init(STDIN_FILENO); } #endif for (;;) { if (inFd == STDIN_FILENO) { len = unix_read(inFd, buf, BUFSIZE); } else { len = adb_read(inFd, buf, BUFSIZE); } if (len == 0) { D("copy_to_file() : read 0 bytes; exiting\n"); break; Loading @@ -301,9 +310,19 @@ static void copy_to_file(int inFd, int outFd) { D("copy_to_file() : error %d\n", errno); break; } if (outFd == STDOUT_FILENO) { fwrite(buf, 1, len, stdout); fflush(stdout); } else { adb_write(outFd, buf, len); } total += len; } #ifdef HAVE_TERMIO_H if (inFd == STDIN_FILENO) { stdin_raw_restore(STDIN_FILENO); } #endif D("copy_to_file() finished after %lu bytes\n", total); free(buf); } Loading Loading @@ -940,7 +959,6 @@ static const char *find_product_out_path(const char *hint) return path_buf; } static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2, int *show_progress, int *copy_attrs) { *show_progress = 0; Loading Loading @@ -977,7 +995,6 @@ int adb_commandline(int argc, char **argv) int is_server = 0; int persist = 0; int r; int quote; transport_type ttype = kTransportAny; char* serial = NULL; char* server_port_str = NULL; Loading Loading @@ -1198,19 +1215,14 @@ top: return r; } snprintf(buf, sizeof buf, "shell:%s", argv[1]); snprintf(buf, sizeof(buf), "shell:%s", argv[1]); argc -= 2; argv += 2; while (argc-- > 0) { strcat(buf, " "); /* quote empty strings and strings with spaces */ quote = (**argv == 0 || strchr(*argv, ' ')); if (quote) strcat(buf, "\""); strcat(buf, *argv++); if (quote) strcat(buf, "\""); char *quoted = dupAndQuote(*argv++); strncat(buf, " ", sizeof(buf) - 1); strncat(buf, quoted, sizeof(buf) - 1); free(quoted); } for(;;) { Loading Loading @@ -1242,6 +1254,36 @@ top: } } if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) { int exec_in = !strcmp(argv[0], "exec-in"); int fd; snprintf(buf, sizeof buf, "exec:%s", argv[1]); argc -= 2; argv += 2; while (argc-- > 0) { char *quoted = dupAndQuote(*argv++); strncat(buf, " ", sizeof(buf) - 1); strncat(buf, quoted, sizeof(buf) - 1); free(quoted); } fd = adb_connect(buf); if (fd < 0) { fprintf(stderr, "error: %s\n", adb_error()); return -1; } if (exec_in) { copy_to_file(STDIN_FILENO, fd); } else { copy_to_file(fd, STDOUT_FILENO); } adb_close(fd); return 0; } if(!strcmp(argv[0], "kill-server")) { int fd; fd = _adb_connect("host:kill"); Loading adb/services.c +108 −44 Original line number Diff line number Diff line Loading @@ -184,11 +184,26 @@ 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 adjustment to prevent killing int fd = adb_open("/proc/self/oom_adj", O_WRONLY); if (fd >= 0) { adb_write(fd, "0", 1); adb_close(fd); } else { D("adb: unable to update oom_adj\n"); } } static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) { D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); #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); 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; Loading Loading @@ -216,43 +231,70 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 } if (*pid == 0) { int pts; init_subproc_child(); setsid(); pts = unix_open(devname, O_RDWR); int pts = unix_open(devname, O_RDWR); 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); execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { D("adb: unable to open %s\n", text); return ptm; } #endif /* !HAVE_WIN32_PROC */ } 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); #ifdef HAVE_WIN32_PROC fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); return -1; #else /* !HAVE_WIN32_PROC */ // 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(); // Only hook up stdin/stdout; drop stderr dup2(sv[1], STDIN_FILENO); dup2(sv[1], STDOUT_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 { // 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; adb_close(sv[1]); return sv[0]; } #endif /* !HAVE_WIN32_PROC */ } Loading Loading @@ -296,18 +338,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; } D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); 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_subproc ret_fd=%d pid=%d\n", ret_fd, pid); sti = malloc(sizeof(stinfo)); if(sti == 0) fatal("cannot allocate stinfo"); Loading @@ -318,7 +374,7 @@ static int create_subproc_thread(const char *name) 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; } Loading Loading @@ -367,27 +423,35 @@ int service_to_fd(const char *name) } 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); 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) { Loading Loading
adb/Android.mk +0 −1 Original line number Diff line number Diff line Loading @@ -102,7 +102,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ adb.c \ backup_service.c \ fdevent.c \ transport.c \ transport_local.c \ Loading
adb/adb.h +6 −6 Original line number Diff line number Diff line Loading @@ -326,11 +326,6 @@ int create_jdwp_connection_fd(int jdwp_pid); int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd); #if !ADB_HOST typedef enum { BACKUP, RESTORE } BackupOperation; int backup_service(BackupOperation operation, char* args); void framebuffer_service(int fd, void *cookie); void remount_service(int fd, void *cookie); #endif Loading Loading @@ -418,7 +413,7 @@ void adb_qemu_trace(const char* fmt, ...); # define D(...) ((void)0) # define DR(...) ((void)0) # define ADB_TRACING 0 #endif #endif /* ADB_TRACE */ #if !DEBUG_PACKETS Loading Loading @@ -476,6 +471,11 @@ int connection_state(atransport *t); extern int HOST; extern int SHELL_EXIT_NOTIFY_FD; typedef enum { SUBPROC_PTY = 0, SUBPROC_RAW = 1, } subproc_mode; #define CHUNK_SIZE (64*1024) #if !ADB_HOST Loading
adb/backup_service.cdeleted 100644 → 0 +0 −152 Original line number Diff line number Diff line /* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <unistd.h> #include <stdio.h> #include "sysdeps.h" #define TRACE_TAG TRACE_ADB #include "adb.h" typedef struct { pid_t pid; int fd; } backup_harvest_params; // socketpair but do *not* mark as close_on_exec static int backup_socketpair(int sv[2]) { int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); if (rc < 0) return -1; return 0; } // harvest the child process then close the read end of the socketpair static void* backup_child_waiter(void* args) { int status; backup_harvest_params* params = (backup_harvest_params*) args; waitpid(params->pid, &status, 0); adb_close(params->fd); free(params); return NULL; } /* returns the data socket passing the backup data here for forwarding */ int backup_service(BackupOperation op, char* args) { pid_t pid; int s[2]; char* operation; // Command string depends on our invocation if (op == BACKUP) { operation = "backup"; } else { operation = "restore"; } D("backup_service(%s, %s)\n", operation, args); // set up the pipe from the subprocess to here // parent will read s[0]; child will write s[1] if (backup_socketpair(s)) { D("can't create backup/restore socketpair\n"); fprintf(stderr, "unable to create backup/restore socketpair\n"); return -1; } D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]); close_on_exec(s[0]); // only the side we hold on to // spin off the child process to run the backup command pid = fork(); if (pid < 0) { // failure D("can't fork for %s\n", operation); fprintf(stderr, "unable to fork for %s\n", operation); adb_close(s[0]); adb_close(s[1]); return -1; } // Great, we're off and running. if (pid == 0) { // child -- actually run the backup here char* p; int argc; char portnum[16]; char** bu_args; // fixed args: [0] is 'bu', [1] is the port number, [2] is the 'operation' string argc = 3; for (p = (char*)args; p && *p; ) { argc++; while (*p && *p != ':') p++; if (*p == ':') p++; } bu_args = (char**) alloca(argc*sizeof(char*) + 1); // run through again to build the argv array argc = 0; bu_args[argc++] = "bu"; snprintf(portnum, sizeof(portnum), "%d", s[1]); bu_args[argc++] = portnum; bu_args[argc++] = operation; for (p = (char*)args; p && *p; ) { bu_args[argc++] = p; while (*p && *p != ':') p++; if (*p == ':') { *p = 0; p++; } } bu_args[argc] = NULL; // Close the half of the socket that we don't care about, route 'bu's console // to the output socket, and off we go adb_close(s[0]); // off we go execvp("/system/bin/bu", (char * const *)bu_args); // oops error - close up shop and go home fprintf(stderr, "Unable to exec 'bu', bailing\n"); exit(-1); } else { adb_thread_t t; backup_harvest_params* params; // parent, i.e. adbd -- close the sending half of the socket D("fork() returned pid %d\n", pid); adb_close(s[1]); // spin a thread to harvest the child process params = (backup_harvest_params*) malloc(sizeof(backup_harvest_params)); params->pid = pid; params->fd = s[0]; if (adb_thread_create(&t, backup_child_waiter, params)) { adb_close(s[0]); free(params); D("Unable to create child harvester\n"); return -1; } } // we'll be reading from s[0] as the data is sent by the child process return s[0]; }
adb/commandline.c +57 −15 Original line number Diff line number Diff line Loading @@ -287,8 +287,17 @@ static void copy_to_file(int inFd, int outFd) { long total = 0; D("copy_to_file(%d -> %d)\n", inFd, outFd); #ifdef HAVE_TERMIO_H if (inFd == STDIN_FILENO) { stdin_raw_init(STDIN_FILENO); } #endif for (;;) { if (inFd == STDIN_FILENO) { len = unix_read(inFd, buf, BUFSIZE); } else { len = adb_read(inFd, buf, BUFSIZE); } if (len == 0) { D("copy_to_file() : read 0 bytes; exiting\n"); break; Loading @@ -301,9 +310,19 @@ static void copy_to_file(int inFd, int outFd) { D("copy_to_file() : error %d\n", errno); break; } if (outFd == STDOUT_FILENO) { fwrite(buf, 1, len, stdout); fflush(stdout); } else { adb_write(outFd, buf, len); } total += len; } #ifdef HAVE_TERMIO_H if (inFd == STDIN_FILENO) { stdin_raw_restore(STDIN_FILENO); } #endif D("copy_to_file() finished after %lu bytes\n", total); free(buf); } Loading Loading @@ -940,7 +959,6 @@ static const char *find_product_out_path(const char *hint) return path_buf; } static void parse_push_pull_args(char **arg, int narg, char const **path1, char const **path2, int *show_progress, int *copy_attrs) { *show_progress = 0; Loading Loading @@ -977,7 +995,6 @@ int adb_commandline(int argc, char **argv) int is_server = 0; int persist = 0; int r; int quote; transport_type ttype = kTransportAny; char* serial = NULL; char* server_port_str = NULL; Loading Loading @@ -1198,19 +1215,14 @@ top: return r; } snprintf(buf, sizeof buf, "shell:%s", argv[1]); snprintf(buf, sizeof(buf), "shell:%s", argv[1]); argc -= 2; argv += 2; while (argc-- > 0) { strcat(buf, " "); /* quote empty strings and strings with spaces */ quote = (**argv == 0 || strchr(*argv, ' ')); if (quote) strcat(buf, "\""); strcat(buf, *argv++); if (quote) strcat(buf, "\""); char *quoted = dupAndQuote(*argv++); strncat(buf, " ", sizeof(buf) - 1); strncat(buf, quoted, sizeof(buf) - 1); free(quoted); } for(;;) { Loading Loading @@ -1242,6 +1254,36 @@ top: } } if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) { int exec_in = !strcmp(argv[0], "exec-in"); int fd; snprintf(buf, sizeof buf, "exec:%s", argv[1]); argc -= 2; argv += 2; while (argc-- > 0) { char *quoted = dupAndQuote(*argv++); strncat(buf, " ", sizeof(buf) - 1); strncat(buf, quoted, sizeof(buf) - 1); free(quoted); } fd = adb_connect(buf); if (fd < 0) { fprintf(stderr, "error: %s\n", adb_error()); return -1; } if (exec_in) { copy_to_file(STDIN_FILENO, fd); } else { copy_to_file(fd, STDOUT_FILENO); } adb_close(fd); return 0; } if(!strcmp(argv[0], "kill-server")) { int fd; fd = _adb_connect("host:kill"); Loading
adb/services.c +108 −44 Original line number Diff line number Diff line Loading @@ -184,11 +184,26 @@ 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 adjustment to prevent killing int fd = adb_open("/proc/self/oom_adj", O_WRONLY); if (fd >= 0) { adb_write(fd, "0", 1); adb_close(fd); } else { D("adb: unable to update oom_adj\n"); } } static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) { D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); #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); 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; Loading Loading @@ -216,43 +231,70 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1 } if (*pid == 0) { int pts; init_subproc_child(); setsid(); pts = unix_open(devname, O_RDWR); int pts = unix_open(devname, O_RDWR); 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); execl(cmd, cmd, arg0, arg1, NULL); fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", cmd, strerror(errno), errno); exit(-1); } else { D("adb: unable to open %s\n", text); return ptm; } #endif /* !HAVE_WIN32_PROC */ } 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); #ifdef HAVE_WIN32_PROC fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); return -1; #else /* !HAVE_WIN32_PROC */ // 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(); // Only hook up stdin/stdout; drop stderr dup2(sv[1], STDIN_FILENO); dup2(sv[1], STDOUT_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 { // 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; adb_close(sv[1]); return sv[0]; } #endif /* !HAVE_WIN32_PROC */ } Loading Loading @@ -296,18 +338,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; } D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); 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_subproc ret_fd=%d pid=%d\n", ret_fd, pid); sti = malloc(sizeof(stinfo)); if(sti == 0) fatal("cannot allocate stinfo"); Loading @@ -318,7 +374,7 @@ static int create_subproc_thread(const char *name) 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; } Loading Loading @@ -367,27 +423,35 @@ int service_to_fd(const char *name) } 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); 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) { Loading