aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/cstr/cstr.c4
-rw-r--r--lib/sys/brk.h3
-rw-r--r--lib/sys/close.h2
-rw-r--r--lib/sys/dup2.h2
-rw-r--r--lib/sys/execve.h2
-rw-r--r--lib/sys/exit.h2
-rw-r--r--lib/sys/fork.h3
-rw-r--r--lib/sys/mmap.h3
-rw-r--r--lib/sys/munmap.h3
-rw-r--r--lib/sys/pipe.h2
-rw-r--r--lib/sys/read.h3
-rw-r--r--lib/sys/reboot.h3
-rw-r--r--lib/sys/sbrk.h3
-rw-r--r--lib/sys/start.S6
-rw-r--r--lib/sys/stat.h3
-rw-r--r--lib/sys/write.h3
-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
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
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;
+}