Serenity Operating System
at master 120 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, Alex Major 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <LibCore/ArgsParser.h> 9#include <LibCore/DirIterator.h> 10#include <LibCore/File.h> 11#include <LibMain/Main.h> 12 13static bool s_set_variable = false; 14 15static DeprecatedString get_variable(StringView name) 16{ 17 auto path = DeprecatedString::formatted("/sys/kernel/variables/{}", name); 18 auto file = Core::File::open(path, Core::File::OpenMode::Read); 19 if (file.is_error()) { 20 warnln("Failed to open {}: {}", path, file.error()); 21 return {}; 22 } 23 auto buffer = file.value()->read_until_eof(); 24 if (buffer.is_error()) { 25 warnln("Failed to read {}: {}", path, buffer.error()); 26 return {}; 27 } 28 return { (char const*)buffer.value().data(), buffer.value().size(), Chomp }; 29} 30 31static bool read_variable(StringView name) 32{ 33 auto value = get_variable(name); 34 if (value.is_null()) 35 return false; 36 outln("{} = {}", name, value); 37 return true; 38} 39 40static bool write_variable(StringView name, StringView value) 41{ 42 auto old_value = get_variable(name); 43 if (old_value.is_null()) 44 return false; 45 auto path = DeprecatedString::formatted("/sys/kernel/variables/{}", name); 46 auto file = Core::File::open(path, Core::File::OpenMode::Write); 47 if (file.is_error()) { 48 warnln("Failed to open {}: {}", path, file.error()); 49 return false; 50 } 51 if (auto result = file.value()->write_until_depleted(value.bytes()); result.is_error()) { 52 warnln("Failed to write {}: {}", path, result.error()); 53 return false; 54 } 55 outln("{}: {} -> {}", name, old_value, value); 56 return true; 57} 58 59static int handle_variables(Vector<StringView> const& variables) 60{ 61 bool success = false; 62 for (auto const& variable : variables) { 63 auto maybe_index = variable.find('='); 64 if (!maybe_index.has_value()) { 65 success = read_variable(variable); 66 continue; 67 } 68 auto equal_index = maybe_index.release_value(); 69 auto name = variable.substring_view(0, equal_index); 70 auto value = variable.substring_view(equal_index + 1, variable.length() - equal_index - 1); 71 if (name.is_empty()) 72 warnln("Malformed setting '{}'", variable); 73 else if (!s_set_variable) 74 warnln("Must specify '-w' to set variables"); 75 else 76 success = write_variable(name, value); 77 } 78 return success ? 0 : 1; 79} 80 81static int handle_show_all() 82{ 83 Core::DirIterator di("/sys/kernel/variables", Core::DirIterator::SkipDots); 84 if (di.has_error()) { 85 outln("DirIterator: {}", di.error()); 86 return 1; 87 } 88 89 bool success = false; 90 while (di.has_next()) { 91 auto name = di.next_path(); 92 success = read_variable(name); 93 } 94 return success ? 0 : 1; 95} 96 97ErrorOr<int> serenity_main(Main::Arguments arguments) 98{ 99 bool show_all = false; 100 Vector<StringView> variables; 101 102 Core::ArgsParser args_parser; 103 args_parser.set_general_help("Show or modify system-internal values. This requires root, and can crash your system."); 104 args_parser.add_option(show_all, "Show all variables", "all", 'a'); 105 args_parser.add_option(s_set_variable, "Set variables", "write", 'w'); 106 args_parser.add_positional_argument(variables, "variable[=value]", "variables", Core::ArgsParser::Required::No); 107 args_parser.parse(arguments); 108 109 if (!show_all && variables.is_empty()) { 110 args_parser.print_usage(stdout, arguments.strings[0]); 111 return 1; 112 } 113 114 if (show_all) { 115 // Ignore `variables`, even if they are supplied. Just like the real procps does. 116 return handle_show_all(); 117 } 118 119 return handle_variables(variables); 120}