Author | Jamozed <[email protected]> |
Date | 2021-11-22 10:02:29 |
Commit | 2144355beea4bd8b25f8a45384eb1d664ed11d26 |
Parent | eb2d3d49c4af21075e194c16ca170ee04ccb68cb |
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;