Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 1 | // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 5 | #include <string> |
| 6 | #include <vector> |
| 7 | |
| 8 | #include <base/command_line.h> |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 9 | #include <base/files/file_path.h> |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 10 | #include <base/logging.h> |
| 11 | #include <base/process/process.h> |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 12 | #include <base/strings/string_util.h> |
| 13 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 14 | #include <brillo/flag_helper.h> |
| 15 | |
| 16 | #include "syslog-cat/syslogcat.h" |
| 17 | |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 18 | namespace { |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 19 | constexpr char kDefaultSeverityStdout[] = "info"; |
| 20 | constexpr char kDefaultSeverityStderr[] = "warn"; |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 21 | constexpr char kSyslogSocketPath[] = "/run/rsyslogd/stdout"; |
| 22 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 23 | int SeverityFromString(const base::StringPiece& severity) { |
| 24 | std::string severity_lower = base::ToLowerASCII(severity); |
| 25 | if (severity_lower == "0" || severity_lower == "emerg") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 26 | return 0; |
| 27 | } |
| 28 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 29 | if (severity_lower == "1" || severity_lower == "alert") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 30 | return 1; |
| 31 | } |
| 32 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 33 | if (severity_lower == "2" || severity_lower == "critical" || |
| 34 | severity_lower == "crit") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 35 | return 2; |
| 36 | } |
| 37 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 38 | if (severity_lower == "3" || severity_lower == "err" || |
| 39 | severity_lower == "error") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 40 | return 3; |
| 41 | } |
| 42 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 43 | if (severity_lower == "4" || severity_lower == "warn" || |
| 44 | severity_lower == "warning") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 45 | return 4; |
| 46 | } |
| 47 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 48 | if (severity_lower == "5" || severity_lower == "notice") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 49 | return 5; |
| 50 | } |
| 51 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 52 | if (severity_lower == "6" || severity_lower == "info") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 53 | return 6; |
| 54 | } |
| 55 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 56 | if (severity_lower == "7" || severity_lower == "debug") { |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 57 | return 7; |
| 58 | } |
| 59 | |
| 60 | return -1; |
| 61 | } |
| 62 | |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 63 | } // namespace |
| 64 | |
| 65 | int main(int argc, char* argv[]) { |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 66 | DEFINE_string(identifier, "", "Identifier string of syslog"); |
| 67 | DEFINE_string(severity_stdout, kDefaultSeverityStdout, |
| 68 | "Severity value which is used in sendin stdout to syslog"); |
| 69 | DEFINE_string(severity_stderr, kDefaultSeverityStderr, |
| 70 | "Severity value which is used in sendin stderr to syslog"); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 71 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 72 | brillo::FlagHelper::Init( |
| 73 | argc, argv, |
| 74 | "Captures the stdout/stderr of the specified program and forward them " |
| 75 | "to syslog."); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 76 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 77 | const auto& sv = base::CommandLine::ForCurrentProcess()->GetArgs(); |
| 78 | if (sv.size() == 0) { |
| 79 | LOG(ERROR) << "Syslog-cat requres the command line to execute."; |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 80 | return 1; |
| 81 | } |
| 82 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 83 | const std::string& target_command = sv[0]; |
| 84 | |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 85 | // Prepare a identifier. |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 86 | std::string identifier = FLAGS_identifier; |
| 87 | if (identifier.empty()) { |
| 88 | // Fallback to the default. |
| 89 | identifier = base::FilePath(target_command).BaseName().value(); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 90 | } |
| 91 | if (identifier.empty()) { |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 92 | // Failed to fallback for some reason. |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 93 | LOG(ERROR) << "Failed to extract a identifier string."; |
| 94 | return 1; |
| 95 | } |
| 96 | |
| 97 | // Prepare a severity for stdout. |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 98 | int severity_stdout = SeverityFromString(FLAGS_severity_stdout); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 99 | if (severity_stdout < 0) { |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 100 | LOG(ERROR) << "Invalid --severity_stdout value '" << severity_stdout |
| 101 | << "'. It must be a number between 0 (EMERG) and 7 (DEBUG) or " |
| 102 | "valid severity string."; |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 103 | return 1; |
| 104 | } |
| 105 | |
| 106 | // Prepare a severity for stderr. |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 107 | int severity_stderr = SeverityFromString(FLAGS_severity_stderr); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 108 | if (severity_stderr < 0) { |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 109 | LOG(ERROR) << "Invalid --severity_stderr value '" << severity_stderr |
| 110 | << "'. It must be a number between 0 (EMERG) and 7 (DEBUG) or " |
| 111 | "valid severity string."; |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 112 | return 1; |
| 113 | } |
| 114 | |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 115 | // Prepare a command line for the target process. |
| 116 | int target_command_argc = sv.size(); |
| 117 | std::vector<const char*> target_command_argv(target_command_argc + 1); |
| 118 | for (int i = 0; i < target_command_argc; i++) |
| 119 | target_command_argv[i] = sv[i].c_str(); |
| 120 | target_command_argv[target_command_argc] = nullptr; |
| 121 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 122 | ExecuteCommandWithRedirection(target_command, target_command_argv, identifier, |
| 123 | severity_stdout, severity_stderr, |
| 124 | base::FilePath(kSyslogSocketPath), |
| 125 | base::FilePath(kSyslogSocketPath)); |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 126 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 127 | // The method above should never return unless an error happens. |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 128 | |
Yoshiki Iguchi | c4ac5f9 | 2020-12-01 04:17:45 +0900 | [diff] [blame] | 129 | // Crashes itself by the FATAL error message. |
| 130 | LOG(FATAL) << "Executing the command is unexpectedly failed."; |
Yoshiki Iguchi | a10d37f | 2020-08-24 12:54:11 +0900 | [diff] [blame] | 131 | } |