diff options
Diffstat (limited to 'c')
| -rw-r--r-- | c/gbos.h | 2 | ||||
| -rw-r--r-- | c/libc.s | 12 | ||||
| -rw-r--r-- | c/sh.c | 25 | ||||
| -rw-r--r-- | c/spin.c | 6 |
4 files changed, 38 insertions, 7 deletions
@@ -41,4 +41,6 @@ unsigned char lookup(const char *name); /* command name -> program id */ unsigned char kill(unsigned char pid); /* terminate a pid (1 is immortal)*/ unsigned char psget(unsigned char slot, unsigned char *buf); /* {pid,state,prog}*/ void progname(unsigned char id, char *buf); /* id -> name */ +void yield(void); +unsigned char reap(void); /* reap a finished bg job, or 0 */ #endif @@ -187,3 +187,15 @@ _progname: ld c, #21 ; SYS_PROGNAME rst #0x30 ret + + .globl _yield, _reap + ;; void yield(void) +_yield: + ld c, #11 ; SYS_YIELD + rst #0x30 + ret + ;; unsigned char reap(void) -> A (reaped pid, or 0) +_reap: + ld c, #22 ; SYS_REAP + rst #0x30 + ret @@ -34,9 +34,10 @@ static void set_cmdline(char **tok, unsigned char start, unsigned char end) { *p = 0; } -/* run tok[start..end): parse its own >/< redirects, honor forced in/out. */ +/* run tok[start..end): parse its own >/< redirects, honor forced in/out. + If bg, launch in the background (don't wait; leave fds to the child). */ static void run(char **tok, unsigned char start, unsigned char end, - unsigned char infd, unsigned char outfd) { + unsigned char infd, unsigned char outfd, unsigned char bg) { unsigned char i, cmdend = end, myin = NOFD, myout = NOFD, id, pid; for (i = start; i < end; i++) { if (isop(tok[i], '>')) { @@ -58,7 +59,13 @@ static void run(char **tok, unsigned char start, unsigned char end, else if (outfd != NOFD) setout(outfd); exec(id); } - wait(); + if (bg) { putc('['); putu(pid); puts("]"); nl(); return; } /* background */ + /* wait for THIS child; report any background jobs that finish meanwhile */ + for (;;) { + unsigned char r = wait(); + if (r == pid || r == NOFD) break; + putc('['); putu(r); puts(" done]"); nl(); + } done: if (myin != NOFD) close(myin); if (myout != NOFD) close(myout); @@ -68,7 +75,9 @@ void main(void) { char line[80]; char *tok[16]; for (;;) { - unsigned char nt, i, pipepos, c; + unsigned char nt, i, pipepos, c, bg; + /* reap finished background jobs */ + { unsigned char p; while ((p = reap())) { putc('['); putu(p); puts(" done]"); nl(); } } puts("$ "); /* read a line (echoing), stop at newline; exit on EOF */ i = 0; @@ -81,19 +90,21 @@ void main(void) { line[i] = 0; nt = tokenize(line, tok, 16); if (nt == 0) continue; + bg = 0; + if (isop(tok[nt - 1], '&')) { bg = 1; nt--; 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); + run(tok, 0, pipepos, NOFD, pw, 0); close(pw); { unsigned char pr = open("__pipe", O_READ); - run(tok, pipepos + 1, nt, pr, NOFD); + run(tok, pipepos + 1, nt, pr, NOFD, 0); close(pr); } fremove("__pipe"); } else { - run(tok, 0, nt, NOFD, NOFD); + run(tok, 0, nt, NOFD, NOFD, bg); } } } diff --git a/c/spin.c b/c/spin.c new file mode 100644 index 0000000..2a3d4e8 --- /dev/null +++ b/c/spin.c @@ -0,0 +1,6 @@ +#include "gbos.h" +/* spin: a harmless long-running process that just yields forever. + Useful as a target for `ps` and `kill`. */ +void main(void) { + for (;;) yield(); +} |
