commandline.c revision df3fb65e983bcad35e71ff28b70e774fafabbffc
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <string.h> 20#include <errno.h> 21#include <unistd.h> 22#include <limits.h> 23#include <stdarg.h> 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <ctype.h> 27#include <assert.h> 28 29#include "sysdeps.h" 30 31#ifdef HAVE_TERMIO_H 32#include <termios.h> 33#endif 34 35#define TRACE_TAG TRACE_ADB 36#include "adb.h" 37#include "adb_client.h" 38#include "file_sync_service.h" 39 40#ifdef SH_HISTORY 41#include "shlist.h" 42#include "history.h" 43#endif 44 45enum { 46 IGNORE_DATA, 47 WIPE_DATA, 48 FLASH_DATA 49}; 50 51static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); 52 53void get_my_path(char s[PATH_MAX]); 54int find_sync_dirs(const char *srcarg, 55 char **android_srcdir_out, char **data_srcdir_out); 56int install_app(transport_type transport, char* serial, int argc, char** argv); 57int uninstall_app(transport_type transport, char* serial, int argc, char** argv); 58 59static const char *gProductOutPath = NULL; 60 61static char *product_file(const char *extra) 62{ 63 int n; 64 char *x; 65 66 if (gProductOutPath == NULL) { 67 fprintf(stderr, "adb: Product directory not specified; " 68 "use -p or define ANDROID_PRODUCT_OUT\n"); 69 exit(1); 70 } 71 72 n = strlen(gProductOutPath) + strlen(extra) + 2; 73 x = malloc(n); 74 if (x == 0) { 75 fprintf(stderr, "adb: Out of memory (product_file())\n"); 76 exit(1); 77 } 78 79 snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra); 80 return x; 81} 82 83void version(FILE * out) { 84 fprintf(out, "Android Debug Bridge version %d.%d.%d\n", 85 ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION); 86} 87 88void help() 89{ 90 version(stderr); 91 92 fprintf(stderr, 93 "\n" 94 " -d - directs command to the only connected USB device\n" 95 " returns an error if more than one USB device is present.\n" 96 " -e - directs command to the only running emulator.\n" 97 " returns an error if more than one emulator is running.\n" 98 " -s <serial number> - directs command to the USB device or emulator with\n" 99 " the given serial number. Overrides ANDROID_SERIAL\n" 100 " envivornment variable.\n" 101 " -p <product name or path> - simple product name like 'sooner', or\n" 102 " a relative/absolute path to a product\n" 103 " out directory like 'out/target/product/sooner'.\n" 104 " If -p is not specified, the ANDROID_PRODUCT_OUT\n" 105 " environment variable is used, which must\n" 106 " be an absolute path.\n" 107 " devices - list all connected devices\n" 108 "\n" 109 "device commands:\n" 110 " adb push <local> <remote> - copy file/dir to device\n" 111 " adb pull <remote> <local> - copy file/dir from device\n" 112 " adb sync [ <directory> ] - copy host->device only if changed\n" 113 " (see 'adb help all')\n" 114 " adb shell - run remote shell interactively\n" 115 " adb shell <command> - run remote shell command\n" 116 " adb emu <command> - run emulator console command\n" 117 " adb logcat [ <filter-spec> ] - View device log\n" 118 " adb forward <local> <remote> - forward socket connections\n" 119 " forward specs are one of: \n" 120 " tcp:<port>\n" 121 " localabstract:<unix domain socket name>\n" 122 " localreserved:<unix domain socket name>\n" 123 " localfilesystem:<unix domain socket name>\n" 124 " dev:<character device name>\n" 125 " jdwp:<process pid> (remote only)\n" 126 " adb jdwp - list PIDs of processes hosting a JDWP transport\n" 127 " adb install [-l] [-r] <file> - push this package file to the device and install it\n" 128 " ('-l' means forward-lock the app)\n" 129 " ('-r' means reinstall the app, keeping its data)\n" 130 " adb uninstall [-k] <package> - remove this app package from the device\n" 131 " ('-k' means keep the data and cache directories)\n" 132 " adb bugreport - return all information from the device\n" 133 " that should be included in a bug report.\n" 134 "\n" 135 " adb help - show this help message\n" 136 " adb version - show version num\n" 137 "\n" 138 "DATAOPTS:\n" 139 " (no option) - don't touch the data partition\n" 140 " -w - wipe the data partition\n" 141 " -d - flash the data partition\n" 142 "\n" 143 "scripting:\n" 144 " adb wait-for-device - block until device is online\n" 145 " adb start-server - ensure that there is a server running\n" 146 " adb kill-server - kill the server if it is running\n" 147 " adb get-state - prints: offline | bootloader | device\n" 148 " adb get-serialno - prints: <serial-number>\n" 149 " adb status-window - continuously print device status for a specified device\n" 150 " adb remount - remounts the /system partition on the device read-write\n" 151 " adb root - restarts adb with root permissions\n" 152 "\n" 153 "networking:\n" 154 " adb ppp <tty> [parameters] - Run PPP over USB.\n" 155 " Note: you should not automatically start a PPP connection.\n" 156 " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n" 157 " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n" 158 "\n" 159 "adb sync notes: adb sync [ <directory> ]\n" 160 " <localdir> can be interpreted in several ways:\n" 161 "\n" 162 " - If <directory> is not specified, both /system and /data partitions will be updated.\n" 163 "\n" 164 " - If it is \"system\" or \"data\", only the corresponding partition\n" 165 " is updated.\n" 166 ); 167} 168 169int usage() 170{ 171 help(); 172 return 1; 173} 174 175#ifdef HAVE_TERMIO_H 176static struct termios tio_save; 177 178static void stdin_raw_init(int fd) 179{ 180 struct termios tio; 181 182 if(tcgetattr(fd, &tio)) return; 183 if(tcgetattr(fd, &tio_save)) return; 184 185 tio.c_lflag = 0; /* disable CANON, ECHO*, etc */ 186 187 /* no timeout but request at least one character per read */ 188 tio.c_cc[VTIME] = 0; 189 tio.c_cc[VMIN] = 1; 190 191 tcsetattr(fd, TCSANOW, &tio); 192 tcflush(fd, TCIFLUSH); 193} 194 195static void stdin_raw_restore(int fd) 196{ 197 tcsetattr(fd, TCSANOW, &tio_save); 198 tcflush(fd, TCIFLUSH); 199} 200#endif 201 202static void read_and_dump(int fd) 203{ 204 char buf[4096]; 205 int len; 206 207 while(fd >= 0) { 208 len = adb_read(fd, buf, 4096); 209 if(len == 0) { 210 break; 211 } 212 213 if(len < 0) { 214 if(errno == EINTR) continue; 215 break; 216 } 217 /* we want to output to stdout, so no adb_write here !! */ 218 unix_write(1, buf, len); 219 } 220} 221 222#ifdef SH_HISTORY 223int shItemCmp( void *val, void *idata ) 224{ 225 return( (strcmp( val, idata ) == 0) ); 226} 227#endif 228 229static void *stdin_read_thread(void *x) 230{ 231 int fd, fdi; 232 unsigned char buf[1024]; 233#ifdef SH_HISTORY 234 unsigned char realbuf[1024], *buf_ptr; 235 SHLIST history; 236 SHLIST *item = &history; 237 int cmdlen = 0, ins_flag = 0; 238#endif 239 int r, n; 240 int state = 0; 241 242 int *fds = (int*) x; 243 fd = fds[0]; 244 fdi = fds[1]; 245 free(fds); 246 247#ifdef SH_HISTORY 248 shListInitList( &history ); 249#endif 250 for(;;) { 251 /* fdi is really the client's stdin, so use read, not adb_read here */ 252 r = unix_read(fdi, buf, 1024); 253 if(r == 0) break; 254 if(r < 0) { 255 if(errno == EINTR) continue; 256 break; 257 } 258#ifdef SH_HISTORY 259 if( (r == 3) && /* Arrow processing */ 260 (memcmp( (void *)buf, SH_ARROW_ANY, 2 ) == 0) ) { 261 switch( buf[2] ) { 262 case SH_ARROW_UP: 263 item = shListGetNextItem( &history, item ); 264 break; 265 case SH_ARROW_DOWN: 266 item = shListGetPrevItem( &history, item ); 267 break; 268 default: 269 item = NULL; 270 break; 271 } 272 memset( buf, SH_DEL_CHAR, cmdlen ); 273 if( item != NULL ) { 274 n = snprintf( (char *)(&buf[cmdlen]), sizeof buf - cmdlen, "%s", (char *)(item->data) ); 275 memcpy( realbuf, item->data, n ); 276 } 277 else { /* Clean buffer */ 278 item = &history; 279 n = 0; 280 } 281 r = n + cmdlen; 282 cmdlen = n; 283 ins_flag = 0; 284 if( r == 0 ) 285 continue; 286 } 287 else { 288#endif 289 for(n = 0; n < r; n++){ 290 switch(buf[n]) { 291 case '\n': 292#ifdef SH_HISTORY 293 if( ins_flag && (SH_BLANK_CHAR <= realbuf[0]) ) { 294 buf_ptr = malloc(cmdlen + 1); 295 if( buf_ptr != NULL ) { 296 memcpy( buf_ptr, realbuf, cmdlen ); 297 buf_ptr[cmdlen] = '\0'; 298 if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) { 299 shListInsFirstItem( &history, (void *)buf_ptr ); 300 item = &history; 301 } 302 } 303 } 304 cmdlen = 0; 305 ins_flag = 0; 306#endif 307 state = 1; 308 break; 309 case '\r': 310 state = 1; 311 break; 312 case '~': 313 if(state == 1) state++; 314 break; 315 case '.': 316 if(state == 2) { 317 fprintf(stderr,"\n* disconnect *\n"); 318 #ifdef HAVE_TERMIO_H 319 stdin_raw_restore(fdi); 320 #endif 321 exit(0); 322 } 323 default: 324#ifdef SH_HISTORY 325 if( buf[n] == SH_DEL_CHAR ) { 326 if( cmdlen > 0 ) 327 cmdlen--; 328 } 329 else { 330 realbuf[cmdlen] = buf[n]; 331 cmdlen++; 332 } 333 ins_flag = 1; 334#endif 335 state = 0; 336 } 337 } 338#ifdef SH_HISTORY 339 } 340#endif 341 r = adb_write(fd, buf, r); 342 if(r <= 0) { 343 break; 344 } 345 } 346#ifdef SH_HISTORY 347 shListDelAllItems( &history, (shListFree)free ); 348#endif 349 return 0; 350} 351 352int interactive_shell(void) 353{ 354 adb_thread_t thr; 355 int fdi, fd; 356 int *fds; 357 358 fd = adb_connect("shell:"); 359 if(fd < 0) { 360 fprintf(stderr,"error: %s\n", adb_error()); 361 return 1; 362 } 363 fdi = 0; //dup(0); 364 365 fds = malloc(sizeof(int) * 2); 366 fds[0] = fd; 367 fds[1] = fdi; 368 369#ifdef HAVE_TERMIO_H 370 stdin_raw_init(fdi); 371#endif 372 adb_thread_create(&thr, stdin_read_thread, fds); 373 read_and_dump(fd); 374#ifdef HAVE_TERMIO_H 375 stdin_raw_restore(fdi); 376#endif 377 return 0; 378} 379 380 381static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial) 382{ 383 if (serial) { 384 snprintf(buffer, buflen, "host-serial:%s:%s", serial, command); 385 } else { 386 const char* prefix = "host"; 387 if (ttype == kTransportUsb) 388 prefix = "host-usb"; 389 else if (ttype == kTransportLocal) 390 prefix = "host-local"; 391 392 snprintf(buffer, buflen, "%s:%s", prefix, command); 393 } 394} 395 396static void status_window(transport_type ttype, const char* serial) 397{ 398 char command[4096]; 399 char *state = 0; 400 char *laststate = 0; 401 402 /* silence stderr */ 403#ifdef _WIN32 404 /* XXX: TODO */ 405#else 406 int fd; 407 fd = unix_open("/dev/null", O_WRONLY); 408 dup2(fd, 2); 409 adb_close(fd); 410#endif 411 412 format_host_command(command, sizeof command, "get-state", ttype, serial); 413 414 for(;;) { 415 adb_sleep_ms(250); 416 417 if(state) { 418 free(state); 419 state = 0; 420 } 421 422 state = adb_query(command); 423 424 if(state) { 425 if(laststate && !strcmp(state,laststate)){ 426 continue; 427 } else { 428 if(laststate) free(laststate); 429 laststate = strdup(state); 430 } 431 } 432 433 printf("%c[2J%c[2H", 27, 27); 434 printf("Android Debug Bridge\n"); 435 printf("State: %s\n", state ? state : "offline"); 436 fflush(stdout); 437 } 438} 439 440/** duplicate string and quote all \ " ( ) chars + space character. */ 441static char * 442dupAndQuote(const char *s) 443{ 444 const char *ts; 445 size_t alloc_len; 446 char *ret; 447 char *dest; 448 449 ts = s; 450 451 alloc_len = 0; 452 453 for( ;*ts != '\0'; ts++) { 454 alloc_len++; 455 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { 456 alloc_len++; 457 } 458 } 459 460 ret = (char *)malloc(alloc_len + 1); 461 462 ts = s; 463 dest = ret; 464 465 for ( ;*ts != '\0'; ts++) { 466 if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { 467 *dest++ = '\\'; 468 } 469 470 *dest++ = *ts; 471 } 472 473 *dest++ = '\0'; 474 475 return ret; 476} 477 478/** 479 * Run ppp in "notty" mode against a resource listed as the first parameter 480 * eg: 481 * 482 * ppp dev:/dev/omap_csmi_tty0 <ppp options> 483 * 484 */ 485int ppp(int argc, char **argv) 486{ 487#ifdef HAVE_WIN32_PROC 488 fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]); 489 return -1; 490#else 491 char *adb_service_name; 492 pid_t pid; 493 int fd; 494 495 if (argc < 2) { 496 fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n", 497 argv[0]); 498 499 return 1; 500 } 501 502 adb_service_name = argv[1]; 503 504 fd = adb_connect(adb_service_name); 505 506 if(fd < 0) { 507 fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n", 508 adb_service_name, adb_error()); 509 return 1; 510 } 511 512 pid = fork(); 513 514 if (pid < 0) { 515 perror("from fork()"); 516 return 1; 517 } else if (pid == 0) { 518 int err; 519 int i; 520 const char **ppp_args; 521 522 // copy args 523 ppp_args = (const char **) alloca(sizeof(char *) * argc + 1); 524 ppp_args[0] = "pppd"; 525 for (i = 2 ; i < argc ; i++) { 526 //argv[2] and beyond become ppp_args[1] and beyond 527 ppp_args[i - 1] = argv[i]; 528 } 529 ppp_args[i-1] = NULL; 530 531 // child side 532 533 dup2(fd, STDIN_FILENO); 534 dup2(fd, STDOUT_FILENO); 535 adb_close(STDERR_FILENO); 536 adb_close(fd); 537 538 err = execvp("pppd", (char * const *)ppp_args); 539 540 if (err < 0) { 541 perror("execing pppd"); 542 } 543 exit(-1); 544 } else { 545 // parent side 546 547 adb_close(fd); 548 return 0; 549 } 550#endif /* !HAVE_WIN32_PROC */ 551} 552 553static int send_shellcommand(transport_type transport, char* serial, char* buf) 554{ 555 int fd, ret; 556 557 for(;;) { 558 fd = adb_connect(buf); 559 if(fd >= 0) 560 break; 561 fprintf(stderr,"- waiting for device -\n"); 562 adb_sleep_ms(1000); 563 do_cmd(transport, serial, "wait-for-device", 0); 564 } 565 566 read_and_dump(fd); 567 ret = adb_close(fd); 568 if (ret) 569 perror("close"); 570 571 return ret; 572} 573 574static int logcat(transport_type transport, char* serial, int argc, char **argv) 575{ 576 char buf[4096]; 577 578 char *log_tags; 579 char *quoted_log_tags; 580 581 log_tags = getenv("ANDROID_LOG_TAGS"); 582 quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags); 583 584 snprintf(buf, sizeof(buf), 585 "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat", 586 quoted_log_tags); 587 588 free(quoted_log_tags); 589 590 argc -= 1; 591 argv += 1; 592 while(argc-- > 0) { 593 char *quoted; 594 595 quoted = dupAndQuote (*argv++); 596 597 strncat(buf, " ", sizeof(buf)-1); 598 strncat(buf, quoted, sizeof(buf)-1); 599 free(quoted); 600 } 601 602 send_shellcommand(transport, serial, buf); 603 return 0; 604} 605 606#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make" 607static int top_works(const char *top) 608{ 609 if (top != NULL && adb_is_absolute_host_path(top)) { 610 char path_buf[PATH_MAX]; 611 snprintf(path_buf, sizeof(path_buf), 612 "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top); 613 return access(path_buf, F_OK) == 0; 614 } 615 return 0; 616} 617 618static char *find_top_from(const char *indir, char path_buf[PATH_MAX]) 619{ 620 strcpy(path_buf, indir); 621 while (1) { 622 if (top_works(path_buf)) { 623 return path_buf; 624 } 625 char *s = adb_dirstop(path_buf); 626 if (s != NULL) { 627 *s = '\0'; 628 } else { 629 path_buf[0] = '\0'; 630 return NULL; 631 } 632 } 633} 634 635static char *find_top(char path_buf[PATH_MAX]) 636{ 637 char *top = getenv("ANDROID_BUILD_TOP"); 638 if (top != NULL && top[0] != '\0') { 639 if (!top_works(top)) { 640 fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top); 641 return NULL; 642 } 643 } else { 644 top = getenv("TOP"); 645 if (top != NULL && top[0] != '\0') { 646 if (!top_works(top)) { 647 fprintf(stderr, "adb: bad TOP value \"%s\"\n", top); 648 return NULL; 649 } 650 } else { 651 top = NULL; 652 } 653 } 654 655 if (top != NULL) { 656 /* The environment pointed to a top directory that works. 657 */ 658 strcpy(path_buf, top); 659 return path_buf; 660 } 661 662 /* The environment didn't help. Walk up the tree from the CWD 663 * to see if we can find the top. 664 */ 665 char dir[PATH_MAX]; 666 top = find_top_from(getcwd(dir, sizeof(dir)), path_buf); 667 if (top == NULL) { 668 /* If the CWD isn't under a good-looking top, see if the 669 * executable is. 670 */ 671 get_my_path(dir); 672 top = find_top_from(dir, path_buf); 673 } 674 return top; 675} 676 677/* <hint> may be: 678 * - A simple product name 679 * e.g., "sooner" 680TODO: debug? sooner-debug, sooner:debug? 681 * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir 682 * e.g., "out/target/product/sooner" 683 * - An absolute path to the PRODUCT_OUT dir 684 * e.g., "/src/device/out/target/product/sooner" 685 * 686 * Given <hint>, try to construct an absolute path to the 687 * ANDROID_PRODUCT_OUT dir. 688 */ 689static const char *find_product_out_path(const char *hint) 690{ 691 static char path_buf[PATH_MAX]; 692 693 if (hint == NULL || hint[0] == '\0') { 694 return NULL; 695 } 696 697 /* If it's already absolute, don't bother doing any work. 698 */ 699 if (adb_is_absolute_host_path(hint)) { 700 strcpy(path_buf, hint); 701 return path_buf; 702 } 703 704 /* If there are any slashes in it, assume it's a relative path; 705 * make it absolute. 706 */ 707 if (adb_dirstart(hint) != NULL) { 708 if (getcwd(path_buf, sizeof(path_buf)) == NULL) { 709 fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno)); 710 return NULL; 711 } 712 if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) { 713 fprintf(stderr, "adb: Couldn't assemble path\n"); 714 return NULL; 715 } 716 strcat(path_buf, OS_PATH_SEPARATOR_STR); 717 strcat(path_buf, hint); 718 return path_buf; 719 } 720 721 /* It's a string without any slashes. Try to do something with it. 722 * 723 * Try to find the root of the build tree, and build a PRODUCT_OUT 724 * path from there. 725 */ 726 char top_buf[PATH_MAX]; 727 const char *top = find_top(top_buf); 728 if (top == NULL) { 729 fprintf(stderr, "adb: Couldn't find top of build tree\n"); 730 return NULL; 731 } 732//TODO: if we have a way to indicate debug, look in out/debug/target/... 733 snprintf(path_buf, sizeof(path_buf), 734 "%s" OS_PATH_SEPARATOR_STR 735 "out" OS_PATH_SEPARATOR_STR 736 "target" OS_PATH_SEPARATOR_STR 737 "product" OS_PATH_SEPARATOR_STR 738 "%s", top_buf, hint); 739 if (access(path_buf, F_OK) < 0) { 740 fprintf(stderr, "adb: Couldn't find a product dir " 741 "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf); 742 return NULL; 743 } 744 return path_buf; 745} 746 747int adb_commandline(int argc, char **argv) 748{ 749 char buf[4096]; 750 int no_daemon = 0; 751 int is_daemon = 0; 752 int persist = 0; 753 int r; 754 int quote; 755 transport_type ttype = kTransportAny; 756 char* serial = NULL; 757 758 /* If defined, this should be an absolute path to 759 * the directory containing all of the various system images 760 * for a particular product. If not defined, and the adb 761 * command requires this information, then the user must 762 * specify the path using "-p". 763 */ 764 gProductOutPath = getenv("ANDROID_PRODUCT_OUT"); 765 if (gProductOutPath == NULL || gProductOutPath[0] == '\0') { 766 gProductOutPath = NULL; 767 } 768 // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint 769 770 serial = getenv("ANDROID_SERIAL"); 771 772 /* modifiers and flags */ 773 while(argc > 0) { 774 if(!strcmp(argv[0],"nodaemon")) { 775 no_daemon = 1; 776 } else if (!strcmp(argv[0], "fork-server")) { 777 /* this is a special flag used only when the ADB client launches the ADB Server */ 778 is_daemon = 1; 779 } else if(!strcmp(argv[0],"persist")) { 780 persist = 1; 781 } else if(!strncmp(argv[0], "-p", 2)) { 782 const char *product = NULL; 783 if (argv[0][2] == '\0') { 784 if (argc < 2) return usage(); 785 product = argv[1]; 786 argc--; 787 argv++; 788 } else { 789 product = argv[1] + 2; 790 } 791 gProductOutPath = find_product_out_path(product); 792 if (gProductOutPath == NULL) { 793 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", 794 product); 795 return usage(); 796 } 797 } else if (argv[0][0]=='-' && argv[0][1]=='s') { 798 if (isdigit(argv[0][2])) { 799 serial = argv[0] + 2; 800 } else { 801 if(argc < 2) return usage(); 802 serial = argv[1]; 803 argc--; 804 argv++; 805 } 806 } else if (!strcmp(argv[0],"-d")) { 807 ttype = kTransportUsb; 808 } else if (!strcmp(argv[0],"-e")) { 809 ttype = kTransportLocal; 810 } else { 811 /* out of recognized modifiers and flags */ 812 break; 813 } 814 argc--; 815 argv++; 816 } 817 818 adb_set_transport(ttype, serial); 819 820 if ((argc > 0) && (!strcmp(argv[0],"server"))) { 821 if (no_daemon || is_daemon) { 822 r = adb_main(is_daemon); 823 } else { 824 r = launch_server(); 825 } 826 if(r) { 827 fprintf(stderr,"* could not start server *\n"); 828 } 829 return r; 830 } 831 832top: 833 if(argc == 0) { 834 return usage(); 835 } 836 837 /* adb_connect() commands */ 838 839 if(!strcmp(argv[0], "devices")) { 840 char *tmp; 841 snprintf(buf, sizeof buf, "host:%s", argv[0]); 842 tmp = adb_query(buf); 843 if(tmp) { 844 printf("List of devices attached \n"); 845 printf("%s\n", tmp); 846 return 0; 847 } else { 848 return 1; 849 } 850 } 851 852 if (!strcmp(argv[0], "emu")) { 853 return adb_send_emulator_command(argc, argv); 854 } 855 856 if(!strcmp(argv[0], "shell")) { 857 int r; 858 int fd; 859 860 if(argc < 2) { 861 return interactive_shell(); 862 } 863 864 snprintf(buf, sizeof buf, "shell:%s", argv[1]); 865 argc -= 2; 866 argv += 2; 867 while(argc-- > 0) { 868 strcat(buf, " "); 869 870 /* quote empty strings and strings with spaces */ 871 quote = (**argv == 0 || strchr(*argv, ' ')); 872 if (quote) 873 strcat(buf, "\""); 874 strcat(buf, *argv++); 875 if (quote) 876 strcat(buf, "\""); 877 } 878 879 for(;;) { 880 fd = adb_connect(buf); 881 if(fd >= 0) { 882 read_and_dump(fd); 883 adb_close(fd); 884 r = 0; 885 } else { 886 fprintf(stderr,"error: %s\n", adb_error()); 887 r = -1; 888 } 889 890 if(persist) { 891 fprintf(stderr,"\n- waiting for device -\n"); 892 adb_sleep_ms(1000); 893 do_cmd(ttype, serial, "wait-for-device", 0); 894 } else { 895 return r; 896 } 897 } 898 } 899 900 if(!strcmp(argv[0], "kill-server")) { 901 int fd; 902 fd = _adb_connect("host:kill"); 903 if(fd == -1) { 904 fprintf(stderr,"* server not running *\n"); 905 return 1; 906 } 907 return 0; 908 } 909 910 if(!strcmp(argv[0], "remount")) { 911 int fd = adb_connect("remount:"); 912 if(fd >= 0) { 913 read_and_dump(fd); 914 adb_close(fd); 915 return 0; 916 } 917 fprintf(stderr,"error: %s\n", adb_error()); 918 return 1; 919 } 920 921 if(!strcmp(argv[0], "root")) { 922 int fd = adb_connect("root:"); 923 if(fd >= 0) { 924 read_and_dump(fd); 925 adb_close(fd); 926 return 0; 927 } 928 fprintf(stderr,"error: %s\n", adb_error()); 929 return 1; 930 } 931 932 if(!strcmp(argv[0], "bugreport")) { 933 if (argc != 1) { 934 return 1; 935 } 936 do_cmd(ttype, serial, "shell", "dumpstate", "-", 0); 937 return 0; 938 } 939 940 /* adb_command() wrapper commands */ 941 942 if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { 943 char* service = argv[0]; 944 if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { 945 if (ttype == kTransportUsb) { 946 service = "wait-for-usb"; 947 } else if (ttype == kTransportLocal) { 948 service = "wait-for-local"; 949 } else { 950 service = "wait-for-any"; 951 } 952 } 953 954 format_host_command(buf, sizeof buf, service, ttype, serial); 955 956 if (adb_command(buf)) { 957 D("failure: %s *\n",adb_error()); 958 fprintf(stderr,"error: %s\n", adb_error()); 959 return 1; 960 } 961 962 /* Allow a command to be run after wait-for-device, 963 * e.g. 'adb wait-for-device shell'. 964 */ 965 if(argc > 1) { 966 argc--; 967 argv++; 968 goto top; 969 } 970 return 0; 971 } 972 973 if(!strcmp(argv[0], "forward")) { 974 if(argc != 3) return usage(); 975 if (serial) { 976 snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial,argv[1],argv[2]); 977 } else { 978 snprintf(buf, sizeof buf, "host:forward:%s;%s",argv[1],argv[2]); 979 } 980 if(adb_command(buf)) { 981 fprintf(stderr,"error: %s\n", adb_error()); 982 return 1; 983 } 984 return 0; 985 } 986 987 /* do_sync_*() commands */ 988 989 if(!strcmp(argv[0], "ls")) { 990 if(argc != 2) return usage(); 991 return do_sync_ls(argv[1]); 992 } 993 994 if(!strcmp(argv[0], "push")) { 995 if(argc != 3) return usage(); 996 return do_sync_push(argv[1], argv[2], 0 /* no verify APK */); 997 } 998 999 if(!strcmp(argv[0], "pull")) { 1000 if(argc != 3) return usage(); 1001 return do_sync_pull(argv[1], argv[2]); 1002 } 1003 1004 if(!strcmp(argv[0], "install")) { 1005 if (argc < 2) return usage(); 1006 return install_app(ttype, serial, argc, argv); 1007 } 1008 1009 if(!strcmp(argv[0], "uninstall")) { 1010 if (argc < 2) return usage(); 1011 return uninstall_app(ttype, serial, argc, argv); 1012 } 1013 1014 if(!strcmp(argv[0], "sync")) { 1015 char *srcarg, *android_srcpath, *data_srcpath; 1016 int ret; 1017 if(argc < 2) { 1018 /* No local path was specified. */ 1019 srcarg = NULL; 1020 } else if(argc == 2) { 1021 /* A local path or "android"/"data" arg was specified. */ 1022 srcarg = argv[1]; 1023 } else { 1024 return usage(); 1025 } 1026 ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath); 1027 if(ret != 0) return usage(); 1028 1029 if(android_srcpath != NULL) 1030 ret = do_sync_sync(android_srcpath, "/system"); 1031 if(ret == 0 && data_srcpath != NULL) 1032 ret = do_sync_sync(data_srcpath, "/data"); 1033 1034 free(android_srcpath); 1035 free(data_srcpath); 1036 return ret; 1037 } 1038 1039 /* passthrough commands */ 1040 1041 if(!strcmp(argv[0],"get-state") || 1042 !strcmp(argv[0],"get-serialno")) 1043 { 1044 char *tmp; 1045 1046 format_host_command(buf, sizeof buf, argv[0], ttype, serial); 1047 tmp = adb_query(buf); 1048 if(tmp) { 1049 printf("%s\n", tmp); 1050 return 0; 1051 } else { 1052 return 1; 1053 } 1054 } 1055 1056 /* other commands */ 1057 1058 if(!strcmp(argv[0],"status-window")) { 1059 status_window(ttype, serial); 1060 return 0; 1061 } 1062 1063 if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) { 1064 return logcat(ttype, serial, argc, argv); 1065 } 1066 1067 if(!strcmp(argv[0],"ppp")) { 1068 return ppp(argc, argv); 1069 } 1070 1071 if (!strcmp(argv[0], "start-server")) { 1072 return adb_connect("host:start-server"); 1073 } 1074 1075 if (!strcmp(argv[0], "jdwp")) { 1076 int fd = adb_connect("jdwp"); 1077 if (fd >= 0) { 1078 read_and_dump(fd); 1079 adb_close(fd); 1080 return 0; 1081 } else { 1082 fprintf(stderr, "error: %s\n", adb_error()); 1083 return -1; 1084 } 1085 } 1086 1087 /* "adb /?" is a common idiom under Windows */ 1088 if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) { 1089 help(); 1090 return 0; 1091 } 1092 1093 if(!strcmp(argv[0], "version")) { 1094 version(stdout); 1095 return 0; 1096 } 1097 1098 usage(); 1099 return 1; 1100} 1101 1102static int do_cmd(transport_type ttype, char* serial, char *cmd, ...) 1103{ 1104 char *argv[16]; 1105 int argc; 1106 va_list ap; 1107 1108 va_start(ap, cmd); 1109 argc = 0; 1110 1111 if (serial) { 1112 argv[argc++] = "-s"; 1113 argv[argc++] = serial; 1114 } else if (ttype == kTransportUsb) { 1115 argv[argc++] = "-d"; 1116 } else if (ttype == kTransportLocal) { 1117 argv[argc++] = "-e"; 1118 } 1119 1120 argv[argc++] = cmd; 1121 while((argv[argc] = va_arg(ap, char*)) != 0) argc++; 1122 va_end(ap); 1123 1124#if 0 1125 int n; 1126 fprintf(stderr,"argc = %d\n",argc); 1127 for(n = 0; n < argc; n++) { 1128 fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]); 1129 } 1130#endif 1131 1132 return adb_commandline(argc, argv); 1133} 1134 1135int find_sync_dirs(const char *srcarg, 1136 char **android_srcdir_out, char **data_srcdir_out) 1137{ 1138 char *android_srcdir, *data_srcdir; 1139 1140 if(srcarg == NULL) { 1141 android_srcdir = product_file("system"); 1142 data_srcdir = product_file("data"); 1143 } else { 1144 /* srcarg may be "data", "system" or NULL. 1145 * if srcarg is NULL, then both data and system are synced 1146 */ 1147 if(strcmp(srcarg, "system") == 0) { 1148 android_srcdir = product_file("system"); 1149 data_srcdir = NULL; 1150 } else if(strcmp(srcarg, "data") == 0) { 1151 android_srcdir = NULL; 1152 data_srcdir = product_file("data"); 1153 } else { 1154 /* It's not "system" or "data". 1155 */ 1156 return 1; 1157 } 1158 } 1159 1160 if(android_srcdir_out != NULL) 1161 *android_srcdir_out = android_srcdir; 1162 else 1163 free(android_srcdir); 1164 1165 if(data_srcdir_out != NULL) 1166 *data_srcdir_out = data_srcdir; 1167 else 1168 free(data_srcdir); 1169 1170 return 0; 1171} 1172 1173static int pm_command(transport_type transport, char* serial, 1174 int argc, char** argv) 1175{ 1176 char buf[4096]; 1177 1178 snprintf(buf, sizeof(buf), "shell:pm"); 1179 1180 while(argc-- > 0) { 1181 char *quoted; 1182 1183 quoted = dupAndQuote(*argv++); 1184 1185 strncat(buf, " ", sizeof(buf)-1); 1186 strncat(buf, quoted, sizeof(buf)-1); 1187 free(quoted); 1188 } 1189 1190 send_shellcommand(transport, serial, buf); 1191 return 0; 1192} 1193 1194int uninstall_app(transport_type transport, char* serial, int argc, char** argv) 1195{ 1196 /* if the user choose the -k option, we refuse to do it until devices are 1197 out with the option to uninstall the remaining data somehow (adb/ui) */ 1198 if (argc == 3 && strcmp(argv[1], "-k") == 0) 1199 { 1200 printf( 1201 "The -k option uninstalls the application while retaining the data/cache.\n" 1202 "At the moment, there is no way to remove the remaining data.\n" 1203 "You will have to reinstall the application with the same signature, and fully uninstall it.\n" 1204 "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]); 1205 return -1; 1206 } 1207 1208 /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */ 1209 return pm_command(transport, serial, argc, argv); 1210} 1211 1212static int delete_file(transport_type transport, char* serial, char* filename) 1213{ 1214 char buf[4096]; 1215 char* quoted; 1216 1217 snprintf(buf, sizeof(buf), "shell:rm "); 1218 quoted = dupAndQuote(filename); 1219 strncat(buf, quoted, sizeof(buf)-1); 1220 free(quoted); 1221 1222 send_shellcommand(transport, serial, buf); 1223 return 0; 1224} 1225 1226int install_app(transport_type transport, char* serial, int argc, char** argv) 1227{ 1228 struct stat st; 1229 int err; 1230 const char *const WHERE = "/data/local/tmp/%s"; 1231 char to[PATH_MAX]; 1232 char* filename = argv[argc - 1]; 1233 const char* p; 1234 1235 p = adb_dirstop(filename); 1236 if (p) { 1237 p++; 1238 snprintf(to, sizeof to, WHERE, p); 1239 } else { 1240 snprintf(to, sizeof to, WHERE, filename); 1241 } 1242 if (p[0] == '\0') { 1243 } 1244 1245 err = stat(filename, &st); 1246 if (err != 0) { 1247 fprintf(stderr, "can't find '%s' to install\n", filename); 1248 return 1; 1249 } 1250 if (!S_ISREG(st.st_mode)) { 1251 fprintf(stderr, "can't install '%s' because it's not a file\n", 1252 filename); 1253 return 1; 1254 } 1255 1256 if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) { 1257 /* file in place; tell the Package Manager to install it */ 1258 argv[argc - 1] = to; /* destination name, not source location */ 1259 pm_command(transport, serial, argc, argv); 1260 delete_file(transport, serial, to); 1261 } 1262 1263 return err; 1264} 1265