adb: rationalize fatal/error logging.

Let's use LOG(FATAL)/PLOG(FATAL) for actual fatal stuff.

Add a Windows error(3) and move folks who didn't really mean "abort"
fatal over to it. Also get rid of syntax_error which wasn't adding a
lot of value, and most of the places it was adding "usage: " didn't seem
entirely appropriate anyway.

In particular, we seemed to have confused fastdeploy.cpp into aborting
in most user error cases, and none of the reviewers noticed. Clearly
we'd all lost track of far too many options.

(I've also cleaned up a few random instances of fprintf(3) + exit(2).)

Bug: N/A
Test: manual
Change-Id: I3e8440848a24e30d928de9eded505916bc324786
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 62e8908..9c0eeca 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -73,39 +73,6 @@
         android::base::GetExecutablePath().c_str());
 }
 
-void fatal(const char *fmt, ...) {
-    va_list ap;
-    va_start(ap, fmt);
-    char buf[1024];
-    vsnprintf(buf, sizeof(buf), fmt, ap);
-
-#if ADB_HOST
-    fprintf(stderr, "error: %s\n", buf);
-#else
-    LOG(ERROR) << "error: " << buf;
-#endif
-
-    va_end(ap);
-    abort();
-}
-
-void fatal_errno(const char* fmt, ...) {
-    int err = errno;
-    va_list ap;
-    va_start(ap, fmt);
-    char buf[1024];
-    vsnprintf(buf, sizeof(buf), fmt, ap);
-
-#if ADB_HOST
-    fprintf(stderr, "error: %s: %s\n", buf, strerror(err));
-#else
-    LOG(ERROR) << "error: " << buf << ": " << strerror(err);
-#endif
-
-    va_end(ap);
-    abort();
-}
-
 uint32_t calculate_apacket_checksum(const apacket* p) {
     uint32_t sum = 0;
     for (size_t i = 0; i < p->msg.data_length; ++i) {
@@ -118,7 +85,7 @@
 {
     apacket* p = new apacket();
     if (p == nullptr) {
-      fatal("failed to allocate an apacket");
+        LOG(FATAL) << "failed to allocate an apacket";
     }
 
     memset(&p->msg, 0, sizeof(p->msg));
diff --git a/adb/adb.h b/adb/adb.h
index f434e2d..e2911e8 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -124,9 +124,6 @@
 
 void print_packet(const char* label, apacket* p);
 
-void fatal(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
-void fatal_errno(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
-
 void handle_packet(apacket* p, atransport* t);
 
 int launch_server(const std::string& socket_spec);
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 437720e..bc184c5 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -57,11 +57,11 @@
 void close_stdin() {
     int fd = unix_open(kNullFileName, O_RDONLY);
     if (fd == -1) {
-        fatal_errno("failed to open %s", kNullFileName);
+        PLOG(FATAL) << "failed to open " << kNullFileName;
     }
 
     if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
-        fatal_errno("failed to redirect stdin to %s", kNullFileName);
+        PLOG(FATAL) << "failed to redirect stdin to " << kNullFileName;
     }
     unix_close(fd);
 }
@@ -316,18 +316,6 @@
     return android_dir;
 }
 
-int syntax_error(const char* fmt, ...) {
-    fprintf(stderr, "adb: usage: ");
-
-    va_list ap;
-    va_start(ap, fmt);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-
-    fprintf(stderr, "\n");
-    return 1;
-}
-
 std::string GetLogFilePath() {
 #if defined(_WIN32)
     const char log_name[] = "adb.log";
@@ -337,13 +325,13 @@
     DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path);
     if (nchars >= arraysize(temp_path) || nchars == 0) {
         // If string truncation or some other error.
-        fatal("cannot retrieve temporary file path: %s\n",
-              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        LOG(FATAL) << "cannot retrieve temporary file path: "
+                   << android::base::SystemErrorCodeToString(GetLastError());
     }
 
     std::string temp_path_utf8;
     if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) {
-        fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8");
+        PLOG(FATAL) << "cannot convert temporary file path from UTF-16 to UTF-8";
     }
 
     return temp_path_utf8 + log_name;
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index ad83302..442ca2b 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -26,8 +26,6 @@
 
 #include "adb.h"
 
-int syntax_error(const char*, ...) __attribute__((__format__(__printf__, 1, 2)));
-
 void close_stdin();
 
 bool getcwd(std::string* cwd);
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index d69dbef..e1b75b0 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -134,7 +134,7 @@
     // The last argument must be the APK file
     const char* file = argv[argc - 1];
     if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
-        return syntax_error("filename doesn't end .apk: %s", file);
+        error(1, 0, "filename doesn't end .apk: %s", file);
     }
 
     if (use_fastdeploy == true) {
@@ -224,7 +224,7 @@
         }
     }
 
-    if (last_apk == -1) return syntax_error("need APK file on command line");
+    if (last_apk == -1) error(1, 0, "need APK file on command line");
 
     int result = -1;
     std::vector<const char*> apk_file = {argv[last_apk]};
@@ -311,7 +311,7 @@
     }
 
     if (installMode == INSTALL_STREAM && _use_legacy_install() == true) {
-        return syntax_error("Attempting to use streaming install on unsupported deivce.");
+        error(1, 0, "Attempting to use streaming install on unsupported device");
     }
 
     if (use_fastdeploy == true && is_reinstall == false) {
@@ -370,7 +370,7 @@
         }
     }
 
