blob: 01a81f1ee1982aacbdb25b5d8b43e2507837d259 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crash-reporter/crash_sender_util.h"
#include <stdlib.h>
#include <map>
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/flag_helper.h>
#include "crash-reporter/crash_sender_paths.h"
#include "crash-reporter/paths.h"
namespace util {
namespace {
// getenv() wrapper that returns an empty string, if the environment variable is
// not defined.
std::string GetEnv(const std::string& name) {
const char* value = getenv(name.c_str());
return value ? value : "";
}
// Shows the usage of crash_sender and exits the process as a success.
void ShowUsageAndExit() {
printf(
"Usage: crash_sender [options]\n"
"Options:\n"
" -e <var>=<val> Set env |var| to |val| (only some vars)\n");
exit(EXIT_SUCCESS);
}
} // namespace
void ParseCommandLine(int argc, const char* const* argv) {
std::map<std::string, std::string> env_vars;
for (const EnvPair& pair : kEnvironmentVariables) {
// Honor the existing value if it's already set.
const char* value = getenv(pair.name);
env_vars[pair.name] = value ? value : pair.value;
}
// Process -e options, and collect other options.
std::vector<const char*> new_argv;
new_argv.push_back(argv[0]);
for (int i = 1; i < argc; ++i) {
if (std::string(argv[i]) == "-e") {
if (i + 1 < argc) {
++i;
std::string name_value = argv[i];
std::vector<std::string> pair = base::SplitString(
name_value, "=", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
if (pair.size() == 2) {
if (env_vars.count(pair[0]) == 0) {
LOG(ERROR) << "Unknown variable name: " << pair[0];
exit(EXIT_FAILURE);
}
env_vars[pair[0]] = pair[1];
} else {
LOG(ERROR) << "Malformed value for -e: " << name_value;
exit(EXIT_FAILURE);
}
} else {
LOG(ERROR) << "Value for -e is missing";
exit(EXIT_FAILURE);
}
} else {
new_argv.push_back(argv[i]);
}
}
// argv[argc] should be a null pointer per the C standard.
new_argv.push_back(nullptr);
// Process the remaining flags.
DEFINE_bool(h, false, "Show this help and exit");
brillo::FlagHelper::Init(new_argv.size() - 1, new_argv.data(),
"Chromium OS Crash Sender");
// TODO(satorux): Remove this once -e option is gone.
if (FLAGS_h)
ShowUsageAndExit();
// Set the predefined environment variables.
for (const auto& it : env_vars)
setenv(it.first.c_str(), it.second.c_str(), 1 /* overwrite */);
}
bool IsMock() {
return base::PathExists(
paths::GetAt(paths::kSystemRunStateDirectory, paths::kMockCrashSending));
}
bool ShouldPauseSending() {
return (base::PathExists(paths::Get(paths::kPauseCrashSending)) &&
GetEnv("OVERRIDE_PAUSE_SENDING") == "0");
}
} // namespace util