ESH

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

AuthorJamozed <[email protected]>
Date2021-11-22 10:02:29
Commit2144355beea4bd8b25f8a45384eb1d664ed11d26
Parenteb2d3d49c4af21075e194c16ca170ee04ccb68cb

Implement stdout redirects

Currently redirects and pipes do not play well with one another, this is undoubtedly a result of poor implementation, and instead, at least in theory, these two components should be entirely independent.

Diffstat

M src/bltn.h | 6 +++---
M src/exec.c | 47 +++++++++++++++++++++++++++++++++++++++--------
M src/lineread.h | 6 +++---
M src/parse.c | 49 +++++++++++++++++++++++++++++++------------------
M src/parse.h | 4 ++--

5 files changed, 78 insertions, 34 deletions

diff --git a/src/bltn.h b/src/bltn.h
index 4e811dc..d38f92a 100644
--- a/src/bltn.h
+++ b/src/bltn.h
@@ -30,10 +30,10 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
-#ifndef OMKOV_ESH_BLTN_H_XQ5D812A
-#define OMKOV_ESH_BLTN_H_XQ5D812A
+#ifndef ESH_BLTN_H_XQ5D812A
+#define ESH_BLTN_H_XQ5D812A
 
 struct bltn { const char *s; int (*f)(int, char *[]); };
 extern struct bltn bltns[];
 
-#endif // OMKOV_ESH_BLTN_H_XQ5D812A
+#endif // ESH_BLTN_H_XQ5D812A
diff --git a/src/exec.c b/src/exec.c
index d3e882f..93a76ae 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -30,11 +30,18 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
+/*
+	FIXME pipes and redirects are too order dependent, and so sometimes fail.
+	TODO implement stdin and stderr redirection.
+*/
+
 #include "bltn.h"
 #include "esh.h"
 
 #include "cll/error.h"
 
+#include <fcntl.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
@@ -45,14 +52,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #include <string.h>
 
 static int execute_comm(ast a, int fdi, int fd[2]);
-static int execute_pipe(ast a, int fdi);
+static int execute_pipe(ast a, int fdi, int fd[2]);
+static int execute_rdin(ast a, int fdi);
+static int execute_rout(ast a, int fdi);
+static int execute_rerr(ast a, int fdi);
 
 /* Execute a program. */
 int execute(ast a, int fdi, int fd[2]) {
 	switch (a->k) {
-	case AK_COMM: { return execute_comm(a, fdi, fd); }
-	case AK_PIPE: { return execute_pipe(a, fdi); }
-	default: { error(-1, "%s: Unimplemented AST", ast_ks[a->k]); }
+	case AK_COMM: {} return execute_comm(a, fdi, fd);
+	case AK_PIPE: {} return execute_pipe(a, fdi, fd);
+	// case AK_RDIN: {} return execute_rdin(a, fdi);
+	case AK_ROUT: {} return execute_rout(a, fdi);
+	// case AK_RERR: {} return execute_rerr(a, fdi);
+	default: { warn("%s: Unimplemented AST", ast_ks[a->k]); } return -1;
 	}
 }
 