-    if (first_apk == -1) return syntax_error("need APK file on command line");
+    if (first_apk == -1) error(1, 0, "need APK file on command line");
 
     std::string install_cmd;
     if (_use_legacy_install()) {
diff --git a/adb/client/bugreport.cpp b/adb/client/bugreport.cpp
index fe98737..83eb157 100644
--- a/adb/client/bugreport.cpp
+++ b/adb/client/bugreport.cpp
@@ -197,7 +197,7 @@
 };
 
 int Bugreport::DoIt(int argc, const char** argv) {
-    if (argc > 2) return syntax_error("adb bugreport [PATH]");
+    if (argc > 2) error(1, 0, "usage: adb bugreport [PATH]");
 
     // Gets bugreportz version.
     std::string bugz_stdout, bugz_stderr;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 07b5747..0e03201 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -71,8 +71,7 @@
 static std::string product_file(const std::string& file) {
     const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
     if (ANDROID_PRODUCT_OUT == nullptr) {
-        fprintf(stderr, "adb: product directory not specified; set $ANDROID_PRODUCT_OUT\n");
-        exit(1);
+        error(1, 0, "product directory not specified; set $ANDROID_PRODUCT_OUT");
     }
     return std::string{ANDROID_PRODUCT_OUT} + OS_PATH_SEPARATOR_STR + file;
 }
@@ -318,7 +317,7 @@
 #ifdef _WIN32
         old_stdin_mode = _setmode(STDIN_FILENO, _O_BINARY);
         if (old_stdin_mode == -1) {
-            fatal_errno("could not set stdin to binary");
+            PLOG(FATAL) << "could not set stdin to binary";
         }
 #endif
     }
@@ -327,7 +326,7 @@
     if (outFd == STDOUT_FILENO) {
         old_stdout_mode = _setmode(STDOUT_FILENO, _O_BINARY);
         if (old_stdout_mode == -1) {
-            fatal_errno("could not set stdout to binary");
+            PLOG(FATAL) << "could not set stdout to binary";
         }
     }
 #endif
@@ -338,7 +337,7 @@
         stdin_raw_restore();
 #ifdef _WIN32
         if (_setmode(STDIN_FILENO, old_stdin_mode) == -1) {
-            fatal_errno("could not restore stdin mode");
+            PLOG(FATAL) << "could not restore stdin mode";
         }
 #endif
     }
@@ -346,7 +345,7 @@
 #ifdef _WIN32
     if (outFd == STDOUT_FILENO) {
         if (_setmode(STDOUT_FILENO, old_stdout_mode) == -1) {
-            fatal_errno("could not restore stdout mode");
+            PLOG(FATAL) << "could not restore stdout mode";
         }
     }
 #endif
