blob: 1a95c727fdd39af7d0c3e772cb99a7916316f902 [file] [log] [blame]
// Copyright 2020 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 <string>
#include <vector>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/process/process.h>
#include <base/strings/string_util.h>
#include <brillo/flag_helper.h>
#include "syslog-cat/syslogcat.h"
namespace {
constexpr char kDefaultSeverityStdout[] = "info";
constexpr char kDefaultSeverityStderr[] = "warn";
constexpr char kSyslogSocketPath[] = "/run/rsyslogd/stdout";
int SeverityFromString(const base::StringPiece& severity) {
std::string severity_lower = base::ToLowerASCII(severity);
if (severity_lower == "0" || severity_lower == "emerg") {
return 0;
}
if (severity_lower == "1" || severity_lower == "alert") {
return 1;
}
if (severity_lower == "2" || severity_lower == "critical" ||
severity_lower == "crit") {
return 2;
}
if (severity_lower == "3" || severity_lower == "err" ||
severity_lower == "error") {
return 3;
}
if (severity_lower == "4" || severity_lower == "warn" ||
severity_lower == "warning") {
return 4;
}
if (severity_lower == "5" || severity_lower == "notice") {
return 5;
}
if (severity_lower == "6" || severity_lower == "info") {
return 6;
}
if (severity_lower == "7" || severity_lower == "debug") {
return 7;
}
return -1;
}
} // namespace
int main(int argc, char* argv[]) {
DEFINE_string(identifier, "", "Identifier string of syslog");
DEFINE_string(severity_stdout, kDefaultSeverityStdout,
"Severity value which is used in sendin stdout to syslog");
DEFINE_string(severity_stderr, kDefaultSeverityStderr,
"Severity value which is used in sendin stderr to syslog");
brillo::FlagHelper::Init(
argc, argv,
"Captures the stdout/stderr of the specified program and forward them "
"to syslog.");
const auto& sv = base::CommandLine::ForCurrentProcess()->GetArgs();
if (sv.size() == 0) {
LOG(ERROR) << "Syslog-cat requres the command line to execute.";
return 1;
}
const std::string& target_command = sv[0];
// Prepare a identifier.
std::string identifier = FLAGS_identifier;
if (identifier.empty()) {
// Fallback to the default.
identifier = base::FilePath(target_command).BaseName().value();
}
if (identifier.empty()) {
// Failed to fallback for some reason.
LOG(ERROR) << "Failed to extract a identifier string.";
return 1;
}
// Prepare a severity for stdout.
int severity_stdout = SeverityFromString(FLAGS_severity_stdout);
if (severity_stdout < 0) {
LOG(ERROR) << "Invalid --severity_stdout value '" << severity_stdout
<< "'. It must be a number between 0 (EMERG) and 7 (DEBUG) or "
"valid severity string.";
return 1;
}
// Prepare a severity for stderr.
int severity_stderr = SeverityFromString(FLAGS_severity_stderr);
if (severity_stderr < 0) {
LOG(ERROR) << "Invalid --severity_stderr value '" << severity_stderr
<< "'. It must be a number between 0 (EMERG) and 7 (DEBUG) or "
"valid severity string.";
return 1;
}
// Prepare a command line for the target process.
int target_command_argc = sv.size();
std::vector<const char*> target_command_argv(target_command_argc + 1);
for (int i = 0; i < target_command_argc; i++)
target_command_argv[i] = sv[i].c_str();
target_command_argv[target_command_argc] = nullptr;
ExecuteCommandWithRedirection(target_command, target_command_argv, identifier,
severity_stdout, severity_stderr,
base::FilePath(kSyslogSocketPath),
base::FilePath(kSyslogSocketPath));
// The method above should never return unless an error happens.
// Crashes itself by the FATAL error message.
LOG(FATAL) << "Executing the command is unexpectedly failed.";
}