ESH

Executive Shell
git clone http://git.omkov.net/ESH
Log | Tree | Refs | README | Download

AuthorJakob Wakeling <[email protected]>
Date2023-12-27 04:28:40
Commitda120bbed651b0731eaba4e5ca3549c977c56067
Parent4681f43be8f6000ca434160684a57036247c5750

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