标 题: adb 源码分析 adb shell篇
作 者: Y4ng
时 间: 2012-11-01 14:05:30 星期五
链 接: http://www.cnblogs.com/Y4ng/p/adb_shell.html
/* int adb_commandline(int argc, char **argv) */ if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) .................. if(argc < 2) { D("starting interactive shell\n"); r = interactive_shell(); if (h) { printf("\x1b[0m"); fflush(stdout); } return r; }
int interactive_shell(void) { adb_thread_t thr; int fdi, fd; int *fds; fd = adb_connect("shell:"); if(fd < 0) { fprintf(stderr,"error: %s\n", adb_error()); return 1; } fdi = 0; //dup(0); fds = (int *)malloc(sizeof(int) * 2); fds[0] = fd; fds[1] = fdi; #ifdef HAVE_TERMIO_H stdin_raw_init(fdi); #endif adb_thread_create(&thr, stdin_read_thread, fds); /* 开启一个从控制台接收命令的线程 */ read_and_dump(fd); /* 主态模式读取由adb服务端发送过来的数据 */ #ifdef HAVE_TERMIO_H stdin_raw_restore(fdi); #endif return 0; }
static void *stdin_read_thread(void *x) { int fd, fdi; unsigned char buf[1024]; int r, n; int state = 0; int *fds = (int*) x; fd = fds[0]; fdi = fds[1]; free(fds); for(;;) { /* fdi is really the client's stdin, so use read, not adb_read here */ D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi); r = unix_read(fdi, buf, 1024); /*控制台命令读取*/ D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi); if(r == 0) break; if(r < 0) { if(errno == EINTR) continue; break; } for(n = 0; n < r; n++){ switch(buf[n]) { case '\n': state = 1; break; case '\r': state = 1; break; case '~': if(state == 1) state++; break; case '.': if(state == 2) { fprintf(stderr,"\n* disconnect *\n"); #ifdef HAVE_TERMIO_H stdin_raw_restore(fdi); #endif exit(0); } default: state = 0; } } r = adb_write(fd, buf, r); /* 将收到的命令发送到adb服务端 */ if(r <= 0) { break; } } return 0; }
static void read_and_dump(int fd) { char buf[4096]; int len; while(fd >= 0) { D("read_and_dump(): pre adb_read(fd=%d)\n", fd); len = adb_read(fd, buf, 4096); /* shell: 模式下 adb客户端的recv 会一直等待数据*/ D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len); if(len == 0) { /*直到adb服务端shutdown,会收到一个长度为 0 的数据才会退出循环, 优雅的退出*/ break; } if(len < 0) { if(errno == EINTR) continue; break; } fwrite(buf, 1, len, stdout); fflush(stdout); } }