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