@@ -660,9 +659,9 @@
 
 static int adb_shell(int argc, const char** argv) {
     FeatureSet features;
-    std::string error;
-    if (!adb_get_feature_set(&features, &error)) {
-        fprintf(stderr, "error: %s\n", error.c_str());
+    std::string error_message;
+    if (!adb_get_feature_set(&features, &error_message)) {
+        fprintf(stderr, "error: %s\n", error_message.c_str());
         return 1;
     }
 
@@ -685,7 +684,7 @@
         switch (opt) {
             case 'e':
                 if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
-                    return syntax_error("-e requires a single-character argument or 'none'");
+                    error(1, 0, "-e requires a single-character argument or 'none'");
                 }
                 escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
                 break;
@@ -933,31 +932,29 @@
  */
 static int ppp(int argc, const char** argv) {
 #if defined(_WIN32)
-    fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
-    return -1;
+    error(1, 0, "adb %s not implemented on Win32", argv[0]);
+    __builtin_unreachable();
 #else
-    if (argc < 2) return syntax_error("adb %s <adb service name> [ppp opts]", argv[0]);
+    if (argc < 2) error(1, 0, "usage: adb %s <adb service name> [ppp opts]", argv[0]);
 
     const char* adb_service_name = argv[1];
-    std::string error;
-    int fd = adb_connect(adb_service_name, &error);
+    std::string error_message;
+    int fd = adb_connect(adb_service_name, &error_message);
     if (fd < 0) {
-        fprintf(stderr, "adb: could not open adb service %s: %s\n", adb_service_name, error.c_str());
-        return 1;
+        error(1, 0, "could not open adb service %s: %s", adb_service_name, error_message.c_str());
     }
 
     pid_t pid = fork();
+    if (pid == -1) {
+        error(1, errno, "fork failed");
+    }
 
-    if (pid < 0) {
-        perror("from fork()");
-        return 1;
-    } else if (pid == 0) {
-        int err;
+    if (pid == 0) {
+        // child side
         int i;
-        const char **ppp_args;
 
         // copy args
-        ppp_args = (const char **) alloca(sizeof(char *) * argc + 1);
+        const char** ppp_args = (const char**)alloca(sizeof(char*) * argc + 1);
         ppp_args[0] = "pppd";
         for (i = 2 ; i < argc ; i++) {
             //argv[2] and beyond become ppp_args[1] and beyond
@@ -965,25 +962,18 @@
         }
         ppp_args[i-1] = nullptr;
 
-        // child side
-
         dup2(fd, STDIN_FILENO);
         dup2(fd, STDOUT_FILENO);
         adb_close(STDERR_FILENO);
         adb_close(fd);
 
-        err = execvp("pppd", (char * const *)ppp_args);
-
-        if (err < 0) {
-            perror("execing pppd");
-        }
-        exit(-1);
-    } else {
-        // parent side
-
-        adb_close(fd);
-        return 0;
+        execvp("pppd", (char* const*)ppp_args);
+        error(1, errno, "exec pppd failed");
     }
+
+    // parent side
+    adb_close(fd);
+    return 0;
 #endif /* !defined(_WIN32) */
 }
 
@@ -1161,7 +1151,7 @@
     /* find, extract, and use any -f argument */
     for (int i = 1; i < argc; i++) {
         if (!strcmp("-f", argv[i])) {
-            if (i == argc - 1) return syntax_error("backup -f passed with no filename");
+            if (i == argc - 1) error(1, 0, "backup -f passed with no filename");
             filename = argv[i+1];
             for (int j = i+2; j <= argc; ) {
                 argv[i++] = argv[j++];
@@ -1173,7 +1163,7 @@
 
     // Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
     // a list of packages is required.
-    if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
+    if (argc < 2) error(1, 0, "backup either needs a list of packages or -all/-shared");
 
     adb_unlink(filename);
     int outFd = adb_creat(filename, 0640);
@@ -1209,7 +1199,7 @@
 }
 
 static int restore(int argc, const char** argv) {
-    if (argc != 2) return syntax_error("restore requires an argument");
+    if (argc != 2) error(1, 0, "restore requires an argument");
 
     const char* filename = argv[1];
     int tarFd = adb_open(filename, O_RDONLY);
@@ -1263,8 +1253,7 @@
             } else if (!strcmp(*arg, "--")) {
                 ignore_flags = true;
             } else {
-                syntax_error("unrecognized option '%s'", *arg);
-                exit(1);
+                error(1, 0, "unrecognized option '%s'", *arg);
             }
         }
         ++arg;
@@ -1342,7 +1331,7 @@
             /* this is a special flag used only when the ADB client launches the ADB Server */
             is_daemon = true;
         } else if (!strcmp(argv[0], "--reply-fd")) {
-            if (argc < 2) return syntax_error("--reply-fd requires an argument");
+            if (argc < 2) error(1, 0, "--reply-fd requires an argument");
             const char* reply_fd_str = argv[1];
             argc--;
             argv++;
@@ -1355,7 +1344,7 @@
             if (isdigit(argv[0][2])) {
                 serial = argv[0] + 2;
             } else {
-                if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
+                if (argc < 2 || argv[0][2] != '\0') error(1, 0, "-s requires an argument");
                 serial = argv[1];
                 argc--;
                 argv++;
@@ -1371,7 +1360,7 @@
             }
             transport_id = strtoll(id, const_cast<char**>(&id), 10);
             if (*id != '\0') {
-                return syntax_error("invalid transport id");
+                error(1, 0, "invalid transport id");
             }
         } else if (!strcmp(argv[0],"-d")) {
             transport_type = kTransportUsb;
@@ -1381,7 +1370,7 @@
             gListenAll = 1;
         } else if (!strncmp(argv[0], "-H", 2)) {
             if (argv[0][2] == '\0') {
-                if (argc < 2) return syntax_error("-H requires an argument");
+                if (argc < 2) error(1, 0, "-H requires an argument");
                 server_host_str = argv[1];
                 argc--;
                 argv++;
@@ -1390,7 +1379,7 @@
             }
         } else if (!strncmp(argv[0], "-P", 2)) {
             if (argv[0][2] == '\0') {
-                if (argc < 2) return syntax_error("-P requires an argument");
+                if (argc < 2) error(1, 0, "-P requires an argument");
                 server_port_str = argv[1];
                 argc--;
                 argv++;
@@ -1398,7 +1387,7 @@
                 server_port_str = argv[0] + 2;
             }
         } else if (!strcmp(argv[0], "-L")) {
-            if (argc < 2) return syntax_error("-L requires an argument");
+            if (argc < 2) error(1, 0, "-L requires an argument");
             server_socket_str = argv[1];
             argc--;
             argv++;
@@ -1411,7 +1400,7 @@
     }
 
     if ((server_host_str || server_port_str) && server_socket_str) {
-        return syntax_error("-L is incompatible with -H or -P");
+        error(1, 0, "-L is incompatible with -H or -P");
     }
 
     // If -L, -H, or -P are specified, ignore environment variables.
@@ -1428,11 +1417,10 @@
         server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
         if (server_port_str && strlen(server_port_str) > 0) {
             if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
-                fprintf(stderr,
-                        "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive"
-                        " number less than 65535. Got \"%s\"\n",
-                        server_port_str);
-                exit(1);
+                error(1, 0,
+                      "$ANDROID_ADB_SERVER_PORT must be a positive number less than 65535: "
+                      "got \"%s\"",
+                      server_port_str);
             }
         }
 
@@ -1444,7 +1432,7 @@
             rc = asprintf(&temp, "tcp:%d", server_port);
         }
         if (rc < 0) {
-            fatal("failed to allocate server socket specification");
+            LOG(FATAL) << "failed to allocate server socket specification";
         }
         server_socket_str = temp;
     }
@@ -1506,7 +1494,7 @@
         } else if (argc == 2 && !strcmp(argv[1], "-l")) {
             listopt = argv[1];
         } else {
-            return syntax_error("adb devices [-l]");
+            error(1, 0, "adb devices [-l]");
         }
 
         std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
@@ -1514,13 +1502,13 @@
         return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "connect")) {
-        if (argc != 2) return syntax_error("adb connect <host>[:<port>]");
+        if (argc != 2) error(1, 0, "usage: adb connect <host>[:<port>]");
 
         std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
         return adb_query_command(query);
     }
     else if (!strcmp(argv[0], "disconnect")) {
-        if (argc > 2) return syntax_error("adb disconnect [<host>[:<port>]]");
+        if (argc > 2) error(1, 0, "usage: adb disconnect [<host>[:<port>]]");
 
         std::string query = android::base::StringPrintf("host:disconnect:%s",
                                                         (argc == 2) ? argv[1] : "");
@@ -1535,7 +1523,7 @@
     else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
         int exec_in = !strcmp(argv[0], "exec-in");
 
-        if (argc < 2) return syntax_error("adb %s command", argv[0]);
+        if (argc < 2) error(1, 0, "usage: adb %s command", argv[0]);
 
         std::string cmd = "exec:";
         cmd += argv[1];
@@ -1565,17 +1553,17 @@
         return adb_kill_server() ? 0 : 1;
     }
     else if (!strcmp(argv[0], "sideload")) {
-        if (argc != 2) return syntax_error("sideload requires an argument");
+        if (argc != 2) error(1, 0, "sideload requires an argument");
         if (adb_sideload_host(argv[1])) {
             return 1;
         } else {
             return 0;
         }
     } else if (!strcmp(argv[0], "tcpip")) {
-        if (argc != 2) return syntax_error("tcpip requires an argument");
+        if (argc != 2) error(1, 0, "tcpip requires an argument");
         int port;
         if (!android::base::ParseInt(argv[1], &port, 1, 65535)) {
-            return syntax_error("tcpip: invalid port: %s", argv[1]);
+            error(1, 0, "tcpip: invalid port: %s", argv[1]);
         }
         return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
     }
