aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/exec.c')
-rw-r--r--sys/cmd/rc/exec.c244
1 files changed, 169 insertions, 75 deletions
diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c
index 868b1dc..80cd645 100644
--- a/sys/cmd/rc/exec.c
+++ b/sys/cmd/rc/exec.c
@@ -16,21 +16,12 @@ struct Builtin{
static Word nullpath = { .str="", .link=nil };
struct Builtin builtin[]={
- {".", xdot},
+ {".", xdot},
+ {"fg", xfg},
+ {"jobs", xjob},
0,
};
-/* stub out until we need */
-void Xasync(void){}
-void Xconcatenate(void){}
-void Xexit(void){}
-void Xfunc(void){}
-void Xfor(void){}
-void Xglob(void){}
-void Xjump(void){}
-void Xmatch(void){}
-void Xpipe(void){}
-void Xread(void){}
// -----------------------------------------------------------------------
// internal
@@ -40,10 +31,10 @@ static
void
pushword(char *str)
{
- if(!shell->args)
- fatal("attempt to push on empty argument stack");
+ if(!proc->args)
+ fatal("attempt to push on empty argument stack\n");
- shell->args->word = makeword(str, shell->args->word);
+ proc->args->word = makeword(str, proc->args->word);
}
static
@@ -51,14 +42,14 @@ void
popword(void)
{
Word *w;
- if(!shell->args)
- fatal("tried to pop word on empty argument stack");
+ if(!proc->args)
+ fatal("tried to pop word on empty argument stack\n");
- w = shell->args->word;
+ w = proc->args->word;
if(!w)
- fatal("tried to pop word but nothing there");
+ fatal("tried to pop word but nothing there\n");
- shell->args->word = w->link;
+ proc->args->word = w->link;
efree(w->str);
efree(w);
}
@@ -110,21 +101,21 @@ pushlist(void)
List *stack = emalloc(sizeof(*stack));
stack->word = nil;
- stack->link = shell->args;
+ stack->link = proc->args;
- shell->args = stack;
+ proc->args = stack;
}
static
void
poplist(void)
{
- List *stack = shell->args;
+ List *stack = proc->args;
if(!stack)
- fatal("attempted to pop an empty argument stack");
+ fatal("attempted to pop an empty argument stack\n");
freelist(stack->word);
- shell->args = stack->link;
+ proc->args = stack->link;
efree(stack);
}
@@ -149,12 +140,12 @@ void
xx(void)
{
popword(); // "exec"
- if(!shell->args->word){
+ if(!proc->args->word){
Xerror("empty argument list");
return;
}
- execute(shell->args->word, path(shell->args->word->str));
+ execute(proc->args->word, path(proc->args->word->str));
poplist();
}
@@ -169,13 +160,38 @@ xforkx(void)
case -1:
return -1;
case 0: // child
- clearwait();
+ clearwait(proc);
+
+ if(shell.interactive){
+ proc->pid = getpid();
+ if(proc->pgid <= 0)
+ proc->pgid = proc->pid;
+
+ setpgid(pid, proc->pgid);
+ tcsetpgrp(0, proc->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);
+ }
+
pushword("exec");
xx();
- exit(1);
+
+ exit(1); // NOTE: xx does not return!
/*unreachable*/
- default:
- addwait(pid);
+ default: // parent
+ addwait(proc, pid);
+
+ /* ensure the state matches for parent and child */
+ proc->pid = pid;
+ if(proc->pgid <= 0)
+ proc->pgid = pid;
+ setpgid(pid, proc->pgid);
+
return pid;
}
}
@@ -189,9 +205,9 @@ pushredir(int type, int from, int to)
r->type = type;
r->from = from;
r->to = to;
- r->link = shell->redir;
+ r->link = proc->redir;
- shell->redir = r;
+ proc->redir = r;
}
/* byte code */
@@ -209,9 +225,11 @@ run(Code *c, int pc, Var *local)
new->cmd.io = nil;
new->flag.eof = 0;
new->line = 1;
- new->link = shell;
+ new->link = proc;
+
+ new->pgid = new->pid = -1;
- shell = new;
+ proc = new;
}
// -----------------------------------------------------------------------
@@ -281,23 +299,22 @@ xdot(void)
Thread *old;
char file[512];
- old = shell;
popword();
#if 0
- if(old->args->word && strcmp(old->args->word->str, "-i")==0){
+ if(proc->args->word && strcmp(proc->args->word->str, "-i")==0){
iflag = 1;
popword();
}
#endif
/* get input file */
- if(!old->args->word){
+ if(!proc->args->word){
Xerror("usage: . [-i] file [arg ...]\n");
return;
}
- base = strdup(old->args->word->str);
+ base = strdup(proc->args->word->str);
popword();
- for(fd=-1, p=path(base); p ; p = p->link){
+ for(fd=-1, p=path(base); p; p = p->link){
strcpy(file, p->str);
if(file[0])
@@ -315,15 +332,17 @@ xdot(void)
return;
}
/* set up for a new command loop */
+ old = proc; // store pointer to old code
run(dotcmd, 1, nil);
- pushredir(Rclose, fd, 0);
- shell->cmd.path = base;
- shell->cmd.io = openfd(fd);
+ /* operations on new command stack */
+ pushredir(Rclose, fd, 0);
+ proc->cmd.path = base;
+ proc->cmd.io = openfd(fd);
/* push $* value */
pushlist();
- shell->args->word = old->args->word;
+ proc->args->word = old->args->word;
/* free caller's copy of $* */
argv = old->args;
@@ -337,6 +356,50 @@ xdot(void)
}
void
+xjob(void)
+{
+ int i;
+ Thread *job;
+
+ for(i = 0, job = shell.jobs; job; job = job->next)
+ report(job,i);
+
+ poplist();
+}
+
+void
+xfg(void)
+{
+ int i;
+ Thread *job, *old;
+
+ popword(); // fg
+
+ /* get input job id */
+ if(!proc->args->word){
+ print(errio, "usage: fg [pid|\%num]\n");
+ poplist();
+ return;
+ }
+
+ i = atoi(proc->args->word->str);
+ popword(); // [jobid]
+
+ for(job=shell.jobs; i > 0; job=job->next, --i)
+ ;
+ assert(!job->flag.done);
+
+ addwait(job, job->pid);
+ job->flag.stop = 0;
+
+ poplist(); // this goes here?
+
+ job->link = proc, proc = job; // XXX: can this leave orphans?
+ foreground(job, 1);
+ printf("hi\n");
+}
+
+void
xboot(int argc, char *argv[])
{
int i;
@@ -369,10 +432,10 @@ xboot(int argc, char *argv[])
for(i = argc-1; i > 0; --i)
pushword(argv[i]);
- /* interpreter loop */
+ /* main interpreter loop */
for(;;){
- shell->code.i++;
- (*shell->code.exe[shell->code.i-1].f)();
+ proc->code.i++;
+ (*proc->code.exe[proc->code.i-1].f)();
}
}
@@ -390,31 +453,50 @@ Xerror(char *msg)
{
print(errio, "rc: %s", msg);
flush(errio);
- while(!shell->flag.i)
+ while(!proc->flag.i)
Xreturn();
}
void
Xreturn(void)
{
- Thread *run = shell;
+ Thread *run = proc;
+
+ /*
+ * If our job is still running we must:
+ * 1. move program one step back to rerun Xreturn upon recall
+ * 2. return to our calling thread
+ * 3. don't free!
+ */
+ if(run->flag.stop){
+ run->code.i--;
+ proc = run->link;
+ return;
+ }
- printf("returning\n");
+ /*
+ * If our job has finished:
+ * 1. remove from our list
+ * 2. clean up its memory!
+ */
+ if(run->flag.done)
+ deljob(run);
while(run->args)
poplist();
freecode(run->code.exe);
+ efree(run->wait.pid);
- shell = run->link;
+ proc = run->link;
efree(run);
- if(!shell)
+ if(!proc)
exit(0);
}
void
Xword(void)
{
- pushword(shell->code.exe[shell->code.i++].s);
+ pushword(proc->code.exe[proc->code.i++].s);
}
void
@@ -424,18 +506,18 @@ Xdollar(void)
char *s, *t;
Word *a, *star;
- if(count(shell->args->word)!=1){
+ if(count(proc->args->word)!=1){
Xerror("variable name not singleton!\n");
return;
}
- s = shell->args->word->str;
+ s = proc->args->word->str;
// deglob(s);
n = 0;
for(t = s;'0'<=*t && *t<='9';t++)
n = n*10+*t-'0';
- a = shell->args->link->word;
+ a = proc->args->link->word;
if(n==0 || *t)
a = copywords(var(s)->val, a);
@@ -450,7 +532,7 @@ Xdollar(void)
}
poplist();
- shell->args->word = a;
+ proc->args->word = a;
}
void
@@ -458,22 +540,22 @@ Xassign(void)
{
Var *v;
- if(count(shell->args->word)!=1){
+ if(count(proc->args->word)!=1){
Xerror("variable name not singleton!\n");
return;
}
//deglob(runq->argv->words->word);
- v = var(shell->args->word->str);
+ v = var(proc->args->word->str);
poplist();
//globlist();
freewords(v->val);
- v->val = shell->args->word;
+ v->val = proc->args->word;
v->new = 1;
if(v->update)
v->update(v);
- shell->args->word = nil;
+ proc->args->word = nil;
poplist();
}
@@ -485,7 +567,7 @@ Xreadcmd(void)
Word *prompt;
flush(errio);
- root = shell;
+ root = proc;
if(yyparse()){
exit(1);
@@ -494,21 +576,22 @@ Xreadcmd(void)
run(compiled, 1, root->local);
}
+ // killzombies();
freeparsetree();
}
void
Xlocal(void)
{
- if(count(shell->args->word)!=1){
+ if(count(proc->args->word)!=1){
Xerror("variable name must be singleton\n");
return;
}
//deglob(shell->args->word->str);
- shell->local = makevar(strdup(shell->args->word->str), shell->local);
- shell->local->val = copywords(shell->args->link->word, nil);
- shell->local->new = 1;
+ proc->local = makevar(strdup(proc->args->word->str), proc->local);
+ proc->local->val = copywords(proc->args->link->word, nil);
+ proc->local->new = 1;
poplist();
poplist();
@@ -517,13 +600,13 @@ Xlocal(void)
void
Xunlocal(void)
{
- Var *v = shell->local, *hide;
+ Var *v = proc->local, *hide;
if(!v)
- fatal("Xunlocal: no locals!", 0);
+ fatal("Xunlocal: no locals!\n", 0);
printf("unlocal\n");
- shell->local = v->link;
+ proc->local = v->link;
hide = var(v->name);
hide->new = 1;
@@ -540,12 +623,12 @@ Xbasic(void)
int pid, status;
struct Builtin *b;
- arg = shell->args->word;
+ arg = proc->args->word;
if(!arg){
Xerror("empty argument list\n");
return;
}
- print(errio, "recieved arg: %v\n", arg); // for debugging
+ /* print(errio, "recieved arg: %v\n", arg); // for debugging */
flush(errio);
v = var(arg->str);
@@ -561,6 +644,10 @@ Xbasic(void)
}
}
+ /* if we are here then it's an external command */
+ killzombies();
+ addjob(proc);
+
// run the external command
if((pid = xforkx()) < 0) {
Xerror("try again");
@@ -568,9 +655,16 @@ Xbasic(void)
}
poplist();
- do{
- waitpid(pid, &status, 0);
- } while(!WIFEXITED(status) && !WIFSIGNALED(status));
- printf("done waiting\n");
+ if(!shell.interactive)
+ waitall(proc);
+
+ foreground(proc, 0); // waits for child
}
+
+void
+Xexit(void)
+{
+ exit(shell.status);
+}
+