19b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris/*
29b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Copyright (C) 2009 The Android Open Source Project
39b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
49b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
59b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * you may not use this file except in compliance with the License.
69b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * You may obtain a copy of the License at
79b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
89b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
99b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris *
109b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * Unless required by applicable law or agreed to in writing, software
119b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
129b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * See the License for the specific language governing permissions and
149b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris * limitations under the License.
159b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris */
169b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
179b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <errno.h>
189b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <stdio.h>
199b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <sys/socket.h>
209b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <sys/types.h>
219b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <unistd.h>
229b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
239b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <cutils/properties.h>
249b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris#include <cutils/sockets.h>
259b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
269b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// This program will trigger the dumpstate service to start a call to
279b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// dumpstate, then connect to the dumpstate local client to read the
289b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// output. All of the dumpstate output is written to stdout, including
299b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris// any errors encountered while reading/writing the output.
309b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferrisint main() {
312628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
322628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme  fprintf(stderr, "=============================================================================\n");
332628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme  fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
342628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme  fprintf(stderr, "=============================================================================\n\n\n");
352628e9e939fda323fa44c5cb743f4a77b12a312aFelipe Leme
369b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Start the dumpstate service.
379b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  property_set("ctl.start", "dumpstate");
389b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
399b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Socket will not be available until service starts.
409b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  int s;
419b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  for (int i = 0; i < 20; i++) {
429b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
439b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                            SOCK_STREAM);
449b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    if (s >= 0)
459b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
469b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    // Try again in 1 second.
479b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    sleep(1);
489b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
499b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
509b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  if (s == -1) {
519b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    printf("Failed to connect to dumpstate service: %s\n", strerror(errno));
529b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    return 1;
539b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
549b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
559b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // Set a timeout so that if nothing is read in 3 minutes, we'll stop
569b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // reading and quit. No timeout in dumpstate is longer than 60 seconds,
579b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  // so this gives lots of leeway in case of unforeseen time outs.
589b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  struct timeval tv;
599b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  tv.tv_sec = 3 * 60;
609b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  tv.tv_usec = 0;
619b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
629b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
639b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
649b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
659b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  while (1) {
669b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    char buffer[65536];
679b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
689b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    if (bytes_read == 0) {
699b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
709b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    } else if (bytes_read == -1) {
719b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      // EAGAIN really means time out, so change the errno.
729b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      if (errno == EAGAIN) {
739b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        errno = ETIMEDOUT;
749b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      }
759b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      printf("\nBugreport read terminated abnormally (%s).\n", strerror(errno));
769b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      break;
779b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    }
789b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
799b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_to_send = bytes_read;
809b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    ssize_t bytes_written;
819b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    do {
829b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO,
839b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                                               buffer + bytes_read - bytes_to_send,
849b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris                                               bytes_to_send));
859b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      if (bytes_written == -1) {
869b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
879b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris               bytes_read, bytes_to_send, strerror(errno));
889b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris        return 1;
899b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      }
909b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris      bytes_to_send -= bytes_written;
919b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris    } while (bytes_written != 0 && bytes_to_send > 0);
929b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  }
939b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris
94997abb668b9248c2174c6cf169a0b7c6a02fd2cbElliott Hughes  close(s);
959b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris  return 0;
969b73bf07d73dbab5b792632e1e233edbad77f5fdChristopher Ferris}
97