diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-01-18 15:35:38 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-01-18 15:35:38 +0100 |
commit | 7e044cf2930cf63b30de8f30b3ea75851eda7d2b (patch) | |
tree | aa1b15a3d84f28d6c57626220d6a849cbde76260 | |
parent | f7cc4541626279b07626b9d98beba03a7230b518 (diff) | |
download | serenity-7e044cf2930cf63b30de8f30b3ea75851eda7d2b.zip |
Add a simple /bin/sysctl that wraps the files in /proc/sys.
-rw-r--r-- | AK/StringBuilder.cpp | 6 | ||||
-rwxr-xr-x | Kernel/sync.sh | 1 | ||||
-rw-r--r-- | Userland/.gitignore | 1 | ||||
-rw-r--r-- | Userland/Makefile | 9 | ||||
-rw-r--r-- | Userland/sysctl.cpp | 138 |
5 files changed, 151 insertions, 4 deletions
diff --git a/AK/StringBuilder.cpp b/AK/StringBuilder.cpp index 0e155df72c..572a8e8590 100644 --- a/AK/StringBuilder.cpp +++ b/AK/StringBuilder.cpp @@ -40,12 +40,14 @@ void StringBuilder::appendf(const char* fmt, ...) ByteBuffer StringBuilder::to_byte_buffer() { m_buffer.trim(m_length); - return m_buffer; + return move(m_buffer); } String StringBuilder::build() { - return String((const char*)m_buffer.pointer(), m_length); + auto string = String((const char*)m_buffer.pointer(), m_length); + m_buffer.clear(); + return string; } } diff --git a/Kernel/sync.sh b/Kernel/sync.sh index 180586f108..d69fb747b8 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -43,6 +43,7 @@ cp -v ../Userland/touch mnt/bin/touch cp -v ../Userland/sync mnt/bin/sync cp -v ../Userland/more mnt/bin/more cp -v ../Userland/guitest mnt/bin/guitest +cp -v ../Userland/sysctl mnt/bin/sysctl cp -v ../Terminal/Terminal mnt/bin/Terminal sh sync-local.sh cp -v kernel.map mnt/ diff --git a/Userland/.gitignore b/Userland/.gitignore index 94dd3a2a12..b977ea519a 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -22,3 +22,4 @@ touch sync more guitest +sysctl diff --git a/Userland/Makefile b/Userland/Makefile index 7dc23d5970..c34165565d 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -19,7 +19,8 @@ OBJS = \ mkdir.o \ touch.o \ more.o \ - guitest.o + guitest.o \ + sysctl.o APPS = \ id \ @@ -43,7 +44,8 @@ APPS = \ touch \ sync \ more \ - guitest + guitest \ + sysctl ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc @@ -129,6 +131,9 @@ more: more.o guitest: guitest.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +sysctl: sysctl.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/sysctl.cpp b/Userland/sysctl.cpp new file mode 100644 index 0000000000..13c7e564ab --- /dev/null +++ b/Userland/sysctl.cpp @@ -0,0 +1,138 @@ +#include <stdio.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> +#include <string.h> +#include <getopt.h> +#include <fcntl.h> +#include <AK/AKString.h> +#include <AK/StringBuilder.h> +#include <AK/Vector.h> + +static bool flag_show_all = false; +static int show_all(); +static int handle_var(const char*); + +static void usage() +{ + printf("usage: sysctl [-a] [variable[=value]]\n"); +} + +int main(int argc, char** argv) +{ + int opt; + while ((opt = getopt(argc, argv, "a")) != -1) { + switch (opt) { + case 'a': + flag_show_all = true; + break; + default: + usage(); + return 0; + } + } + + if (flag_show_all) + return show_all(); + + if (optind >= argc) { + usage(); + return 0; + } + + const char* var = argv[optind]; + + return handle_var(var); +} + +int show_all() +{ + DIR* dirp = opendir("/proc/sys"); + if (!dirp) { + perror("opendir"); + return 1; + } + char pathbuf[256]; + + while (auto* de = readdir(dirp)) { + if (de->d_name[0] == '.') + continue; + sprintf(pathbuf, "/proc/sys/%s", de->d_name); + int fd = open(pathbuf, O_RDONLY); + if (fd < 0) { + perror("open"); + continue; + } + char buffer[1024]; + int nread = read(fd, buffer, sizeof(buffer)); + close(fd); + if (nread < 0) { + perror("read"); + continue; + } + buffer[nread] = '\0'; + printf("%s = %s", de->d_name, buffer); + if (nread && buffer[nread - 1] != '\n') + printf("\n"); + } + closedir(dirp); + return 0; +} + +static String read_var(const String& name) +{ + StringBuilder builder; + builder.append("/proc/sys/"); + builder.append(name); + auto path = builder.build(); + int fd = open(path.characters(), O_RDONLY); + if (fd < 0) { + perror("open"); + exit(1); + } + char buffer[1024]; + int nread = read(fd, buffer, sizeof(buffer)); + close(fd); + if (nread < 0) { + perror("read"); + exit(1); + } + return String(buffer, nread, Chomp); +} + +static void write_var(const String& name, const String& value) +{ + StringBuilder builder; + builder.append("/proc/sys/"); + builder.append(name); + auto path = builder.build(); + int fd = open(path.characters(), O_WRONLY); + if (fd < 0) { + perror("open"); + exit(1); + } + int nwritten = write(fd, value.characters(), value.length()); + if (nwritten < 0) { + perror("read"); + exit(1); + } + close(fd); +} + +int handle_var(const char* var) +{ + String spec(var, Chomp); + auto parts = spec.split('='); + String variable_name = parts[0]; + bool is_write = parts.size() > 1; + + if (!is_write) { + printf("%s = %s\n", variable_name.characters(), read_var(variable_name).characters()); + return 0; + } + + printf("%s = %s", variable_name.characters(), read_var(variable_name).characters()); + write_var(variable_name, parts[1]); + printf(" -> %s\n", read_var(variable_name).characters()); + return 0; +} |