@@ -74,7 +87,7 @@ static int execute_comm(ast a, int fdi, int fd[2]) {
 
 		dup2(fdi, fileno(stdin));
 
-		if (fd) { close(fd[0]); dup2(fd[1], fileno(stdout)); }
+		if (fd) { if (fd[0]) { close(fd[0]); } dup2(fd[1], fileno(stdout)); }
 
 		if (execvp((char *)av[0], (char **)av) == -1) {
 			if (errno == ENOENT) { warn("%s: Command not found", av[0]); }
@@ -92,7 +105,25 @@ static int execute_comm(ast a, int fdi, int fd[2]) {
 }
 
 /* Execute a pipe statement. */
-static int execute_pipe(ast a, int fdi) {
-	int fd[2]; if (pipe(fd) == -1) { warn("PIPE: %s", serr()); return -1; }
-	execute(a->lc, fdi, fd); return execute(a->rc, fd[0], NULL);
+static int execute_pipe(ast a, int fdi, int fd[2]) {
+	int pd[2]; if (pipe(pd) == -1) { warn("PIPE: %s", serr()); return -1; }
+	execute(a->lc, fdi, pd); return execute(a->rc, pd[0], fd);
+}
+
+/* Execute a redirect stdin statement. */
+static int execute_rdin(ast a, int fdi) {
+	
+}
+
+/* Execute a redirect stdout statement. */
+static int execute_rout(ast a, int fdi) {
+	int fd[2] = { 0 }; fd[1] = open(a->rc->s, O_WRONLY | O_CREAT | O_TRUNC);
+	if (fd[1] == -1) { warn("%s: %s", a->rc->s, serr()); return -1; }
+	
+	return execute(a->lc, fdi, fd);
+}
+
+/* Execute a redirect stderr statement. */
+static int execute_rerr(ast a, int fdi) {
+	
 }
diff --git a/src/lineread.h b/src/lineread.h
index 6352471..9109830 100644
--- a/src/lineread.h
+++ b/src/lineread.h
@@ -30,12 +30,12 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 */
 
-#ifndef OMKOV_ESH_LINEREAD_H_RPVXY3N7
-#define OMKOV_ESH_LINEREAD_H_RPVXY3N7
+#ifndef ESH_LINEREAD_H_RPVXY3N7
+#define ESH_LINEREAD_H_RPVXY3N7
 
 #include "util/util.h"
 
 extern char *lineread(void);
 extern void  linefree(void);
 
-#endif // OMKOV_ESH_LINEREAD_H_RPVXY3N7
+#endif // ESH_LINEREAD_H_RPVXY3N7
diff --git a/src/parse.c b/src/parse.c
index 09107cd..753b722 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -44,22 +44,26 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #include <stdlib.h>
 
 char *ast_ks[] = {
-	"NULL", "COMM", "PIPE",
-	"RDIN", "ROUT", "RERR"
+	"NULL", "WORD", "COMM",
+	"PIPE", "RDIN", "ROUT", "RERR"
 };
 
+static ast parse_word(lex *l);
 static ast parse_comm(lex *l);
 static ast parse_pipe(lex *l, ast lc);
-static ast parse_rdin(lex *l);
-static ast parse_rout(lex *l);
-static ast parse_rerr(lex *l);
+static ast parse_rdin(lex *l, ast lc);
+static ast parse_rout(lex *l, ast lc);
+static ast parse_rerr(lex *l, ast lc);
 
 /* Initialise an AST node. */
 ast ast_init(void) { return assert_calloc(1, sizeof (struct ast_s)); }
 
 /* Uninitialise an AST node and its children. */
 void ast_free(ast a) {
-	if (a) { ast_free(a->lc); ast_free(a->rc); stack_free(&a->c); free(a); };
+	if (a) {
+		ast_free(a->lc); ast_free(a->rc); stack_free(&a->c);
+		if (a->k == AK_WORD) { free(a->s); } free(a);
+	}
 }
 
 #define T (lex_peek(l)) /* Current Token */
@@ -76,15 +80,21 @@ ast parse(lex *l) {
 
 	ast lhs = parse_comm(l);
 
-	switch (lex_next(l).k) {
-	case TK_PIPE: {} return parse_pipe(l, lhs);
-	case TK_RDIN: {} return lhs;
-	case TK_ROUT: {} return lhs;
-	case TK_RERR: {} return lhs;
+	for (;;) switch (lex_next(l).k) {
+	case TK_PIPE: { lhs = parse_pipe(l, lhs); } continue;
+	case TK_RDIN: { lhs = parse_rdin(l, lhs); } continue;
+	case TK_ROUT: { lhs = parse_rout(l, lhs); } continue;
+	case TK_RERR: { lhs = parse_rerr(l, lhs); } continue;
 	default: {} return lhs;
 	}
 }
 
+/* Parse a single word. */
+static ast parse_word(lex *l) {
+	ast a = ast_init(); a->k = AK_WORD;
+	a->s = lex_next(l).s; return a;
+}
+
 /* Parse a command statement. */
 static ast parse_comm(lex *l) {
 	ast a = ast_init(); a->k = AK_COMM;
@@ -100,22 +110,25 @@ static ast parse_comm(lex *l) {
 /* Parse a pipe statement. */
 static ast parse_pipe(lex *l, ast lc) {
 	ast a = ast_init(); a->k = AK_PIPE;
-	a->lc = lc; a->rc = parse(l); return a;
+	a->lc = lc; a->rc = parse_comm(l); return a;
 }
 
 /* Parse a redirect stdin statement. */
-static ast parse_rdin(lex *l) {
-	
+static ast parse_rdin(lex *l, ast lc) {
+	ast a = ast_init(); a->k = AK_RDIN;
+	a->lc = lc; a->rc = parse_word(l); return a;
 }
 
 /* Parse a redirect stdout statement. */
-static ast parse_rout(lex *l) {
-	
+static ast parse_rout(lex *l, ast lc) {
+	ast a = ast_init(); a->k = AK_ROUT;
+	a->lc = lc; a->rc = parse_word(l); return a;
 }
 
 /* Parse a redirect stderr statement. */
-static ast parse_rerr(lex *l) {
-	
+static ast parse_rerr(lex *l, ast lc) {
+	ast a = ast_init(); a->k = AK_RERR;
+	a->lc = lc; a->rc = parse_word(l); return a;
 }
 
 /* Print parser debug output with an indent. */
diff --git a/src/parse.h b/src/parse.h
index 254e910..697a7e6 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -38,8 +38,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 #include "util/util.h"
 
 typedef enum {
-	AK_NULL, AK_COMM, AK_PIPE,
-	AK_RDIN, AK_ROUT, AK_RERR,
+	AK_NULL, AK_WORD, AK_COMM,
+	AK_PIPE, AK_RDIN, AK_ROUT, AK_RERR,
 } ast_k;
 
 typedef struct ast_s *ast;