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