summaryrefslogtreecommitdiff
path: root/src/user/sh.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /src/user/sh.cc
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz
lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'src/user/sh.cc')
-rw-r--r--src/user/sh.cc423
1 files changed, 0 insertions, 423 deletions
diff --git a/src/user/sh.cc b/src/user/sh.cc
deleted file mode 100644
index 47aad9e..0000000
--- a/src/user/sh.cc
+++ /dev/null
@@ -1,423 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2026 Richard QIn
- */
-#include "ulib/stdio.h"
-#include "ulib/stdlib.h"
-#include "ulib/string.h"
-#include "user/user.h"
-#include "common/fcntl.h"
-#include "drivers/uart_color.h"
-
-constexpr int MAX_ARGS = 10;
-const char *WHITESPACE = " \t\r\n\v";
-const char *SYMBOLS = "<|>&;()";
-
-void panic(const char *s)
-{
- printf("shell panic: %s\n", s);
- exit(1);
-}
-
-int fork_or_panic()
-{
- int pid = fork();
- if (pid == -1)
- panic("fork");
- return pid;
-}
-
-struct Command
-{
- virtual ~Command() = default;
-
- virtual void run() = 0;
-};
-
-struct ExecCommand : public Command
-{
- char *argv[MAX_ARGS];
-
- ExecCommand()
- {
- memset(argv, 0, sizeof(argv));
- }
-
- void run() override
- {
- if (argv[0] == nullptr)
- exit(1);
-
- exec(argv[0], argv);
-
- printf("exec %s failed\n", argv[0]);
- exit(1);
- }
-};
-
-struct RedirCommand : public Command
-{
- Command *sub_cmd;
- char *file;
- char *efile; // file name end pointer (used by parser)
- int mode;
- int fd;
-
- RedirCommand(Command *c, char *f, char *ef, int m, int fd_in)
- : sub_cmd(c), file(f), efile(ef), mode(m), fd(fd_in) {}
-
- ~RedirCommand() { delete sub_cmd; }
-
- void run() override
- {
- close(fd);
-
- int newfd = open(file, mode);
-
- if (newfd < 0)
- {
- printf("open %s failed\n", file);
- exit(1);
- }
-
- if (newfd != fd)
- {
-
- if (dup(newfd) != fd)
- {
- printf("Redirection failed: could not move fd %d to %d\n", newfd, fd);
- exit(1);
- }
- close(newfd);
- }
-
- sub_cmd->run();
- }
-};
-
-struct PipeCommand : public Command
-{
- Command *left;
- Command *right;
-
- PipeCommand(Command *l, Command *r) : left(l), right(r) {}
- ~PipeCommand()
- {
- delete left;
- delete right;
- }
-
- void run() override
- {
- int p[2];
- if (pipe(p) < 0)
- panic("pipe");
-
- if (fork_or_panic() == 0)
- {
- // Left child: write to pipe
- close(1); // close stdout
- dup(p[1]); // dup write-end to stdout
- close(p[0]);
- close(p[1]);
- left->run();
- }
-
- if (fork_or_panic() == 0)
- {
- // Right child: read from pipe
- close(0); // close stdin
- dup(p[0]); // dup read-end to stdin
- close(p[0]);
- close(p[1]);
- right->run();
- }
-
- close(p[0]);
- close(p[1]);
- wait(0);
- wait(0);
- exit(0);
- }
-};
-
-struct ListCommand : public Command
-{
- Command *left;
- Command *right;
-
- ListCommand(Command *l, Command *r) : left(l), right(r) {}
- ~ListCommand()
- {
- delete left;
- delete right;
- }
-
- void run() override
- {
- if (fork_or_panic() == 0)
- {
- left->run();
- }
- wait(0);
- right->run();
- }
-};
-
-struct BackCommand : public Command
-{
- Command *sub_cmd;
-
- BackCommand(Command *c) : sub_cmd(c) {}
- ~BackCommand() { delete sub_cmd; }
-
- void run() override
- {
- if (fork_or_panic() == 0)
- {
- sub_cmd->run();
- }
- // Parent doesn't wait
- exit(0);
- }
-};
-
-class Parser
-{
-public:
- static Command *parse(char *s)
- {
- char *es = s + strlen(s);
- Command *cmd = parse_line(&s, es);
- peek(&s, es, "");
- if (s != es)
- {
- printf("leftovers: %s\n", s);
- // panic("syntax"); // strict syntax check
- }
- terminate_strings(cmd);
- return cmd;
- }
-
-private:
- // Helper: NUL-terminate strings found during parsing
- static void terminate_strings(Command *cmd)
- {
- if (!cmd)
- return;
- }
-
- static char get_token(char **ps, char *es, char **q, char **eq)
- {
- char *s;
- int ret;
-
- s = *ps;
- while (s < es && strchr(WHITESPACE, *s))
- s++;
- if (q)
- *q = s;
- ret = *s;
- switch (*s)
- {
- case 0:
- break;
- case '|':
- case '(':
- case ')':
- case ';':
- case '&':
- case '<':
- s++;
- break;
- case '>':
- s++;
- if (*s == '>')
- {
- ret = '+';
- s++;
- }
- break;
- default:
- ret = 'a';
- while (s < es && !strchr(WHITESPACE, *s) && !strchr(SYMBOLS, *s))
- s++;
- break;
- }
- if (eq)
- *eq = s;
-
- while (s < es && strchr(WHITESPACE, *s))
- s++;
- *ps = s;
- return ret;
- }
-
- static int peek(char **ps, char *es, const char *toks)
- {
- char *s = *ps;
- while (s < es && strchr(WHITESPACE, *s))
- s++;
- *ps = s;
- return *s && strchr(toks, *s);
- }
-
- // Recursive Descent Parsers
-
- static Command *parse_line(char **ps, char *es)
- {
- Command *cmd = parse_pipe(ps, es);
- while (peek(ps, es, "&"))
- {
- get_token(ps, es, 0, 0);
- cmd = new BackCommand(cmd);
- }
- if (peek(ps, es, ";"))
- {
- get_token(ps, es, 0, 0);
- cmd = new ListCommand(cmd, parse_line(ps, es));
- }
- return cmd;
- }
-
- static Command *parse_pipe(char **ps, char *es)
- {
- Command *cmd = parse_exec(ps, es);
- if (peek(ps, es, "|"))
- {
- get_token(ps, es, 0, 0);
- cmd = new PipeCommand(cmd, parse_pipe(ps, es));
- }
- return cmd;
- }
-
- static Command *parse_exec(char **ps, char *es)
- {
- char *q, *eq;
- int tok, argc;
- ExecCommand *cmd = new ExecCommand();
- Command *ret = cmd;
-
- argc = 0;
- ret = parse_redirs(ret, ps, es);
- while (!peek(ps, es, "|)&;"))
- {
- if ((tok = get_token(ps, es, &q, &eq)) == 0)
- break;
- if (tok != 'a')
- panic("syntax");
-
- cmd->argv[argc] = q;
- *eq = 0; // Temp
-
- argc++;
- if (argc >= MAX_ARGS)
- panic("too many args");
- ret = parse_redirs(ret, ps, es);
- }
- cmd->argv[argc] = 0;
- return ret;
- }
-
- static Command *parse_redirs(Command *cmd, char **ps, char *es)
- {
- int tok;
- char *q, *eq;
-
- while (peek(ps, es, "<>"))
- {
- tok = get_token(ps, es, 0, 0);
- if (get_token(ps, es, &q, &eq) != 'a')
- panic("missing file for redirection");
-
- *eq = 0; // Null terminate filename immediately
-
- switch (tok)
- {
- case '<':
- cmd = new RedirCommand(cmd, q, eq, O_RDONLY, 0);
- break;
- case '>':
- cmd = new RedirCommand(cmd, q, eq, O_WRONLY | O_CREATE | O_TRUNC, 1);
- break;
- case '+': // >>
- cmd = new RedirCommand(cmd, q, eq, O_WRONLY | O_CREATE, 1); // Append not fully supported in simple OS yet?
- break;
- }
- }
- return cmd;
- }
-};
-
-int getcmd(char *buf, int nbuf)
-{
- write(1, "$ ", 2);
- memset(buf, 0, nbuf);
-
- int n = read(0, buf, nbuf - 1);
-
- if (n < 0)
- return -1;
-
- buf[n] = 0;
- return 0;
-}
-
-int main()
-{
- static char buf[100];
-
-
- printf(ANSI_GREEN "\n[Lume Shell] Welcome! \n" ANSI_RESET);
- printf(ANSI_YELLOW "[Lume Shell] Start your journey of exploration!" ANSI_RESET);
- printf("\n");
-
- while (getcmd(buf, sizeof(buf)) >= 0)
- {
- int len = strlen(buf);
- if (len > 0 && buf[len - 1] == '\n')
- {
- buf[len - 1] = 0;
- }
-
- if (buf[0] == 'c' && buf[1] == 'd' && (buf[2] == ' ' || buf[2] == '\n' || buf[2] == 0))
- {
- if (buf[strlen(buf) - 1] == '\n')
- buf[strlen(buf) - 1] = 0;
-
- char *path = buf + 3;
- if (buf[2] == '\n' || buf[2] == 0)
- {
- printf("cd: argument missing\n");
- continue;
- }
-
- if (chdir(path) < 0)
- {
- printf("cannot cd %s\n", path);
- }
- continue;
- }
- if (strcmp(buf, "shutdown") == 0 || strcmp(buf, "poweroff") == 0)
- {
- printf(ANSI_BLUE "System shutting down..." ANSI_RESET);
- printf("\n");
- shutdown();
-
- continue;
- }
-
- if (fork_or_panic() == 0)
- {
- Command *cmd = Parser::parse(buf);
- if (cmd)
- {
- cmd->run();
- delete cmd;
- }
- exit(0);
- }
- wait(0);
- }
- return 0;
-} \ No newline at end of file