From 2c0dd8d9abd56944f6800d7aeb036026172d93f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexe=C3=AF=20KADIR?= Date: Fri, 16 Feb 2024 17:13:52 +0100 Subject: [PATCH] Added support for CLI style commands --- .gitignore | 1 + Makefile | 4 --- src/command.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/command.h | 50 +++++++++++++++++++++++++++ src/sandbox.c | 40 ++++++++++++---------- src/sandbox.h | 31 +---------------- 6 files changed, 168 insertions(+), 51 deletions(-) create mode 100644 src/command.c create mode 100644 src/command.h diff --git a/.gitignore b/.gitignore index 69f851d..aa61156 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ [bB]in/ +.vscode/ \ No newline at end of file diff --git a/Makefile b/Makefile index b0f27fd..9756b41 100644 --- a/Makefile +++ b/Makefile @@ -6,20 +6,16 @@ CF = -Wall -lkrb5 -lvirt -ljson-c -g # ---- ---- # build: $(shell find . -name "*.c") $(shell find . -name "*.h") - @echo "Building sandbox..." @mkdir -p bin @$(CC) $(CF) -o ./bin/sandbox $(shell find . -name "*.c") run: build - @echo "Running sandbox..." @./bin/sandbox debug: build - @echo "Debugging sandbox..." @gdb -q ./bin/sandbox clean: - @echo "Cleaning sandbox..." @rm -rf ./bin .PHONY: build run clean diff --git a/src/command.c b/src/command.c new file mode 100644 index 0000000..ed5688a --- /dev/null +++ b/src/command.c @@ -0,0 +1,93 @@ +#include "command.h" + +#include "sandbox.h" + +#include +#include + +Command COMMANDS[] = { + {"help", "[command]", "Shows help for all or a specific command.", CMD_HELP}, + {"version", "", "Shows the version of the program.", CMD_VERSION}, + {NULL}, + {"add-entry", " [--root|-r ] [--backing|-b ]", "Adds a new entry to the pool", CMD_ADD_ENTRY}, + {"remove-entry", "", "Removes an entry from the pool", CMD_REMOVE_ENTRY}, + {"list-entries", "", "Lists all entries in the pool", CMD_LIST_ENTRIES}, + {"clear-entries", "", "Clears all entries from the pool", CMD_CLEAR_ENTRIES}, + {NULL}, + {"add-backing", "", "Adds a backing disk to the pool from the given entry", CMD_ADD_BACKING}, + {"remove-backing", "", "Removes a backing disk from the pool", CMD_REMOVE_BACKING}, + {"list-backings", "[--tree|-t]", "Lists all backing disks in the pool", CMD_LIST_BACKINGS}, + {"clear-backings", "", "Clears all backing disks from the pool", CMD_CLEAR_BACKINGS}, + {NULL}, + {"start", " [--no-pci] [--vnc ] [--iso ]", "Starts the sandbox with the given entry", CMD_START}, + {"power", "", "Sends a power signal to the sandbox", CMD_POWER}, + {"stop", "[--force|-f] [--timeout|-t ]", "Stops the sandbox", CMD_STOP}, + {"status", "", "Shows the status of the sandbox", CMD_STATUS}, +}; + +Command* find_command(const char* name) { + Command* match = NULL; + + // Find all matching commands (starting with the given name) + size_t length = strlen(name); + for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) { + if (COMMANDS[i].name == NULL) + continue; + + // Check the sizes + if (strlen(COMMANDS[i].name) < length) + continue; + + if (strncmp(name, COMMANDS[i].name, length) == 0) { + // Check for multiple matches + if (match != NULL) + return NULL; + + match = &COMMANDS[i]; + } + } + + return match; +} + +void show_help() { + printf("Usage: sandbox [args]\n\n"); + printf("Commands:\n"); + for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) { + if (COMMANDS[i].name == NULL) { + printf("\n"); + continue; + } + + printf(" %s %s\n", COMMANDS[i].name, COMMANDS[i].args); + printf(" %s\n", COMMANDS[i].description); + } + printf("\n"); + printf("For more information about a specific command, use 'sandbox help '.\n"); +} + +void show_command_help(const Command* command) { + printf("Usage: sandbox %s %s\n", command->name, command->args); + printf(" %s\n", command->description); +} + +int cmd_help(int argc, char** argv) { + if (argc == 0) { + show_help(); + return 0; + } + + Command* command = find_command(argv[0]); + if (command == NULL) { + printf("Unknown command '%s'.\n", argv[0]); + return 1; + } + + show_command_help(command); + return 0; +} + +int cmd_version(int argc, char** argv) { + printf("Sandbox version v" SANDBOX_VERSION "\n"); + return 0; +} diff --git a/src/command.h b/src/command.h new file mode 100644 index 0000000..a164047 --- /dev/null +++ b/src/command.h @@ -0,0 +1,50 @@ +#pragma once + +#include + +typedef enum { + CMD_UNKNOWN, + + CMD_HELP, + CMD_VERSION, + + CMD_ADD_ENTRY, + CMD_REMOVE_ENTRY, + CMD_LIST_ENTRIES, + CMD_CLEAR_ENTRIES, + + CMD_ADD_BACKING, + CMD_REMOVE_BACKING, + CMD_LIST_BACKINGS, + CMD_CLEAR_BACKINGS, + + CMD_START, + CMD_POWER, + CMD_STOP, + CMD_STATUS, +} CommandID; + +typedef struct { + const char* name; + const char* args; + const char* description; + CommandID id; +} Command; + +extern Command COMMANDS[]; + +/// @brief Finds the best matching command for the given command name. +/// @param name The name of the command to find. +/// @return The best matching command or NULL if no or multiple matches were found. No need to free the result. +Command* find_command(const char* name); + +/// @brief Shows the help for all commands. +void show_help(); + +/// @brief Shows the help for a specific command. +/// @param command The command to show the help for. +void show_command_help(const Command* command); + +int cmd_help(int argc, char** argv); + +int cmd_version(int argc, char** argv); \ No newline at end of file diff --git a/src/sandbox.c b/src/sandbox.c index 4497949..854fd10 100644 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -1,28 +1,34 @@ #include "sandbox.h" #include "utils.h" +#include "command.h" #include #include #include +#include int main(int argc, char* argv[]) { + if (argc < 2) { + show_help(); + return 0; + } + + Command* command = find_command(argv[1]); + if (command == NULL) { + log_message(LOG_ERROR, "Unknown command '%s'.", argv[1]); + return 1; + } + + switch (command->id) { + case CMD_HELP: + return cmd_help(argc - 2, argv + 2); + case CMD_VERSION: + return cmd_version(argc - 2, argv + 2); + default: + log_message(LOG_ERROR, "Command '%s' is not implemented.", command->name); + break; + } + return 0; } - -Command* find_command(const char* name) { - Command* match = NULL; - - // Find all matching commands (starting with the given name) - size_t length = strlen(name); - for (size_t i = 0; i < sizeof(COMMANDS) / sizeof(COMMANDS[0]); i++) - if (strncmp(name, COMMANDS[i].name, length) == 0) { - // Check for multiple matches - if (match != NULL) - return NULL; - - match = &COMMANDS[i]; - } - - return match; -} diff --git a/src/sandbox.h b/src/sandbox.h index 9520cbe..cf11893 100644 --- a/src/sandbox.h +++ b/src/sandbox.h @@ -2,35 +2,6 @@ #include -typedef struct { - const char* name; - const char* args; - const char* description; -} Command; - -Command COMMANDS[] = { - {"help", "[command]", "Shows help for all or a specific command."}, - {"version", NULL, "Shows the version of the program."}, - {NULL, NULL, NULL}, - {"add-entry", " [--root|-r ] [--backing|-b ]", "Adds a new entry to the pool"}, - {"remove-entry", "", "Removes an entry from the pool"}, - {"list-entries", NULL, "Lists all entries in the pool"}, - {"clear-entries", NULL, "Clears all entries from the pool"}, - {NULL, NULL, NULL}, - {"add-backing", "", "Adds a backing disk to the pool from the given entry"}, - {"remove-backing", "", "Removes a backing disk from the pool"}, - {"list-backings", "[--tree|-t]", "Lists all backing disks in the pool"}, - {"clear-backings", NULL, "Clears all backing disks from the pool"}, - {NULL, NULL, NULL}, - {"start", " [--no-pci] [--vnc ] [--iso ]", "Starts the sandbox with the given entry"}, - {"power", NULL, "Sends a power signal to the sandbox"}, - {"stop", "[--force|-f] [--timeout|-t ]", "Stops the sandbox"}, - {"status", NULL, "Shows the status of the sandbox"}, -}; +#define SANDBOX_VERSION "1.0.0" int main(int argc, char* argv[]); - -/// @brief Finds the best matching command for the given command name. -/// @param name The name of the command to find. -/// @return The best matching command or NULL if no or multiple matches were found. No need to free the result. -Command* find_command(const char* name);