12628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme/*
22628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Copyright (C) 2016 The Android Open Source Project
32628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme *
42628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
52628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * you may not use this file except in compliance with the License.
62628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * You may obtain a copy of the License at
72628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme *
82628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
92628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme *
102628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * Unless required by applicable law or agreed to in writing, software
112628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
122628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * See the License for the specific language governing permissions and
142628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme * limitations under the License.
152628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme */
162628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
172628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <errno.h>
18ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme#include <getopt.h>
192628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <stdio.h>
202628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <sys/socket.h>
212628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <sys/types.h>
222628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <unistd.h>
232628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
242628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <cutils/properties.h>
252628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme#include <cutils/sockets.h>
262628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
27ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic constexpr char VERSION[] = "1.0";
28ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme
29ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic void show_usage() {
30ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme  fprintf(stderr,
31ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme          "usage: bugreportz [-h | -v]\n"
32ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme          "  -h: to display this help message\n"
33ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme          "  -v: to display the version\n"
34ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme          "  or no arguments to generate a zipped bugreport\n");
35ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme}
36ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme
37ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemestatic void show_version() {
38ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme  fprintf(stderr, "%s\n", VERSION);
39ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme}
40ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme
41ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Lemeint main(int argc, char *argv[]) {
42ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme
43ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme    if (argc > 1) {
44ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        /* parse arguments */
45ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        int c;
46ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        while ((c = getopt(argc, argv, "vh")) != -1) {
47ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme            switch (c) {
48ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                case 'h':
49ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    show_usage();
50ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    return EXIT_SUCCESS;
51ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                case 'v':
52ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    show_version();
53ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    return EXIT_SUCCESS;
54ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                default:
55ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    show_usage();
56ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme                    return EXIT_FAILURE;
57ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme            }
58ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        }
59ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        // passed an argument not starting with -
60ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        if (optind > 1 || argv[optind] != nullptr) {
61ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme            show_usage();
62ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme            return EXIT_FAILURE;
63ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme        }
64ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme    }
65ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme
66ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme    // TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
67ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme    // should be reused instead.
682628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
692628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    // Start the dumpstatez service.
702628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    property_set("ctl.start", "dumpstatez");
712628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
722628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    // Socket will not be available until service starts.
732628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    int s;
742628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    for (int i = 0; i < 20; i++) {
752628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
762628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        if (s >= 0)
772628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            break;
782628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        // Try again in 1 second.
792628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        sleep(1);
802628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    }
812628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
822628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    if (s == -1) {
831634d841af26421a76ef4c723095786da6d350a4Felipe Leme        printf("FAIL:Failed to connect to dumpstatez service: %s\n", strerror(errno));
841634d841af26421a76ef4c723095786da6d350a4Felipe Leme        return EXIT_SUCCESS;
852628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    }
862628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
872628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    // Set a timeout so that if nothing is read in 10 minutes, we'll stop
882628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    // reading and quit. No timeout in dumpstate is longer than 60 seconds,
892628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    // so this gives lots of leeway in case of unforeseen time outs.
902628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    struct timeval tv;
912628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    tv.tv_sec = 10 * 60;
922628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    tv.tv_usec = 0;
932628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
941634d841af26421a76ef4c723095786da6d350a4Felipe Leme        fprintf(stderr, "WARNING: Cannot set socket timeout: %s\n", strerror(errno));
952628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    }
962628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
972628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    while (1) {
982628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        char buffer[65536];
992628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        ssize_t bytes_read = TEMP_FAILURE_RETRY(
1002628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                read(s, buffer, sizeof(buffer)));
1012628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        if (bytes_read == 0) {
1022628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            break;
1032628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        } else if (bytes_read == -1) {
1042628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            // EAGAIN really means time out, so change the errno.
1052628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            if (errno == EAGAIN) {
1062628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                errno = ETIMEDOUT;
1072628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            }
1081634d841af26421a76ef4c723095786da6d350a4Felipe Leme            printf("FAIL:Bugreport read terminated abnormally (%s)\n", strerror(errno));
1092628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            break;
1102628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        }
1112628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
1122628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        ssize_t bytes_to_send = bytes_read;
1132628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        ssize_t bytes_written;
1142628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        do {
1152628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            bytes_written = TEMP_FAILURE_RETRY(
1162628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                    write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send,
1172628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                            bytes_to_send));
1182628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            if (bytes_written == -1) {
1191634d841af26421a76ef4c723095786da6d350a4Felipe Leme                fprintf(stderr,
1202628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                        "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
1212628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme                        bytes_read, bytes_to_send, strerror(errno));
1221634d841af26421a76ef4c723095786da6d350a4Felipe Leme                break;
1232628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            }
1242628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme            bytes_to_send -= bytes_written;
1252628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme        } while (bytes_written != 0 && bytes_to_send > 0);
1262628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme    }
1272628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
1281634d841af26421a76ef4c723095786da6d350a4Felipe Leme    if (close(s) == -1) {
1291634d841af26421a76ef4c723095786da6d350a4Felipe Leme        fprintf(stderr, "WARNING: error closing socket: %s\n", strerror(errno));
1301634d841af26421a76ef4c723095786da6d350a4Felipe Leme    }
131ceeb64281d012cfac99827adbcdb5800b2ce0542Felipe Leme    return EXIT_SUCCESS;
1322628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme}
133