@@ -1607,7 +1595,7 @@
     } else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
         bool reverse = !strcmp(argv[0], "reverse");
         --argc;
-        if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
+        if (argc < 1) error(1, 0, "%s requires an argument", argv[0]);
         ++argv;
 
         // Determine the <host-prefix> for this command.
@@ -1626,46 +1614,44 @@
             }
         }
 
-        std::string cmd, error;
+        std::string cmd, error_message;
         if (strcmp(argv[0], "--list") == 0) {
-            if (argc != 1) return syntax_error("--list doesn't take any arguments");
+            if (argc != 1) error(1, 0, "--list doesn't take any arguments");
             return adb_query_command(host_prefix + ":list-forward");
         } else if (strcmp(argv[0], "--remove-all") == 0) {
-            if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
+            if (argc != 1) error(1, 0, "--remove-all doesn't take any arguments");
             cmd = host_prefix + ":killforward-all";
         } else if (strcmp(argv[0], "--remove") == 0) {
             // forward --remove <local>
-            if (argc != 2) return syntax_error("--remove requires an argument");
+            if (argc != 2) error(1, 0, "--remove requires an argument");
             cmd = host_prefix + ":killforward:" + argv[1];
         } else if (strcmp(argv[0], "--no-rebind") == 0) {
             // forward --no-rebind <local> <remote>
-            if (argc != 3) return syntax_error("--no-rebind takes two arguments");
-            if (forward_targets_are_valid(argv[1], argv[2], &error)) {
+            if (argc != 3) error(1, 0, "--no-rebind takes two arguments");
+            if (forward_targets_are_valid(argv[1], argv[2], &error_message)) {
                 cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
             }
         } else {
             // forward <local> <remote>
-            if (argc != 2) return syntax_error("forward takes two arguments");
-            if (forward_targets_are_valid(argv[0], argv[1], &error)) {
+            if (argc != 2) error(1, 0, "forward takes two arguments");
+            if (forward_targets_are_valid(argv[0], argv[1], &error_message)) {
                 cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
             }
         }
 
-        if (!error.empty()) {
-            fprintf(stderr, "error: %s\n", error.c_str());
-            return 1;
+        if (!error_message.empty()) {
+            error(1, 0, "error: %s", error_message.c_str());
         }
 
-        int fd = adb_connect(cmd, &error);
-        if (fd < 0 || !adb_status(fd, &error)) {
+        int fd = adb_connect(cmd, &error_message);
+        if (fd < 0 || !adb_status(fd, &error_message)) {
             adb_close(fd);
-            fprintf(stderr, "error: %s\n", error.c_str());
-            return 1;
+            error(1, 0, "error: %s", error_message.c_str());
         }
 
         // Server or device may optionally return a resolved TCP port number.
         std::string resolved_port;
-        if (ReadProtocolString(fd, &resolved_port, &error) && !resolved_port.empty()) {
+        if (ReadProtocolString(fd, &resolved_port, &error_message) && !resolved_port.empty()) {
             printf("%s\n", resolved_port.c_str());
         }
 
@@ -1674,7 +1660,7 @@
     }
     /* do_sync_*() commands */
     else if (!strcmp(argv[0], "ls")) {
-        if (argc != 2) return syntax_error("ls requires an argument");
+        if (argc != 2) error(1, 0, "ls requires an argument");
         return do_sync_ls(argv[1]) ? 0 : 1;
     }
     else if (!strcmp(argv[0], "push")) {
@@ -1684,7 +1670,7 @@
         const char* dst = nullptr;
 
         parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, &sync);
-        if (srcs.empty() || !dst) return syntax_error("push requires an argument");
+        if (srcs.empty() || !dst) error(1, 0, "push requires an argument");
         return do_sync_push(srcs, dst, sync) ? 0 : 1;
     }
     else if (!strcmp(argv[0], "pull")) {
@@ -1693,19 +1679,19 @@
         const char* dst = ".";
 
         parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, nullptr);
-        if (srcs.empty()) return syntax_error("pull requires an argument");
+        if (srcs.empty()) error(1, 0, "pull requires an argument");
         return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
     }
     else if (!strcmp(argv[0], "install")) {
-        if (argc < 2) return syntax_error("install requires an argument");
+        if (argc < 2) error(1, 0, "install requires an argument");
         return install_app(argc, argv);
     }
     else if (!strcmp(argv[0], "install-multiple")) {
-        if (argc < 2) return syntax_error("install-multiple requires an argument");
+        if (argc < 2) error(1, 0, "install-multiple requires an argument");
         return install_multiple_app(argc, argv);
     }
     else if (!strcmp(argv[0], "uninstall")) {
-        if (argc < 2) return syntax_error("uninstall requires an argument");
+        if (argc < 2) error(1, 0, "uninstall requires an argument");
         return uninstall_app(argc, argv);
     }
     else if (!strcmp(argv[0], "sync")) {
@@ -1719,7 +1705,7 @@
         } else if (argc == 2) {
             src = argv[1];
         } else {
-            return syntax_error("adb sync [-l] [PARTITION]");
+            error(1, 0, "usage: adb sync [-l] [PARTITION]");
         }
 
         if (src.empty()) src = "all";
@@ -1734,7 +1720,8 @@
                 if (!do_sync_sync(src_dir, "/" + partition, list_only)) return 1;
             }
         }
