1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
171c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby#include <stddef.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
26408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#define  TRACE_TAG  TRACE_SERVICES
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "file_sync_service.h"
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#  ifndef HAVE_WINSOCK
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#    include <netinet/in.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#    include <netdb.h>
34408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#    include <sys/ioctl.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#  endif
36cc1de48dcdf06c76ee14abbe2a237aa51b5b3badMike Lockwood#else
37e3aeeb4de34dbb93e832e6554f494122ba633f3bKen Sumrall#  include <cutils/android_reboot.h>
38893a4a47e8c9290128b9254af0246e36f821c260Nick Kralevich#  include <cutils/properties.h>
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct stinfo stinfo;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct stinfo {
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void (*func)(int fd, void *cookie);
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *cookie;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid *service_bootstrap_func(void *x)
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    stinfo *sti = x;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sti->func(sti->fd, sti->cookie);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(sti);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
589470c2f1ab555311633d52e5ed8303a813061cdfBenoit Goby#if !ADB_HOST
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Projectvoid restart_root_service(int fd, void *cookie)
61e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project{
62e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    char buf[100];
63e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    char value[PROPERTY_VALUE_MAX];
64e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project
65e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    if (getuid() == 0) {
66e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        snprintf(buf, sizeof(buf), "adbd is already running as root\n");
67e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        writex(fd, buf, strlen(buf));
68e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        adb_close(fd);
69e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    } else {
70e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        property_get("ro.debuggable", value, "");
71e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        if (strcmp(value, "1") != 0) {
72e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project            snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
73e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project            writex(fd, buf, strlen(buf));
74ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood            adb_close(fd);
75e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project            return;
76e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        }
77e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project
787941cf87f624e7747b5bb868a27904c7a3be0ca4Benoit Goby        property_set("service.adb.root", "1");
79e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        snprintf(buf, sizeof(buf), "restarting adbd as root\n");
80e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        writex(fd, buf, strlen(buf));
81e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        adb_close(fd);
82e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    }
83e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project}
84e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project
85ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwoodvoid restart_tcp_service(int fd, void *cookie)
86ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood{
87ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    char buf[100];
88ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    char value[PROPERTY_VALUE_MAX];
89ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes    int port = (int) (uintptr_t) cookie;
90ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood
91ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    if (port <= 0) {
92ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        snprintf(buf, sizeof(buf), "invalid port\n");
93ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        writex(fd, buf, strlen(buf));
94ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        adb_close(fd);
95ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        return;
96ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    }
97ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood
98ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    snprintf(value, sizeof(value), "%d", port);
99ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    property_set("service.adb.tcp.port", value);
100ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
101ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    writex(fd, buf, strlen(buf));
102ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    adb_close(fd);
103ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood}
104ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood
105ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwoodvoid restart_usb_service(int fd, void *cookie)
106ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood{
107ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    char buf[100];
108ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood
109ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    property_set("service.adb.tcp.port", "0");
110ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    snprintf(buf, sizeof(buf), "restarting in USB mode\n");
111ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    writex(fd, buf, strlen(buf));
112ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    adb_close(fd);
113ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood}
114ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood
115ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwoodvoid reboot_service(int fd, void *arg)
116ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood{
117ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    char buf[100];
118ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich    char property_val[PROPERTY_VALUE_MAX];
11902916aa20e3ffbe4b738bb12dc1607a7ec6a8c37Nick Kralevich    int ret;
120ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood
121ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    sync();
122d969faa161310d0a3792766320daa3200b84bd74Mike Lockwood
123ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich    ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg);
124ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich    if (ret >= (int) sizeof(property_val)) {
125ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich        snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
126ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich        writex(fd, buf, strlen(buf));
127ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich        goto cleanup;
128ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich    }
129ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich
130ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich    ret = property_set(ANDROID_RB_PROPERTY, property_val);
131ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    if (ret < 0) {
132ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevich        snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
133ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood        writex(fd, buf, strlen(buf));
134917045222a69021eb36aea96708649c709685509Nick Kralevich        goto cleanup;
135ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    }
136917045222a69021eb36aea96708649c709685509Nick Kralevich    // Don't return early. Give the reboot command time to take effect
137917045222a69021eb36aea96708649c709685509Nick Kralevich    // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
138917045222a69021eb36aea96708649c709685509Nick Kralevich    while(1) { pause(); }
139ca8e66a8b0f843812014a28d49208f9f6f64ecbcNick Kralevichcleanup:
140b6b40079e6d5b32026cc2abfcb71adfd49e8d954Mike Lockwood    free(arg);
141ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    adb_close(fd);
142ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood}
143ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood
144252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turnervoid reverse_service(int fd, void* arg)
145252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner{
146252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    const char* command = arg;
147252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
148252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
149252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        sendfailmsg(fd, "not a reverse forwarding command");
150252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
151252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    free(arg);
152252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    adb_close(fd);
153252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
154252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int create_service_thread(void (*func)(int, void *), void *cookie)
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    stinfo *sti;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_thread_t t;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int s[2];
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(adb_socketpair(s)) {
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("cannot create service socket pair\n");
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sti = malloc(sizeof(stinfo));
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(sti == 0) fatal("cannot allocate stinfo");
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sti->func = func;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sti->cookie = cookie;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sti->fd = s[1];
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(adb_thread_create( &t, service_bootstrap_func, sti)){
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(sti);
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s[0]);
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s[1]);
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("cannot create service thread\n");
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("service thread started, %d:%d\n",s[0], s[1]);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return s[0];
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
186408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if !ADB_HOST
1875d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
1885d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkeystatic void init_subproc_child()
1895d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey{
1905d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    setsid();
1915d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
19207ce7cab72d9b3e5c701491daf8fd457d035eec8Rom Lemarchand    // Set OOM score adjustment to prevent killing
193fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich    int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
1945d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (fd >= 0) {
1955d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_write(fd, "0", 1);
1965d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(fd);
1975d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    } else {
19807ce7cab72d9b3e5c701491daf8fd457d035eec8Rom Lemarchand       D("adb: unable to update oom_score_adj\n");
1995d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    }
2005d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey}
2015d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2025d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkeystatic int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
2045d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    D("create_subproc_pty(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
20591acb14877e7138879057f794a61ee2fd424a41dJoe Onorato#ifdef HAVE_WIN32_PROC
2065d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    fprintf(stderr, "error: create_subproc_pty not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
207408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    return -1;
20891acb14877e7138879057f794a61ee2fd424a41dJoe Onorato#else /* !HAVE_WIN32_PROC */
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ptm;
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
211fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich    ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ptm < 0){
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217a6ff5c95a3fa798d661e09aa628cd0c5e5c8608fElliott Hughes    char devname[64];
218a6ff5c95a3fa798d661e09aa628cd0c5e5c8608fElliott Hughes    if(grantpt(ptm) || unlockpt(ptm) || ptsname_r(ptm, devname, sizeof(devname)) != 0) {
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
220408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_close(ptm);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
224408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    *pid = fork();
225408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(*pid < 0) {
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("- fork failed: %s -\n", strerror(errno));
227408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_close(ptm);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2315d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (*pid == 0) {
2325d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        init_subproc_child();
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich        int pts = unix_open(devname, O_RDWR | O_CLOEXEC);
2355d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        if (pts < 0) {
236408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
237408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            exit(-1);
238408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        }
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2405d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        dup2(pts, STDIN_FILENO);
2415d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        dup2(pts, STDOUT_FILENO);
2425d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        dup2(pts, STDERR_FILENO);
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
24495ef82866c7a922bf588027aa38c58a45eb84d9cBenoit Goby        adb_close(pts);
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(ptm);
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        execl(cmd, cmd, arg0, arg1, NULL);
248408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
249408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                cmd, strerror(errno), errno);
250408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        exit(-1);
251408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    } else {
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return ptm;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
25491acb14877e7138879057f794a61ee2fd424a41dJoe Onorato#endif /* !HAVE_WIN32_PROC */
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
2565d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2575d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkeystatic int create_subproc_raw(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
2585d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey{
2595d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    D("create_subproc_raw(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
2605d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey#ifdef HAVE_WIN32_PROC
2615d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    fprintf(stderr, "error: create_subproc_raw not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
2625d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    return -1;
2635d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey#else /* !HAVE_WIN32_PROC */
2645d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2655d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    // 0 is parent socket, 1 is child socket
2665d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    int sv[2];
2675d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
2685d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        printf("[ cannot create socket pair - %s ]\n", strerror(errno));
2695d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        return -1;
2705d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    }
2715d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2725d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    *pid = fork();
2735d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (*pid < 0) {
2745d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        printf("- fork failed: %s -\n", strerror(errno));
2755d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(sv[0]);
2765d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(sv[1]);
2775d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        return -1;
2785d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    }
2795d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2805d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (*pid == 0) {
2815d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(sv[0]);
2825d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        init_subproc_child();
2835d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2845d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        dup2(sv[1], STDIN_FILENO);
2855d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        dup2(sv[1], STDOUT_FILENO);
286960df97c2356f5a804d3ef87fe49f788d7ecdfafJeff Sharkey        dup2(sv[1], STDERR_FILENO);
287960df97c2356f5a804d3ef87fe49f788d7ecdfafJeff Sharkey
2885d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(sv[1]);
2895d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
2905d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        execl(cmd, cmd, arg0, arg1, NULL);
2915d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
2925d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey                cmd, strerror(errno), errno);
2935d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        exit(-1);
2945d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    } else {
2955d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        adb_close(sv[1]);
2965d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        return sv[0];
2975d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    }
2985d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey#endif /* !HAVE_WIN32_PROC */
2995d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey}
300408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif  /* !ABD_HOST */
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define SHELL_COMMAND "/bin/sh"
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define SHELL_COMMAND "/system/bin/sh"
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
308408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if !ADB_HOST
309408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrallstatic void subproc_waiter_service(int fd, void *cookie)
310408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
311ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes    pid_t pid = (pid_t) (uintptr_t) cookie;
312408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
313408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("entered. fd=%d of pid=%d\n", fd, pid);
314408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    for (;;) {
315408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        int status;
316408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        pid_t p = waitpid(pid, &status, 0);
317408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        if (p == pid) {
318408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
319408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            if (WIFSIGNALED(status)) {
320408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                D("*** Killed by signal %d\n", WTERMSIG(status));
321408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                break;
322408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            } else if (!WIFEXITED(status)) {
323408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                D("*** Didn't exit!!. status %d\n", status);
324408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                break;
325408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            } else if (WEXITSTATUS(status) >= 0) {
326408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                D("*** Exit code %d\n", WEXITSTATUS(status));
327408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall                break;
328408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            }
329408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall         }
330408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
331408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
332408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if (SHELL_EXIT_NOTIFY_FD >=0) {
333408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      int res;
334408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
335408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall      D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
336408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        SHELL_EXIT_NOTIFY_FD, pid, res, errno);
337408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
338408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
339408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
3405d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkeystatic int create_subproc_thread(const char *name, const subproc_mode mode)
341408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall{
342408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    stinfo *sti;
343408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    adb_thread_t t;
344408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    int ret_fd;
3455d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    pid_t pid = -1;
3465d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
3475d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    const char *arg0, *arg1;
3485d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (name == 0 || *name == 0) {
3495d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        arg0 = "-"; arg1 = 0;
350408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    } else {
3515d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        arg0 = "-c"; arg1 = name;
3525d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    }
3535d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey
3545d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    switch (mode) {
3555d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    case SUBPROC_PTY:
3565d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        ret_fd = create_subproc_pty(SHELL_COMMAND, arg0, arg1, &pid);
3575d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        break;
3585d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    case SUBPROC_RAW:
3595d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        ret_fd = create_subproc_raw(SHELL_COMMAND, arg0, arg1, &pid);
3605d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        break;
3615d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    default:
3625d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        fprintf(stderr, "invalid subproc_mode %d\n", mode);
3635d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        return -1;
364408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
3655d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    D("create_subproc ret_fd=%d pid=%d\n", ret_fd, pid);
366408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
367408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    sti = malloc(sizeof(stinfo));
368408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    if(sti == 0) fatal("cannot allocate stinfo");
369408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    sti->func = subproc_waiter_service;
370ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes    sti->cookie = (void*) (uintptr_t) pid;
371408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    sti->fd = ret_fd;
372408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
3735d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    if (adb_thread_create(&t, service_bootstrap_func, sti)) {
374408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        free(sti);
375408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        adb_close(ret_fd);
3765d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        fprintf(stderr, "cannot create service thread\n");
377408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        return -1;
378408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    }
379408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
3805d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    D("service thread started, fd=%d pid=%d\n", ret_fd, pid);
381408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    return ret_fd;
382408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall}
383408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif
384408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint service_to_fd(const char *name)
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret = -1;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strncmp(name, "tcp:", 4)) {
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int port = atoi(name + 4);
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name = strchr(name + 4, ':');
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(name == 0) {
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = socket_loopback_client(port, SOCK_STREAM);
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret >= 0)
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                disable_tcp_nagle(ret);
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = socket_network_client(name + 1, port, SOCK_STREAM);
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "local:", 6)) {
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = socket_local_client(name + 6,
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "localreserved:", 14)) {
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = socket_local_client(name + 14,
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "localabstract:", 14)) {
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = socket_local_client(name + 14,
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "localfilesystem:", 16)) {
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = socket_local_client(name + 16,
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
4179470c2f1ab555311633d52e5ed8303a813061cdfBenoit Goby#if !ADB_HOST
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp("dev:", name, 4)) {
419fe8d7f4f2e775d46d61f7c2d29a4e852434984daNick Kralevich        ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "framebuffer:", 12)) {
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = create_service_thread(framebuffer_service, 0);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(name, "jdwp:", 5)) {
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = create_jdwp_connection_fd(atoi(name+5));
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!HOST && !strncmp(name, "shell:", 6)) {
4255d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        ret = create_subproc_thread(name + 6, SUBPROC_PTY);
4265d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey    } else if(!HOST && !strncmp(name, "exec:", 5)) {
4275d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        ret = create_subproc_thread(name + 5, SUBPROC_RAW);
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "sync:", 5)) {
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = create_service_thread(file_sync_service, NULL);
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if(!strncmp(name, "remount:", 8)) {
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = create_service_thread(remount_service, NULL);
432ee15662140632672a6878787a1ff26f5ebdc1e68Mike Lockwood    } else if(!strncmp(name, "reboot:", 7)) {
433b6b40079e6d5b32026cc2abfcb71adfd49e8d954Mike Lockwood        void* arg = strdup(name + 7);
4345d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        if (arg == NULL) return -1;
435b6b40079e6d5b32026cc2abfcb71adfd49e8d954Mike Lockwood        ret = create_service_thread(reboot_service, arg);
436e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project    } else if(!strncmp(name, "root:", 5)) {
437e037fd7e193ecccbb5c0888e49f6d58c224bc11dThe Android Open Source Project        ret = create_service_thread(restart_root_service, NULL);
438d2f5415c603f7d9961f7a0b05579a0768e071410Christopher Tate    } else if(!strncmp(name, "backup:", 7)) {
4395d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        char* arg = strdup(name + 7);
440d2f5415c603f7d9961f7a0b05579a0768e071410Christopher Tate        if (arg == NULL) return -1;
4415d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        char* c = arg;
4425d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        for (; *c != '\0'; c++) {
4435d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey            if (*c == ':')
4445d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey                *c = ' ';
4455d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        }
4465d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        char* cmd;
4475d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        if (asprintf(&cmd, "/system/bin/bu backup %s", arg) != -1) {
4485d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey            ret = create_subproc_thread(cmd, SUBPROC_RAW);
4495d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey            free(cmd);
4505d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        }
4515d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        free(arg);
452702967afb1bebc97c0b8a23c075d4932820ef7a3Christopher Tate    } else if(!strncmp(name, "restore:", 8)) {
4535d9d434efadf1c535c7fea634d5306e18c68ef1fJeff Sharkey        ret = create_subproc_thread("/system/bin/bu restore", SUBPROC_RAW);
454ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    } else if(!strncmp(name, "tcpip:", 6)) {
455ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        int port;
456ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        if (sscanf(name + 6, "%d", &port) == 0) {
457ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood            port = 0;
458ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        }
459ccecf1425412beb2bc3bb38d470293fdc244d6f1Elliott Hughes        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
460ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood    } else if(!strncmp(name, "usb:", 4)) {
461ff19670d485fd5ee296e23b00b035ac22975c647Mike Lockwood        ret = create_service_thread(restart_usb_service, NULL);
462252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    } else if (!strncmp(name, "reverse:", 8)) {
463252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        char* cookie = strdup(name + 8);
464252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (cookie == NULL) {
465252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            ret = -1;
466252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        } else {
467252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            ret = create_service_thread(reverse_service, cookie);
468252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            if (ret < 0) {
469252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                free(cookie);
470252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
471252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ret >= 0) {
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close_on_exec(ret);
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ret;
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct state_info {
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    transport_type transport;
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* serial;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int state;
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void wait_for_state(int fd, void* cookie)
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct state_info* sinfo = cookie;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* err = "unknown error";
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("wait_for_state %d\n", sinfo->state);
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(t != 0) {
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        writex(fd, "OKAY", 4);
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sendfailmsg(fd, err);
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (sinfo->serial)
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(sinfo->serial);
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(sinfo);
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_close(fd);
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("wait_for_state is done\n");
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
5071c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5081c45ee92e2372f3c552744823143fb093fdbda9dBenoit Gobystatic void connect_device(char* host, char* buffer, int buffer_size)
5091c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby{
5101c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    int port, fd;
5111c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char* portstr = strchr(host, ':');
5121c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char hostbuf[100];
5131c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char serial[100];
5141c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    int ret;
5151c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5161c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
5171c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (portstr) {
5181c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
5191c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby            snprintf(buffer, buffer_size, "bad host name %s", host);
5201c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby            return;
5211c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        }
5221c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        // zero terminate the host at the point we found the colon
5231c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        hostbuf[portstr - host] = 0;
5241c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        if (sscanf(portstr + 1, "%d", &port) == 0) {
5251c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby            snprintf(buffer, buffer_size, "bad port number %s", portstr);
5261c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby            return;
5271c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        }
5281c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    } else {
5291c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
5301c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5311c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5321c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
5331c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
534aecc6a6657746afc9b95a960eedad10484bf14acKen Lierman    fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
5351c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (fd < 0) {
5361c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
5371c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return;
5381c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5391c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5401c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    D("client: connected on remote on fd %d\n", fd);
5411c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    close_on_exec(fd);
5421c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    disable_tcp_nagle(fd);
5431c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5441c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    ret = register_socket_transport(fd, serial, port, 0);
5451c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (ret < 0) {
5461c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        adb_close(fd);
5471c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size, "already connected to %s", serial);
5481c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    } else {
5491c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size, "connected to %s", serial);
5501c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5511c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby}
5521c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5531c45ee92e2372f3c552744823143fb093fdbda9dBenoit Gobyvoid connect_emulator(char* port_spec, char* buffer, int buffer_size)
5541c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby{
5551c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char* port_separator = strchr(port_spec, ',');
5561c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (!port_separator) {
5571c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size,
5581c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                "unable to parse '%s' as <console port>,<adb port>",
5591c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                port_spec);
5601c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return;
5611c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5621c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5631c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    // Zero-terminate console port and make port_separator point to 2nd port.
5641c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    *port_separator++ = 0;
5651c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    int console_port = strtol(port_spec, NULL, 0);
5661c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    int adb_port = strtol(port_separator, NULL, 0);
5671c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (!(console_port > 0 && adb_port > 0)) {
5681c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        *(port_separator - 1) = ',';
5691c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size,
5701c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                "Invalid port numbers: Expected positive numbers, got '%s'",
5711c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                port_spec);
5721c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return;
5731c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5741c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5751c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    /* Check if the emulator is already known.
5761c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * Note: There's a small but harmless race condition here: An emulator not
5771c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * present just yet could be registered by another invocation right
5781c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * after doing this check here. However, local_connect protects
5791c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * against double-registration too. From here, a better error message
5801c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * can be produced. In the case of the race condition, the very specific
5811c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * error message won't be shown, but the data doesn't get corrupted. */
5821c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
5831c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (known_emulator != NULL) {
5841c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size,
5851c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                "Emulator on port %d already registered.", adb_port);
5861c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return;
5871c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5881c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5891c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    /* Check if more emulators can be registered. Similar unproblematic
5901c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby     * race condition as above. */
5911c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    int candidate_slot = get_available_local_transport_index();
5921c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (candidate_slot < 0) {
5931c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
5941c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return;
5951c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
5961c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
5971c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    /* Preconditions met, try to connect to the emulator. */
5981c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
5991c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size,
6001c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                "Connected to emulator on ports %d,%d", console_port, adb_port);
6011c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    } else {
6021c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        snprintf(buffer, buffer_size,
6031c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                "Could not connect to emulator on ports %d,%d",
6041c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby                console_port, adb_port);
6051c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
6061c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby}
6071c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
6081c45ee92e2372f3c552744823143fb093fdbda9dBenoit Gobystatic void connect_service(int fd, void* cookie)
6091c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby{
6101c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char buf[4096];
6111c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char resp[4096];
6121c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    char *host = cookie;
6131c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
6141c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    if (!strncmp(host, "emu:", 4)) {
6151c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        connect_emulator(host + 4, buf, sizeof(buf));
6161c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    } else {
6171c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        connect_device(host, buf, sizeof(buf));
6181c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    }
6191c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby
6201c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    // Send response for emulator and device
6211c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
6221c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    writex(fd, resp, strlen(resp));
6231c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    adb_close(fd);
6241c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby}
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectasocket*  host_service_to_socket(const char*  name, const char *serial)
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(name,"track-devices")) {
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_device_tracker();
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct state_info* sinfo = malloc(sizeof(struct state_info));
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serial)
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->serial = strdup(serial);
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->serial = NULL;
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name += strlen("wait-for-");
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(name, "local", strlen("local"))) {
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->transport = kTransportLocal;
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->state = CS_DEVICE;
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(name, "usb", strlen("usb"))) {
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->transport = kTransportUsb;
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->state = CS_DEVICE;
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(name, "any", strlen("any"))) {
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->transport = kTransportAny;
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sinfo->state = CS_DEVICE;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(sinfo);
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return NULL;
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int fd = create_service_thread(wait_for_state, sinfo);
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return create_local_socket(fd);
6581c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby    } else if (!strncmp(name, "connect:", 8)) {
6591c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        const char *host = name + 8;
6601c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        int fd = create_service_thread(connect_service, (void *)host);
6611c45ee92e2372f3c552744823143fb093fdbda9dBenoit Goby        return create_local_socket(fd);
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* ADB_HOST */
666