From 5bb366513b4d7be16be214822f0115eae9190659 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Mon, 7 Oct 2019 15:23:20 +0200 Subject: [PATCH] Remove os/src/app/cli_monitor Nowadays, we use standard command-line tools like vim to edit init configurations dynamically, which alleviates the need for a custom CLI. The CLI-monitor component was too limited for use cases like Sculpt anyway. The patch also removes the ancient (and untested for long time) terminal_mux.run script, which used to be the only remaining user of the CLI monitor. Issue #3512 --- repos/gems/run/terminal_mux.run | 164 ---- repos/os/include/cli_monitor/child.h | 355 ------- repos/os/include/cli_monitor/ram.h | 140 --- repos/os/src/app/cli_monitor/child.h | 65 -- repos/os/src/app/cli_monitor/child_registry.h | 83 -- repos/os/src/app/cli_monitor/command_line.h | 173 ---- repos/os/src/app/cli_monitor/format_util.h | 114 --- repos/os/src/app/cli_monitor/help_command.h | 31 - repos/os/src/app/cli_monitor/kill_command.h | 84 -- repos/os/src/app/cli_monitor/line_editor.h | 890 ------------------ repos/os/src/app/cli_monitor/main.cc | 225 ----- repos/os/src/app/cli_monitor/no_extension.cc | 17 - repos/os/src/app/cli_monitor/ram_command.h | 135 --- repos/os/src/app/cli_monitor/start_command.h | 255 ----- repos/os/src/app/cli_monitor/status_command.h | 157 --- .../cli_monitor/subsystem_config_registry.h | 195 ---- repos/os/src/app/cli_monitor/table.h | 101 -- repos/os/src/app/cli_monitor/target.mk | 4 - repos/os/src/app/cli_monitor/terminal_util.h | 36 - repos/os/src/app/cli_monitor/yield_command.h | 82 -- repos/os/src/server/fs_log/README | 2 +- 21 files changed, 1 insertion(+), 3307 deletions(-) delete mode 100644 repos/gems/run/terminal_mux.run delete mode 100644 repos/os/include/cli_monitor/child.h delete mode 100644 repos/os/include/cli_monitor/ram.h delete mode 100644 repos/os/src/app/cli_monitor/child.h delete mode 100644 repos/os/src/app/cli_monitor/child_registry.h delete mode 100644 repos/os/src/app/cli_monitor/command_line.h delete mode 100644 repos/os/src/app/cli_monitor/format_util.h delete mode 100644 repos/os/src/app/cli_monitor/help_command.h delete mode 100644 repos/os/src/app/cli_monitor/kill_command.h delete mode 100644 repos/os/src/app/cli_monitor/line_editor.h delete mode 100644 repos/os/src/app/cli_monitor/main.cc delete mode 100644 repos/os/src/app/cli_monitor/no_extension.cc delete mode 100644 repos/os/src/app/cli_monitor/ram_command.h delete mode 100644 repos/os/src/app/cli_monitor/start_command.h delete mode 100644 repos/os/src/app/cli_monitor/status_command.h delete mode 100644 repos/os/src/app/cli_monitor/subsystem_config_registry.h delete mode 100644 repos/os/src/app/cli_monitor/table.h delete mode 100644 repos/os/src/app/cli_monitor/target.mk delete mode 100644 repos/os/src/app/cli_monitor/terminal_util.h delete mode 100644 repos/os/src/app/cli_monitor/yield_command.h diff --git a/repos/gems/run/terminal_mux.run b/repos/gems/run/terminal_mux.run deleted file mode 100644 index 84c7ccd10..000000000 --- a/repos/gems/run/terminal_mux.run +++ /dev/null @@ -1,164 +0,0 @@ -# -# \brief Example for using the terminal_mux server over UART -# \author Norman Feske -# \date 2013-02-20 -# - -assert_spec x86 - -# -# On Linux, we don't have a UART driver, on which this run script depends. -# -if {[have_spec linux]} { puts "Run script does not support Linux"; exit 0 } - -set build_components { - core init noux lib/libc_noux app/cli_monitor test/bomb test/signal - test/resource_yield timer drivers/uart server/terminal_mux - server/terminal_log noux-pkg/vim -} - -build $build_components - -create_boot_directory - -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -install_config $config - - -# -# Boot modules -# - -# generic modules -set boot_modules { - core init timer ld.lib.so noux terminal_mux terminal_log - test-signal cli_monitor test-resource_yield posix.lib.so - libc.lib.so vfs.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so - vim.tar pc_uart_drv -} - -set fiasco_serial_esc_arg "" - -build_boot_image $boot_modules - -append qemu_args " -nographic " - -# -# On all kernels, we write the core debug output to the kdb.log file, -# and use qemu's stdio as the UART used by terminal_mux. -# -append qemu_args " -serial file:kdb.log " -append qemu_args " -serial mon:stdio" - -run_genode_until forever diff --git a/repos/os/include/cli_monitor/child.h b/repos/os/include/cli_monitor/child.h deleted file mode 100644 index 3550871d0..000000000 --- a/repos/os/include/cli_monitor/child.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * \brief Child handling - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__CLI_MONITOR__CHILD_H_ -#define _INCLUDE__CLI_MONITOR__CHILD_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* CLI-monitor includes */ -#include - -namespace Cli_monitor { class Child_base; } - - -class Cli_monitor::Child_base : public Genode::Child_policy -{ - public: - - /* - * XXX derive donated quota from information to be provided by - * the used 'Connection' interfaces - */ - enum { DONATED_RAM_QUOTA = 128*1024 }; - - class Quota_exceeded : public Genode::Exception { }; - - typedef Genode::size_t size_t; - typedef Genode::Cap_quota Cap_quota; - - typedef Genode::Registered Parent_service; - - private: - - Genode::Env &_env; - - Ram &_ram; - - Genode::Allocator &_alloc; - - Genode::Session_label const _label; - Binary_name const _binary_name; - - Genode::Pd_session_capability _ref_pd_cap; - Genode::Pd_session &_ref_pd; - - Cap_quota _cap_quota; - - size_t _ram_quota; - size_t _ram_limit; - - struct Parent_services : Genode::Registry - { - Genode::Allocator &_alloc; - Parent_services(Genode::Allocator &alloc) : _alloc(alloc) { } - ~Parent_services() - { - for_each([&] (Parent_service &s) { Genode::destroy(_alloc, &s); }); - } - } _parent_services { _alloc }; - - enum { ENTRYPOINT_STACK_SIZE = 12*1024 }; - Genode::Rpc_entrypoint _entrypoint; - - Genode::Child_policy_dynamic_rom_file _config_policy; - - /** - * If set to true, immediately withdraw resources yielded by the child - */ - bool _withdraw_on_yield_response = false; - - /** - * Arguments of current resource request from the child - */ - Genode::Parent::Resource_args _resource_args { }; - - Genode::Signal_context_capability _yield_response_sigh_cap; - - Genode::Signal_context_capability _exit_sig_cap; - - /* true if child is scheduled for destruction */ - bool _exited = false; - - Genode::Child _child; - - Genode::Service &_matching_service(Genode::Service::Name const &name, - Genode::Session_label const &label) - { - Genode::Service *service = nullptr; - - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(name, label))) - return *service; - - /* populate session-local parent service registry on demand */ - _parent_services.for_each([&] (Parent_service &s) { - if (s.name() == name) - service = &s; }); - - if (service) - return *service; - - return *new (_alloc) Parent_service(_parent_services, _env, name); - } - - public: - - /** - * Constructor - * - * \param ref_ram used as reference account for the child'd RAM - * session and for allocating the backing store - * for the child's configuration - * \param alloc allocator used to fill parent-service registry - * on demand - */ - Child_base(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Name const &label, - Binary_name const &binary_name, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Cap_quota cap_quota, - Genode::size_t ram_quota, - Genode::size_t ram_limit, - Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) - : - _env(env), _ram(ram), _alloc(alloc), - _label(label), _binary_name(binary_name), - _ref_pd_cap (ref_pd_cap), _ref_pd (ref_pd), - _cap_quota(cap_quota), _ram_quota(ram_quota), _ram_limit(ram_limit), - _entrypoint(&ref_pd, ENTRYPOINT_STACK_SIZE, _label.string(), false), - _config_policy(local_rm, "config", _entrypoint, &_env.ram()), - _yield_response_sigh_cap(yield_response_sig_cap), - _exit_sig_cap(exit_sig_cap), - _child(local_rm, _entrypoint, *this) - { } - - Genode::Session_label label() const { return _label; } - - void configure(char const *config, size_t config_len) - { - _config_policy.load(config, config_len); - } - - void start() - { - _entrypoint.activate(); - } - - /** - * Issue yield request to the child - */ - void yield(size_t amount, bool greedy) - { - if (requested_ram_quota()) - return; /* resource request in flight */ - - char buf[128]; - Genode::snprintf(buf, sizeof(buf), "ram_quota=%ld", amount); - _withdraw_on_yield_response = greedy; - _child.yield(buf); - } - - /** - * Return amount of RAM currently requested by the child - */ - size_t requested_ram_quota() const - { - return Genode::Arg_string::find_arg(_resource_args.string(), "ram_quota").ulong_value(0); - } - - /** - * Withdraw quota from the child - * - * \throw Ram::Transfer_quota_failed - */ - void withdraw_ram_quota(size_t amount) - { - if (!amount) - return; - - _ram.withdraw_from(_child.pd_session_cap(), amount); - _ram_quota -= amount; - } - - /** - * Upgrade quota of child - * - * \throw Ram::Transfer_quota_failed - */ - void upgrade_ram_quota(size_t amount) - { - _ram.transfer_to(_child.pd_session_cap(), amount); - _ram_quota += amount; - - /* wake up child if resource request is in flight */ - size_t const req = requested_ram_quota(); - if (req && _child.pd().avail_ram().value >= req) { - _child.notify_resource_avail(); - - /* clear request state */ - _resource_args = Genode::Parent::Resource_args(""); - } - } - - /** - * Try to respond to a current resource request issued by the child - * - * This method evaluates the conditions, under which a resource - * request can be answered: There must be enough room between the - * current quota and the configured limit, and there must be enough - * slack memory available. If both conditions are met, the quota - * of the child gets upgraded. - */ - void try_response_to_resource_request() - { - size_t const req = requested_ram_quota(); - - if (!req) - return; /* no resource request in flight */ - - /* - * Respond to the current request if the requested quota fits - * within the limit and if there is enough free quota available. - */ - if (req <= _ram.status().avail && req + _ram_quota <= _ram_limit) { - try { upgrade_ram_quota(req); } - catch (Ram::Transfer_quota_failed) { } - } - } - - /** - * Set limit for on-demand RAM quota expansion - */ - void ram_limit(size_t limit) - { - _ram_limit = limit; - try_response_to_resource_request(); - } - - struct Ram_status - { - size_t quota = 0, limit = 0, xfer = 0, used = 0, avail = 0, req = 0; - - Ram_status() { } - Ram_status(size_t quota, size_t limit, size_t xfer, size_t used, - size_t avail, size_t req) - : - quota(quota), limit(limit), xfer(xfer), used(used), - avail(avail), req(req) - { } - }; - - /** - * Return RAM quota status of the child - * - * XXX should be a const method, but the 'Pd_session' accessors - * are not const - */ - Ram_status ram_status() - { - return Ram_status(_ram_quota, - _ram_limit, - _ram_quota - _child.pd().ram_quota().value, - _child.pd().used_ram().value, - _child.pd().avail_ram().value, - requested_ram_quota()); - } - - /** - * Return true if child exited and should be destructed - */ - bool exited() const { return _exited; } - - - /**************************** - ** Child_policy interface ** - ****************************/ - - Name name() const override { return _label; } - Binary_name binary_name() const override { return _binary_name; } - - Genode::Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; } - Genode::Pd_session &ref_pd() override { return _ref_pd; } - - void init(Genode::Pd_session &session, Genode::Pd_session_capability cap) override - { - session.ref_account(_ref_pd_cap); - _ref_pd.transfer_quota(cap, _cap_quota); - _ref_pd.transfer_quota(cap, Genode::Ram_quota{_ram_quota}); - } - - Route resolve_session_request(Genode::Service::Name const &name, - Genode::Session_label const &label) override - { - return Route { .service = _matching_service(name, label), - .label = label, - .diag = Genode::Session::Diag() }; - } - - void yield_response() override - { - if (_withdraw_on_yield_response) { - enum { RESERVE = 4*1024*1024 }; - - size_t amount = _child.pd().avail_ram().value < RESERVE - ? 0 : _child.pd().avail_ram().value - RESERVE; - - /* try to immediately withdraw freed-up resources */ - try { withdraw_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { } - } - - /* propagate yield-response signal */ - Genode::Signal_transmitter(_yield_response_sigh_cap).submit(); - } - - void resource_request(Genode::Parent::Resource_args const &args) override - { - _resource_args = args; - try_response_to_resource_request(); - } - - void exit(int exit_value) override - { - Genode::log("subsystem \"", name(), "\" exited with value ", exit_value); - _exited = true; - - /* trigger destruction of the child */ - Genode::Signal_transmitter(_exit_sig_cap).submit(); - } -}; - -#endif /* _INCLUDE__CLI_MONITOR__CHILD_H_ */ diff --git a/repos/os/include/cli_monitor/ram.h b/repos/os/include/cli_monitor/ram.h deleted file mode 100644 index 7f6a42ae2..000000000 --- a/repos/os/include/cli_monitor/ram.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * \brief RAM management - * \author Norman Feske - * \date 2013-10-14 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__CLI_MONITOR__RAM_H_ -#define _INCLUDE__CLI_MONITOR__RAM_H_ - -/* Genode includes */ -#include - -namespace Cli_monitor { class Ram; } - - -class Cli_monitor::Ram -{ - private: - - typedef Genode::size_t size_t; - - Genode::Pd_session &_pd; - Genode::Pd_session_capability _pd_cap; - - Genode::Lock mutable _lock { }; - - Genode::Signal_context_capability _yield_sigh; - Genode::Signal_context_capability _resource_avail_sigh; - - size_t _preserve; - - void _validate_preservation() - { - if (_pd.avail_ram().value < _preserve) - Genode::Signal_transmitter(_yield_sigh).submit(); - - /* verify to answer outstanding resource requests too */ - if (_pd.avail_ram().value > _preserve) - Genode::Signal_transmitter(_resource_avail_sigh).submit(); - } - - public: - - struct Status - { - size_t quota, used, avail, preserve; - Status(size_t quota, size_t used, size_t avail, size_t preserve) - : quota(quota), used(used), avail(avail), preserve(preserve) { } - }; - - Ram(Genode::Pd_session &pd, - Genode::Pd_session_capability pd_cap, - size_t preserve, - Genode::Signal_context_capability yield_sigh, - Genode::Signal_context_capability resource_avail_sigh) - : - _pd(pd), _pd_cap(pd_cap), - _yield_sigh(yield_sigh), - _resource_avail_sigh(resource_avail_sigh), - _preserve(preserve) - { } - - size_t preserve() const - { - Genode::Lock::Guard guard(_lock); - - return _preserve; - } - - void preserve(size_t preserve) - { - Genode::Lock::Guard guard(_lock); - - _preserve = preserve; - - _validate_preservation(); - } - - Status status() const - { - Genode::Lock::Guard guard(_lock); - - return Status(_pd.ram_quota().value, _pd.used_ram().value, - _pd.avail_ram().value, _preserve); - } - - void validate_preservation() - { - Genode::Lock::Guard guard(_lock); - - _validate_preservation(); - } - - /** - * Exception type - */ - class Transfer_quota_failed { }; - - /** - * \throw Transfer_quota_failed - */ - void withdraw_from(Genode::Pd_session_capability from, size_t amount) - { - using namespace Genode; - - Lock::Guard guard(_lock); - - try { Pd_session_client(from).transfer_quota(_pd_cap, Ram_quota{amount}); } - catch (...) { throw Transfer_quota_failed(); } - - Signal_transmitter(_resource_avail_sigh).submit(); - } - - /** - * \throw Transfer_quota_failed - */ - void transfer_to(Genode::Pd_session_capability to, size_t amount) - { - Genode::Lock::Guard guard(_lock); - - if (_pd.avail_ram().value < (_preserve + amount)) { - Genode::Signal_transmitter(_yield_sigh).submit(); - throw Transfer_quota_failed(); - } - - try { _pd.transfer_quota(to, Genode::Ram_quota{amount}); } - catch (...) { throw Transfer_quota_failed(); } - } - - size_t avail() const { return _pd.avail_ram().value; } -}; - -#endif /* _INCLUDE__CLI_MONITOR__RAM_H_ */ diff --git a/repos/os/src/app/cli_monitor/child.h b/repos/os/src/app/cli_monitor/child.h deleted file mode 100644 index 755c3241c..000000000 --- a/repos/os/src/app/cli_monitor/child.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * \brief Child carrying application-specific context information - * \author Norman Feske - * \date 2014-10-02 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CHILD_H_ -#define _CHILD_H_ - -/* public CLI-monitor includes */ -#include - -/* local includes */ -#include - -namespace Cli_monitor { struct Child; } - - -struct Cli_monitor::Child : Child_base, private List::Element -{ - friend class List; - - using List::Element::next; - - Argument argument; - - Child(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Name const &label, - Binary_name const &binary, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Cap_quota cap_quota, - Genode::size_t ram_quota, - Genode::size_t ram_limit, - Genode::Signal_context_capability yield_response_sig_cap, - Genode::Signal_context_capability exit_sig_cap) - : - Child_base(env, - ram, - alloc, - label, - binary, - ref_pd, - ref_pd_cap, - local_rm, - cap_quota, - ram_quota, - ram_limit, - yield_response_sig_cap, - exit_sig_cap), - argument(label.string(), "subsystem") - { } -}; - -#endif /* _CHILD_H_ */ diff --git a/repos/os/src/app/cli_monitor/child_registry.h b/repos/os/src/app/cli_monitor/child_registry.h deleted file mode 100644 index abc8c2794..000000000 --- a/repos/os/src/app/cli_monitor/child_registry.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * \brief Registry of running children - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CHILD_REGISTRY_H_ -#define _CHILD_REGISTRY_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Cli_monitor { class Child_registry; } - - -class Cli_monitor::Child_registry : public List -{ - private: - - /** - * Return true if a child with the specified name already exists - */ - bool _child_name_exists(const char *label) - { - for (Child *child = first() ; child; child = child->next()) - if (child->name() == label) - return true; - return false; - } - - public: - - enum { CHILD_NAME_MAX_LEN = 64 }; - - /** - * Produce new unique child name - */ - void unique_child_name(const char *prefix, char *dst, int dst_len) - { - char buf[CHILD_NAME_MAX_LEN]; - char suffix[8]; - suffix[0] = 0; - - for (int cnt = 1; true; cnt++) { - - /* build program name composed of prefix and numeric suffix */ - snprintf(buf, sizeof(buf), "%s%s", prefix, suffix); - - /* if such a program name does not exist yet, we are happy */ - if (!_child_name_exists(buf)) { - strncpy(dst, buf, dst_len); - return; - } - - /* increase number of suffix */ - snprintf(suffix, sizeof(suffix), ".%d", cnt + 1); - } - } - - /** - * Call functor 'fn' for each child - * - * The functor receives the child name as 'char const *'. - */ - template - void for_each_child_name(FN const &fn) const - { - for (Child const *child = first() ; child; child = child->next()) - fn(child->name()); - } -}; - -#endif /* _CHILD_REGISTRY_H_ */ diff --git a/repos/os/src/app/cli_monitor/command_line.h b/repos/os/src/app/cli_monitor/command_line.h deleted file mode 100644 index 5016e63bf..000000000 --- a/repos/os/src/app/cli_monitor/command_line.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * \brief Utility for command-line parsing - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _COMMAND_LINE_H_ -#define _COMMAND_LINE_H_ - -#include - -namespace Cli_monitor { class Command_line; } - - -class Cli_monitor::Command_line -{ - private: - - char const *_cmd_line; - Command &_command; - - bool _parameter_is_known(Token token) - { - return Argument_tracker::lookup(token, _command.parameters()) != 0; - } - - Token _tag_token(char const *tag) - { - for (Token token(_cmd_line); token; token = token.next()) - if (strcmp(token.start(), tag, token.len()) == 0 - && strlen(tag) == token.len() - && _parameter_is_known(token)) - return token; - - return Token(); - } - - Token _value_token(char const *tag) - { - return _tag_token(tag).next().next(); - } - - static bool _is_parameter(Token token) - { - return token[0] == '-' && token[1] == '-'; - } - - - public: - - /** - * Constructor - * - * \param cmd_line null-terminated command line string - * \param command meta data about the command - */ - Command_line(char const *cmd_line, Command &command) - : _cmd_line(cmd_line), _command(command) { } - - /** - * Return true if tag is specified at the command line - */ - bool parameter_exists(char const *tag) - { - return _tag_token(tag); - } - - /** - * Return number argument specified for the given tag - */ - template - bool parameter(char const *tag, T &result) - { - Token value = _value_token(tag); - return value && Genode::ascii_to(value.start(), result) != 0; - } - - /** - * Return string argument specified for the given tag - */ - bool parameter(char const *tag, char *result, size_t result_len) - { - Token value = _value_token(tag); - if (!value) - return false; - - value.string(result, result_len); - return true; - } - - bool argument(unsigned index, char *result, size_t result_len) - { - Argument_tracker argument_tracker(_command); - - /* argument counter */ - unsigned cnt = 0; - - for (Token token(_cmd_line); token; token = token.next()) { - - argument_tracker.supply_token(token); - - if (!argument_tracker.valid()) - return false; - - if (!argument_tracker.expect_arg()) - continue; - - Token arg = token.next(); - if (!arg) - return false; - - /* - * The 'arg' token could either the tag of a parameter or - * an argument. We only want to count the arguments. So - * we skip tokens that have the usual form a parameter tag. - */ - if (_is_parameter(arg)) - continue; - - if (cnt == index) { - arg.string(result, result_len); - return true; - } - cnt++; - } - return false; - } - - /** - * Validate parameter tags - * - * \return tag token of first unexpected parameter, or - * invalid token if no unexpected parameter was found - */ - Token unexpected_parameter() - { - Argument_tracker argument_tracker(_command); - - for (Token token(_cmd_line); token; token = token.next()) { - - argument_tracker.supply_token(token); - - if (!argument_tracker.valid()) - return token; - - if (!argument_tracker.expect_arg()) - continue; - - Token arg = token.next(); - - /* ignore non-parameter tokens (i.e., normal arguments) */ - if (!_is_parameter(arg)) - continue; - - /* if parameter with the given tag exists, we are fine */ - if (_parameter_is_known(arg)) - continue; - - /* we hit an unknown parameter tag */ - return arg; - } - return Token(); - } -}; - -#endif /* _COMMAND_LINE_H_ */ diff --git a/repos/os/src/app/cli_monitor/format_util.h b/repos/os/src/app/cli_monitor/format_util.h deleted file mode 100644 index cd3a9feb1..000000000 --- a/repos/os/src/app/cli_monitor/format_util.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * \brief Utilities for formatting output to terminal - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _FORMAT_UTIL_H_ -#define _FORMAT_UTIL_H_ - -/* local includes */ -#include - -namespace Cli_monitor { - - /** - * Print rational number with two fractional decimals - */ - static inline size_t format_number(char *dst, size_t len, size_t const value, - size_t const quotient, char const *unit) - { - size_t const integer = value / quotient; - size_t const n = snprintf(dst, len, "%ld.", integer); - size_t const remainder = ((value - (integer * quotient))*100) / quotient; - - if (len == n) return n; - - return n + snprintf(dst + n, len - n, "%s%ld%s", - remainder < 10 ? "0" : "", remainder, unit); - } - - - /** - * Print number of bytes using the best suitable unit - */ - static inline size_t format_bytes(char *dst, size_t len, size_t bytes) - { - enum { KB = 1024, MB = 1024*KB }; - - if (bytes > MB) - return format_number(dst, len, bytes, MB, " MiB"); - - if (bytes > KB) - return format_number(dst, len, bytes, KB, " KiB"); - - return snprintf(dst, len, "%ld bytes", bytes); - } - - - /** - * Print number in MiB, without unit - */ - static inline size_t format_mib(char *dst, size_t len, size_t bytes) - { - enum { KB = 1024, MB = 1024*KB }; - - return format_number(dst, len, bytes, MB , ""); - } - - - static inline size_t format_bytes(size_t bytes) - { - char buf[128]; - return format_bytes(buf, sizeof(buf), bytes); - } - - - static inline size_t format_mib(size_t bytes) - { - char buf[128]; - return format_mib(buf, sizeof(buf), bytes); - } - - - static inline void tprint_bytes(Terminal::Session &terminal, size_t bytes) - { - char buf[128]; - format_bytes(buf, sizeof(buf), bytes); - Terminal::tprintf(terminal, "%s", buf); - } - - - static inline void tprint_mib(Terminal::Session &terminal, size_t bytes) - { - char buf[128]; - format_mib(buf, sizeof(buf), bytes); - Terminal::tprintf(terminal, "%s", buf); - } - - - static inline void tprint_status_bytes(Terminal::Session &terminal, - char const *label, size_t bytes) - { - Terminal::tprintf(terminal, label); - tprint_bytes(terminal, bytes); - Terminal::tprintf(terminal, "\n"); - } - - - static void tprint_padding(Terminal::Session &terminal, size_t pad, char c = ' ') - { - char const buf[2] = { c, 0 }; - for (unsigned i = 0; i < pad; i++) - Terminal::tprintf(terminal, buf); - } -} - -#endif /* _FORMAT_UTIL_H_ */ diff --git a/repos/os/src/app/cli_monitor/help_command.h b/repos/os/src/app/cli_monitor/help_command.h deleted file mode 100644 index 691ed30cd..000000000 --- a/repos/os/src/app/cli_monitor/help_command.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * \brief Help command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _HELP_COMMAND_H_ -#define _HELP_COMMAND_H_ - -namespace Cli_monitor { struct Help_command; } - - -struct Cli_monitor::Help_command : Command -{ - Help_command() : Command("help", "brief help information") { } - - void execute(Command_line &, Terminal::Session &terminal) override - { - tprintf(terminal, " Press [tab] for a list of commands.\n"); - tprintf(terminal, " When given a command, press [tab] for a list of arguments.\n"); - } -}; - -#endif /* _HELP_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/kill_command.h b/repos/os/src/app/cli_monitor/kill_command.h deleted file mode 100644 index bd8875625..000000000 --- a/repos/os/src/app/cli_monitor/kill_command.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * \brief Kill command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _KILL_COMMAND_H_ -#define _KILL_COMMAND_H_ - -/* local includes */ -#include - -namespace Cli_monitor { struct Kill_command; } - - -struct Cli_monitor::Kill_command : Command -{ - Child_registry &_children; - - Genode::Allocator &_alloc; - - Parameter _kill_all_param { "--all", Parameter::VOID, "kill all subsystems" }; - - void _destroy_child(Child *child, Terminal::Session &terminal) - { - tprintf(terminal, "destroying subsystem '%s'\n", child->name().string()); - _children.remove(child); - Genode::destroy(_alloc, child); - } - - Kill_command(Child_registry &children, Genode::Allocator &alloc) - : - Command("kill", "destroy subsystem"), _children(children), _alloc(alloc) - { - add_parameter(_kill_all_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - bool const kill_all = cmd.parameter_exists("--all"); - - if (kill_all) { - for (Child *child = _children.first(); child; child = _children.first()) - _destroy_child(child, terminal); - return; - } - - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - /* lookup child by its unique name */ - for (Child *child = _children.first(); child; child = child->next()) { - if (child->name() == label) { - _destroy_child(child, terminal); - return; - } - } - - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - } -}; - -#endif /* _KILL_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/line_editor.h b/repos/os/src/app/cli_monitor/line_editor.h deleted file mode 100644 index 1fbcd09af..000000000 --- a/repos/os/src/app/cli_monitor/line_editor.h +++ /dev/null @@ -1,890 +0,0 @@ -/* - * \brief Line editor for command-line interfaces - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _LINE_EDITOR_H_ -#define _LINE_EDITOR_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include - -namespace Cli_monitor { - - using Genode::List; - using Genode::max; - using Genode::strlen; - using Genode::strncpy; - using Genode::snprintf; - using Genode::strcmp; - using Genode::size_t; - using Genode::off_t; - using Genode::Interface; - - struct Completable; - struct Argument; - struct Parameter; - struct Command_line; - struct Command; - struct Command_registry; - struct Scanner_policy; - struct Argument_tracker; - struct Line_editor; - - typedef Genode::Token Token; -} - - -struct Cli_monitor::Completable -{ - typedef Genode::String<64> Name; - typedef Genode::String<160> Short_help; - - Name const _name; - Short_help const _short_help; - - Name name() const { return _name; } - Short_help short_help() const { return _short_help; } - - Completable(char const *name, char const *short_help) - : _name(name), _short_help(short_help) { } -}; - - -/** - * Representation of normal command-line argument - */ -struct Cli_monitor::Argument : Completable -{ - Argument(char const *name, char const *short_help) - : Completable(name, short_help) { } - - char const *name_suffix() const { return ""; } -}; - - -/** - * Representation of a parameter of the form '--tag value' - */ -struct Cli_monitor::Parameter : List::Element, Completable -{ - enum Type { IDENT, NUMBER, VOID }; - - Type const _type; - - Parameter(char const *name, Type type, char const *short_help) - : - Completable(name, short_help), _type(type) - { } - - bool needs_value() const { return _type != VOID; } - - char const *name_suffix() const - { - switch (_type) { - case IDENT: return ""; - case NUMBER: return ""; - case VOID: return ""; - } - return ""; - } -}; - - -/** - * Representation of a command that can have arguments and parameters - */ -struct Cli_monitor::Command : private List::Element, - private Completable -{ - List _parameters { }; - - friend class List; - - using List::Element::next; - using Completable::name; - using Completable::short_help; - - /** - * Functor that takes a command 'Argument' object as argument - */ - struct Argument_fn : Interface - { - virtual void operator () (Argument const &) const = 0; - }; - - Command(char const *name, char const *short_help) - : Completable(name, short_help) { } - - virtual ~Command() { } - - void add_parameter(Parameter &par) { _parameters.insert(&par); } - - char const *name_suffix() const { return ""; } - - List ¶meters() { return _parameters; } - - virtual void execute(Command_line &, Terminal::Session &terminal) = 0; - - /** - * Command-specific support for 'for_each_argument' - */ - virtual void _for_each_argument(Argument_fn const &) const { }; - - /** - * Execute functor 'fn' for each command argument - */ - template - void for_each_argument(FN const &fn) const - { - struct _Fn : Argument_fn - { - FN const &fn; - void operator () (Argument const &arg) const override { fn(arg); } - _Fn(FN const &fn) : fn(fn) { } - } _fn(fn); - - _for_each_argument(_fn); - } -}; - - -struct Cli_monitor::Command_registry : List { }; - - -/** - * Scanner policy that accepts '-', '.' and '_' as valid identifier characters - */ -struct Cli_monitor::Scanner_policy -{ - static bool identifier_char(char c, unsigned i) - { - return Genode::is_letter(c) || (c == '_') || (c == '-') || (c == '.') - || (i && Genode::is_digit(c)); - } -}; - - -/** - * State machine used for sequentially parsing command-line arguments - */ -struct Cli_monitor::Argument_tracker -{ - private: - - Command &_command; - - enum State { EXPECT_COMMAND, EXPECT_SPACE_BEFORE_ARG, EXPECT_ARG, - EXPECT_SPACE_BEFORE_VAL, EXPECT_VAL, INVALID }; - - State _state; - - /** - * Return true if there is exactly one complete match and no additional - * partial matches - */ - static bool _one_matching_argument(char const *str, size_t str_len, - Command const &command) - { - unsigned complete_cnt = 0, partial_cnt = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - partial_cnt++; - - if (strlen(arg.name().string()) == str_len) - complete_cnt++; - } - }; - - command.for_each_argument(argument_fn); - - return partial_cnt == 1 && complete_cnt == 1; - } - - public: - - Argument_tracker(Command &command) - : _command(command), _state(EXPECT_COMMAND) { } - - template - static T *lookup(char const *str, size_t str_len, - List &list) - { - Token tag(str, str_len); - for (T *curr = list.first(); curr; curr = curr->next()) - if (strcmp(tag.start(), curr->name().string(), tag.len()) == 0 - && strlen(curr->name().string()) == tag.len()) - return curr; - - return 0; - } - - template - static T *lookup(Token token, List &list) - { - return lookup(token.start(), token.len(), list); - } - - void supply_token(Token token, bool token_may_be_incomplete = false) - { - switch (_state) { - - case INVALID: break; - - case EXPECT_COMMAND: - - if (token.type() == Token::IDENT) { - _state = EXPECT_SPACE_BEFORE_ARG; - break; - } - _state = INVALID; - break; - - case EXPECT_SPACE_BEFORE_ARG: - - if (token.type() == Token::WHITESPACE) - _state = EXPECT_ARG; - break; - - case EXPECT_ARG: - - if (token.type() == Token::IDENT) { - - Parameter *parameter = - lookup(token.start(), token.len(), _command.parameters()); - - if (parameter && parameter->needs_value()) { - _state = EXPECT_SPACE_BEFORE_VAL; - break; - } - - if (!token_may_be_incomplete - || _one_matching_argument(token.start(), token.len(), _command)) - _state = EXPECT_SPACE_BEFORE_ARG; - } - break; - - case EXPECT_SPACE_BEFORE_VAL: - - if (token.type() == Token::WHITESPACE) - _state = EXPECT_VAL; - break; - - case EXPECT_VAL: - - if (token.type() == Token::IDENT - || token.type() == Token::NUMBER) { - - _state = EXPECT_SPACE_BEFORE_ARG; - } - break; - } - } - - bool valid() const { return _state != INVALID; } - bool expect_arg() const { return _state == EXPECT_ARG; } - bool expect_space() const { return _state == EXPECT_SPACE_BEFORE_ARG - || _state == EXPECT_SPACE_BEFORE_VAL; } -}; - - -/** - * Editing and completion logic - */ -class Cli_monitor::Line_editor -{ - private: - - char const *_prompt; - size_t const _prompt_len; - char * const _buf; - size_t const _buf_size; - unsigned _cursor_pos = 0; - Terminal::Session &_terminal; - Command_registry &_commands; - bool _complete = false; - - /** - * State tracker for escape sequences within user input - * - * This tracker is used to decode special keys (e.g., cursor keys). - */ - struct Seq_tracker - { - enum State { INIT, GOT_ESC, GOT_FIRST } _state = INIT; - char _normal = 0, _first = 0, _second = 0; - bool _sequence_complete { false }; - - Seq_tracker() { } - - void input(char c) - { - switch (_state) { - case INIT: - if (c == 27) - _state = GOT_ESC; - else - _normal = c; - _sequence_complete = false; - break; - - case GOT_ESC: - _first = c; - _state = GOT_FIRST; - break; - - case GOT_FIRST: - _second = c; - _state = INIT; - _sequence_complete = true; - break; - } - } - - bool normal() const { return _state == INIT && !_sequence_complete; } - - char normal_char() const { return _normal; } - - bool _fn_complete(char match_first, char match_second) const - { - return _sequence_complete - && _first == match_first - && _second == match_second; - } - - bool key_up() const { return _fn_complete(91, 65); } - bool key_down() const { return _fn_complete(91, 66); } - bool key_right() const { return _fn_complete(91, 67); } - bool key_left() const { return _fn_complete(91, 68); } - bool key_delete() const { return _fn_complete(91, 51); } - }; - - Seq_tracker _seq_tracker { }; - - void _write(char c) { _terminal.write(&c, sizeof(c)); } - - void _write(char const *s) { _terminal.write(s, strlen(s)); } - - void _write_spaces(unsigned num) - { - for (unsigned i = 0; i < num; i++) - _write(' '); - } - - void _write_newline() { _write(10); } - - void _clear_until_end_of_line() { _write("\e[K "); } - - void _move_cursor_to(unsigned pos) - { - char seq[10]; - snprintf(seq, sizeof(seq), "\e[%ldG", pos + _prompt_len); - _write(seq); - } - - void _delete_character() - { - strncpy(&_buf[_cursor_pos], &_buf[_cursor_pos + 1], _buf_size); - - _move_cursor_to(_cursor_pos); - _write(&_buf[_cursor_pos]); - _clear_until_end_of_line(); - _move_cursor_to(_cursor_pos); - } - - void _insert_character(char c) - { - /* insert regular character */ - if (_cursor_pos >= _buf_size - 1) - return; - - /* make room in the buffer */ - for (unsigned i = _buf_size - 1; i > _cursor_pos; i--) - _buf[i] = _buf[i - 1]; - _buf[_cursor_pos] = c; - - /* update terminal */ - _write(&_buf[_cursor_pos]); - _cursor_pos++; - _move_cursor_to(_cursor_pos); - } - - void _fresh_prompt() - { - _write(_prompt); - _write(_buf); - _move_cursor_to(_cursor_pos); - } - - void _handle_key() - { - enum { BACKSPACE = 8, - TAB = 9, - LINE_FEED = 10, - CARRIAGE_RETURN = 13 }; - - if (_seq_tracker.key_left()) { - if (_cursor_pos > 0) { - _cursor_pos--; - _write(BACKSPACE); - } - return; - } - - if (_seq_tracker.key_right()) { - if (_cursor_pos < strlen(_buf)) { - _cursor_pos++; - _move_cursor_to(_cursor_pos); - } - return; - } - - if (_seq_tracker.key_delete()) - _delete_character(); - - if (!_seq_tracker.normal()) - return; - - char const c = _seq_tracker.normal_char(); - - if (c == TAB) { - _perform_completion(); - return; - } - - if (c == CARRIAGE_RETURN || c == LINE_FEED) { - if (strlen(_buf) > 0) { - _write(LINE_FEED); - _complete = true; - } - return; - } - - if (c == BACKSPACE) { - if (_cursor_pos > 0) { - _cursor_pos--; - _delete_character(); - } - return; - } - - if (c == 126) - return; - - _insert_character(c); - } - - template - COMPLETABLE *_lookup_matching(char const *str, size_t str_len, - List &list) - { - Token tag(str, str_len); - COMPLETABLE *curr = list.first(); - for (; curr; curr = curr->next()) { - if (strcmp(tag.start(), curr->name(), tag.len()) == 0 - && strlen(curr->name()) == tag.len()) - return curr; - } - return nullptr; - } - - Command *_lookup_matching_command() - { - Token cmd(_buf, _cursor_pos); - for (Command *curr = _commands.first(); curr; curr = curr->next()) - if (strcmp(cmd.start(), curr->name().string(), cmd.len()) == 0 - && _cursor_pos > cmd.len()) - return curr; - return nullptr; - } - - template - unsigned _num_partial_matches(char const *str, size_t str_len, List &list) - { - Token token(str, str_len); - - unsigned num_partial_matches = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - num_partial_matches++; - } - return num_partial_matches; - } - - unsigned _num_matching_arguments(char const *str, size_t str_len, - Command const &command) const - { - unsigned num_matches = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - num_matches++; - }; - - command.for_each_argument(argument_fn); - - return num_matches; - } - - /** - * Determine the name-column width of list of partial matches - */ - template - size_t _width_of_partial_matches(char const *str, size_t str_len, - List &list) - { - Token token(str, str_len); - - size_t max_name_len = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - size_t const name_len = strlen(curr->name().string()) - + strlen(curr->name_suffix()); - max_name_len = max(max_name_len, name_len); - } - return max_name_len; - } - - unsigned _width_of_matching_arguments(char const *str, size_t str_len, - Command const &command) const - { - size_t max_name_len = 0; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - size_t const name_len = strlen(arg.name().string()); - if (name_len > max_name_len) - max_name_len = name_len; - } - }; - - command.for_each_argument(argument_fn); - - return max_name_len; - } - - template - char const *_any_partial_match_name(char const *str, size_t str_len, - List &list) - { - Token token(str, str_len); - - for (T *curr = list.first(); curr; curr = curr->next()) - if (strcmp(token.start(), curr->name().string(), token.len()) == 0) - return curr->name().string(); - - return 0; - } - - Argument::Name _any_matching_argument(char const *str, size_t str_len, - Command const &command) const - { - Argument::Name name; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - name = arg.name(); - }; - - command.for_each_argument(argument_fn); - - return name; - } - - template - void _list_partial_matches(char const *str, size_t str_len, - unsigned pad, List &list) - { - Token token(str, str_len); - - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) != 0) - continue; - - _write_newline(); - _write_spaces(2); - _write(curr->name().string()); - _write_spaces(1); - _write(curr->name_suffix()); - - /* pad short help with whitespaces */ - size_t const name_len = strlen(curr->name().string()) - + strlen(curr->name_suffix()); - _write_spaces(pad + 3 - name_len); - _write(curr->short_help().string()); - } - } - - void _list_matching_arguments(char const *str, size_t str_len, - unsigned pad, Command const &command) - { - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) { - - _write_newline(); - _write_spaces(2); - _write(arg.name().string()); - _write_spaces(1); - _write(arg.name_suffix()); - - /* pad short help with whitespaces */ - size_t const name_len = strlen(arg.name().string()) - + strlen(arg.name_suffix()); - _write_spaces(pad + 3 - name_len); - _write(arg.short_help().string()); - } - }; - - command.for_each_argument(argument_fn); - } - - template - void _do_completion(char const *str, size_t str_len, List &list) - { - Token token(str, str_len); - - /* look up completable token */ - T *partial_match = 0; - for (T *curr = list.first(); curr; curr = curr->next()) { - if (strcmp(token.start(), curr->name().string(), token.len()) == 0) { - partial_match = curr; - break; - } - } - - if (!partial_match) - return; - - for (unsigned i = token.len(); i < strlen(partial_match->name().string()); i++) - _insert_character(partial_match->name().string()[i]); - - _insert_character(' '); - } - - void _do_argument_completion(char const *str, size_t str_len, - Command const &command) - { - Argument::Name partial_match; - - auto argument_fn = [&] (Argument const &arg) { - - if (strcmp(arg.name().string(), str, str_len) == 0) - partial_match = arg.name(); - }; - - command.for_each_argument(argument_fn); - - for (unsigned i = str_len; i < strlen(partial_match.string()); i++) - _insert_character(partial_match.string()[i]); - - _insert_character(' '); - } - - void _complete_argument(char const *str, size_t str_len, Command &command) - { - unsigned const matching_parameters = - _num_partial_matches(str, str_len, command.parameters()); - - unsigned const matching_arguments = - _num_matching_arguments(str, str_len, command); - - /* matches are ambiguous */ - if (matching_arguments + matching_parameters > 1) { - - /* - * Try to complete additional characters that are common among - * all matches. - */ - char buf[Completable::Name::size()]; - strncpy(buf, str, Genode::min(sizeof(buf), str_len + 1)); - - /* pick any representative as a template to take characters from */ - char const *name = _any_partial_match_name(str, str_len, command.parameters()); - Argument::Name arg_name; - if (!name) { - arg_name = _any_matching_argument(str, str_len, command); - if (strlen(arg_name.string())) - name = arg_name.string(); - } - - size_t i = str_len; - for (; (i < sizeof(buf) - 1) && (i < strlen(name)); i++) { - - buf[i + 0] = name[i]; - buf[i + 1] = 0; - - if (matching_parameters != - _num_partial_matches(buf, i + 1, command.parameters())) - break; - - if (matching_arguments != - _num_matching_arguments(buf, i + 1, command)) - break; - - _insert_character(buf[i]); - } - - /* - * If we managed to do a partial completion, let's yield - * control to the user. - */ - if (i > str_len) - return; - - /* - * No automatic completion was possible, print list of possible - * parameters and arguments - */ - size_t const pad = - max(_width_of_partial_matches(str, str_len, command.parameters()), - _width_of_matching_arguments(str, str_len, command)); - - _list_partial_matches(str, str_len, pad, command.parameters()); - _list_matching_arguments(str, str_len, pad, command); - - _write_newline(); - _fresh_prompt(); - - return; - } - - if (matching_parameters == 1) - _do_completion(str, str_len, command.parameters()); - - if (matching_arguments == 1) - _do_argument_completion(str, str_len, command); - } - - void _perform_completion() - { - Command *command = _lookup_matching_command(); - - if (!command) { - unsigned const matches = _num_partial_matches(_buf, _cursor_pos, _commands); - - if (matches == 1) - _do_completion(_buf, _cursor_pos, _commands); - - if (matches > 1) { - unsigned const pad = - _width_of_partial_matches(_buf, _cursor_pos, _commands); - _list_partial_matches(_buf, _cursor_pos, pad, _commands); - _write_newline(); - _fresh_prompt(); - } - return; - } - - /* - * We hava a valid command, now try to complete the parameters... - */ - - /* determine token under the cursor */ - Argument_tracker argument_tracker(*command); - - Token token(_buf, _buf_size); - for (; token; token = token.next()) { - - argument_tracker.supply_token(token, true); - - if (!argument_tracker.valid()) - return; - - unsigned long const token_pos = (unsigned long)(token.start() - _buf); - - /* we have reached the token under the cursor */ - if (token.type() == Token::IDENT - && _cursor_pos >= token_pos - && _cursor_pos <= token_pos + token.len()) { - - if (argument_tracker.expect_arg()) { - char const *start = token.start(); - size_t const len = _cursor_pos - token_pos; - - _complete_argument(start, len, *command); - return; - } - } - } - - /* the cursor is positioned at beginning of new argument */ - if (argument_tracker.expect_arg()) - _complete_argument("", 0, *command); - - if (argument_tracker.expect_space()) - _insert_character(' '); - } - - public: - - /** - * Constructor - * - * \param prompt string to be printed at the beginning of the line - * \param buf destination buffer - * \param buf_size destination buffer size - * \param terminal terminal used as output device - * \param commands meta information about commands and their arguments - */ - Line_editor(char const *prompt, char *buf, size_t buf_size, - Terminal::Session &terminal, Command_registry &commands) - : - _prompt(prompt), _prompt_len(strlen(prompt)), - _buf(buf), _buf_size(buf_size), - _terminal(terminal), _commands(commands) - { - reset(); - } - - /** - * Reset prompt to initial state after construction - */ - void reset() - { - _buf[0] = 0; - _complete = false; - _cursor_pos = 0; - _seq_tracker = Seq_tracker(); - _fresh_prompt(); - } - - /** - * Supply a character of user input - */ - void submit_input(char c) - { - _seq_tracker.input(c); - _handle_key(); - } - - /** - * Returns true if the editing is complete, i.e., the user pressed the - * return key. - */ - bool completed() const { return _complete; } -}; - -#endif /* _LINE_EDITOR_H_ */ diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc deleted file mode 100644 index 6c0a6029e..000000000 --- a/repos/os/src/app/cli_monitor/main.cc +++ /dev/null @@ -1,225 +0,0 @@ -/* - * \brief Simple command-line interface for managing Genode subsystems - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include - -/* public CLI-monitor includes */ -#include - -/* local includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Cli_monitor { - - struct Main; - using namespace Genode; -} - - -/****************** - ** Main program ** - ******************/ - -struct Cli_monitor::Main -{ - Genode::Env &_env; - - Terminal::Connection _terminal { _env }; - - Command_registry _commands { }; - - Child_registry _children { }; - - Command *_lookup_command(char const *buf) - { - Token token(buf); - for (Command *curr = _commands.first(); curr; curr = curr->next()) - if (strcmp(token.start(), curr->name().string(), token.len()) == 0 - && strlen(curr->name().string()) == token.len()) - return curr; - return 0; - } - - enum { COMMAND_MAX_LEN = 1000 }; - char _command_buf[COMMAND_MAX_LEN]; - Line_editor _line_editor { - "genode> ", _command_buf, sizeof(_command_buf), _terminal, _commands }; - - void _handle_terminal_read_avail(); - - Signal_handler
_terminal_read_avail_handler { - _env.ep(), *this, &Main::_handle_terminal_read_avail }; - - /** - * Handler for child yield responses, or RAM resource-avail signals - */ - void _handle_yield_response() - { - for (Child *child = _children.first(); child; child = child->next()) - child->try_response_to_resource_request(); - } - - Signal_handler
_yield_response_handler { - _env.ep(), *this, &Main::_handle_yield_response }; - - void _handle_child_exit() - { - Child *next = nullptr; - for (Child *child = _children.first(); child; child = next) { - next = child->next(); - if (child->exited()) { - _children.remove(child); - Genode::destroy(_heap, child); - } - } - } - - Signal_handler
_child_exit_handler { - _env.ep(), *this, &Main::_handle_child_exit }; - - void _handle_yield_broadcast() - { - /* - * Compute argument of yield request to be broadcasted to all - * processes. - */ - size_t amount = 0; - - /* amount needed to reach preservation limit */ - Ram::Status ram_status = _ram.status(); - if (ram_status.avail < ram_status.preserve) - amount += ram_status.preserve - ram_status.avail; - - /* sum of pending resource requests */ - for (Child *child = _children.first(); child; child = child->next()) - amount += child->requested_ram_quota(); - - for (Child *child = _children.first(); child; child = child->next()) - child->yield(amount, true); - } - - Signal_handler
_yield_broadcast_handler { - _env.ep(), *this, &Main::_handle_yield_broadcast }; - - Genode::Attached_rom_dataspace _config { _env, "config" }; - - Xml_node _vfs_config() const - { - try { return _config.xml().sub_node("vfs"); } - catch (Genode::Xml_node::Nonexistent_sub_node) { - Genode::error("missing '' configuration"); - throw; - } - } - - size_t _ram_preservation_from_config() const - { - if (!_config.xml().has_sub_node("preservation")) - return 0; - - return _config.xml().sub_node("preservation") - .attribute_value("name", Genode::Number_of_bytes(0)); - } - - Ram _ram { _env.pd(), _env.pd_session_cap(), _ram_preservation_from_config(), - _yield_broadcast_handler, _yield_response_handler }; - - Heap _heap { _env.ram(), _env.rm() }; - - Vfs::Simple_env _vfs_env { _env, _heap, _vfs_config() }; - - Subsystem_config_registry _subsystem_config_registry { _vfs_env.root_dir(), _heap, _env.ep() }; - - template - struct Registered : T - { - template - Registered(Command_registry &commands, ARGS &&... args) - : T(args...) { commands.insert(this); } - }; - - /* initialize generic commands */ - Registered _help_command { _commands }; - Registered _kill_command { _commands, _children, _heap }; - Registered _start_command { _commands, _env, _ram, _heap, - _env.pd(), _env.pd_session_cap(), - _env.rm(), _children, - _subsystem_config_registry, - _yield_response_handler, - _child_exit_handler }; - Registered _status_command { _commands, _ram, _children }; - Registered _yield_command { _commands, _children }; - Registered _ram_command { _commands, _children, _ram }; - - Main(Env &env) : _env(env) - { - _terminal.read_avail_sigh(_terminal_read_avail_handler); - } -}; - - -void Cli_monitor::Main::_handle_terminal_read_avail() -{ - /* supply pending terminal input to line editor */ - while (_terminal.avail() && !_line_editor.completed()) { - char c = 0; - _terminal.read(&c, 1); - _line_editor.submit_input(c); - } - - if (!_line_editor.completed()) - return; - - Command *command = _lookup_command(_command_buf); - if (!command) { - Token cmd_name(_command_buf); - tprintf(_terminal, "Error: unknown command \""); - _terminal.write(cmd_name.start(), cmd_name.len()); - tprintf(_terminal, "\"\n"); - _line_editor.reset(); - return; - } - - /* validate parameters against command meta data */ - Command_line cmd_line(_command_buf, *command); - Token unexpected = cmd_line.unexpected_parameter(); - if (unexpected) { - tprintf(_terminal, "Error: unexpected parameter \""); - _terminal.write(unexpected.start(), unexpected.len()); - tprintf(_terminal, "\"\n"); - _line_editor.reset(); - return; - } - command->execute(cmd_line, _terminal); - - /* - * The command might result in a change of the RAM usage. Validate - * that the preservation is satisfied. - */ - _ram.validate_preservation(); - _line_editor.reset(); -} - - -void Component::construct(Genode::Env &env) { static Cli_monitor::Main main(env); } diff --git a/repos/os/src/app/cli_monitor/no_extension.cc b/repos/os/src/app/cli_monitor/no_extension.cc deleted file mode 100644 index e64df753d..000000000 --- a/repos/os/src/app/cli_monitor/no_extension.cc +++ /dev/null @@ -1,17 +0,0 @@ -/* - * \brief Dummy implementation of CLI extension interface - * \author Norman Feske - * \date 2013-03-21 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include - -void Cli_monitor::init_extension(Command_registry &) { } - diff --git a/repos/os/src/app/cli_monitor/ram_command.h b/repos/os/src/app/cli_monitor/ram_command.h deleted file mode 100644 index a080db7df..000000000 --- a/repos/os/src/app/cli_monitor/ram_command.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * \brief RAM command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _RAM_COMMAND_H_ -#define _RAM_COMMAND_H_ - -/* local includes */ -#include - -namespace Cli_monitor { struct Ram_command; } - - -struct Cli_monitor::Ram_command : Command -{ - Child_registry &_children; - Ram &_ram; - - Parameter _quota_param { "--quota", Parameter::NUMBER, "new RAM quota" }; - Parameter _limit_param { "--limit", Parameter::NUMBER, "on-demand quota limit" }; - - Ram_command(Child_registry &children, Ram &ram) - : - Command("ram", "set RAM quota of subsystem"), - _children(children), _ram(ram) - { - add_parameter(_quota_param); - add_parameter(_limit_param); - } - - void _set_quota(Terminal::Session &terminal, Child &child, size_t const new_quota) - { - size_t const old_quota = child.ram_status().quota; - - if (new_quota > old_quota) { - - size_t amount = new_quota - old_quota; - size_t const avail = _ram.avail(); - if (amount > avail) { - tprintf(terminal, "upgrade of '%s' exceeds available quota of ", - child.name().string()); - tprint_bytes(terminal, avail); - tprintf(terminal, "\n"); - amount = avail; - } - - tprintf(terminal, "upgrading quota of '%s' to ", child.name().string()); - tprint_bytes(terminal, old_quota + amount); - tprintf(terminal, "\n"); - - try { - child.upgrade_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { - tprintf(terminal, "Error: transfer_quota failed\n"); } - - } if (new_quota < old_quota) { - - size_t amount = old_quota - new_quota; - size_t const avail = child.ram_status().avail; - - if (amount > avail) { - tprintf(terminal, "withdrawal of "); - tprint_bytes(terminal, amount); - tprintf(terminal, " exceeds available quota of "); - tprint_bytes(terminal, avail); - tprintf(terminal, "\n"); - amount = avail; - } - - tprintf(terminal, "depleting quota of '%s' to ", child.name().string()); - tprint_bytes(terminal, old_quota - amount); - tprintf(terminal, "\n"); - - try { - child.withdraw_ram_quota(amount); } - catch (Ram::Transfer_quota_failed) { - tprintf(terminal, "Error: transfer_quota failed\n"); } - } - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - /* lookup child by its unique name */ - Child *child = _children.first(); - for (; child; child = child->next()) - if (child->name() == label) - break; - - if (!child) { - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - return; - } - - bool const limit_specified = cmd.parameter_exists("--limit"); - Genode::Number_of_bytes limit = 0; - if (limit_specified) { - cmd.parameter("--limit", limit); - child->ram_limit(limit); - } - - if (cmd.parameter_exists("--quota")) { - Genode::Number_of_bytes quota = 0; - cmd.parameter("--quota", quota); - _set_quota(terminal, *child, quota); - } - } -}; - -#endif /* _RAM_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/start_command.h b/repos/os/src/app/cli_monitor/start_command.h deleted file mode 100644 index e217c59ee..000000000 --- a/repos/os/src/app/cli_monitor/start_command.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * \brief Start command - * \author Norman Feske - * \date 2013-03-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _START_COMMAND_H_ -#define _START_COMMAND_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Cli_monitor { class Start_command; } - - -class Cli_monitor::Start_command : public Command -{ - private: - - typedef Genode::Xml_node Xml_node; - typedef Genode::Signal_context_capability Signal_context_capability; - typedef Genode::Dataspace_capability Dataspace_capability; - - Genode::Env &_env; - Ram &_ram; - Genode::Allocator &_alloc; - Child_registry &_children; - Genode::Pd_session &_ref_pd; - Genode::Pd_session_capability _ref_pd_cap; - Genode::Region_map &_local_rm; - Subsystem_config_registry &_subsystem_configs; - List _arguments { }; - Signal_context_capability _yield_response_sigh_cap; - Signal_context_capability _exit_sig_cap; - - void _execute_subsystem(char const *name, Command_line &cmd, - Terminal::Session &terminal, - Genode::Xml_node subsystem_node) - { - size_t count = 1; - Genode::Number_of_bytes ram = 0; - Genode::Number_of_bytes ram_limit = 0; - size_t caps = subsystem_node.attribute_value("caps", 0UL); - - /* read default RAM quota from config */ - try { - Xml_node rsc = subsystem_node.sub_node("resource"); - for (;; rsc = rsc.next("resource")) { - if (rsc.attribute("name").has_value("RAM")) { - rsc.attribute("quantum").value(ram); - - if (rsc.has_attribute("limit")) - rsc.attribute("limit").value(ram_limit); - break; - } - } - } catch (...) { } - - cmd.parameter("--count", count); - cmd.parameter("--ram", ram); - cmd.parameter("--ram-limit", ram_limit); - - /* acount for cli_monitor local metadata */ - size_t preserve_ram = 100*1024; - if (count * (ram + preserve_ram) > _ram.avail()) { - tprintf(terminal, "Error: RAM quota exceeds available quota\n"); - return; - } - - bool const verbose = cmd.parameter_exists("--verbose"); - - /* - * Determine binary name - * - * Use subsystem name by default, override with '' declaration. - */ - typedef Genode::String<128> Binary_name; - Binary_name binary_name; - try { - Xml_node bin = subsystem_node.sub_node("binary"); - binary_name = bin.attribute_value("name", Binary_name()); - } catch (...) { } - - for (unsigned i = 0; i < count; i++) { - - /* generate unique child name */ - char label[Child_registry::CHILD_NAME_MAX_LEN]; - _children.unique_child_name(name, label, sizeof(label)); - - tprintf(terminal, "starting new subsystem '%s'\n", label); - - if (verbose) { - tprintf(terminal, " RAM quota: "); - tprint_bytes(terminal, ram); - tprintf(terminal,"\n"); - if (ram_limit) { - tprintf(terminal, " RAM limit: "); - tprint_bytes(terminal, ram_limit); - tprintf(terminal,"\n"); - } - tprintf(terminal, " binary: %s\n", binary_name.string()); - } - - Child *child = 0; - try { - child = new (_alloc) - Child(_env, _ram, _alloc, label, binary_name, - _ref_pd, _ref_pd_cap, _local_rm, - Genode::Cap_quota{caps}, ram, ram_limit, - _yield_response_sigh_cap, _exit_sig_cap); - } - catch (Genode::Service_denied) { - tprintf(terminal, "Error: could not start child \"%s\"\n", - binary_name); - return; - } - catch (Child::Quota_exceeded) { - tprintf(terminal, "Error: insufficient memory, need "); - tprint_bytes(terminal, ram + Child::DONATED_RAM_QUOTA); - tprintf(terminal, ", have "); - tprint_bytes(terminal, _ram.avail()); - tprintf(terminal, "\n"); - return; - } - catch (Genode::Allocator::Out_of_memory) { - tprintf(terminal, "Error: could not allocate meta data, out of memory\n"); - return; - } - - /* configure child */ - try { - Xml_node config_node = subsystem_node.sub_node("config"); - config_node.with_raw_node([&] (char const *start, size_t length) { - child->configure(start, length); }); - - if (verbose) - tprintf(terminal, " config: inline\n"); - } catch (...) { - if (verbose) - tprintf(terminal, " config: none\n"); - } - - _children.insert(child); - child->start(); - } - } - - Parameter _count_param { "--count", Parameter::NUMBER, "number of instances" }; - Parameter _ram_param { "--ram", Parameter::NUMBER, "initial RAM quota" }; - Parameter _ram_limit_param { "--ram-limit", Parameter::NUMBER, "limit for expanding RAM quota" }; - Parameter _verbose_param { "--verbose", Parameter::VOID, "show diagnostics" }; - - public: - - Start_command(Genode::Env &env, - Ram &ram, - Genode::Allocator &alloc, - Genode::Pd_session &ref_pd, - Genode::Pd_session_capability ref_pd_cap, - Genode::Region_map &local_rm, - Child_registry &children, - Subsystem_config_registry &subsustem_configs, - Signal_context_capability yield_response_sigh_cap, - Signal_context_capability exit_sig_cap) - : - Command("start", "create new subsystem"), - _env(env), _ram(ram), _alloc(alloc), _children(children), - _ref_pd(ref_pd), _ref_pd_cap(ref_pd_cap), _local_rm(local_rm), - _subsystem_configs(subsustem_configs), - _yield_response_sigh_cap(yield_response_sigh_cap), - _exit_sig_cap(exit_sig_cap) - { - add_parameter(_count_param); - add_parameter(_ram_param); - add_parameter(_ram_limit_param); - add_parameter(_verbose_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - /* functor for processing a subsystem configuration */ - auto process_subsystem_config_fn = [&] (Genode::Xml_node node) { - - if (!node.has_attribute("name")) { - Genode::warning("Missing name in '' configuration"); - return; - } - - typedef Genode::String<64> Name; - Name const name = node.attribute_value("name", Name()); - - char const *prefix = "config: "; - size_t const prefix_len = strlen(prefix); - - char help[Parameter::Short_help::size() + prefix_len]; - strncpy(help, prefix, ~0); - try { - Genode::Xml_attribute const help_attr = node.attribute("help"); - help_attr.with_raw_value([&] (char const *start, size_t len) { - strncpy(help + prefix_len, start, - Genode::min(len, Parameter::Short_help::size())); }); - } - catch (Xml_node::Nonexistent_attribute) { - Genode::warning("Missing help in '' configuration"); - return; - } - - Argument arg(name.string(), help); - fn(arg); - }; - - /* scan subsystem config registry for possible subsystem arguments */ - _subsystem_configs.for_each_config(process_subsystem_config_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char name[128]; - name[0] = 0; - if (cmd.argument(0, name, sizeof(name)) == false) { - tprintf(terminal, "Error: no configuration name specified\n"); - return; - } - - char buf[128]; - if (cmd.argument(1, buf, sizeof(buf))) { - tprintf(terminal, "Error: unexpected argument \"%s\"\n", buf); - return; - } - - try { - _subsystem_configs.for_config(name, [&] (Genode::Xml_node node) - { - _execute_subsystem(name, cmd, terminal, node); - }); - - } catch (Subsystem_config_registry::Nonexistent_subsystem_config) { - tprintf(terminal, "Error: no configuration for \"%s\"\n", name); - } - } - - List &arguments() { return _arguments; } -}; - -#endif /* _START_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/status_command.h b/repos/os/src/app/cli_monitor/status_command.h deleted file mode 100644 index 929a56d6f..000000000 --- a/repos/os/src/app/cli_monitor/status_command.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * \brief Status command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _STATUS_COMMAND_H_ -#define _STATUS_COMMAND_H_ - -/* local includes */ -#include -#include - -namespace Cli_monitor { struct Status_command; } - - -struct Cli_monitor::Status_command : Command -{ - Child_registry &_children; - Ram &_ram; - - Status_command(Ram &ram, Child_registry &children) - : - Command("status", "show runtime status"), - _children(children), _ram(ram) - { } - - void execute(Command_line &, Terminal::Session &terminal) override - { - using Terminal::tprintf; - - Ram::Status const ram_status = _ram.status(); - - tprint_status_bytes(terminal, " RAM quota: ", ram_status.quota); - tprint_status_bytes(terminal, " used: ", ram_status.used); - tprint_status_bytes(terminal, " avail: ", ram_status.avail); - tprint_status_bytes(terminal, " preserve: ", ram_status.preserve); - - tprintf(terminal, "\n"); - - struct Child_info - { - enum Column { NAME, QUOTA, LIMIT, XFER, USED, AVAIL, STATUS }; - - constexpr static size_t num_columns() { return STATUS + 1; } - - char const *name = 0; - Child::Ram_status ram_status { }; - - static char const *label(Column column) - { - switch (column) { - case NAME: return "process"; - case QUOTA: return "quota"; - case LIMIT: return "limit"; - case XFER: return "xfer"; - case USED: return "alloc"; - case AVAIL: return "avail"; - case STATUS: return "status"; - }; - return ""; - } - - size_t len(Column column) const - { - switch (column) { - case NAME: return strlen(name); - case QUOTA: return format_mib(ram_status.quota); - case LIMIT: - return ram_status.limit ? format_mib(ram_status.limit) : 0; - - case XFER: return format_mib(ram_status.xfer); - case USED: return format_mib(ram_status.used); - case AVAIL: return format_mib(ram_status.avail); - case STATUS: - { - size_t const req = ram_status.req; - return req ? strlen("req ") + format_mib(req) : 0; - } - }; - return 0; - } - - static bool left_aligned(Column column) - { - switch (column) { - case NAME: return true; - case QUOTA: return false; - case LIMIT: return false; - case XFER: return false; - case USED: return false; - case AVAIL: return false; - case STATUS: return true; - }; - return false; - } - - void print_cell(Terminal::Session &terminal, Column column) - { - switch (column) { - case NAME: tprintf(terminal, "%s", name); break; - case QUOTA: tprint_mib(terminal, ram_status.quota); break; - case LIMIT: - - if (ram_status.limit) - tprint_mib(terminal, ram_status.limit); - break; - - case XFER: tprint_mib(terminal, ram_status.xfer); break; - case USED: tprint_mib(terminal, ram_status.used); break; - case AVAIL: tprint_mib(terminal, ram_status.avail); break; - case STATUS: - if (ram_status.req) { - tprintf(terminal, "req "); - tprint_mib(terminal, ram_status.req); - } - break; - }; - } - - Child_info() { } - Child_info(char const *name, Child::Ram_status ram_status) - : - name(name), ram_status(ram_status) - { } - }; - - /* - * Take snapshot of child information. - */ - size_t num_children = 0; - for (Child *c = _children.first(); c; c = c->next()) - num_children++; - - Child_info child_info[num_children]; - unsigned i = 0; - for (Child *c = _children.first(); c && i < num_children; c = c->next(), i++) - child_info[i] = Child_info(c->name().string(), c->ram_status()); - - /* - * Print table - */ - if (num_children) { - Table::print(terminal, child_info, num_children); - tprintf(terminal, "\n"); - } - } -}; - -#endif /* _STATUS_COMMAND_H_ */ diff --git a/repos/os/src/app/cli_monitor/subsystem_config_registry.h b/repos/os/src/app/cli_monitor/subsystem_config_registry.h deleted file mode 100644 index 3477b8ea6..000000000 --- a/repos/os/src/app/cli_monitor/subsystem_config_registry.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * \brief Registry of subsystem configuration - * \author Norman Feske - * \date 2015-01-27 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _SUBSYSTEM_CONFIG_REGISTRY_H_ -#define _SUBSYSTEM_CONFIG_REGISTRY_H_ - -/* Genode includes */ -#include -#include - -namespace Cli_monitor { class Subsystem_config_registry; } - - -class Cli_monitor::Subsystem_config_registry -{ - public: - - /** - * Exception type - */ - class Nonexistent_subsystem_config { }; - - private: - - Vfs::File_system &_fs; - Genode::Allocator &_alloc; - Genode::Entrypoint &_ep; - - enum { CONFIG_BUF_SIZE = 32*1024 }; - char _config_buf[CONFIG_BUF_SIZE]; - - char const *_subsystems_path() { return "/subsystems"; } - char const *_subsystem_suffix() { return ".subsystem"; } - - /** - * Return index of ".subsystem" suffix in dirent name - * - * \return index, or 0 if no matching suffix could be found - */ - unsigned _subsystem_suffix(Vfs::Directory_service::Dirent const &dirent) - { - unsigned found = 0; - for (unsigned i = 0; i < sizeof(dirent.name.buf) && dirent.name.buf[i]; i++) - if (Genode::strcmp(_subsystem_suffix(), &dirent.name.buf[i]) == 0) - found = i; - - return found; - } - - - public: - - /** - * Constructor - */ - Subsystem_config_registry(Vfs::File_system &fs, Genode::Allocator &alloc, - Genode::Entrypoint &ep) - : - _fs(fs), _alloc(alloc), _ep(ep) - { } - - /** - * Execute functor 'fn' for specified subsystem name - * - * The functor is called with the subsystem XML node as argument - * - * \throw Nonexistent_subsystem_config - */ - template - void for_config(char const *name, FN const &fn) - { - using Genode::error; - - /* - * Load subsystem configuration - */ - - Genode::Path<256> path(_subsystems_path()); - path.append("/"); - path.append(name); - path.append(_subsystem_suffix()); - - Vfs::Vfs_handle *handle = nullptr; - - Vfs::Directory_service::Open_result const open_result = - _fs.open(path.base(), - Vfs::Directory_service::OPEN_MODE_RDONLY, - &handle, _alloc); - - Vfs::Vfs_handle::Guard handle_guard(handle); - - if (open_result != Vfs::Directory_service::OPEN_OK) { - error("could not open '", path, "', err=", (int)open_result); - throw Nonexistent_subsystem_config(); - } - - Vfs::file_size out_count = 0; - - handle->fs().queue_read(handle, sizeof(_config_buf)); - - Vfs::File_io_service::Read_result read_result; - - while ((read_result = - handle->fs().complete_read(handle, _config_buf, - sizeof(_config_buf), - out_count)) == - Vfs::File_io_service::READ_QUEUED) - _ep.wait_and_dispatch_one_io_signal(); - - if (read_result != Vfs::File_io_service::READ_OK) { - error("could not read '", path, "', err=", (int)read_result); - throw Nonexistent_subsystem_config(); - } - - try { - Genode::Xml_node subsystem_node(_config_buf, out_count); - fn(subsystem_node); - - } catch (Genode::Xml_node::Invalid_syntax) { - error("subsystem configuration has invalid syntax"); - throw Nonexistent_subsystem_config(); - - } catch (Genode::Xml_node::Nonexistent_sub_node) { - error("invalid subsystem configuration"); - throw Nonexistent_subsystem_config(); - } - } - - /** - * Call specified functor for each subsystem config - */ - template - void for_each_config(FN const &fn) - { - using Genode::error; - - Vfs::Vfs_handle *dir_handle; - - if (_fs.opendir(_subsystems_path(), false, &dir_handle, _alloc) != - Vfs::Directory_service::OPENDIR_OK) { - error("could not access directory '", _subsystems_path(), "'"); - return; - } - - /* iterate over the directory entries */ - for (unsigned i = 0;; i++) { - - Vfs::Directory_service::Dirent dirent { }; - - dir_handle->seek(i * sizeof(dirent)); - dir_handle->fs().queue_read(dir_handle, sizeof(dirent)); - - Vfs::file_size out_count; - while (dir_handle->fs().complete_read(dir_handle, - (char*)&dirent, - sizeof(dirent), - out_count) == - Vfs::File_io_service::READ_QUEUED) - _ep.wait_and_dispatch_one_io_signal(); - - if (dirent.type == Vfs::Directory_service::Dirent_type::END) { - _fs.close(dir_handle); - return; - } - - unsigned const subsystem_suffix = _subsystem_suffix(dirent); - - /* if file has a matching suffix, apply 'fn' */ - if (subsystem_suffix) { - - /* subsystem name is file name without the suffix */ - char name[sizeof(dirent.name.buf)]; - Genode::strncpy(name, dirent.name.buf, subsystem_suffix + 1); - - try { - for_config(name, fn); - } catch (Nonexistent_subsystem_config) { } - } - } - - _fs.close(dir_handle); - } -}; - -#endif /* _PROCESS_ARG_REGISTRY_H_ */ diff --git a/repos/os/src/app/cli_monitor/table.h b/repos/os/src/app/cli_monitor/table.h deleted file mode 100644 index 2ba99495f..000000000 --- a/repos/os/src/app/cli_monitor/table.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * \brief Utility for printing a table to the terminal - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TABLE_H_ -#define _TABLE_H_ - -#include - -namespace Cli_monitor { template class Table; } - - -template -class Cli_monitor::Table -{ - private: - - static void _print_cell(TI &info, Terminal::Session &terminal, - typename TI::Column column, size_t column_size) - { - size_t const padding = column_size - info.len(column); - - if (!TI::left_aligned(column)) - tprint_padding(terminal, padding); - - info.print_cell(terminal, column); - - if (TI::left_aligned(column)) - tprint_padding(terminal, padding); - } - - /** - * Print centered title of table column - */ - static void _print_label(Terminal::Session &terminal, - typename TI::Column column, size_t column_size) - { - size_t const padding = column_size - strlen(TI::label(column)); - size_t const left_padding = padding / 2; - - tprint_padding(terminal, left_padding); - tprintf(terminal, "%s", TI::label(column)); - tprint_padding(terminal, padding - left_padding); - } - - public: - - static void print(Terminal::Session &terminal, TI info[], unsigned num_rows) - { - /* - * Determine formatting of table - */ - size_t column_size[TI::num_columns()]; - for (unsigned i = 0; i < TI::num_columns(); i++) - column_size[i] = strlen(TI::label((typename TI::Column)i)); - - for (unsigned i = 0; i < num_rows; i++) { - for (unsigned j = 0; j < TI::num_columns(); j++) - column_size[j] = max(column_size[j], - info[i].len((typename TI::Column)j)); - } - - /* - * Print table - */ - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - _print_label(terminal, (typename TI::Column)j, column_size[j]); - if (j < TI::num_columns() - 1) tprintf(terminal, " | "); - } - tprintf(terminal, "\n"); - - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - for (unsigned i = 0; i < column_size[j]; i++) - tprintf(terminal, "-"); - if (j < TI::num_columns() - 1) tprintf(terminal, "-+-"); - } - tprintf(terminal, "\n"); - - for (unsigned i = 0; i < num_rows; i++) { - tprintf(terminal, " "); - for (unsigned j = 0; j < TI::num_columns(); j++) { - _print_cell(info[i], terminal, (typename TI::Column)j, column_size[j]); - if (j < TI::num_columns() - 1) tprintf(terminal, " | "); - } - tprintf(terminal, "\n"); - } - } -}; - -#endif /* _TABLE_H_ */ diff --git a/repos/os/src/app/cli_monitor/target.mk b/repos/os/src/app/cli_monitor/target.mk deleted file mode 100644 index 41ee20a17..000000000 --- a/repos/os/src/app/cli_monitor/target.mk +++ /dev/null @@ -1,4 +0,0 @@ -TARGET = cli_monitor -SRC_CC = main.cc -LIBS = base vfs -INC_DIR += $(PRG_DIR) diff --git a/repos/os/src/app/cli_monitor/terminal_util.h b/repos/os/src/app/cli_monitor/terminal_util.h deleted file mode 100644 index 75413a144..000000000 --- a/repos/os/src/app/cli_monitor/terminal_util.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * \brief Convenience functions for operating on a terminal session - * \author Norman Feske - * \date 2013-03-19 - */ - -#ifndef _TERMINAL_UTIL_H_ -#define _TERMINAL_UTIL_H_ - -/* Genode includes */ -#include -#include - -namespace Terminal { - - static inline void tprintf(Session &terminal, const char *format_args, ...) - { - using namespace Genode; - - enum { MAX_LEN = 256 }; - char buf[MAX_LEN]; - - /* process format string */ - va_list list; - va_start(list, format_args); - - String_console sc(buf, MAX_LEN); - sc.vprintf(format_args, list); - - va_end(list); - - terminal.write(buf, strlen(buf)); - } -} - -#endif /* _TERMINAL_UTIL_H_ */ diff --git a/repos/os/src/app/cli_monitor/yield_command.h b/repos/os/src/app/cli_monitor/yield_command.h deleted file mode 100644 index bc0e2ebdf..000000000 --- a/repos/os/src/app/cli_monitor/yield_command.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * \brief Yield command - * \author Norman Feske - * \date 2013-10-05 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _YIELD_COMMAND_H_ -#define _YIELD_COMMAND_H_ - -/* local includes */ -#include - -namespace Cli_monitor { struct Yield_command; } - - -struct Cli_monitor::Yield_command : Command -{ - Child_registry &_children; - - Parameter _ram_param { "--ram", Parameter::NUMBER, "RAM quota to free" }; - Parameter _greedy_param { "--greedy", Parameter::VOID, "withdraw yielded RAM quota" }; - - Yield_command(Child_registry &children) - : - Command("yield", "instruct subsystem to yield resources"), - _children(children) - { - add_parameter(_ram_param); - add_parameter(_greedy_param); - } - - void _for_each_argument(Argument_fn const &fn) const override - { - auto child_name_fn = [&] (Child_base::Name const &child_name) { - Argument arg(child_name.string(), ""); - fn(arg); - }; - - _children.for_each_child_name(child_name_fn); - } - - void execute(Command_line &cmd, Terminal::Session &terminal) override - { - char label[128]; - label[0] = 0; - if (cmd.argument(0, label, sizeof(label)) == false) { - tprintf(terminal, "Error: no subsystem name specified\n"); - return; - } - - Genode::Number_of_bytes ram = 0; - cmd.parameter("--ram", ram); - - bool const greedy = cmd.parameter_exists("--greedy"); - - /* lookup child by its unique name */ - Child *child = _children.first(); - for (; child; child = child->next()) - if (child->name() == label) - break; - - if (!child) { - tprintf(terminal, "Error: subsystem '%s' does not exist\n", label); - return; - } - - child->yield(ram, greedy); - - tprintf(terminal, "requesting '%s' to yield ", child->name().string()); - tprint_bytes(terminal, ram); - tprintf(terminal, "\n"); - } -}; - -#endif /* _YIELD_COMMAND_H_ */ diff --git a/repos/os/src/server/fs_log/README b/repos/os/src/server/fs_log/README index db41b850b..0c35d004d 100644 --- a/repos/os/src/server/fs_log/README +++ b/repos/os/src/server/fs_log/README @@ -18,7 +18,7 @@ the file "/log". ! ! ! -! +! ! ! !