-        return found ? 0 : syntax_error("don't know how to sync %s partition", src.c_str());
+        if (!found) error(1, 0, "don't know how to sync %s partition", src.c_str());
+        return 0;
     }
     /* passthrough commands */
     else if (!strcmp(argv[0],"get-state") ||
@@ -1765,7 +1752,7 @@
         return restore(argc, argv);
     }
     else if (!strcmp(argv[0], "keygen")) {
-        if (argc != 2) return syntax_error("keygen requires an argument");
+        if (argc != 2) error(1, 0, "keygen requires an argument");
         // Always print key generation information for keygen command.
         adb_trace_enable(AUTH);
         return adb_auth_keygen(argv[1]);
@@ -1780,7 +1767,7 @@
         return adb_connect_command("host:track-devices");
     } else if (!strcmp(argv[0], "raw")) {
         if (argc != 2) {
-            return syntax_error("adb raw SERVICE");
+            error(1, 0, "usage: adb raw SERVICE");
         }
         return adb_connect_command(argv[1]);
     }
@@ -1823,11 +1810,11 @@
                 std::string err;
                 return adb_query_command("host:reconnect-offline");
             } else {
-                return syntax_error("adb reconnect [device|offline]");
+                error(1, 0, "usage: adb reconnect [device|offline]");
             }
         }
     }
 
-    syntax_error("unknown command %s", argv[0]);
-    return 1;
+    error(1, 0, "unknown command %s", argv[0]);
+    __builtin_unreachable();
 }
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index 183a1fa..933b913 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -27,6 +27,7 @@
 #include "client/file_sync_client.h"
 #include "commandline.h"
 #include "fastdeploycallbacks.h"
+#include "sysdeps.h"
 #include "utils/String16.h"
 
 static constexpr long kRequiredAgentVersion = 0x00000001;
@@ -72,13 +73,14 @@
 static std::string get_agent_component_host_path(const char* local_path, const char* sdk_path) {
     std::string adb_dir = android::base::GetExecutableDirectory();
     if (adb_dir.empty()) {
-        fatal("Could not determine location of adb!");
+        error(1, 0, "Could not determine location of adb!");
     }
 
     if (g_use_localagent) {
         const char* product_out = getenv("ANDROID_PRODUCT_OUT");
         if (product_out == nullptr) {
-            fatal("Could not locate %s because $ANDROID_PRODUCT_OUT is not defined", local_path);
+            error(1, 0, "Could not locate %s because $ANDROID_PRODUCT_OUT is not defined",
+                  local_path);
         }
         return android::base::StringPrintf("%s%s", product_out, local_path);
     } else {
@@ -103,10 +105,10 @@
                 android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentPath);
         int ret = send_shell_command(chmodCommand);
         if (ret != 0) {
-            fatal("Error executing %s returncode: %d", chmodCommand.c_str(), ret);
+            error(1, 0, "Error executing %s returncode: %d", chmodCommand.c_str(), ret);
         }
     } else {
-        fatal("Error pushing agent files to device");
+        error(1, 0, "Error pushing agent files to device");
     }
 
     return true;
@@ -136,7 +138,7 @@
 
     agent_version = get_agent_version();
     if (agent_version != kRequiredAgentVersion) {
-        fatal("After update agent version remains incorrect! Expected %ld but version is %ld",
+        error(1, 0, "After update agent version remains incorrect! Expected %ld but version is %ld",
               kRequiredAgentVersion, agent_version);
     }
 }
@@ -153,26 +155,28 @@
 }
 
 static std::string get_packagename_from_apk(const char* apkPath) {
+#undef open
     std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
+#define open ___xxx_unix_open
     if (zipFile == nullptr) {
-        fatal("Could not open %s", apkPath);
+        error(1, errno, "Could not open %s", apkPath);
     }
     android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
     if (entry == nullptr) {
-        fatal("Could not find AndroidManifest.xml inside %s", apkPath);
+        error(1, 0, "Could not find AndroidManifest.xml inside %s", apkPath);
     }
     uint32_t manifest_len = 0;
     if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
-        fatal("Could not read AndroidManifest.xml inside %s", apkPath);
+        error(1, 0, "Could not read AndroidManifest.xml inside %s", apkPath);
     }
     std::vector<char> manifest_data(manifest_len);
     if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
-        fatal("Could not uncompress AndroidManifest.xml inside %s", apkPath);
+        error(1, 0, "Could not uncompress AndroidManifest.xml inside %s", apkPath);
     }
     android::ResXMLTree tree;
     android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
     if (setto_status != android::OK) {
-        fatal("Could not parse AndroidManifest.xml inside %s", apkPath);
+        error(1, 0, "Could not parse AndroidManifest.xml inside %s", apkPath);
     }
     android::ResXMLParser::event_code_t code;
     while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
@@ -213,7 +217,8 @@
                 break;
         }
     }
-    fatal("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
+    error(1, 0, "Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
+    __builtin_unreachable();
 }
 
 void extract_metadata(const char* apkPath, FILE* outputFp) {
@@ -227,7 +232,7 @@
     DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
     int returnCode = send_shell_command(extractCommand, false, &cb);
     if (returnCode != 0) {
-        fatal("Executing %s returned %d\n", extractCommand.c_str(), returnCode);
+        error(1, 0, "Executing %s returned %d", extractCommand.c_str(), returnCode);
     }
 }
 
@@ -236,8 +241,9 @@
         // This should never happen on a Windows machine
         const char* host_out = getenv("ANDROID_HOST_OUT");
         if (host_out == nullptr) {
-            fatal("Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT is not "
-                  "defined");
+            error(1, 0,
+                  "Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT "
+                  "is not defined");
         }
         return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
                                            host_out);
