From 5559da2299dc50b50c62d7d1b92b769803fb9321 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 22 May 2024 19:50:54 -0400 Subject: init: Add maintenance shell Signed-off-by: Ian Moffett --- usr.sbin/init/Makefile | 2 +- usr.sbin/init/main.c | 7 +- usr.sbin/init/mshell.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++ usr.sbin/init/mshell.h | 35 ++++++++++ 4 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 usr.sbin/init/mshell.c create mode 100644 usr.sbin/init/mshell.h 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 +#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 +#include +#include +#include +#include +#include +#include +#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 */ -- cgit v1.2.3