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