commandline.c revision dd6b36e334809e7a99f0bce45353cdd7e4dac4e1
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        "                                 environment 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        "                                 (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        );
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        fwrite(buf, 1, len, stdout);
225        fflush(stdout);
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 ret;
1046        if(argc < 2) {
1047            /* No local path was specified. */
1048            srcarg = NULL;
1049        } else if(argc == 2) {
1050            /* A local path or "android"/"data" arg was specified. */
1051            srcarg = argv[1];
1052        } else {
1053            return usage();
1054        }
1055        ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath);
1056        if(ret != 0) return usage();
1057
1058        if(android_srcpath != NULL)
1059            ret = do_sync_sync(android_srcpath, "/system");
1060        if(ret == 0 && data_srcpath != NULL)
1061            ret = do_sync_sync(data_srcpath, "/data");
1062
1063        free(android_srcpath);
1064        free(data_srcpath);
1065        return ret;
1066    }
1067
1068    /* passthrough commands */
1069
1070    if(!strcmp(argv[0],"get-state") ||
1071        !strcmp(argv[0],"get-serialno"))
1072    {
1073        char *tmp;
1074
1075        format_host_command(buf, sizeof buf, argv[0], ttype, serial);
1076        tmp = adb_query(buf);
1077        if(tmp) {
1078            printf("%s\n", tmp);
1079            return 0;
1080        } else {
1081            return 1;
1082        }
1083    }
1084
1085    /* other commands */
1086
1087    if(!strcmp(argv[0],"status-window")) {
1088        status_window(ttype, serial);
1089        return 0;
1090    }
1091
1092    if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) {
1093        return logcat(ttype, serial, argc, argv);
1094    }
1095
1096    if(!strcmp(argv[0],"ppp")) {
1097        return ppp(argc, argv);
1098    }
1099
1100    if (!strcmp(argv[0], "start-server")) {
1101        return adb_connect("host:start-server");
1102    }
1103
1104    if (!strcmp(argv[0], "jdwp")) {
1105        int  fd = adb_connect("jdwp");
1106        if (fd >= 0) {
1107            read_and_dump(fd);
1108            adb_close(fd);
1109            return 0;
1110        } else {
1111            fprintf(stderr, "error: %s\n", adb_error());
1112            return -1;
1113        }
1114    }
1115
1116    /* "adb /?" is a common idiom under Windows */
1117    if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
1118        help();
1119        return 0;
1120    }
1121
1122    if(!strcmp(argv[0], "version")) {
1123        version(stdout);
1124        return 0;
1125    }
1126
1127    usage();
1128    return 1;
1129}
1130
1131static int do_cmd(transport_type ttype, char* serial, char *cmd, ...)
1132{
1133    char *argv[16];
1134    int argc;
1135    va_list ap;
1136
1137    va_start(ap, cmd);
1138    argc = 0;
1139
1140    if (serial) {
1141        argv[argc++] = "-s";
1142        argv[argc++] = serial;
1143    } else if (ttype == kTransportUsb) {
1144        argv[argc++] = "-d";
1145    } else if (ttype == kTransportLocal) {
1146        argv[argc++] = "-e";
1147    }
1148
1149    argv[argc++] = cmd;
1150    while((argv[argc] = va_arg(ap, char*)) != 0) argc++;
1151    va_end(ap);
1152
1153#if 0
1154    int n;
1155    fprintf(stderr,"argc = %d\n",argc);
1156    for(n = 0; n < argc; n++) {
1157        fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]);
1158    }
1159#endif
1160
1161    return adb_commandline(argc, argv);
1162}
1163
1164int find_sync_dirs(const char *srcarg,
1165        char **android_srcdir_out, char **data_srcdir_out)
1166{
1167    char *android_srcdir, *data_srcdir;
1168
1169    if(srcarg == NULL) {
1170        android_srcdir = product_file("system");
1171        data_srcdir = product_file("data");
1172    } else {
1173        /* srcarg may be "data", "system" or NULL.
1174         * if srcarg is NULL, then both data and system are synced
1175         */
1176        if(strcmp(srcarg, "system") == 0) {
1177            android_srcdir = product_file("system");
1178            data_srcdir = NULL;
1179        } else if(strcmp(srcarg, "data") == 0) {
1180            android_srcdir = NULL;
1181            data_srcdir = product_file("data");
1182        } else {
1183            /* It's not "system" or "data".
1184             */
1185            return 1;
1186        }
1187    }
1188
1189    if(android_srcdir_out != NULL)
1190        *android_srcdir_out = android_srcdir;
1191    else
1192        free(android_srcdir);
1193
1194    if(data_srcdir_out != NULL)
1195        *data_srcdir_out = data_srcdir;
1196    else
1197        free(data_srcdir);
1198
1199    return 0;
1200}
1201
1202static int pm_command(transport_type transport, char* serial,
1203                      int argc, char** argv)
1204{
1205    char buf[4096];
1206
1207    snprintf(buf, sizeof(buf), "shell:pm");
1208
1209    while(argc-- > 0) {
1210        char *quoted;
1211
1212        quoted = dupAndQuote(*argv++);
1213
1214        strncat(buf, " ", sizeof(buf)-1);
1215        strncat(buf, quoted, sizeof(buf)-1);
1216        free(quoted);
1217    }
1218
1219    send_shellcommand(transport, serial, buf);
1220    return 0;
1221}
1222
1223int uninstall_app(transport_type transport, char* serial, int argc, char** argv)
1224{
1225    /* if the user choose the -k option, we refuse to do it until devices are
1226       out with the option to uninstall the remaining data somehow (adb/ui) */
1227    if (argc == 3 && strcmp(argv[1], "-k") == 0)
1228    {
1229        printf(
1230            "The -k option uninstalls the application while retaining the data/cache.\n"
1231            "At the moment, there is no way to remove the remaining data.\n"
1232            "You will have to reinstall the application with the same signature, and fully uninstall it.\n"
1233            "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]);
1234        return -1;
1235    }
1236
1237    /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */
1238    return pm_command(transport, serial, argc, argv);
1239}
1240
1241static int delete_file(transport_type transport, char* serial, char* filename)
1242{
1243    char buf[4096];
1244    char* quoted;
1245
1246    snprintf(buf, sizeof(buf), "shell:rm ");
1247    quoted = dupAndQuote(filename);
1248    strncat(buf, quoted, sizeof(buf)-1);
1249    free(quoted);
1250
1251    send_shellcommand(transport, serial, buf);
1252    return 0;
1253}
1254
1255int install_app(transport_type transport, char* serial, int argc, char** argv)
1256{
1257    struct stat st;
1258    int err;
1259    const char *const DATA_DEST = "/data/local/tmp/%s";
1260    const char *const SD_DEST = "/sdcard/tmp/%s";
1261    const char* where = DATA_DEST;
1262    char to[PATH_MAX];
1263    char* filename = argv[argc - 1];
1264    const char* p;
1265    int i;
1266
1267    for (i = 0; i < argc; i++) {
1268        if (!strcmp(argv[i], "-s"))
1269            where = SD_DEST;
1270    }
1271
1272    p = adb_dirstop(filename);
1273    if (p) {
1274        p++;
1275        snprintf(to, sizeof to, where, p);
1276    } else {
1277        snprintf(to, sizeof to, where, filename);
1278    }
1279    if (p[0] == '\0') {
1280    }
1281
1282    err = stat(filename, &st);
1283    if (err != 0) {
1284        fprintf(stderr, "can't find '%s' to install\n", filename);
1285        return 1;
1286    }
1287    if (!S_ISREG(st.st_mode)) {
1288        fprintf(stderr, "can't install '%s' because it's not a file\n",
1289                filename);
1290        return 1;
1291    }
1292
1293    if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) {
1294        /* file in place; tell the Package Manager to install it */
1295        argv[argc - 1] = to;       /* destination name, not source location */
1296        pm_command(transport, serial, argc, argv);
1297        delete_file(transport, serial, to);
1298    }
1299
1300    return err;
1301}
1302