aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2021-11-16 14:46:55 -0800
committerNicholas Noll <nbnoll@eml.cc>2021-11-16 14:46:55 -0800
commite923adef5df8077259ed9973a4bffb0e08999fbe (patch)
tree60b7bf91db2d6eb54e3777f395419d23369842b6
parent29138fff8643194ec49cb79304d2a878d46c378b (diff)
chore: integrated redir code
-rw-r--r--src/cmd/rc/code.c10
-rw-r--r--src/cmd/rc/exec.c112
-rw-r--r--src/cmd/rc/exec.h1
-rw-r--r--src/cmd/rc/job.c3
-rw-r--r--src/cmd/rc/lex.c2
-rw-r--r--src/cmd/rc/parse.c2
-rw-r--r--src/cmd/rc/rc.h1
-rw-r--r--src/cmd/rc/syntax.y2
-rw-r--r--src/cmd/rc/sys.c9
-rw-r--r--src/cmd/rc/tree.c19
-rw-r--r--src/cmd/rc/var.c2
11 files changed, 135 insertions, 28 deletions
diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c
index dd0e99c..748c964 100644
--- a/src/cmd/rc/code.c
+++ b/src/cmd/rc/code.c
@@ -164,7 +164,7 @@ walk(Tree *node)
break;
case '=':
- for(n=node; node && node->type == '='; node = node->child[2])
+ for(n=node; node && node->type == '='; node=node->child[2])
;
if(node){
for(node=n; node->type=='='; node = node->child[2]){
@@ -317,6 +317,14 @@ walk(Tree *node)
storepc(addr1);
break;
+ case '`':
+ emitf(Xsubcmd);
+ addr1 = emiti(0);
+ walk(node->child[0]);
+ emitf(Xexit);
+ storepc(addr1);
+ break;
+
case Tpipe:
emitf(Xpipe);
diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c
index 28b6135..28941a0 100644
--- a/src/cmd/rc/exec.c
+++ b/src/cmd/rc/exec.c
@@ -168,8 +168,7 @@ undoredirs(void)
Xpopredir();
}
-static inline
-int
+static inline int
exitsnext(void)
{
Code *c = &runner->code.exe[runner->code.i];
@@ -191,8 +190,7 @@ defaultsignal(void)
signal(SIGCHLD, SIG_DFL);
}
-static inline
-void
+static inline void
setpid(Thread *job, int pid)
{
job->pid = pid;
@@ -206,8 +204,7 @@ setpid(Thread *job, int pid)
/* fork/execute helpers */
-static inline
-void
+static inline void
initchild(Thread *job, int fg)
{
int pid = getpid();
@@ -224,8 +221,7 @@ initchild(Thread *job, int fg)
clearwait(job);
}
-static inline
-void
+static inline void
initparent(Thread *job, int pid, int fg)
{
setpid(job, pid);
@@ -239,8 +235,7 @@ initparent(Thread *job, int pid, int fg)
addwait(job, pid);
}
-static
-void
+static void
xx(void)
{
popword(); // "exec"
@@ -248,32 +243,29 @@ xx(void)
Xerror("empty argument list");
return;
}
-
+ // set up file descriptors
redirect(runner->redir.end);
execute(runner->args->word, path(runner->args->word->str));
poplist();
}
-static
-int
+static int
xforkx(void)
{
int n, pid;
switch(pid=fork()){
case -1:
- Xerror("try again\n");
+ Xerror("fork failed: try again\n");
return -1;
case 0: // child
initchild(runner, 1);
-
pushword("exec");
xx();
-
- exit(2); // NOTE: unreachable: xx does not return
+ exit(2); // reach here on failed execs
+ break;
default: // parent
initparent(runner, pid, 0);
-
return pid;
}
}
@@ -286,7 +278,7 @@ pushredir(int type, int from, int to)
r->type = type;
r->from = from;
- r->to = to;
+ r->to = to;
r->link = runner->redir.end, runner->redir.end = r;
}
@@ -1080,7 +1072,7 @@ Xjoin(void)
}
s = runner->args->word->str;
- // deglob(s)
+ deglob(s);
arg = var(s)->val;
poplist();
@@ -1283,6 +1275,86 @@ Xsubshell(void)
}
void
+Xsubcmd(void)
+{
+ Io *io;
+ rune r;
+ Var *ifs;
+ Word *w, *nw;
+ int n, c, pid, pfd[2];
+ char *s, *end, *hit, *q, buf[8193];
+
+ ifs = var("ifs");
+ end = arrend(buf)-1;
+ hit = ifs->val ? ifs->val->str : "";
+
+ if(pipe(pfd)<0){
+ Xerror("pipe failed");
+ return;
+ }
+
+ switch(pid=fork()){
+ case -1:
+ Xerror("fork failed: try again");
+ close(pfd[0]), close(pfd[1]);
+ return;
+
+ case 0: // child
+ initchild(runner, 1);
+
+ close(pfd[0]);
+ run(runner->code.exe, runner->code.i+1, runner->local, 1);
+ pushredir(Ropen, pfd[1], 1);
+ break;
+
+ default: // parent
+ initparent(runner, pid, 0);
+ close(pfd[1]);
+ io = openfd(pfd[0]);
+
+ s = buf;
+ w = nil;
+ while((c=get(io))!=EOF){
+ if(s != end){
+ *s++ = c;
+ for(q=hit; *q; q+=n){
+ n = utf8·decode(q, &r);
+ if(s-buf >= n && memcmp(s-n, q, n)==0){
+ s -= n;
+ goto finish;
+ }
+ }
+ continue;
+ }
+ finish:
+ if(s != buf){
+ *s = 0;
+ w = makeword(buf, w);
+ }
+ s = buf;
+ }
+ if(s != buf){
+ *s = 0;
+ w = makeword(buf, w);
+ }
+
+ waitfor(runner, pid);
+ terminate(io);
+
+ /* reverse the list */
+ while(w){
+ nw = w->link;
+ w->link = runner->args->word;
+ runner->args->word = w;
+ w = nw;
+ }
+ assert(runner->wait.status == Pdone);
+ deljob(runner);
+ runner->code.i = runner->code.exe[runner->code.i].i;
+ }
+}
+
+void
Xpipewait(void)
{
foreground(runner, 0);
diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h
index 9db7e60..d7eee73 100644
--- a/src/cmd/rc/exec.h
+++ b/src/cmd/rc/exec.h
@@ -8,6 +8,7 @@
*/
void Xnewpgid(void);
+void Xsubcmd(void);
void Xunmark(void);
void Xwrite(void);
void Xread(void);
diff --git a/src/cmd/rc/job.c b/src/cmd/rc/job.c
index 1587951..3a53365 100644
--- a/src/cmd/rc/job.c
+++ b/src/cmd/rc/job.c
@@ -88,4 +88,7 @@ deljob(Thread *job)
;
*jp = job->link;
+ // XXX: I think this is mandatory hygeine
+ job->status = Pnil;
+ job->pgid = job->pid = -1;
}
diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c
index 0eb023c..a22dc7d 100644
--- a/src/cmd/rc/lex.c
+++ b/src/cmd/rc/lex.c
@@ -529,6 +529,8 @@ yylex(void)
*w = 0;
node = token(Tword, lexer.buf);
node->quoted = 1;
+
+ yylval.tree = node;
return node->type;
default:
diff --git a/src/cmd/rc/parse.c b/src/cmd/rc/parse.c
index 7ff860e..6a08f17 100644
--- a/src/cmd/rc/parse.c
+++ b/src/cmd/rc/parse.c
@@ -1651,7 +1651,7 @@ yyreduce:
case 25: /* cmd: basic */
#line 87 "src/cmd/rc/syntax.y"
- { (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); }
+ { (yyval.tree) = basictree((yyvsp[0].tree)); }
#line 1656 "src/cmd/rc/parse.c"
break;
diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
index 720c6f2..f5c8a6d 100644
--- a/src/cmd/rc/rc.h
+++ b/src/cmd/rc/rc.h
@@ -217,6 +217,7 @@ Tree *maketree(void);
Tree *maketree1(int, Tree*);
Tree *maketree2(int, Tree*, Tree*);
Tree *maketree3(int, Tree*, Tree*, Tree*);
+Tree *basictree(Tree*);
Tree *token(int, char *);
Tree *hangchild1(Tree *, Tree *, int);
diff --git a/src/cmd/rc/syntax.y b/src/cmd/rc/syntax.y
index 4acd92f..36e1dad 100644
--- a/src/cmd/rc/syntax.y
+++ b/src/cmd/rc/syntax.y
@@ -84,7 +84,7 @@ epilog:
cmd:
/* empty */ %prec Twhile { $$ = nil; }
-| basic { $$ = maketree1(Tbasic, $1); }
+| basic { $$ = basictree($1); }
| block epilog { $$ = hangepilog($1, $2); }
| cmd Tpipe nl cmd { $$ = hangchild2($2, $1, 0, $4, 1); }
| cmd Tandand nl cmd { $$ = maketree2(Tandand, $1, $4); }
diff --git a/src/cmd/rc/sys.c b/src/cmd/rc/sys.c
index a845122..9b6124b 100644
--- a/src/cmd/rc/sys.c
+++ b/src/cmd/rc/sys.c
@@ -3,14 +3,13 @@
// -----------------------------------------------------------------------
// internal
-static
-char**
+static char**
mkargv(Word *args)
{
char **argv=emalloc((count(args)+2)*sizeof(char *));
- char **argp=argv+1; /* leave one at front for runcoms */
+ char **argp=argv+1; /* leave one at front for executable */
- for(;args;args=args->link)
+ for(; args; args=args->link)
*argp++=args->str;
*argp=nil;
@@ -107,9 +106,11 @@ redirect(Redir *r)
case Rdup:
dup2(r->from, r->to); // TODO: error checking
break;
+
case Rclose:
close(r->from);
break;
+
default:
fatal("unrecognized redirection type %d\n", r->type);
}
diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c
index 3703a25..3b7aeb8 100644
--- a/src/cmd/rc/tree.c
+++ b/src/cmd/rc/tree.c
@@ -78,6 +78,25 @@ hangchild3(Tree *node, Tree *c0, Tree *c1, Tree *c2)
return node;
}
+/*
+ * add a Tbasic node.
+ * percolate all the redirections up to the root
+ */
+Tree*
+basictree(Tree *cmd)
+{
+ Tree *c;
+ cmd = maketree1(Tbasic, cmd);
+ for(c=cmd->child[0]; c->type==Targs; c = c->child[0]){
+ if(c->child[1]->type == Tdup || c->child[1]->type == Tredir){
+ c->child[1]->child[1] = cmd;
+ cmd = c->child[1];
+ c->child[1] = nil;
+ }
+ }
+ return cmd;
+}
+
Tree*
hangepilog(Tree *cmd, Tree *epi)
{
diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c
index 6004bb9..e2d3e08 100644
--- a/src/cmd/rc/var.c
+++ b/src/cmd/rc/var.c
@@ -6,7 +6,7 @@
// -----------------------------------------------------------------------
// globals
-struct Keyword
+struct Keyword
{
char *name;
int type;