diff options
Diffstat (limited to 'smash')
| -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 |
11 files changed, 230 insertions, 60 deletions
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; +} |