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