1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <ftw.h>
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <getopt.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/stat.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <algorithm>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <vector>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/default_transport/client_channel_factory.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::default_transport::ClientChannelFactory;
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr long kClientTimeoutMs = 0;  // Don't wait for non-existent services.
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconstexpr int kDumpBufferSize = 2 * 4096;  // Two pages.
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ControlClient : public android::pdx::ClientBase<ControlClient> {
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit ControlClient(const std::string& service_path, long timeout_ms);
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void Reload();
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string Dump();
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ControlClient(const ControlClient&) = delete;
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const ControlClient&) = delete;
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkobool option_verbose = false;
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostatic struct option long_options[] = {
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    {"reload", required_argument, 0, 0},
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    {"dump", required_argument, 0, 0},
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    {"verbose", no_argument, 0, 0},
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    {0, 0, 0, 0},
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define printf_verbose(fmt, ... /*args*/) \
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  do {                                    \
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (option_verbose)                   \
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      printf(fmt, ##__VA_ARGS__);         \
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } while (0)
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid HexDump(const void* pointer, size_t length);
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoControlClient::ControlClient(const std::string& service_path, long timeout_ms)
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : BASE{ClientChannelFactory::Create(service_path), timeout_ms} {}
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid ControlClient::Reload() {
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::Transaction trans{*this};
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = trans.Send<void>(android::pdx::opcodes::REPORT_SYSPROP_CHANGE,
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                 nullptr, 0, nullptr, 0);
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    fprintf(stderr, "Failed to send reload: %s\n",
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            status.GetErrorMessage().c_str());
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::string ControlClient::Dump() {
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  android::pdx::Transaction trans{*this};
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::vector<char> buffer(kDumpBufferSize);
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto status = trans.Send<int>(android::pdx::opcodes::DUMP_STATE, nullptr, 0,
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                buffer.data(), buffer.size());
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf_verbose("ControlClient::Dump: ret=%d\n", ReturnStatusOrError(status));
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    fprintf(stderr, "Failed to send dump request: %s\n",
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            status.GetErrorMessage().c_str());
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return "";
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (status.get() > static_cast<ssize_t>(buffer.capacity())) {
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    fprintf(stderr, "Service returned a larger size than requested: %d\n",
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            status.get());
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return "";
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (option_verbose)
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    HexDump(buffer.data(), status.get());
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return std::string(buffer.data(), status.get());
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint Usage(const std::string& command_name) {
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("Usage: %s [options]\n", command_name.c_str());
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("\t--verbose                      : Use verbose messages.\n");
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf(
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      "\t--reload <all | service path>  : Ask service(s) to reload system "
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      "properties.\n");
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf("\t--dump <all | service path>    : Dump service(s) state.\n");
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return -1;
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkotypedef int (*CallbackType)(const char* path, const struct stat* sb,
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                            int type_flag, FTW* ftw_buffer);
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ReloadCommandCallback(const char* path, const struct stat* sb,
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                          int type_flag, FTW* ftw_buffer);
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint DumpCommandCallback(const char* path, const struct stat* sb, int type_flag,
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        FTW* ftw_buffer);
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid CallOnAllFiles(CallbackType callback, const std::string& base_path) {
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int kMaxDepth = 32;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  nftw(base_path.c_str(), callback, kMaxDepth, FTW_PHYS);
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ReloadCommand(const std::string& service_path) {
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf_verbose("ReloadCommand: service_path=%s\n", service_path.c_str());
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (service_path == "" || service_path == "all") {
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    CallOnAllFiles(ReloadCommandCallback,
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                   ClientChannelFactory::GetRootEndpointPath());
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto client = ControlClient::Create(service_path, kClientTimeoutMs);
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!client) {
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      fprintf(stderr, "Failed to open service at \"%s\".\n",
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              service_path.c_str());
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -1;
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
126e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    client->Reload();
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint DumpCommand(const std::string& service_path) {
132e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf_verbose("DumpCommand: service_path=%s\n", service_path.c_str());
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (service_path == "" || service_path == "all") {
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    CallOnAllFiles(DumpCommandCallback,
136e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                   ClientChannelFactory::GetRootEndpointPath());
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto client = ControlClient::Create(service_path, kClientTimeoutMs);
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!client) {
141e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      fprintf(stderr, "Failed to open service at \"%s\".\n",
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              service_path.c_str());
143e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return -1;
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    std::string response = client->Dump();
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (!response.empty()) {
148e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      printf(
149e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          "--------------------------------------------------------------------"
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          "---\n");
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      printf("%s:\n", service_path.c_str());
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      printf("%s\n", response.c_str());
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return 0;
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint ReloadCommandCallback(const char* path, const struct stat*, int type_flag,
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                          FTW*) {
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (type_flag == FTW_F)
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ReloadCommand(path);
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint DumpCommandCallback(const char* path, const struct stat*, int type_flag,
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        FTW*) {
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (type_flag == FTW_F)
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    DumpCommand(path);
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  return 0;
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkovoid HexDump(const void* pointer, size_t length) {
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uintptr_t address = reinterpret_cast<uintptr_t>(pointer);
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (size_t count = 0; count < length; count += 16, address += 16) {
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    printf("0x%08lx: ", static_cast<unsigned long>(address));
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < 16u; i++) {
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (i < std::min(length - count, static_cast<size_t>(16))) {
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        printf("%02x ", *reinterpret_cast<const uint8_t*>(address + i));
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      } else {
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        printf("   ");
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
186e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    printf("|");
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    for (size_t i = 0; i < 16u; i++) {
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      if (i < std::min(length - count, static_cast<size_t>(16))) {
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        char c = *reinterpret_cast<const char*>(address + i);
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (isalnum(c) || c == ' ') {
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          printf("%c", c);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        } else {
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          printf(".");
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        }
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      } else {
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        printf(" ");
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
200e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    printf("|\n");
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoint main(int argc, char** argv) {
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int getopt_code;
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int option_index;
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string option = "";
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string command = "";
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::string command_argument = "";
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Process command line options.
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  while ((getopt_code =
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
217e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    option = long_options[option_index].name;
218e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    printf_verbose("option=%s\n", option.c_str());
219e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    switch (getopt_code) {
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case 0:
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (option == "verbose") {
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          option_verbose = true;
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        } else {
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          command = option;
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          if (optarg)
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            command_argument = optarg;
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        }
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  printf_verbose("command=%s command_argument=%s\n", command.c_str(),
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                 command_argument.c_str());
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (command == "") {
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return Usage(argv[0]);
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (command == "reload") {
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReloadCommand(command_argument);
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else if (command == "dump") {
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return DumpCommand(command_argument);
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  } else {
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return Usage(argv[0]);
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
245