@@ -245,7 +251,7 @@
 
     std::string adb_dir = android::base::GetExecutableDirectory();
     if (adb_dir.empty()) {
-        fatal("Could not locate deploypatchgenerator.jar");
+        error(1, 0, "Could not locate deploypatchgenerator.jar");
     }
     return android::base::StringPrintf(R"(java -jar "%s/deploypatchgenerator.jar")",
                                        adb_dir.c_str());
@@ -257,7 +263,7 @@
             patchPath);
     int returnCode = system(generatePatchCommand.c_str());
     if (returnCode != 0) {
-        fatal("Executing %s returned %d\n", generatePatchCommand.c_str(), returnCode);
+        error(1, 0, "Executing %s returned %d", generatePatchCommand.c_str(), returnCode);
     }
 }
 
@@ -276,7 +282,7 @@
     std::vector<const char*> srcs = {patchPath};
     bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
     if (!push_ok) {
-        fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
+        error(1, 0, "Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
     }
 
     std::string applyPatchCommand =
@@ -285,7 +291,7 @@
 
     int returnCode = send_shell_command(applyPatchCommand);
     if (returnCode != 0) {
-        fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+        error(1, 0, "Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
     }
 }
 
@@ -299,7 +305,7 @@
     std::vector<const char*> srcs{patchPath};
     bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
     if (!push_ok) {
-        fatal("Error pushing %s to %s returned\n", patchPath, patchDevicePath.c_str());
+        error(1, 0, "Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
     }
 
     std::vector<unsigned char> applyOutputBuffer;
@@ -316,6 +322,6 @@
                                         patchDevicePath.c_str(), argsString.c_str());
     int returnCode = send_shell_command(applyPatchCommand);
     if (returnCode != 0) {
-        fatal("Executing %s returned %d\n", applyPatchCommand.c_str(), returnCode);
+        error(1, 0, "Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
     }
 }
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index cb9bcfa..697d9ea 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -325,12 +325,12 @@
         memset(st, 0, sizeof(*st));
         if (have_stat_v2_) {
             if (!ReadFdExactly(fd, &msg.stat_v2, sizeof(msg.stat_v2))) {
-                fatal_errno("protocol fault: failed to read stat response");
+                PLOG(FATAL) << "protocol fault: failed to read stat response";
             }
 
             if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
-                fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
-                            msg.stat_v2.id);
+                PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
+                            << msg.stat_v2.id;
             }
 
             if (msg.stat_v2.error != 0) {
@@ -351,12 +351,12 @@
             return true;
         } else {
             if (!ReadFdExactly(fd, &msg.stat_v1, sizeof(msg.stat_v1))) {
-                fatal_errno("protocol fault: failed to read stat response");
+                PLOG(FATAL) << "protocol fault: failed to read stat response";
             }
 
             if (msg.stat_v1.id != ID_LSTAT_V1) {
-                fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
-                            msg.stat_v1.id);
+                PLOG(FATAL) << "protocol fault: stat response has wrong message id: "
+                            << msg.stat_v1.id;
             }
 
             if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index a7e454d..fb581a6 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -42,13 +42,13 @@
     const std::string log_file_path(GetLogFilePath());
     int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
     if (fd == -1) {
-        fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
+        PLOG(FATAL) << "cannot open " << log_file_path;
     }
     if (dup2(fd, STDOUT_FILENO) == -1) {
-        fatal("cannot redirect stdout: %s", strerror(errno));
+        PLOG(FATAL) << "cannot redirect stdout";
     }
     if (dup2(fd, STDERR_FILENO) == -1) {
-        fatal("cannot redirect stderr: %s", strerror(errno));
+        PLOG(FATAL) << "cannot redirect stderr";
     }
     unix_close(fd);
 
@@ -81,10 +81,10 @@
     // This also keeps stderr unbuffered when it is redirected to adb.log.
     if (is_daemon) {
         if (setvbuf(stdout, nullptr, _IONBF, 0) == -1) {
-            fatal("cannot make stdout unbuffered: %s", strerror(errno));
+            PLOG(FATAL) << "cannot make stdout unbuffered";
         }
         if (setvbuf(stderr, nullptr, _IONBF, 0) == -1) {
-            fatal("cannot make stderr unbuffered: %s", strerror(errno));
+            PLOG(FATAL) << "cannot make stderr unbuffered";
         }
     }
 
@@ -137,7 +137,7 @@
     while (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error) !=
            INSTALL_STATUS_OK) {
         if (std::chrono::steady_clock::now() - start > 0.5s) {
-            fatal("could not install *smartsocket* listener: %s", error.c_str());
+            LOG(FATAL) << "could not install *smartsocket* listener: " << error;
         }
 
         std::this_thread::sleep_for(100ms);
@@ -153,7 +153,7 @@
         // setsid will fail with EPERM if it's already been a lead process of new session.
         // Ignore such error.
         if (setsid() == -1 && errno != EPERM) {
-            fatal("setsid() failed: %s", strerror(errno));
+            PLOG(FATAL) << "setsid() failed";
         }
 #endif
 
@@ -171,19 +171,19 @@
             const DWORD bytes_to_write = arraysize(ack) - 1;
             DWORD written = 0;
             if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
-                fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
-                      android::base::SystemErrorCodeToString(GetLastError()).c_str());
+                LOG(FATAL) << "cannot write ACK to handle " << ack_reply_handle
+                           << android::base::SystemErrorCodeToString(GetLastError());
             }
             if (written != bytes_to_write) {
-                fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes", bytes_to_write,
-                      written);
+                LOG(FATAL) << "cannot write " << bytes_to_write << " bytes of ACK: only wrote "
+                           << written << " bytes";
             }
             CloseHandle(ack_reply_handle);
 #else
             // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
             // "OKAY".
             if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
