aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/exec.c
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-10-19 13:28:01 -0700
committerNicholas Noll <nbnoll@eml.cc>2021-10-19 13:28:01 -0700
commit2b53bca326decd50012883f0cff3b5316a3e100d (patch)
tree570220ba22df388958e296f09add682720de6b51 /sys/cmd/rc/exec.c
parentaf3fa90e8bb41c306c5fe2d2cf105db6bbabd1d9 (diff)
feat(rc): prototype of async jobs
Diffstat (limited to 'sys/cmd/rc/exec.c')
-rw-r--r--sys/cmd/rc/exec.c112
1 files changed, 80 insertions, 32 deletions
diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c
index 87b6bb7..37c289b 100644
--- a/sys/cmd/rc/exec.c
+++ b/sys/cmd/rc/exec.c
@@ -135,6 +135,31 @@ path(char *w)
return path;
}
+static inline
+void
+defaultsignal(void)
+{
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGTSTP, SIG_DFL);
+ signal(SIGTTIN, SIG_DFL);
+ signal(SIGTTOU, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+}
+
+static inline
+void
+setpid(int pid)
+{
+ runner->pid = pid;
+ if(runner->pgid <= 0){
+ runner->pgid = runner->pid;
+ addjob(runner);
+ }
+
+ setpgid(pid, runner->pgid);
+}
+
static
void
xx(void)
@@ -161,21 +186,12 @@ xforkx(void)
return -1;
case 0: // child
clearwait(runner);
+ runner->link = nil;
if(shell.interactive){
- runner->pid = getpid();
- if(runner->pgid <= 0)
- runner->pgid = runner->pid;
-
- setpgid(pid, runner->pgid);
+ setpid(getpid());
tcsetpgrp(0, runner->pgid);
-
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTSTP, SIG_DFL);
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
+ defaultsignal();
}
pushword("exec");
@@ -185,12 +201,7 @@ xforkx(void)
/*unreachable*/
default: // parent
addwait(runner, pid);
-
- /* ensure the state matches for parent and child */
- runner->pid = pid;
- if(runner->pgid <= 0)
- runner->pgid = pid;
- setpgid(pid, runner->pgid);
+ setpid(pid); // ensure the state matches for parent and child
return pid;
}
@@ -213,7 +224,7 @@ pushredir(int type, int from, int to)
/* byte code */
static
void
-run(Code *c, int pc, Var *local)
+run(Code *c, int pc, Var *local, int keeppid)
{
Thread *new = emalloc(sizeof(*new));
@@ -236,7 +247,10 @@ run(Code *c, int pc, Var *local)
new->wait.on = nil;
new->status = 0;
- new->pgid = new->pid = -1;
+ if(keeppid)
+ new->pgid = runner->pgid, new->pid = runner->pid;
+ else
+ new->pgid = new->pid = -1;
new->line = 0;
new->link = runner;
@@ -285,9 +299,9 @@ count(Word *w)
// -----------------------------------------------------------------------
// builtins
-static Code dotcmd[14] =
+static Code dotcmd[14] =
{
- [0] = {.i = 1},
+ [0] = {.i = 0},
[1] = {.f = Xmark},
[2] = {.f = Xword},
[3] = {.s = "0"},
@@ -346,7 +360,7 @@ xdot(void)
}
/* set up for a new command loop */
old = runner; // store pointer to old code
- run(dotcmd, 1, nil);
+ run(dotcmd, 1, nil, 0);
/* operations on new command stack */
pushredir(Rclose, fd, 0);
@@ -434,7 +448,7 @@ xboot(int argc, char *argv[])
bootstrap[i++].f = Xexit;
bootstrap[i].i = 0;
- run(bootstrap, 1, nil);
+ run(bootstrap, 1, nil, 0);
pushlist(); // prime bootstrap argv
argv0 = strdup(argv[0]);
@@ -478,7 +492,7 @@ Xreturn(void)
* 2. return to our calling thread
* 3. don't free!
*/
- case PStop:
+ case Prun: case Pstop:
run->code.i--;
runner = run->link;
return;
@@ -487,7 +501,7 @@ Xreturn(void)
* 1. remove from our list
* 2. continue to clean up its memory
*/
- case PDone:
+ case Pdone:
deljob(run);
/* fallthrough */
default:
@@ -589,7 +603,7 @@ Xreadcmd(void)
--root->code.i;
}else{
--root->code.i; /* re-execute Xreadcmd after codebuf runs */
- run(compiled, 1, root->local);
+ run(compiled, 1, root->local, 0);
}
killzombies();
@@ -630,6 +644,43 @@ Xunlocal(void)
}
void
+Xasync(void)
+{
+ int pid;
+ int null = open("/dev/null", 0);
+ if(!null){
+ Xerror("can not open /dev/null\n");
+ return;
+ }
+
+ switch(pid=fork()){
+ case -1:
+ close(null);
+ Xerror("fork failed: try again");
+ break;
+
+ case 0: // child
+ clearwait(runner);
+ pushredir(Ropen, null, 0);
+ if(shell.interactive){ // NOTE: this needs to read off its caller's interactivity
+ setpid(getpid());
+ defaultsignal();
+ }
+ run(runner->code.exe, runner->code.i+1, runner->local, 1);
+ runner->link = nil;
+ break;
+
+ default: // parent
+ close(null);
+ setpid(pid);
+ addwait(runner, pid);
+
+ runner->code.i = runner->code.exe[runner->code.i].i; /* jump to end of async command */
+ /* don't wait: continue running */
+ }
+}
+
+void
Xbasic(void)
{
Var *v;
@@ -642,7 +693,6 @@ Xbasic(void)
Xerror("empty argument list\n");
return;
}
- flush(shell.err);
v = var(arg->str);
if(v->func){
@@ -658,7 +708,6 @@ Xbasic(void)
}
/* if we are here then it's an external command */
- addjob(runner);
// run the external command
if((pid = xforkx()) < 0) {
@@ -666,12 +715,11 @@ Xbasic(void)
return;
}
- poplist();
-
if(!shell.interactive)
waitall(runner);
foreground(runner, 0); // waits for child
+ poplist();
}
void
@@ -735,5 +783,5 @@ Xflat(void)
void
Xexit(void)
{
- exit(shell.status);
+ exit(runner->status);
}