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