summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGon Namprasertkul <foresterblox@gmail.com>2025-04-30 11:55:32 +0700
committerIan Moffett <ian@osmora.org>2025-05-05 02:55:08 -0400
commit5516b36888da1d0fc78e98a58ace0b808d2d573e (patch)
tree3b19499dedbf28dfc7c84a8caa5bfa7c556df592
parent8799918c7d935703717f0b235d1dba09e400cf00 (diff)
usr: osh: Rewrite console shell
This commit makes the shell prototype more flexible Signed-off-by: Gon Namprasertkul <foresterblox@gmail.com> Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--usr.bin/osh/osh.c167
1 files changed, 127 insertions, 40 deletions
diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c
index dea4b3f..2f592ad 100644
--- a/usr.bin/osh/osh.c
+++ b/usr.bin/osh/osh.c
@@ -42,46 +42,126 @@
":: ..... Proceed with purpose ..... ::\n" \
":::::::::::::::::::::::::::::::::::::::\n"
-#define CMD_ECHO "echo"
+#define HELP \
+ "Default commands:\n" \
+ "help - Display this help message\n" \
+ "echo - Print the arguments to the console\n" \
+ "exit - Exit the shell\n"
+
+#define PROMPT "[root::osmora]~ "
static char buf[64];
static uint8_t i;
+static int running;
+
+struct command {
+ const char *name;
+ void (*func)(int fd, int argc, char *argv[]);
+};
-static void
-cmd_run(int fd)
+void
+cmd_help(int fd, int argc, char *argv[])
+{
+ prcons(fd, HELP);
+}
+
+void
+cmd_exit(int fd, int argc, char *argv[])
+{
+ running = 0;
+}
+
+void
+cmd_echo(int fd, int argc, char *argv[])
+{
+ for (i = 1; i < argc; i++) {
+ prcons(fd, argv[i]);
+ prcons(fd, " ");
+ }
+ prcons(fd, "\n");
+}
+
+int
+parse_args(char *input, char *argv[], int max_args)
{
- int cmp;
- char *p = buf;
- size_t len;
- int valid_cmd = 1;
-
- switch (buf[0]) {
- case 'e':
- len = strlen(CMD_ECHO);
- if (memcmp(buf, CMD_ECHO, len) == 0) {
- p += len + 1;
- prcons(fd, "\n");
- prcons(fd, p);
+ int argc = 0;
+
+ while (*input != '\0') {
+ /* skip leading spaces */
+ while (*input == ' ') {
+ input++;
+ }
+
+ /* check if empty */
+ if (*input == '\0') {
break;
}
- valid_cmd = 0;
- break;
- default:
- valid_cmd = 0;
- break;
+ if (argc < max_args) {
+ argv[argc++] = input; /* mark start of the argument */
+ }
+ /* move forward until next space or end */
+ while (*input != '\0' && *input != ' ') {
+ input++;
+ }
+
+ /* end */
+ if (*input != '\0') {
+ *input = '\0';
+ input++;
+ }
}
- if (!valid_cmd) {
- prcons(fd, "\nunrecognized command\n");
+ return argc;
+}
+
+static char *
+getstr(int fd)
+{
+ char c;
+ uint8_t input;
+ i = 0;
+
+ for (;;) {
+ if (read(fd, &input, 2) <= 0) {
+ continue;
+ }
+
+ c = input & 0xFF;
+
+ /* return on newline */
+ if (c == '\n') {
+ buf[i] = '\0';
+ write(fd, "\n", 1);
+ return buf;
+ }
+
+ /* handle backspaces and DEL */
+ if (c == '\b' || c == 127) {
+ if (i > 0) {
+ i--;
+ write(fd, "\b \b", 3);
+ }
+ } else if (is_ascii(c) && i < sizeof(buf) - 1) {
+ /* write to fd and add to buffer */
+ buf[i++] = c;
+ write(fd, &c, 1);
+ }
}
}
+struct command cmds[] = {
+ {"help", cmd_help},
+ {"echo", cmd_echo},
+ {"exit", cmd_exit},
+ {NULL, NULL}
+};
+
int
-main(int argc, char **argv)
+main(void)
{
- int fd;
- uint16_t input;
+ int fd, found, argc;
+ char *input, *argv[16];
char c;
if ((fd = open("/dev/console", O_RDWR)) < 0) {
@@ -89,30 +169,37 @@ main(int argc, char **argv)
}
i = 0;
+ running = 1;
+ found = 0;
+
prcons(fd, WELCOME);
- prcons(fd, "[root::osmora]~ ");
- for (;;) {
- if (read(fd, &input, 2) <= 0) {
+ while (running) {
+ prcons(fd, PROMPT);
+
+ input = getstr(fd);
+ if (input[0] == '\0') {
continue;
}
- c = input & 0xFF;
- if (!is_ascii(c)) {
+ argc = parse_args(input, argv, sizeof(argv));
+ if (argc == 0) {
continue;
}
- if (i < sizeof(buf)) {
- buf[i++] = c;
- buf[i] = 0;
+ for (i = 0; cmds[i].name != NULL; i++) {
+ if (strcmp(input, cmds[i].name) == 0) {
+ cmds[i].func(fd, argc, argv);
+ found = 1;
+ break;
+ }
}
- if (c == '\n') {
- cmd_run(fd);
- i = 0;
- buf[i] = 0;
- prcons(fd, "[root::osmora]~ ");
- } else {
- write(fd, &c, 1);
+
+ if (found == 0) {
+ prcons(fd, "Unrecognized command\n");
}
+
+ found = 0;
+ buf[0] = '\0';
}
return 0;
}