aboutsummaryrefslogtreecommitdiff
path: root/smash
diff options
context:
space:
mode:
authorNathan P. Reiner <nathan@nathanreiner.xyz>2022-12-15 18:20:33 +0100
committerNathan P. Reiner <nathan@nathanreiner.xyz>2022-12-15 18:20:33 +0100
commit828dd435725ea315abd2ea9875325ee3b17041a9 (patch)
tree72d80411d5cecc8758fc87867521374e90caa44d /smash
parent7536d000ac9a5188378f2749ecfd7f0ccb437573 (diff)
did this while lecture (builtins, parsing, exec and env by stdlib)
Diffstat (limited to 'smash')
-rw-r--r--smash/Makefile9
-rw-r--r--smash/builtin.c86
-rw-r--r--smash/builtin.h9
-rw-r--r--smash/exec.c84
-rw-r--r--smash/exec.h6
-rw-r--r--smash/main.c26
-rw-r--r--smash/parser.c65
-rw-r--r--smash/parser.h2
-rwxr-xr-xsmash/smashbin0 -> 49336 bytes
-rwxr-xr-xsmash/testbin26656 -> 20712 bytes
-rw-r--r--smash/test.c3
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
new file mode 100755
index 0000000..5d0b5e3
--- /dev/null
+++ b/smash/smash
Binary files differ
diff --git a/smash/test b/smash/test
index a76addd..d282011 100755
--- a/smash/test
+++ b/smash/test
Binary files differ
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;
+}