diff options
Diffstat (limited to 'smash/exec.c')
| -rw-r--r-- | smash/exec.c | 84 |
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); +} + |