From 6d50d5b97d49a74a8faf587ec2bbf234626adf0c Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 19 Oct 2021 14:16:54 -0700 Subject: Feat(rc): added subshell commands and cd builtin Slowly chipping away at a decent feature list. Subshell commands are executed by @{ ... }. --- sys/cmd/rc/exec.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) (limited to 'sys/cmd/rc/exec.c') diff --git a/sys/cmd/rc/exec.c b/sys/cmd/rc/exec.c index 37c289b..217f7ee 100644 --- a/sys/cmd/rc/exec.c +++ b/sys/cmd/rc/exec.c @@ -17,6 +17,7 @@ static Word nullpath = { .str="", .link=nil }; struct Builtin builtin[]={ {".", xdot}, + {"cd", xcd}, {"fg", xfg}, {"jobs", xjob}, 0, @@ -326,7 +327,7 @@ xdot(void) Thread *old; char file[512]; - popword(); + popword(); // "." #if 0 if(proc->args->word && strcmp(proc->args->word->str, "-i")==0){ iflag = 1; @@ -382,6 +383,49 @@ xdot(void) //ndot++; } +void +xcd(void) +{ + Word *arg; + Word *cdpath; + char dir[512]; + + popword(); // cd + + arg = runner->args->word; + switch(count(arg)){ + default: + print(shell.err, "usage: cd [directory]\n"); + break; + case 0: + arg = var("home")->val; + if(count(arg) >= 1){ + if(chdir(arg->str) < 0) + print(shell.err, "failed cd: %s\n", strerror(errno)); + }else{ + print(shell.err, "ambiguous cd: $home empty\n"); + } + break; + + case 1: + // TODO: add cdpath + cdpath = &nullpath; + for(; cdpath; cdpath = cdpath->link){ + strcpy(dir, cdpath->str); + if(dir[0]) + strcat(dir,"/"); + strcat(dir, arg->str); + if(chdir(dir) < 0){ + print(shell.err, "failed cd %s: %s\n", dir, strerror(errno)); + } + break; + } + break; + } + + poplist(); +} + void xjob(void) { @@ -680,6 +724,37 @@ Xasync(void) } } +void +Xsubshell(void) +{ + int pid; + + switch(pid=fork()){ + case -1: + Xerror("fork failed: try again"); + break; + + case 0: // child + clearwait(runner); + if(shell.interactive){ // NOTE: this needs to read off its caller's interactivity + setpid(getpid()); + tcsetpgrp(0, runner->pgid); + defaultsignal(); + } + run(runner->code.exe, runner->code.i+1, runner->local, 1); + runner->link = nil; + break; + + default: // parent + setpid(pid); + addwait(runner, pid); + waitfor(runner, pid); // wait until child finishes + runner->code.i = runner->code.exe[runner->code.i].i; // jump to end of subshell command and continue execution + } +} + + + void Xbasic(void) { @@ -780,6 +855,15 @@ Xflat(void) efree(str); } +void +Xbang(void) +{ + if(runner->status) + runner->status = 0; + else + runner->status = 1; +} + void Xexit(void) { -- cgit v1.2.1