aboutsummaryrefslogtreecommitdiff
path: root/smash/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'smash/exec.c')
-rw-r--r--smash/exec.c84
1 files changed, 84 insertions, 0 deletions
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);
+}
+