diff options
| author | Nathan P. Reiner <nathan@nathanreiner.xyz> | 2022-12-15 18:20:33 +0100 |
|---|---|---|
| committer | Nathan P. Reiner <nathan@nathanreiner.xyz> | 2022-12-15 18:20:33 +0100 |
| commit | 828dd435725ea315abd2ea9875325ee3b17041a9 (patch) | |
| tree | 72d80411d5cecc8758fc87867521374e90caa44d | |
| parent | 7536d000ac9a5188378f2749ecfd7f0ccb437573 (diff) | |
did this while lecture (builtins, parsing, exec and env by stdlib)
| -rw-r--r-- | lib/cstr/cstr.c | 4 | ||||
| -rw-r--r-- | lib/sys/brk.h | 3 | ||||
| -rw-r--r-- | lib/sys/close.h | 2 | ||||
| -rw-r--r-- | lib/sys/dup2.h | 2 | ||||
| -rw-r--r-- | lib/sys/execve.h | 2 | ||||
| -rw-r--r-- | lib/sys/exit.h | 2 | ||||
| -rw-r--r-- | lib/sys/fork.h | 3 | ||||
| -rw-r--r-- | lib/sys/mmap.h | 3 | ||||
| -rw-r--r-- | lib/sys/munmap.h | 3 | ||||
| -rw-r--r-- | lib/sys/pipe.h | 2 | ||||
| -rw-r--r-- | lib/sys/read.h | 3 | ||||
| -rw-r--r-- | lib/sys/reboot.h | 3 | ||||
| -rw-r--r-- | lib/sys/sbrk.h | 3 | ||||
| -rw-r--r-- | lib/sys/start.S | 6 | ||||
| -rw-r--r-- | lib/sys/stat.h | 3 | ||||
| -rw-r--r-- | lib/sys/write.h | 3 | ||||
| -rw-r--r-- | smash/Makefile | 9 | ||||
| -rw-r--r-- | smash/builtin.c | 86 | ||||
| -rw-r--r-- | smash/builtin.h | 9 | ||||
| -rw-r--r-- | smash/exec.c | 84 | ||||
| -rw-r--r-- | smash/exec.h | 6 | ||||
| -rw-r--r-- | smash/main.c | 26 | ||||
| -rw-r--r-- | smash/parser.c | 65 | ||||
| -rw-r--r-- | smash/parser.h | 2 | ||||
| -rwxr-xr-x | smash/smash | bin | 0 -> 49336 bytes | |||
| -rwxr-xr-x | smash/test | bin | 26656 -> 20712 bytes | |||
| -rw-r--r-- | smash/test.c | 3 |
27 files changed, 260 insertions, 77 deletions
diff --git a/lib/cstr/cstr.c b/lib/cstr/cstr.c index fcb91f4..f464cf3 100644 --- a/lib/cstr/cstr.c +++ b/lib/cstr/cstr.c @@ -264,7 +264,7 @@ u8 previous_utf8(const char **c) void u64_to_cstr(u64 n, char *cstr, u64 length) { char *p = cstr + length - 1; - u64 d; + u64 d = 0; int i = 0; for (;n && i < length; ++i) { @@ -272,7 +272,7 @@ void u64_to_cstr(u64 n, char *cstr, u64 length) n /= 10; } - d = p - cstr; + d = p - cstr + 1; for (i = 0; i < length - d; ++i) cstr[i] = cstr[i + d]; diff --git a/lib/sys/brk.h b/lib/sys/brk.h index d2221a2..72f1edd 100644 --- a/lib/sys/brk.h +++ b/lib/sys/brk.h @@ -3,7 +3,8 @@ #include "syscalls.h" -static unsigned long brk(void * addr) { +static unsigned long brk(void * addr) +{ return syscall(BRK, addr); } diff --git a/lib/sys/close.h b/lib/sys/close.h index 2aa3a71..5a6fbe4 100644 --- a/lib/sys/close.h +++ b/lib/sys/close.h @@ -3,7 +3,7 @@ #include "syscalls.h" -int close(unsigned int fd) +static int close(unsigned int fd) { syscall(CLOSE, fd); } diff --git a/lib/sys/dup2.h b/lib/sys/dup2.h index 7726efb..9e67eec 100644 --- a/lib/sys/dup2.h +++ b/lib/sys/dup2.h @@ -3,7 +3,7 @@ #include "syscalls.h" -int dup2(unsigned int oldfd, unsigned int newfd) +static int dup2(unsigned int oldfd, unsigned int newfd) { return syscall(DUP2, oldfd, newfd); } diff --git a/lib/sys/execve.h b/lib/sys/execve.h index 04d6dea..62ebefc 100644 --- a/lib/sys/execve.h +++ b/lib/sys/execve.h @@ -3,7 +3,7 @@ #include "syscalls.h" -int execve(const char *pathname, char *const argv[], char *const envp[]) +static int execve(const char *pathname, char *const argv[], char *const envp[]) { return syscall(EXECVE, pathname, argv, envp); } diff --git a/lib/sys/exit.h b/lib/sys/exit.h index 516d714..0063a13 100644 --- a/lib/sys/exit.h +++ b/lib/sys/exit.h @@ -3,7 +3,7 @@ #include "syscalls.h" -_Noreturn void exit(int error_code) +static void exit(int error_code) { syscall(EXIT, error_code); } diff --git a/lib/sys/fork.h b/lib/sys/fork.h index 2ee3ae8..2a8adbf 100644 --- a/lib/sys/fork.h +++ b/lib/sys/fork.h @@ -3,7 +3,8 @@ #include "syscalls.h" -int fork() { +static int fork() +{ return syscall(FORK); } diff --git a/lib/sys/mmap.h b/lib/sys/mmap.h index 7e885c4..d555e68 100644 --- a/lib/sys/mmap.h +++ b/lib/sys/mmap.h @@ -10,7 +10,8 @@ #define MAP_SHARED 0x1 #define MAP_PRIVATE 0x2 -static void * mmap(void * addr, unsigned long size, int prot, int flags, int fd, int offset) { +static void * mmap(void * addr, unsigned long size, int prot, int flags, int fd, int offset) +{ return syscall(MMAP, size, prot, flags, fd, offset); } diff --git a/lib/sys/munmap.h b/lib/sys/munmap.h index 4a876d6..1d30fa2 100644 --- a/lib/sys/munmap.h +++ b/lib/sys/munmap.h @@ -2,7 +2,8 @@ #define MUNMAP_H #include "syscall.h" -static int munmap(void * addr, unsigned long size) { +static int munmap(void * addr, unsigned long size) +{ return syscall(MUNMAP, addr, size); } diff --git a/lib/sys/pipe.h b/lib/sys/pipe.h index f95f366..029d6bb 100644 --- a/lib/sys/pipe.h +++ b/lib/sys/pipe.h @@ -6,7 +6,7 @@ #define PIPE_IN 1 #define PIPE_OUT 0 -int pipe(int *filedes) +static int pipe(int *filedes) { return syscall(PIPE, filedes); } diff --git a/lib/sys/read.h b/lib/sys/read.h index 7dba6e7..61e5576 100644 --- a/lib/sys/read.h +++ b/lib/sys/read.h @@ -2,7 +2,8 @@ #define READ_H #include "syscalls.h" -static int read(unsigned int fd, char * buf, unsigned long count) { +static int read(unsigned int fd, char * buf, unsigned long count) +{ return syscall(READ, fd, buf, count, 0, 0); } diff --git a/lib/sys/reboot.h b/lib/sys/reboot.h index fd119c5..22893ca 100644 --- a/lib/sys/reboot.h +++ b/lib/sys/reboot.h @@ -11,7 +11,8 @@ #define REBOOT_SUSPEND 0xd000fce2 #define REBOOT_NEW_KERNEL 0x45584543 -static int reboot(int cmd) { +static int reboot(int cmd) +{ const int magic1 = 0xfee1dead; const int magic2 = 537993216; diff --git a/lib/sys/sbrk.h b/lib/sys/sbrk.h index 25d9c6c..159c644 100644 --- a/lib/sys/sbrk.h +++ b/lib/sys/sbrk.h @@ -3,7 +3,8 @@ #include "syscalls.h" -static int brk(void * addr) { +static int brk(void * addr) +{ return syscall(BRK, addr); } diff --git a/lib/sys/start.S b/lib/sys/start.S index deafd67..1faf691 100644 --- a/lib/sys/start.S +++ b/lib/sys/start.S @@ -1,6 +1,10 @@ .global _start _start: + mov (%rsp), %rdi + xor %rax, %rax + lea 8(%rsp, %rax, 8), %rsi + lea 16(%rsp, %rdi, 8), %rdx call main - mov %rax, %rdi + mov $0, %rdi mov $60, %rax syscall diff --git a/lib/sys/stat.h b/lib/sys/stat.h index 02bdc48..a6aa9a8 100644 --- a/lib/sys/stat.h +++ b/lib/sys/stat.h @@ -55,7 +55,8 @@ struct stat { u64 __[3]; }; -static int stat(const char * filename, struct stat * statbuf) { +static int stat(const char * filename, struct stat * statbuf) +{ return syscall(STAT, filename, statbuf); } diff --git a/lib/sys/write.h b/lib/sys/write.h index 59f7789..6ad748e 100644 --- a/lib/sys/write.h +++ b/lib/sys/write.h @@ -3,7 +3,8 @@ #include "syscalls.h" -static int write(unsigned int fd, const char * buf, unsigned long count) { +static int write(unsigned int fd, const char * buf, unsigned long count) +{ return syscall(WRITE, fd, buf, count); } diff --git a/smash/Makefile b/smash/Makefile index 4deb244..8a0dcee 100644 --- a/smash/Makefile +++ b/smash/Makefile @@ -1,3 +1,5 @@ +default_target: all + unit_test_parser: gcc parser.c ../lib/cstr/cstr.c ../lib/malloc/malloc.c ../lib/sys/start.S -static -nostdlib -fno-stack-protector -Wno-implicit-function-declaration -o test -DPARSER_UNIT_TEST -g ./test @@ -5,3 +7,10 @@ unit_test_parser: unit_test_variables: gcc variables.c ../lib/avl_tree/avl_tree.c ../lib/cstr/cstr.c ../lib/malloc/malloc.c ../lib/sys/start.S -static -nostdlib -fno-stack-protector -o test -DVARIABLES_UNIT_TEST -g ./test + +unit_test_builtin: + gcc builtin.c ../lib/cstr/cstr.c ../lib/sys/start.S -static -nostdlib -fno-stack-protector -Wno-implicit-function-declaration -o test -DBUILTIN_UNIT_TEST -g + ./test + +all: + gcc main.c exec.c parser.c builtin.c ../lib/avl_tree/avl_tree.c ../lib/cstr/cstr.c ../lib/malloc/malloc.c ../lib/sys/start.S -static -nostdlib -fno-stack-protector -Wno-implicit-function-declaration -o smash -DVARIABLES_UNIT_TEST -g diff --git a/smash/builtin.c b/smash/builtin.c new file mode 100644 index 0000000..ad9c839 --- /dev/null +++ b/smash/builtin.c @@ -0,0 +1,86 @@ +#include "builtin.h" + +#include "../lib/sys/exit.h" +#include "../lib/cstr/cstr.h" +#include "../lib/sys/io.h" + +u64 __find_builtin_function_by_name(const char *name); + +int __builtin_fn_exit(int argc, const char **argv); +int __builtin_fn_cd(int argc, const char **argv); +int __builtin_fn_help(int argc, const char **argv); + +char *builtin_names[] = { + "exit", + "cd", + "help", + 0 +}; + +int (*builtin_functions[])(int argc, const char **argv) = { + __builtin_fn_exit, + __builtin_fn_cd, + __builtin_fn_help +}; + +int __builtin_fn_exit(int argc, const char **argv) +{ + exit(0); +} + +int __builtin_fn_cd(int argc, const char **argv) +{ + /* TODO: Implement */ +} + +int __builtin_fn_help(int argc, const char **argv) +{ + write(STDOUT_FD, "This is the help page...\n", 25); + write(STDOUT_FD, "TODO: help page\n", 16); + return 0; +} + +u64 __find_builtin_function_by_name(const char *name) +{ + char **p = builtin_names; + + while (*p) { + if (cstr_compare(*p, name) == 0) + return p - builtin_names; + ++p; + } + + return -1; + +} + +u8 has_builtin_with_name(const char *name) +{ + return __find_builtin_function_by_name(name) != -1; +} + +int run_builtin(const char *name, const char **argv) +{ + int argc = 0; + u64 builtin_index = __find_builtin_function_by_name(name); + const char **p = argv; + while (*p) { + ++argc; + ++p; + } + + return builtin_functions[builtin_index](argc, argv); +} + +#ifdef BUILTIN_UNIT_TEST + +int main() { + const char *argv[] = { "lelp", 0 }; + + if (has_builtin_with_name(argv[0])) + return run_builtin(argv[0], argv); + + return 0; +} + +#endif diff --git a/smash/builtin.h b/smash/builtin.h new file mode 100644 index 0000000..702268f --- /dev/null +++ b/smash/builtin.h @@ -0,0 +1,9 @@ +#ifndef BUILTIN_H +#define BUILTIN_H + +#include "../lib/sys/sizes.h" + +u8 has_builtin_with_name(const char *name); +int run_builtin(const char *name, const char **argv); + +#endif diff --git a/smash/exec.c b/smash/exec.c new file mode 100644 index 0000000..3b62f41 --- /dev/null +++ b/smash/exec.c @@ -0,0 +1,84 @@ +#include "exec.h" + +#include "../lib/sys/execve.h" +#include "../lib/sys/fork.h" +#include "../lib/sys/wait4.h" +#include "../lib/sys/pipe.h" +#include "../lib/sys/dup2.h" +#include "../lib/sys/close.h" +#include "../lib/sys/io.h" +#include "../lib/sys/exit.h" +#include "../lib/cstr/cstr.h" + +#include "parser.h" +#include "builtin.h" + +void print_call(char **argv) +{ + while (*argv) { + write(STDOUT_FD, *argv, cstr_length(*argv)); + write(STDOUT_FD, "\n", 1); + ++argv; + } +} + +void exec(char *line) +{ + expression_list_t *exps = new_expression_from_line(line); + expression_list_t *exp = exps; + char **envp = { 0 }; + + int pid; + int pipefd[2][2]; + pipefd[0][PIPE_IN] = STDOUT_FD; + pipefd[0][PIPE_OUT] = STDIN_FD; + + while (exp) { + char **argv = new_argv(exp->call); + + pipe(pipefd[1]); + + if (has_builtin_with_name(argv[0])) { + run_builtin(argv[0], (const char**)argv); + break; + } + + pid = fork(); + + if (pid == 0) { + if (pipefd[0][PIPE_OUT] != STDIN_FD) { + dup2(pipefd[0][PIPE_OUT], STDIN_FD); + close(pipefd[0][PIPE_OUT]); + close(pipefd[0][PIPE_IN]); + } + if (exp->next) + dup2(pipefd[1][PIPE_IN], STDOUT_FD); + + close(pipefd[1][PIPE_OUT]); + close(pipefd[1][PIPE_IN]); + + execve(argv[0], argv, envp); + write(STDOUT_FD, "command not found: ", 19); + write(STDOUT_FD, argv[0], cstr_length(argv[0])); + write(STDOUT_FD, "\n", 1); + exit(-1); + } + + if (pipefd[0][PIPE_OUT] != STDIN_FD) { + close(pipefd[0][PIPE_IN]); + close(pipefd[0][PIPE_OUT]); + } + close(pipefd[1][PIPE_IN]); + + pipefd[0][0] = pipefd[1][0]; + pipefd[0][1] = pipefd[1][1]; + + free_argv(argv); + + wait4(pid, 0, 0); + exp = exp->next; + } + + free_expression(exps); +} + diff --git a/smash/exec.h b/smash/exec.h new file mode 100644 index 0000000..74780b0 --- /dev/null +++ b/smash/exec.h @@ -0,0 +1,6 @@ +#ifndef EXEC_H +#define EXEC_H + +void exec(char *line); + +#endif diff --git a/smash/main.c b/smash/main.c new file mode 100644 index 0000000..0b3dc20 --- /dev/null +++ b/smash/main.c @@ -0,0 +1,26 @@ +#include "exec.h" + +#include "../lib/sys/io.h" +#include "../lib/cstr/cstr.h" + +#define BUFSIZ 1024 + +void clear_buf(char *buf) +{ + for (int i = 0; i < BUFSIZ; ++i) + buf[i] = 0; +} + +int main(int argc, char *argv[], char *envp[]) +{ + char buf[BUFSIZ] = {0}; + char prompt[] = "$ "; + + while (1) { + write(STDOUT_FD, prompt, cstr_length(prompt)); + read(STDIN_FD, buf, 1024); + buf[cstr_length(buf) - 1] = 0; + exec(buf); + clear_buf(buf); + } +} diff --git a/smash/parser.c b/smash/parser.c index 22b9ccf..55a6fd2 100644 --- a/smash/parser.c +++ b/smash/parser.c @@ -52,14 +52,16 @@ void free_expression(expression_list_t *expression) } -char **__new_argv(char *exp) +char **new_argv(char *exp) { u64 n = cstr_split(exp, ' '); - char **argv = malloc(sizeof(char*) * n + 1); + char **argv = malloc(sizeof(char*) * (n + 1)); u64 i = 0; char *current = exp; char *next; + argv[n] = 0; + for (; n > 0; --n) { next = (char*)next_split(current); strip_cstr(current, ' '); @@ -70,68 +72,11 @@ char **__new_argv(char *exp) current = next; } - argv[i] = 0; - return argv; } -void __free_argv(char **argv) +void free_argv(char **argv) { free(argv); } - -#ifdef PARSER_UNIT_TEST - -#include "../lib/sys/execve.h" -#include "../lib/sys/fork.h" -#include "../lib/sys/wait4.h" -#include "../lib/sys/pipe.h" -#include "../lib/sys/dup2.h" -#include "../lib/sys/close.h" -#include "../lib/sys/io.h" -#include "../lib/sys/exit.h" - -int main() { - char in[] = "/bin/ls -a | /bin/wc -l"; - expression_list_t *exps = new_expression_from_line(in); - expression_list_t *exp = exps; - char **envp = { 0 }; - - int pid[2]; - int pipefd[2]; - - char **argv1 = __new_argv(exp->call); - char **argv2 = __new_argv(exp->next->call); - - pipe(pipefd); - pid[0] = fork(); - - if (pid[0] == 0) { - close(pipefd[0]); - dup2(pipefd[1], STDOUT_FD); - close(pipefd[1]); - - execve(argv1[0], argv1, envp); - } else { - pid[1] = fork(); - - - close(pipefd[1]); - - if (pid[1] == 0) { - dup2(pipefd[0], STDIN_FD); - close(pipefd[0]); - - execve(argv2[0], argv2, envp); - } else { - close(pipefd[0]); - wait4(pid[0], 0, 0); - wait4(pid[1], 0, 0); - } - } - - return 0; -} - -#endif diff --git a/smash/parser.h b/smash/parser.h index 23eee88..60b344e 100644 --- a/smash/parser.h +++ b/smash/parser.h @@ -10,5 +10,7 @@ typedef struct expression_list_t__ { expression_list_t *new_expression_from_line(char *line); void free_expression(expression_list_t *expression); +char **new_argv(char *exp); +void free_argv(char **argv); #endif diff --git a/smash/smash b/smash/smash Binary files differBinary files differnew file mode 100755 index 0000000..5d0b5e3 --- /dev/null +++ b/smash/smash diff --git a/smash/test.c b/smash/test.c new file mode 100644 index 0000000..cb3f748 --- /dev/null +++ b/smash/test.c @@ -0,0 +1,3 @@ +int main() { + return 0; +} |