From d1a19f0d477a6249d8af9322317b8434b86260ea Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Wed, 13 Oct 2021 08:27:37 -0700 Subject: fix(email): bytes error. updated vendoring --- sys/cmd/rc/simple.c | 507 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 499 insertions(+), 8 deletions(-) (limited to 'sys/cmd/rc/simple.c') diff --git a/sys/cmd/rc/simple.c b/sys/cmd/rc/simple.c index f934aa1..d587227 100644 --- a/sys/cmd/rc/simple.c +++ b/sys/cmd/rc/simple.c @@ -1,13 +1,504 @@ +/* + * Maybe `simple' is a misnomer. + */ +#include "rc.h" +#include "getflags.h" +#include "exec.h" +#include "io.h" +#include "fns.h" +/* + * Search through the following code to see if we're just going to exit. + */ +int +exitnext(void){ + union code *c=&runq->code[runq->pc]; + while(c->f==Xpopredir) c++; + return c->f==Xexit; +} + void Xsimple(void) { - Word *a; - Var *v; + word *a; + thread *p = runq; + var *v; + struct builtin *bp; + int pid; + globlist(); + a = runq->argv->words; + if(a==0){ + Xerror1("empty argument list"); + return; + } + if(flag['x']) + pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */ + v = gvlook(a->word); + if(v->fn) + execfunc(v); + else{ + if(strcmp(a->word, "builtin")==0){ + if(count(a)==1){ + pfmt(err, "builtin: empty argument list\n"); + setstatus("empty arg list"); + poplist(); + return; + } + a = a->next; + popword(); + } + for(bp = Builtin;bp->name;bp++) + if(strcmp(a->word, bp->name)==0){ + (*bp->fnc)(); + return; + } + if(exitnext()){ + /* fork and wait is redundant */ + pushword("exec"); + execexec(); + Xexit(); + } + else{ + flush(err); + Updenv(); /* necessary so changes don't go out again */ + if((pid = execforkexec()) < 0){ + Xerror("try again"); + return; + } + + /* interrupts don't get us out */ + poplist(); + while(Waitfor(pid, 1) < 0) + ; + } + } +} +struct word nullpath = { "", 0}; + +void +doredir(redir *rp) +{ + if(rp){ + doredir(rp->next); + switch(rp->type){ + case ROPEN: + if(rp->from!=rp->to){ + Dup(rp->from, rp->to); + close(rp->from); + } + break; + case RDUP: + Dup(rp->from, rp->to); + break; + case RCLOSE: + close(rp->from); + break; + } + } +} + +word* +searchpath(char *w) +{ + word *path; + if(strncmp(w, "/", 1)==0 +/* || strncmp(w, "#", 1)==0 */ + || strncmp(w, "./", 2)==0 + || strncmp(w, "../", 3)==0 + || (path = vlook("path")->val)==0) + path=&nullpath; + return path; +} + +void +execexec(void) +{ + popword(); /* "exec" */ + if(runq->argv->words==0){ + Xerror1("empty argument list"); + return; + } + doredir(runq->redir); + Execute(runq->argv->words, searchpath(runq->argv->words->word)); + poplist(); +} - a = shell->stack->words; - if (!a) { - Xerror("empty argument list"); - return; - } - v = vlookup(a->word); +void +execfunc(var *func) +{ + word *starval; + popword(); + starval = runq->argv->words; + runq->argv->words = 0; + poplist(); + start(func->fn, func->pc, runq->local); + runq->local = newvar(strdup("*"), runq->local); + runq->local->val = starval; + runq->local->changed = 1; +} + +int +dochdir(char *word) +{ + /* report to /dev/wdir if it exists and we're interactive */ + static int wdirfd = -2; + if(chdir(word)<0) return -1; + if(flag['i']!=0){ + if(wdirfd==-2) /* try only once */ + wdirfd = open("/dev/wdir", OWRITE|OCEXEC); + if(wdirfd>=0) + write(wdirfd, word, strlen(word)); + } + return 1; +} + +void +execcd(void) +{ + word *a = runq->argv->words; + word *cdpath; + char dir[512]; + setstatus("can't cd"); + cdpath = vlook("cdpath")->val; + switch(count(a)){ + default: + pfmt(err, "Usage: cd [directory]\n"); + break; + case 2: + if(a->next->word[0]=='/' || cdpath==0) + cdpath=&nullpath; + for(;cdpath;cdpath = cdpath->next){ + strcpy(dir, cdpath->word); + if(dir[0]) + strcat(dir, "/"); + strcat(dir, a->next->word); + if(dochdir(dir)>=0){ + if(strlen(cdpath->word) + && strcmp(cdpath->word, ".")!=0) + pfmt(err, "%s\n", dir); + setstatus(""); + break; + } + } + if(cdpath==0) + pfmt(err, "Can't cd %s: %r\n", a->next->word); + break; + case 1: + a = vlook("home")->val; + if(count(a)>=1){ + if(dochdir(a->word)>=0) + setstatus(""); + else + pfmt(err, "Can't cd %s: %r\n", a->word); + } + else + pfmt(err, "Can't cd -- $home empty\n"); + break; + } + poplist(); +} + +void +execexit(void) +{ + switch(count(runq->argv->words)){ + default: + pfmt(err, "Usage: exit [status]\nExiting anyway\n"); + case 2: + setstatus(runq->argv->words->next->word); + case 1: Xexit(); + } +} + +void +execshift(void) +{ + int n; + word *a; + var *star; + switch(count(runq->argv->words)){ + default: + pfmt(err, "Usage: shift [n]\n"); + setstatus("shift usage"); + poplist(); + return; + case 2: + n = atoi(runq->argv->words->next->word); + break; + case 1: + n = 1; + break; + } + star = vlook("*"); + for(;n && star->val;--n){ + a = star->val->next; + efree(star->val->word); + efree((char *)star->val); + star->val = a; + star->changed = 1; + } + setstatus(""); + poplist(); +} + +int +octal(char *s) +{ + int n = 0; + while(*s==' ' || *s=='\t' || *s=='\n') s++; + while('0'<=*s && *s<='7') n = n*8+*s++-'0'; + return n; +} + +int +mapfd(int fd) +{ + redir *rp; + for(rp = runq->redir;rp;rp = rp->next){ + switch(rp->type){ + case RCLOSE: + if(rp->from==fd) + fd=-1; + break; + case RDUP: + case ROPEN: + if(rp->to==fd) + fd = rp->from; + break; + } + } + return fd; +} +union code rdcmds[4]; + +void +execcmds(io *f) +{ + static int first = 1; + if(first){ + rdcmds[0].i = 1; + rdcmds[1].f = Xrdcmds; + rdcmds[2].f = Xreturn; + first = 0; + } + start(rdcmds, 1, runq->local); + runq->cmdfd = f; + runq->iflast = 0; +} + +void +execeval(void) +{ + char *cmdline, *s, *t; + int len = 0; + word *ap; + if(count(runq->argv->words)<=1){ + Xerror1("Usage: eval cmd ..."); + return; + } + eflagok = 1; + for(ap = runq->argv->words->next;ap;ap = ap->next) + len+=1+strlen(ap->word); + cmdline = emalloc(len); + s = cmdline; + for(ap = runq->argv->words->next;ap;ap = ap->next){ + for(t = ap->word;*t;) *s++=*t++; + *s++=' '; + } + s[-1]='\n'; + poplist(); + execcmds(opencore(cmdline, len)); + efree(cmdline); +} +union code dotcmds[14]; + +void +execdot(void) +{ + int iflag = 0; + int fd; + list *av; + thread *p = runq; + char *zero; + static int first = 1; + char file[512]; + word *path; + if(first){ + dotcmds[0].i = 1; + dotcmds[1].f = Xmark; + dotcmds[2].f = Xword; + dotcmds[3].s="0"; + dotcmds[4].f = Xlocal; + dotcmds[5].f = Xmark; + dotcmds[6].f = Xword; + dotcmds[7].s="*"; + dotcmds[8].f = Xlocal; + dotcmds[9].f = Xrdcmds; + dotcmds[10].f = Xunlocal; + dotcmds[11].f = Xunlocal; + dotcmds[12].f = Xreturn; + first = 0; + } + else + eflagok = 1; + popword(); + if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ + iflag = 1; + popword(); + } + /* get input file */ + if(p->argv->words==0){ + Xerror1("Usage: . [-i] file [arg ...]"); + return; + } + zero = strdup(p->argv->words->word); + popword(); + fd=-1; + for(path = searchpath(zero);path;path = path->next){ + strcpy(file, path->word); + if(file[0]) + strcat(file, "/"); + strcat(file, zero); + if((fd = open(file, 0))>=0) break; + if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */ + fd = Dup1(0); + if(fd>=0) + break; + } + } + if(fd<0){ + pfmt(err, "%s: ", zero); + setstatus("can't open"); + Xerror(".: can't open"); + return; + } + /* set up for a new command loop */ + start(dotcmds, 1, (struct var *)0); + pushredir(RCLOSE, fd, 0); + runq->cmdfile = zero; + runq->cmdfd = openfd(fd); + runq->iflag = iflag; + runq->iflast = 0; + /* push $* value */ + pushlist(); + runq->argv->words = p->argv->words; + /* free caller's copy of $* */ + av = p->argv; + p->argv = av->next; + efree((char *)av); + /* push $0 value */ + pushlist(); + pushword(zero); + ndot++; +} + +void +execflag(void) +{ + char *letter, *val; + switch(count(runq->argv->words)){ + case 2: + setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set"); + break; + case 3: + letter = runq->argv->words->next->word; + val = runq->argv->words->next->next->word; + if(strlen(letter)==1){ + if(strcmp(val, "+")==0){ + flag[(uchar)letter[0]] = flagset; + break; + } + if(strcmp(val, "-")==0){ + flag[(uchar)letter[0]] = 0; + break; + } + } + default: + Xerror1("Usage: flag [letter] [+-]"); + return; + } + poplist(); +} + +void +execwhatis(void){ /* mildly wrong -- should fork before writing */ + word *a, *b, *path; + var *v; + struct builtin *bp; + char file[512]; + struct io out[1]; + int found, sep; + a = runq->argv->words->next; + if(a==0){ + Xerror1("Usage: whatis name ..."); + return; + } + setstatus(""); + out->fd = mapfd(1); + out->bufp = out->buf; + out->ebuf = &out->buf[NBUF]; + out->strp = 0; + for(;a;a = a->next){ + v = vlook(a->word); + if(v->val){ + pfmt(out, "%s=", a->word); + if(v->val->next==0) + pfmt(out, "%q\n", v->val->word); + else{ + sep='('; + for(b = v->val;b && b->word;b = b->next){ + pfmt(out, "%c%q", sep, b->word); + sep=' '; + } + pfmt(out, ")\n"); + } + found = 1; + } + else + found = 0; + v = gvlook(a->word); + if(v->fn) + pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s); + else{ + for(bp = Builtin;bp->name;bp++) + if(strcmp(a->word, bp->name)==0){ + pfmt(out, "builtin %s\n", a->word); + break; + } + if(!bp->name){ + for(path = searchpath(a->word);path;path = path->next){ + strcpy(file, path->word); + if(file[0]) + strcat(file, "/"); + strcat(file, a->word); + if(Executable(file)){ + pfmt(out, "%s\n", file); + break; + } + } + if(!path && !found){ + pfmt(err, "%s: not found\n", a->word); + setstatus("not found"); + } + } + } + } + poplist(); + flush(err); +} + +void +execwait(void) +{ + switch(count(runq->argv->words)){ + default: + Xerror1("Usage: wait [pid]"); + return; + case 2: + Waitfor(atoi(runq->argv->words->next->word), 0); + break; + case 1: + Waitfor(-1, 0); + break; + } + poplist(); } -- cgit v1.2.1