fpurge(stdout);
push(&history, start);
+ *buffer = ';';
*end = ';';
*++end = '\0';
signal(SIGCHLD, SIG_DFL);
- return start;
+ return buffer;
}
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
+#include <err.h>
+#include <stdio.h> // DEBUG
#include "history.h"
#include "lex.h"
-static char *tokens[BUFLEN + 1];
-static struct cmd cmds[1 + (BUFLEN + 1) / 2 + 1] = {{.type = SEMI}};
+static char *tokens[1 + BUFLEN + 1];
+static struct cmd cmds[1 + (BUFLEN + 1) / 2 + 1] = {{.args = tokens, .f = cmds->freds}};
+
+void printfreds(struct cmd *c) {
+ for (; c->f->mode != END; ++c->f) {
+ printf("%d", c->f->newfd);
+ switch (c->f->mode) {
+ case READ:
+ fputs("<", stdout);
+ break;
+ case WRITE:
+ fputs(">", stdout);
+ break;
+ case READWRITE:
+ fputs("<>", stdout);
+ break;
+ case APPEND:
+ fputs(">>", stdout);
+ break;
+ default:;
+ }
+ puts(c->f->old.name);
+ }
+}
struct cmd *lex(char *b) {
- char **t;
+ char **t, *end;
struct cmd *c;
if (!b) return NULL;
c = cmds;
while (*b) switch (*b) {
default:
- if (!*(b - 1)) {
- if (c->type) {
- (++c)->args = t;
- c->type = NONE;
- }
+ if (!*(b - 1)) { // Start of a token
+ if (!c->args) c->args = t; // Start of a command
*t++ = b;
}
++b;
break;
case '<':
case '>':
+ if (*(b - 1)) {
+ if ((c->f->newfd = strtol(*--t, &end, 10)) < 0 || end != b) {
+ warnx("Invalid file redirection operator");
+ c->args = NULL;
+ return c - 1;
+ }
+ if (c->args == t) c->args = NULL;
+ } else c->f->newfd = *b == '>';
+ c->f->mode = *b++;
+ if (*b == '>') {
+ ++b;
+ ++c->f->mode;
+ }
+ c->f++->old.name = b;
+ if (*b == '&') ++b;
break;
case '&':
case '|':
if (*b == *(b + 1)) *b = '\0';
case ';':
- if (c->type == NONE) {
+ if (c->args) {
*t++ = NULL;
if (!*b) {
++b;
++c->type;
}
c->type += *b;
+ *(c->f) = (struct fred){0};
+ c->f = c->freds;
+
+ (++c)->args = NULL;
}
+ c->f = c->freds;
case ' ':
*b++ = '\0';
}
- *++c = (struct cmd){0};
+ switch (c->type) {
+ case AND:
+ case PIPE:
+ case OR:
+ warnx("Command left open-ended");
+ c->args = NULL;
+ return c - 1;
+ default:
+ *++c = (struct cmd){0};
+ }
return cmds;
}
enum terminator {
- NONE,
SEMI = ';',
BG = '&',
AND,
OR,
};
+enum mode {
+ END,
+ READ = '<',
+ READWRITE,
+ WRITE = '>',
+ APPEND,
+};
+
+enum type {
+ FD,
+ NAME,
+};
+
+// if (cmd->f->type == NAME) cmd->f->old.fd = open(cmd->f->old.name, mode);
+// dup2(cmd->f->newfd, cmd->f->old.fd);
+// if (cmd->f->type == NAME) close(cmd->f->old.fd);
+//
+// // vs.
+//
+// if (*cmd->f->oldfd == '&') fd = open(++cmd->f->oldfd, mode);
+// dup2(cmd->f->newfd, cmd->
+
struct fred {
- int newfd, mode;
- char *oldfd;
+ int newfd;
+ enum mode mode;
+ enum type type;
+ union {
+ int fd;
+ char *name;
+ } old;
};
-/* a>&b -> dup2(b, a); reopen(a, "w");
- * a<&b -> dup2(b, a); reopen(a, "r");
+/* a>&b -> dup2(b, a); reopen(a, "w"); | (1)>&3 -> dup2(3, 1);
+ * a<&b -> dup2(b, a); reopen(a, "r"); | (0)<&3 -> dup2(3, 0);
* x >a >b >c ...
*/
struct cmd {
char **args;
enum terminator type;
+ struct fred *f, freds[(BUFLEN - 1) / 3 + 1];
int pipe[2];
- struct fred freds[(BUFLEN - 1) / 3 + 1];
};
+void printfreds(struct cmd *c);
struct cmd *lex(char *b);
while ((cmd = lex(input()))) {
while (prev = cmd++, cmd->args) {
+ printfreds(cmd);
ispipe = cmd->type == PIPE || prev->type == PIPE;
ispipestart = ispipe && prev->type != PIPE;
ispipeend = ispipe && cmd->type != PIPE;