-                fatal_errno("error writing ACK to fd %d", ack_reply_fd);
+                PLOG(FATAL) << "error writing ACK to fd " << ack_reply_fd;
             }
             unix_close(ack_reply_fd);
 #endif
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index 00aeb9b..cfa5cf4 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -212,8 +212,8 @@
     const HINSTANCE instance = GetModuleHandleW(nullptr);
     if (!instance) {
         // This is such a common API call that this should never fail.
-        fatal("GetModuleHandleW failed: %s",
-              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        LOG(FATAL) << "GetModuleHandleW failed: "
+                   << android::base::SystemErrorCodeToString(GetLastError());
     }
 
     WNDCLASSEXW wndclass;
@@ -223,15 +223,15 @@
     wndclass.hInstance = instance;
     wndclass.lpszClassName = kPowerNotificationWindowClassName;
     if (!RegisterClassExW(&wndclass)) {
-        fatal("RegisterClassExW failed: %s",
-              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        LOG(FATAL) << "RegisterClassExW failed: "
+                   << android::base::SystemErrorCodeToString(GetLastError());
     }
 
     if (!CreateWindowExW(WS_EX_NOACTIVATE, kPowerNotificationWindowClassName,
                          L"ADB Power Notification Window", WS_POPUP, 0, 0, 0, 0, nullptr, nullptr,
                          instance, nullptr)) {
-        fatal("CreateWindowExW failed: %s",
-              android::base::SystemErrorCodeToString(GetLastError()).c_str());
+        LOG(FATAL) << "CreateWindowExW failed: "
+                   << android::base::SystemErrorCodeToString(GetLastError());
     }
 
     MSG msg;
diff --git a/adb/daemon/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 8d28c49..586393e 100644
--- a/adb/daemon/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
@@ -78,7 +78,7 @@
         const char* command = "screencap";
         const char *args[2] = {command, nullptr};
         execvp(command, (char**)args);
-        exit(1);
+        error(1, errno, "exec screencap failed");
     }
 
     adb_close(fds[1]);
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index fe79acd..1363976 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -136,7 +136,7 @@
         this->fde = fdevent_create(socket, jdwp_process_event, this);
 
         if (!this->fde) {
-            fatal("could not create fdevent for new JDWP process");
+            LOG(FATAL) << "could not create fdevent for new JDWP process";
         }
 
         /* start by waiting for the PID */
@@ -200,7 +200,7 @@
     // Message is length-prefixed with 4 hex digits in ASCII.
     static constexpr size_t header_len = 4;
     if (bufferlen < header_len) {
-        fatal("invalid JDWP process list buffer size: %zu", bufferlen);
+        LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
     }
 
     char head[header_len + 1];
@@ -395,7 +395,7 @@
 
         auto proc = std::make_unique<JdwpProcess>(s);
         if (!proc) {
-            fatal("failed to allocate JdwpProcess");
+            LOG(FATAL) << "failed to allocate JdwpProcess";
         }
 
         _jdwp_list.emplace_back(std::move(proc));
@@ -454,7 +454,7 @@
     JdwpSocket* s = new JdwpSocket();
 
     if (!s) {
-        fatal("failed to allocate JdwpSocket");
+        LOG(FATAL) << "failed to allocate JdwpSocket";
     }
 
     install_local_socket(s);
@@ -531,7 +531,7 @@
 asocket* create_jdwp_tracker_service_socket(void) {
     auto t = std::make_unique<JdwpTracker>();
     if (!t) {
-        fatal("failed to allocate JdwpTracker");
+        LOG(FATAL) << "failed to allocate JdwpTracker";
     }
 
     memset(t.get(), 0, sizeof(asocket));
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 1534792..8b07f74 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -78,7 +78,7 @@
 
     // Socket ids should never be 0.
     if (local_socket_next_id == 0) {
-        fatal("local socket id overflow");
+        LOG(FATAL) << "local socket id overflow";
     }
 
     local_socket_list.push_back(s);
@@ -451,7 +451,7 @@
 // Returns a new non-NULL asocket handle.
 asocket* create_remote_socket(unsigned id, atransport* t) {
     if (id == 0) {
-        fatal("invalid remote socket id (0)");
+        LOG(FATAL) << "invalid remote socket id (0)";
     }
     asocket* s = new asocket();
     s->id = id;
@@ -477,9 +477,7 @@
     p->payload.assign(destination, destination + strlen(destination) + 1);
     p->msg.data_length = p->payload.size();
 
-    if (p->msg.data_length > s->get_max_payload()) {
-        fatal("destination oversized");
-    }
+    CHECK_LE(p->msg.data_length, s->get_max_payload());
 
     send_packet(p, s->transport);
 }
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index b8d7e06..bebf4e6 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -25,6 +25,7 @@
 #endif
 
 #include <errno.h>
+#include <error.h>
 
 #include <string>
 #include <vector>
@@ -69,6 +70,8 @@
 #define OS_PATH_SEPARATOR_STR "\\"
 #define ENV_PATH_SEPARATOR_STR ";"
 
+void error(int status, int error, const char* fmt, ...) __attribute__((__format__(printf, 3, 4)));
+
 static __inline__ bool adb_is_separator(char c) {
     return c == '\\' || c == '/';
 }
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 0a08fbb..af15241 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -35,6 +35,7 @@
 #include <cutils/sockets.h>
 
 #include <android-base/errors.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
@@ -46,8 +47,6 @@
 
 #include "sysdeps/uio.h"
 
-extern void fatal(const char *fmt, ...);
-
 /* forward declarations */
 
 typedef const struct FHClassRec_* FHClass;
@@ -98,11 +97,6 @@
 #undef assert
 #endif
 
-#define assert(cond)                                                                       \
-    do {                                                                                   \
-        if (!(cond)) fatal("assertion failed '%s' on %s:%d\n", #cond, __FILE__, __LINE__); \
-    } while (0)
-
 void handle_deleter::operator()(HANDLE h) {
     // CreateFile() is documented to return INVALID_HANDLE_FILE on error,
     // implying that NULL is a valid handle, but this is probably impossible.
@@ -730,8 +724,8 @@
         WSADATA wsaData;
         int rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
         if (rc != 0) {
-            fatal("adb: could not initialize Winsock: %s",
-                  android::base::SystemErrorCodeToString(rc).c_str());
+            LOG(FATAL) << "could not initialize Winsock: "
+                       << android::base::SystemErrorCodeToString(rc);
         }
 
         // Note that we do not call atexit() to register WSACleanup to be called
@@ -1287,11 +1281,11 @@
         }
 
         if (read_count == 0) {   // should be impossible
-            fatal("ReadConsoleInputA returned 0");
+            LOG(FATAL) << "ReadConsoleInputA returned 0";
         }
 
         if (read_count != 1) {   // should be impossible
-            fatal("ReadConsoleInputA did not return one input record");
+            LOG(FATAL) << "ReadConsoleInputA did not return one input record";
         }
 
         // If the console window is resized, emulate SIGWINCH by breaking out
@@ -1309,8 +1303,7 @@
         if ((input_record->EventType == KEY_EVENT) &&
             (input_record->Event.KeyEvent.bKeyDown)) {
             if (input_record->Event.KeyEvent.wRepeatCount == 0) {
-                fatal("ReadConsoleInputA returned a key event with zero repeat"
-                      " count");
+                LOG(FATAL) << "ReadConsoleInputA returned a key event with zero repeat count";
             }
 
             // Got an interesting INPUT_RECORD, so return
@@ -2193,7 +2186,7 @@
     for (int i = 0; i < argc; ++i) {
         std::string arg_narrow;
         if (!android::base::WideToUTF8(argv[i], &arg_narrow)) {
-            fatal_errno("cannot convert argument from UTF-16 to UTF-8");
+            PLOG(FATAL) << "cannot convert argument from UTF-16 to UTF-8";
         }
         narrow_args[i] = strdup(arg_narrow.c_str());
     }
@@ -2644,7 +2637,7 @@
         // If _wenviron is null, then -municode probably wasn't used. That
         // linker flag will cause the entry point to setup _wenviron. It will
         // also require an implementation of wmain() (which we provide above).
-        fatal("_wenviron is not set, did you link with -municode?");
+        LOG(FATAL) << "_wenviron is not set, did you link with -municode?";
     }
 
     // Read name/value pairs from UTF-16 _wenviron and write new name/value
@@ -2763,3 +2756,24 @@
 
     return 0;
 }
+
+void error(int status, int error, const char* fmt, ...) {
+    fflush(stdout);
+    fprintf(stderr, "%s: ", android::base::Basename(android::base::GetExecutablePath()).c_str());
+
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+
+    if (error != 0) {
+        fprintf(stderr, ": %s", strerror(error));
+    }
+
+    putc('\n', stderr);
+    fflush(stderr);
+
+    if (status != 0) {
+        exit(status);
+    }
+}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index d41f9c8..ac4ae98 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -420,7 +420,7 @@
     VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
 
     if (t == nullptr) {
-        fatal("Transport is null");
+        LOG(FATAL) << "Transport is null";
     }
 
     if (t->Write(p) != 0) {
@@ -526,7 +526,7 @@
 
 asocket* create_device_tracker(bool long_output) {
     device_tracker* tracker = new device_tracker();
-    if (tracker == nullptr) fatal("cannot allocate device tracker");
+    if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
 
     D("device tracker %p created", tracker);
 
@@ -632,7 +632,7 @@
     }
 
     if (transport_read_action(_fd, &m)) {
-        fatal_errno("cannot read transport registration socket");
+        PLOG(FATAL) << "cannot read transport registration socket";
     }
 
     t = m.transport;
@@ -706,7 +706,7 @@
     int s[2];
 
     if (adb_socketpair(s)) {
-        fatal_errno("cannot open transport registration socketpair");
+        PLOG(FATAL) << "cannot open transport registration socketpair";
     }
     D("socketpair: (%d,%d)", s[0], s[1]);
 
@@ -736,7 +736,7 @@
     m.action = 1;
     D("transport: %s registered", transport->serial.c_str());
     if (transport_write_action(transport_registration_send, &m)) {
-        fatal_errno("cannot write transport registration socket\n");
+        PLOG(FATAL) << "cannot write transport registration socket";
     }
 }
 
@@ -746,7 +746,7 @@
     m.action = 0;
     D("transport: %s removed", transport->serial.c_str());
     if (transport_write_action(transport_registration_send, &m)) {
-        fatal_errno("cannot write transport registration socket\n");
+        PLOG(FATAL) << "cannot write transport registration socket";
     }
 }
 
diff --git a/base/logging.cpp b/base/logging.cpp
index d60d91d..bd09069 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -53,6 +53,7 @@
 #include <unistd.h>
 #endif
 
+#include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
@@ -71,14 +72,8 @@
   static char progname[MAX_PATH] = {};
 
   if (first) {
-    CHAR longname[MAX_PATH];
-    DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname));
-    if ((nchars >= arraysize(longname)) || (nchars == 0)) {
-      // String truncation or some other error.
-      strcpy(progname, "<unknown>");
-    } else {
-      strcpy(progname, basename(longname));
-    }
+    snprintf(progname, sizeof(progname), "%s",
+             android::base::Basename(android::base::GetExecutablePath()).c_str());
     first = false;
   }