main.cpp revision 13a269ea24a98111d2e84a7ffa3c05ab8a4e73a9
1/*
2 * Copyright (C) 2015 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#define TRACE_TAG ADB
18
19#include "sysdeps.h"
20
21#include <signal.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25
26#include <thread>
27
28#include <android-base/errors.h>
29#include <android-base/file.h>
30#include <android-base/logging.h>
31#include <android-base/quick_exit.h>
32#include <android-base/stringprintf.h>
33
34#include "adb.h"
35#include "adb_auth.h"
36#include "adb_listeners.h"
37#include "adb_utils.h"
38#include "commandline.h"
39#include "sysdeps/chrono.h"
40#include "transport.h"
41
42static std::string GetLogFilePath() {
43#if defined(_WIN32)
44    const char log_name[] = "adb.log";
45    WCHAR temp_path[MAX_PATH];
46
47    // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx
48    DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path);
49    if (nchars >= arraysize(temp_path) || nchars == 0) {
50        // If string truncation or some other error.
51        fatal("cannot retrieve temporary file path: %s\n",
52              android::base::SystemErrorCodeToString(GetLastError()).c_str());
53    }
54
55    std::string temp_path_utf8;
56    if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) {
57        fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8");
58    }
59
60    return temp_path_utf8 + log_name;
61#else
62    const char* tmp_dir = getenv("TMPDIR");
63    if (tmp_dir == nullptr) tmp_dir = "/tmp";
64    return android::base::StringPrintf("%s/adb.%u.log", tmp_dir, getuid());
65#endif
66}
67
68static void setup_daemon_logging(void) {
69    const std::string log_file_path(GetLogFilePath());
70    int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
71    if (fd == -1) {
72        fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
73    }
74    if (dup2(fd, STDOUT_FILENO) == -1) {
75        fatal("cannot redirect stdout: %s", strerror(errno));
76    }
77    if (dup2(fd, STDERR_FILENO) == -1) {
78        fatal("cannot redirect stderr: %s", strerror(errno));
79    }
80    unix_close(fd);
81
82    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
83    LOG(INFO) << adb_version();
84}
85
86#if defined(_WIN32)
87static BOOL WINAPI ctrlc_handler(DWORD type) {
88    // TODO: Consider trying to kill a starting up adb server (if we're in
89    // launch_server) by calling GenerateConsoleCtrlEvent().
90    android::base::quick_exit(STATUS_CONTROL_C_EXIT);
91    return TRUE;
92}
93#endif
94
95int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
96#if defined(_WIN32)
97    // adb start-server starts us up with stdout and stderr hooked up to
98    // anonymous pipes. When the C Runtime sees this, it makes stderr and
99    // stdout buffered, but to improve the chance that error output is seen,
100    // unbuffer stdout and stderr just like if we were run at the console.
101    // This also keeps stderr unbuffered when it is redirected to adb.log.
102    if (is_daemon) {
103        if (setvbuf(stdout, NULL, _IONBF, 0) == -1) {
104            fatal("cannot make stdout unbuffered: %s", strerror(errno));
105        }
106        if (setvbuf(stderr, NULL, _IONBF, 0) == -1) {
107            fatal("cannot make stderr unbuffered: %s", strerror(errno));
108        }
109    }
110
111    SetConsoleCtrlHandler(ctrlc_handler, TRUE);
112#else
113    signal(SIGINT, [](int) {
114        android::base::quick_exit(0);
115    });
116#endif
117
118    init_transport_registration();
119
120    init_mdns_transport_discovery();
121
122    usb_init();
123    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
124
125    std::string error;
126
127    auto start = std::chrono::steady_clock::now();
128
129    // If we told a previous adb server to quit because of version mismatch, we can get to this
130    // point before it's finished exiting. Retry for a while to give it some time.
131    while (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error) !=
132           INSTALL_STATUS_OK) {
133        if (std::chrono::steady_clock::now() - start > 0.5s) {
134            fatal("could not install *smartsocket* listener: %s", error.c_str());
135        }
136
137        std::this_thread::sleep_for(100ms);
138    }
139
140    if (is_daemon) {
141        close_stdin();
142        setup_daemon_logging();
143    }
144
145    adb_auth_init();
146
147    if (is_daemon) {
148#if !defined(_WIN32)
149        // Start a new session for the daemon. Do this here instead of after the fork so
150        // that a ctrl-c between the "starting server" and "done starting server" messages
151        // gets a chance to terminate the server.
152        // setsid will fail with EPERM if it's already been a lead process of new session.
153        // Ignore such error.
154        if (setsid() == -1 && errno != EPERM) {
155            fatal("setsid() failed: %s", strerror(errno));
156        }
157#endif
158
159        // Inform our parent that we are up and running.
160
161        // Any error output written to stderr now goes to adb.log. We could
162        // keep around a copy of the stderr fd and use that to write any errors
163        // encountered by the following code, but that is probably overkill.
164#if defined(_WIN32)
165        const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
166        const CHAR ack[] = "OK\n";
167        const DWORD bytes_to_write = arraysize(ack) - 1;
168        DWORD written = 0;
169        if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
170            fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
171                  android::base::SystemErrorCodeToString(GetLastError()).c_str());
172        }
173        if (written != bytes_to_write) {
174            fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes",
175                  bytes_to_write, written);
176        }
177        CloseHandle(ack_reply_handle);
178#else
179        // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
180        // "OKAY".
181        if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
182            fatal_errno("error writing ACK to fd %d", ack_reply_fd);
183        }
184        unix_close(ack_reply_fd);
185#endif
186    }
187
188    D("Event loop starting");
189    fdevent_loop();
190
191    return 0;
192}
193
194int main(int argc, char** argv) {
195    adb_trace_init(argv);
196    return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
197}
198