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.c86
1 files changed, 85 insertions, 1 deletions
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;
@@ -383,6 +384,49 @@ xdot(void)
}
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)
{
int i;
@@ -681,6 +725,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)
{
Var *v;
@@ -781,6 +856,15 @@ Xflat(void)
}
void
+Xbang(void)
+{
+ if(runner->status)
+ runner->status = 0;
+ else
+ runner->status = 1;
+}
+
+void
Xexit(void)
{
exit(runner->status);