#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/exit.h" #include "../lib/cstr/cstr.h" #include "../lib/io/io.h" #include "../lib/env/env.h" #include "../lib/malloc/malloc.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 __execenv(const char **argv) { const char *path = getenv("PATH"); const char *end; char *filename; while (*path) { end = path; while (*end && *end != ':') ++end; filename = malloc((end - path) + cstr_length(argv[0]) + 2); for (int i = 0; i < end - path; ++i) filename[i] = path[i]; filename[end - path] = '/'; for (int i = 0; i < cstr_length(argv[0]) + 1; ++i) filename[(end - path) + i + 1] = argv[0][i]; execve(filename, argv, getenvp()); free(filename); path = end; if (*path == ':') ++path; } execve(argv[0], argv, getenvp()); } void exec(char *line) { expression_list_t *exps = new_expression_from_line(line); expression_list_t *exp = exps; 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]); __execenv((const char **)argv); wff(STDERR_FD, "command not found: %s\n", argv[0]); exit(-1); } if (pipefd[0][PIPE_OUT] != STDIN_FD) { close(pipefd[0][PIPE_IN]); close(pipefd[0][PIPE_OUT]); } 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); } #ifdef EXEC_UNIT_TEST int main() { char *argv[] = { "ls" }; __execenv(argv); } #endif