mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 14:18:12 +00:00
sysctl: Allow showing or setting multiple variables
The `-w` option is enforced when setting variables.
This commit is contained in:
parent
3d174e3ad2
commit
638f39fbc1
2 changed files with 81 additions and 67 deletions
|
@ -5,7 +5,7 @@ sysctl - configure kernel parameters at runtime
|
||||||
## Synopsis
|
## Synopsis
|
||||||
|
|
||||||
```**sh
|
```**sh
|
||||||
# sysctl [-a] [variable[=value]]
|
# sysctl [-a] [-w] [variable[=value]...]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
@ -16,12 +16,13 @@ Available parameters are listed under /proc/sys/.
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
* `-a`: Display all kernel parameters and associated values
|
* `-a`: Display all kernel parameters and associated values.
|
||||||
|
* `-w`: Set kernel parameters to the specified values.
|
||||||
|
|
||||||
## Arguments
|
## Arguments
|
||||||
|
|
||||||
* `variable`: Retrieve the specified parameter
|
* `variable`: Retrieve the specified parameter.
|
||||||
* `variable=value`: Set the specified parameter to the specified value
|
* `variable=value`: Set the specified parameter to the specified value. The option `-w` has to be specified.
|
||||||
|
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
|
@ -43,8 +44,10 @@ ubsan_is_deadly = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
Set `ubsan_is_deadly` parameter to zero (disabled):
|
Set `ubsan_is_deadly` parameter to zero (disabled):
|
||||||
|
(Note: This requires root privileges)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# sysctl ubsan_is_deadly=0
|
# su
|
||||||
ubsan_is_deadly = 1 -> 0
|
# sysctl -w ubsan_is_deadly=0
|
||||||
|
ubsan_is_deadly: 1 -> 0
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,48 +4,76 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/ByteBuffer.h>
|
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/StringBuilder.h>
|
|
||||||
#include <LibCore/ArgsParser.h>
|
#include <LibCore/ArgsParser.h>
|
||||||
#include <LibCore/DirIterator.h>
|
#include <LibCore/DirIterator.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
|
|
||||||
static String read_var(const String& name)
|
static bool s_set_variable = false;
|
||||||
|
|
||||||
|
static String get_variable(StringView const& name)
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
auto path = String::formatted("/proc/sys/{}", name);
|
||||||
builder.append("/proc/sys/");
|
auto file = Core::File::construct(path);
|
||||||
builder.append(name);
|
if (!file->open(Core::OpenMode::ReadOnly)) {
|
||||||
auto path = builder.to_string();
|
warnln("Failed to open {}: {}", path, file->error_string());
|
||||||
auto f = Core::File::construct(path);
|
return {};
|
||||||
if (!f->open(Core::OpenMode::ReadOnly)) {
|
|
||||||
warnln("Failed to open {}: {}", f->name(), f->error_string());
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
const auto& b = f->read_all();
|
auto buffer = file->read_all();
|
||||||
if (f->error() < 0) {
|
if (file->error() < 0) {
|
||||||
warnln("Failed to read: {}", f->error_string());
|
warnln("Failed to read {}: {}", path, file->error_string());
|
||||||
exit(1);
|
return {};
|
||||||
}
|
}
|
||||||
return String((const char*)b.data(), b.size(), Chomp);
|
return { (char const*)buffer.data(), buffer.size(), Chomp };
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_var(const String& name, const String& value)
|
static bool read_variable(StringView const& name)
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
auto value = get_variable(name);
|
||||||
builder.append("/proc/sys/");
|
if (value.is_null())
|
||||||
builder.append(name);
|
return false;
|
||||||
auto path = builder.to_string();
|
outln("{} = {}", name, value);
|
||||||
auto f = Core::File::construct(path);
|
return true;
|
||||||
if (!f->open(Core::OpenMode::WriteOnly)) {
|
}
|
||||||
warnln("Failed to open: {}", f->error_string());
|
|
||||||
exit(1);
|
static bool write_variable(StringView const& name, StringView const& value)
|
||||||
|
{
|
||||||
|
auto old_value = get_variable(name);
|
||||||
|
if (old_value.is_null())
|
||||||
|
return false;
|
||||||
|
auto path = String::formatted("/proc/sys/{}", name);
|
||||||
|
auto file = Core::File::construct(path);
|
||||||
|
if (!file->open(Core::OpenMode::WriteOnly)) {
|
||||||
|
warnln("Failed to open {}: {}", path, file->error_string());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
f->write(value);
|
if (!file->write(value)) {
|
||||||
if (f->error() < 0) {
|
warnln("Failed to write {}: {}", path, file->error_string());
|
||||||
warnln("Failed to write: {}", f->error_string());
|
return false;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
outln("{}: {} -> {}", name, old_value, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_variables(Vector<String> const& variables)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
for (auto const& variable : variables) {
|
||||||
|
auto maybe_index = variable.find('=');
|
||||||
|
if (!maybe_index.has_value()) {
|
||||||
|
success = read_variable(variable);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto equal_index = maybe_index.release_value();
|
||||||
|
auto name = variable.substring_view(0, equal_index);
|
||||||
|
auto value = variable.substring_view(equal_index + 1, variable.length() - equal_index - 1);
|
||||||
|
if (name.is_empty())
|
||||||
|
warnln("Malformed setting '{}'", variable);
|
||||||
|
else if (!s_set_variable)
|
||||||
|
warnln("Must specify '-w' to set variables");
|
||||||
|
else
|
||||||
|
success = write_variable(name, value);
|
||||||
|
}
|
||||||
|
return success ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_show_all()
|
static int handle_show_all()
|
||||||
|
@ -56,52 +84,35 @@ static int handle_show_all()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
while (di.has_next()) {
|
while (di.has_next()) {
|
||||||
String variable_name = di.next_path();
|
auto name = di.next_path();
|
||||||
outln("{} = {}", variable_name, read_var(variable_name));
|
success = read_variable(name);
|
||||||
}
|
}
|
||||||
return 0;
|
return success ? 0 : 1;
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_var(const String& var)
|
|
||||||
{
|
|
||||||
String spec(var.characters(), Chomp);
|
|
||||||
auto parts = spec.split('=');
|
|
||||||
String variable_name = parts[0];
|
|
||||||
bool is_write = parts.size() > 1;
|
|
||||||
|
|
||||||
if (!is_write) {
|
|
||||||
outln("{} = {}", variable_name, read_var(variable_name));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
out("{} = {}", variable_name, read_var(variable_name));
|
|
||||||
write_var(variable_name, parts[1]);
|
|
||||||
outln(" -> {}", read_var(variable_name));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
bool show_all = false;
|
bool show_all = false;
|
||||||
const char* var = nullptr;
|
Vector<String> variables;
|
||||||
|
|
||||||
Core::ArgsParser args_parser;
|
Core::ArgsParser args_parser;
|
||||||
args_parser.set_general_help(
|
args_parser.set_general_help("Show or modify system-internal values. This requires root, and can crash your system.");
|
||||||
"Show or modify system-internal values. This requires root, and can crash your system.");
|
args_parser.add_option(show_all, "Show all variables", "all", 'a');
|
||||||
args_parser.add_option(show_all, "Show all variables", nullptr, 'a');
|
args_parser.add_option(s_set_variable, "Set variables", "write", 'w');
|
||||||
args_parser.add_positional_argument(var, "variable[=value]", "variable", Core::ArgsParser::Required::No);
|
args_parser.add_positional_argument(variables, "variable[=value]", "variables", Core::ArgsParser::Required::No);
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
if (var == nullptr) {
|
if (!show_all && variables.is_empty()) {
|
||||||
// Not supplied; assume `-a`.
|
args_parser.print_usage(stdout, argv[0]);
|
||||||
show_all = true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_all) {
|
if (show_all) {
|
||||||
// Ignore `var`, even if it was supplied. Just like the real procps does.
|
// Ignore `variables`, even if they are supplied. Just like the real procps does.
|
||||||
return handle_show_all();
|
return handle_show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle_var(var);
|
return handle_variables(variables);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue