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