#include "gbos.h" /* gbos shell: prompt -> read a line -> parse -> run, with I/O redirection ( > file, < file ) and pipes ( cmd1 | cmd2, via a temp file ). Operators must be space-separated (e.g. cat readme > out ). */ #define ARGV0 ((char *)0xA000) /* where a child reads its command line */ /* split s into space-separated tokens (NUL-terminated in place). */ static unsigned char tokenize(char *s, char **tok, unsigned char max) { unsigned char n = 0; for (;;) { while (*s == ' ') *s++ = 0; if (*s == 0) break; if (n < max) tok[n++] = s; while (*s && *s != ' ') s++; } return n; } static unsigned char isop(char *t, char c) { return t[0] == c && t[1] == 0; } /* build the child command line "name\0arg1 arg2\0" at 0xA000 */ static void set_cmdline(char **tok, unsigned char start, unsigned char end) { char *p = ARGV0, *t; unsigned char i; t = tok[start]; while (*t) *p++ = *t++; *p++ = 0; /* NUL after the command word */ for (i = start + 1; i < end; i++) { if (i > start + 1) *p++ = ' '; t = tok[i]; while (*t) *p++ = *t++; } *p = 0; } /* run tok[start..end): parse its own >/< redirects, honor forced in/out. */ static void run(char **tok, unsigned char start, unsigned char end, unsigned char infd, unsigned char outfd) { unsigned char i, cmdend = end, myin = NOFD, myout = NOFD, id, pid; for (i = start; i < end; i++) { if (isop(tok[i], '>')) { if (i + 1 < end) myout = open(tok[i + 1], O_WRITE); if (i < cmdend) cmdend = i; } else if (isop(tok[i], '<')) { if (i + 1 < end) myin = open(tok[i + 1], O_READ); if (i < cmdend) cmdend = i; } } id = lookup(tok[start]); if (id == NOFD) { puts(tok[start]); puts(": not found"); nl(); goto done; } set_cmdline(tok, start, cmdend); pid = fork(); if (pid == 0) { if (myin != NOFD) setin(myin); else if (infd != NOFD) setin(infd); if (myout != NOFD) setout(myout); else if (outfd != NOFD) setout(outfd); exec(id); } wait(); done: if (myin != NOFD) close(myin); if (myout != NOFD) close(myout); } void main(void) { char line[80]; char *tok[16]; for (;;) { unsigned char nt, i, pipepos, c; puts("$ "); /* read a line (echoing), stop at newline; exit on EOF */ i = 0; for (;;) { c = readc(); if (c == EOF) return; if (c == '\r' || c == '\n') { nl(); break; } if (i < 79) { line[i++] = c; putc(c); } } line[i] = 0; nt = tokenize(line, tok, 16); if (nt == 0) continue; pipepos = 0; for (i = 1; i < nt; i++) if (isop(tok[i], '|')) { pipepos = i; break; } if (pipepos) { unsigned char pw = open("__pipe", O_WRITE); run(tok, 0, pipepos, NOFD, pw); close(pw); { unsigned char pr = open("__pipe", O_READ); run(tok, pipepos + 1, nt, pr, NOFD); close(pr); } fremove("__pipe"); } else { run(tok, 0, nt, NOFD, NOFD); } } }