Author | Jakob Wakeling <[email protected]> |
Date | 2023-12-27 04:28:40 |
Commit | da120bbed651b0731eaba4e5ca3549c977c56067 |
Parent | 4681f43be8f6000ca434160684a57036247c5750 |
Implement basic command execution
Diffstat
M | src/eval.c | | | 5 | ++++- |
A | src/exec.c | | | 56 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/exec.h | | | 14 | ++++++++++++++ |
3 files changed, 74 insertions, 1 deletions
diff --git a/src/eval.c b/src/eval.c index 0e6aeb1..742b8c1 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2,9 +2,12 @@ // All rights reserved. #include "eval.h" +#include "exec.h" #include "lex.h" #include "parse.h" +#include <unistd.h> + bool Eflag, pflag; void eval(char *src, u64 len) { @@ -15,6 +18,6 @@ void eval(char *src, u64 len) { a = parse(&l); if (!a) { return; } if (pflag) { ast_debug(a, 0); continue; } - /* TODO execute */ + _ret = execute(a, STDIN_FILENO, NULL); } } diff --git a/src/exec.c b/src/exec.c new file mode 100644 index 0000000..b29b8fe --- /dev/null +++ b/src/exec.c @@ -0,0 +1,56 @@ +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +#include "exec.h" +#include "parse.h" +#include "util/log.h" +#include "util/util.h" + +#include <sys/wait.h> +#include <unistd.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +s32 _ret; + +static s32 execute_comm(ast *a, int fdi, int fd[2]); + +/* Execute a program. */ +s32 execute(ast *a, int fdi, int fd[2]) { + switch (a->k) { + case AK_COMM: {} return execute_comm(a, fdi, fd); + default: { log_warn("Unhandled AST kind \"%s\"", ast_ks[a->k]); } return -1; + } +} + +/* Execute a command statement. */ +static s32 execute_comm(ast *a, int fdi, int fd[2]) { + /* If the command is null, then do nothing */ + if (!a->s) { return _ret; } + + /* TODO handle builtins */ + + pid_t pid; int status; + + /* TODO handle redirects */ + + char **av = a->c.a; + + /* Fork and exec the child process */ + if ((pid = fork()) == 0) { + signal(SIGINT, SIG_DFL); + + dup2(fdi, STDIN_FILENO); + + if (execvp((char *)av[0], (char **)av) == -1) { + if (errno == ENOENT) { log_warn("%s: Command not found", av[0]); } + else { perror((char *)av[0]); } exit(1); + } + } + else if (pid == -1) { perror((char *)av[0]); } + else { waitpid(pid, &status, 0); } + + return WEXITSTATUS(status); +} diff --git a/src/exec.h b/src/exec.h new file mode 100644 index 0000000..bef9204 --- /dev/null +++ b/src/exec.h @@ -0,0 +1,14 @@ +// Copyright (C) 2023, Jakob Wakeling +// All rights reserved. + +#ifndef ESH_EXEC_H_Y968EN5S +#define ESH_EXEC_H_Y968EN5S + +#include "parse.h" +#include "util/util.h" + +extern s32 _ret; + +extern s32 execute(ast *a, int fdi, int fd[2]); + +#endif // ESH_EXEC_H_Y968EN5S