diff --git a/arch/x86_64/init.c b/arch/x86_64/init.c index d468293..18dbdf2 100644 --- a/arch/x86_64/init.c +++ b/arch/x86_64/init.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -104,6 +105,8 @@ int ml_init(uintptr_t arg) { multiboot_info_t *mb = (multiboot_info_t *)arg; + parse_cmdline(PTR32(mb->cmdline)); + init_bootfb(mb); bootstrap_cpu_init(); diff --git a/include/socks/arg.h b/include/socks/arg.h new file mode 100644 index 0000000..609c594 --- /dev/null +++ b/include/socks/arg.h @@ -0,0 +1,14 @@ +#ifndef SOCKS_ARG_H_ +#define SOCKS_ARG_H_ + +#include +#include + +#define CMDLINE_MAX 4096 + +extern kern_status_t parse_cmdline(const char *cmdline); + +extern const char *arg_value(const char *arg_name); +extern bool arg_is_set(const char *arg_name); + +#endif diff --git a/kernel/arg.c b/kernel/arg.c new file mode 100644 index 0000000..48197bc --- /dev/null +++ b/kernel/arg.c @@ -0,0 +1,125 @@ +#include +#include +#include + +static char g_cmdline[CMDLINE_MAX + 1] = {0}; + +static kern_status_t remove_quotes(char *s, size_t max) +{ + size_t i = 0; + while (i < max) { + if (s[i] != '"') { + i++; + continue; + } + + size_t start = i; + size_t end = i + 1; + while (s[end] != '"' && end < max) { + end++; + } + + if (s[end] != '"') { + return KERN_INVALID_ARGUMENT; + } + + /* length of quoted string (excluding quotes) */ + size_t len = end - start - 1; + + /* remove trailing quote */ + s[end] = 0; + + /* add 1 to len to include the null terminator */ + memmove(s + start, s + start + 1, len + 1); + + i = end + 1; + } + + return KERN_OK; +} + +kern_status_t parse_cmdline(const char *cmdline) +{ + strncpy(g_cmdline, cmdline, sizeof g_cmdline - 1); + g_cmdline[sizeof g_cmdline - 1] = 0; + + bool in_string = false; + + for (size_t i = 0; g_cmdline[i]; i++) { + char c = g_cmdline[i]; + + if (c == '"') { + in_string = !in_string; + continue; + } + + if (isspace(c) && !in_string) { + g_cmdline[i] = 0; + } + } + + if (in_string) { + /* unterminated string on command line */ + return KERN_INVALID_ARGUMENT; + } + + remove_quotes(g_cmdline, sizeof g_cmdline); + + return KERN_OK; +} + +static char *advance_to_next_arg(char *s, char *max) +{ + while (*s && s < max) { + s++; + } + + while (!*s && s < max) { + s++; + } + + return s; +} + + +const char *arg_value(const char *arg_name) +{ + char *s = g_cmdline; + char *end = s + sizeof g_cmdline; + + while (s < end) { + size_t len = strlen(s); + size_t name_len = strcspn(s, "="); + + if (!strncmp(s, arg_name, name_len)) { + if (len == name_len) { + /* arg has no value */ + return NULL; + } + + return s + name_len + 1; + } + + s = advance_to_next_arg(s, end); + } + + return NULL; +} + +bool arg_is_set(const char *arg_name) +{ + char *s = g_cmdline; + char *end = s + sizeof g_cmdline; + + while (s < end) { + size_t name_len = strcspn(s, "="); + + if (!strncmp(s, arg_name, name_len)) { + return true; + } + + s = advance_to_next_arg(s, end); + } + + return false; +}