Added a crude alias system for commands
This commit is contained in:
parent
f2f94b70d4
commit
b746e30627
@ -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
|
||||||
|
|
||||||
|
10
src/domain.h
10
src/domain.h
@ -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);
|
|
||||||
|
104
src/sandbox.c
104
src/sandbox.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user