|
@@ -1,508 +0,0 @@
|
|
|
-/*
|
|
|
- * 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;
|
|
|
- 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();
|
|
|
-}
|
|
|
-
|
|
|
-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) {
|
|
|
-#ifdef Unix
|
|
|
- fcntl(wdirfd, F_SETFD, FD_CLOEXEC);
|
|
|
-#endif
|
|
|
- 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[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();
|
|
|
-}
|