/* * This source code is released into the public domain. */ #ifndef LFJAIL_COMMAND_MAP_HH #define LFJAIL_COMMAND_MAP_HH /* * command_map represents a hierarchical list of commands. At each level, * a command is mapped to a handler, which can either be a function, in * which case we execute the function, or another command_map, in which * case we invoke the new map */ #include #include #include #include #include "context.hh" #include "string_utils.hh" #include "usage_error.hh" namespace lfjail::command { namespace detail { struct command_base { command_base(command_base const &) = delete; command_base &operator=(command_base const &) = delete; command_base(std::string_view path) noexcept; virtual auto invoke(context const &, int, char **) -> int = 0; }; } // namespace detail // Declare a global command and add it to the root node. template F> struct command final : detail::command_base { command(std::string_view path, F fn) try : command_base(path) , _func(std::move(fn)) { } catch (std::exception const &exc) { std::cerr << "lfjail: ERROR: failed to initialise command " << path << ": " << exc.what() << "\n"; std::abort(); } auto invoke(context const &ctx, int argc, char **argv) -> int override { return std::invoke(_func, ctx, argc, argv); } private: F _func; }; // Dispatch a command based on argc/argv. auto dispatch(context const &, int argc, char **argv) -> int; // Print a list of commands to stderr. void print_usage(std::string_view prefix); } // namespace lfjail #endif // !LFJAIL_COMMAND_MAP_HH