Added a crude alias system for commands

This commit is contained in:
Alexei KADIR 2024-02-23 18:32:03 +01:00
parent f2f94b70d4
commit b746e30627
4 changed files with 82 additions and 51 deletions

View File

@ -103,7 +103,7 @@ After=multi-user.target
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/fstrim -va ExecStart=
ExecStop=/usr/bin/fstrim -va ExecStop=/usr/bin/fstrim -va
RemainAfterExit=yes RemainAfterExit=yes

View File

@ -13,13 +13,3 @@ result_t container_to_domain_identifier(char** _domain, const char* container);
/// @param domain The domain identifier to convert. /// @param domain The domain identifier to convert.
/// @return The result of the operation. /// @return The result of the operation.
result_t domain_to_container_identifier(char** _container, const char* domain); result_t domain_to_container_identifier(char** _container, const char* domain);
/// @brief Checks whether the given string is a valid domain identifier. If the string is not a valid domain identifier, the call will return a failure result with an error message.
/// @param domain The string to check.
/// @return The result of the operation.
result_t check_domain_identifier(const char* domain);
/// @brief Checks whether the given domain exists. If the domain does not exist, the call will return a failure result with an error message.
/// @param domain The domain to check.
/// @return The result of the operation.
result_t check_domain_exists(const char* domain);

View File

@ -9,12 +9,17 @@
#include <stdbool.h> #include <stdbool.h>
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#define ALIAS(...) \ #define ALIAS(...) \
(const char*[]) { __VA_ARGS__, NULL } (const char*[]) { \
__VA_ARGS__, NULL \
}
#define ALIASES(...) \ #define ALIASES(...) \
(const char**[]) { __VA_ARGS__, NULL } (const char**[]) { \
__VA_ARGS__, NULL \
}
#define ARGUMENTS(...) \ #define ARGUMENTS(...) \
(const Argument[]) { \ (const Argument[]) { \
@ -26,51 +31,86 @@
__VA_ARGS__, {} \ __VA_ARGS__, {} \
} }
Command COMMANDS[] = { #define OPTION_ALIASES(...) \
// Help (const char*[]) { \
__VA_ARGS__, NULL \
}
const Command COMMANDS[] = {
{ {
.handler = command_help, .handler = command_help,
.description = "Display help information.", .description = "Display help information",
.details = "Display help information about the available commands and their options.", .details = "Display help information for a specific command",
.aliases = ALIASES(ALIAS("help")),
.arguments = ARGUMENTS({.name = "command", .required = false, .description = "The command to display help information for."}, .aliases = ALIASES(ALIAS("h"), ALIAS("help", "me")),
{.name = "test", .required = false, .description = "Test."}), .arguments = ARGUMENTS({
.options = OPTIONS({.aliases = ALIASES(ALIAS("--help"), ALIAS("-h")), .arguments = NULL, .description = "Display help information."}, .name = "command",
{.aliases = ALIASES(ALIAS("--test")), .arguments = NULL, .description = "Test."}), .description = "The command to display help information for",
.optional = true,
}),
.options = OPTIONS({
.aliases = OPTION_ALIASES("verbose", "v"),
.description = "Display verbose help information",
.arguments = ARGUMENTS({
.name = "level",
.description = "The level of verbosity to display",
}),
}),
}, },
}; {}};
int main(int argc, char** argv) { int main(int argc, char** argv) {
// Ensure the sandbox user exists if (argc == 1) {
struct passwd* pw = getpwnam(SANDBOX_USER); // Handle no command
if (pw == NULL) { fprintf(stderr, "No command specified\n");
fprintf(stderr, "User '%s' does not exist. Please check that the program is installed correctly.\n", SANDBOX_USER);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Check that the program is either run as root or as the sandbox user // For each command
if (geteuid() != 0 && geteuid() != pw->pw_uid) { for (int i = 0; COMMANDS[i].handler != NULL; i++) {
fprintf(stderr, "This program must be run as root or as the user '%s'.\n", SANDBOX_USER); const Command* command = &COMMANDS[i];
return EXIT_FAILURE;
// For each alias
bool command_matched = false;
int k = 0;
for (int j = 0; command->aliases[j] != NULL; j++) {
const char** alias = command->aliases[j];
// For each string in the alias
bool alias_matched = true;
for (k = 0; alias[k] != NULL; k++)
if (argc <= 1 + k || strcmp(argv[1 + k], alias[k]) != 0) {
alias_matched = false;
break;
} }
// If the program is run as root, switch to the sandbox user // Check if the alias matched
if (geteuid() == 0) { if (alias_matched) {
if (setregid(pw->pw_gid, pw->pw_gid) != 0) { command_matched = true;
fprintf(stderr, "Failed to switch to the group '%s'.\n", pw->pw_name); break;
return EXIT_FAILURE;
}
if (setreuid(pw->pw_uid, pw->pw_uid) != 0) {
fprintf(stderr, "Failed to switch to the user '%s'.\n", pw->pw_name);
return EXIT_FAILURE;
} }
} }
// TODO: Parse commands from the command line // If the command matched
return EXIT_SUCCESS; if (command_matched) {
// Call the command handler
return command->handler(argc - 1 - k, argv + 1 + k);
}
}
fprintf(stderr, "Unknown command: ");
for (int i = 1; i < argc; i++)
fprintf(stderr, "%s ", argv[i]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
} }
int command_help(int argc, char* argv[]) { int command_help(int argc, char* argv[]) {
// Print argv
printf("argc: %d\n", argc);
for (int i = 0; i < argc; i++)
printf("%s\n", argv[i]);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -13,26 +13,27 @@
typedef struct { typedef struct {
const char* name; const char* name;
const bool required;
const char* description; const char* description;
const bool optional;
} Argument; } Argument;
typedef struct { typedef struct {
const char*** aliases; const char** aliases;
const Argument* arguments;
const char* description; const char* description;
const Argument* arguments;
} Option; } Option;
typedef struct { typedef struct {
int (*const handler)(int argc, char* argv[]); int (*handler)(int argc, char* argv[]);
const char* description;
const char* details;
const char*** aliases; const char*** aliases;
const Argument* arguments; const Argument* arguments;
const Option* options; const Option* options;
const char* description;
const char* details;
} Command; } Command;
extern Command COMMANDS[]; extern const Command COMMANDS[];
int main(int argc, char** argv); int main(int argc, char** argv);