diff options
author | Ian Moffett <ian@osmora.org> | 2024-05-22 19:50:54 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-05-22 19:55:00 -0400 |
commit | 5559da2299dc50b50c62d7d1b92b769803fb9321 (patch) | |
tree | 6450d1450a3fc4fb607310b41c1d559126b4de6e | |
parent | d6104baa618686f7f0f0f36216394b60553ac14a (diff) |
init: Add maintenance shell
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | usr.sbin/init/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/init/main.c | 7 | ||||
-rw-r--r-- | usr.sbin/init/mshell.c | 172 | ||||
-rw-r--r-- | usr.sbin/init/mshell.h | 35 |
4 files changed, 214 insertions, 2 deletions
diff --git a/usr.sbin/init/Makefile b/usr.sbin/init/Makefile index 13ac173..1bf7718 100644 --- a/usr.sbin/init/Makefile +++ b/usr.sbin/init/Makefile @@ -3,4 +3,4 @@ include ../sbin.mk .PHONY: all all: @ # $(CC) -pie -nostdlib main.c -o init -e main - $(CC) main.c -o init $(INTERNAL_CFLAGS) + $(CC) main.c mshell.c -o init $(INTERNAL_CFLAGS) diff --git a/usr.sbin/init/main.c b/usr.sbin/init/main.c index 754b98e..4a7176c 100644 --- a/usr.sbin/init/main.c +++ b/usr.sbin/init/main.c @@ -28,6 +28,7 @@ */ #include <stdio.h> +#include "mshell.h" #define VERSION "v0.0.1" @@ -43,7 +44,11 @@ int main(int argc, char **argv) { loginfo("Hyra init " VERSION " loaded\n"); - loginfo("Hello, World!\n"); + loginfo("Dropping into maintenance shell...\n"); + + if (mshell_enter() != 0) + loginfo("Failed to launch mshell!\n"); + loginfo("** EXITING 0 **\n"); return 0; } diff --git a/usr.sbin/init/mshell.c b/usr.sbin/init/mshell.c new file mode 100644 index 0000000..78c3a82 --- /dev/null +++ b/usr.sbin/init/mshell.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Maintenance shell */ + +#include <sys/reboot.h> +#include <sys/auxv.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <termios.h> +#include "mshell.h" + +#define INPUT_SIZE 32 +#define TTY_DEV "/dev/tty1" +#define PROMPT "mshell> " + +struct mshell_state { + uint8_t running : 1; + char input[INPUT_SIZE]; +}; + +static void +help(void) +{ + printf( + "MSHELL COMMANDS\n" + "\thelp - show this message\n" + "\treboot - reboot the system\n" + "\ttty - show the current TTY\n" + "\tpagesize - get the current page size\n" + "\texit - exit the shell\n" + ); +} + +static void +parse_input(struct mshell_state *state) +{ + char cmd[INPUT_SIZE]; + char *p = &state->input[0]; + size_t cmd_idx = 0; + + /* Skip leading whitespace */ + while (*p && *p == ' ') + ++p; + + /* Push the command */ + while (*p && *p != '\n') + cmd[cmd_idx++] = *p++; + + cmd[cmd_idx] = '\0'; + + if (strcmp(cmd, "reboot") == 0) { + reboot(REBOOT_DEFAULT); + } else if (strcmp(cmd, "pagesize") == 0) { + printf("%d\n", auxv_entry(AT_PAGESIZE)); + } else if (strcmp(cmd, "tty") == 0) { + printf("%s\n", TTY_DEV); + } else if (strcmp(cmd, "help") == 0) { + help(); + } else if (strcmp(cmd, "exit") == 0) { + state->running = 0; + } else { + printf("Unknown command '%s'\n", cmd); + printf("Use 'help' for help\n"); + } +} + +int +mshell_enter(void) +{ + int fd, tmp; + size_t input_idx; + struct termios tm_old, tm; + struct mshell_state state = { + .running = 1 + }; + + /* Try opening the TTY */ + fd = open(TTY_DEV, O_RDONLY); + if (fd < 0) + return -1; + + /* Set raw mode */ + tcgetattr(fd, &tm_old); + tm = tm_old; + tm.c_lflag &= ~(ICANON | ECHO); + tcsetattr(fd, 0, &tm); + + printf("%s", PROMPT); + input_idx = 0; + + while (state.running) { + if (read(fd, &tmp, 1) <= 0) + continue; + + switch (tmp) { + case '\n': + /* + * Parse the input, the newline is so that any printed + * text that is the result of a command can have + * its own lines. + */ + printf("\n"); + parse_input(&state); + + /* Reset the buffer */ + input_idx = 0; + state.input[0] = '\0'; + + printf("%s", PROMPT); + fflush(stdout); + break; + case '\b': + if (input_idx > 0) { + /* + * Replace the last char with a '\0' and rewrite + * the prompt. + */ + state.input[--input_idx] = '\0'; + printf("\b"); + fflush(stdout); + continue; + } + + break; + default: + if (input_idx < INPUT_SIZE) { + state.input[input_idx++] = tmp; + state.input[input_idx] = '\0'; + + printf("%c", tmp); + fflush(stdout); + } + + break; + } + + } + + /* Restore TTY state */ + tcsetattr(fd, 0, &tm_old); + close(fd); + return 0; +} diff --git a/usr.sbin/init/mshell.h b/usr.sbin/init/mshell.h new file mode 100644 index 0000000..9e9b456 --- /dev/null +++ b/usr.sbin/init/mshell.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MSHELL_H +#define MSHELL_H + +int mshell_enter(void); + +#endif /* MSHELL_H */ |