diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /utils/rcsh/simple.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'utils/rcsh/simple.c')
| -rw-r--r-- | utils/rcsh/simple.c | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/utils/rcsh/simple.c b/utils/rcsh/simple.c new file mode 100644 index 00000000..1c3a89b3 --- /dev/null +++ b/utils/rcsh/simple.c @@ -0,0 +1,528 @@ +#include "rc.h" + +typedef struct Builtin Builtin; + +struct Builtin +{ + char *name; + void (*fnc)(void); +}; + +int exitnext(void); +void execexec(void); +void execfunc(Var *func); +void execcd(void); +void execwhatis(void); +void execeval(void); +void execexit(void); +void execshift(void); +void execwait(void); +void execdot(void); +void execflag(void); + +Builtin builtin[]={ + "cd", execcd, + "whatis", execwhatis, + "eval", execeval, + "exec", execexec, /* but with popword first */ + "exit", execexit, + "shift", execshift, + "wait", execwait, + ".", execdot, + "flag", execflag, + 0 +}; + +int mapfd(int fd); + +void +Xsimple(void) +{ + Word *a; + Thread *p=runq; + Var *v; + Builtin *bp; + uint pid; + char **argv; + + globlist(); + a=runq->argv->words; + if(a==0){ + Xerror("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; + } + } + + updenv(); + argv = procargv(0, 0, 0, 0, runq->argv->words); + pid = proc(argv, mapfd(0), mapfd(1), mapfd(2)); + free(argv); + + if(pid == 0) + pfmt(err, "%s: %r\n", runq->argv->words->word); + else + waitfor(pid); + poplist(); +#ifdef XXX + if(exitnext()){ + /* fork and wait is redundant */ + pushword("exec"); + execexec(); + Xexit(); + } + else{ + flush(err); + updenv(); + switch(pid=fork()){ + case -1: + Xperror("try again"); + return; + case 0: + pushword("exec"); + execexec(); + Exit("can't exec"); + default: + poplist(); + /* interrupts don't get us out */ + while(Waitfor(pid, 1) < 0) + ; + } + } +#endif + } +} + +Word nullpath={ "", 0}; + +Word * +searchpath(char *w) +{ + Word *path; + + return &nullpath; + + if(strncmp(w, "/", 1) == 0 + || strncmp(w, "#", 1) == 0 + || *w && w[1] == ':' + || strncmp(w, "./", 2) == 0 + || strncmp(w, "../", 3) == 0 + || (path=vlook("path")->val) == 0) + path=&nullpath; + return path; +} + +/* + * Search through the following code to see if we're just going to exit. + */ +int +exitnext(void) +{ + Code *c=&runq->code[runq->pc]; + + while(c->f==Xpopredir) + c++; + return c->f==Xexit; +} + +#ifdef XXX + +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; + } + } +} + + +#endif + +void +execexec(void) +{ + popword(); /* "exec" */ + if(runq->argv->words==0){ + Xerror("empty argument list"); + return; + } + fatal("execexec not done yet"); +/* + 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, 0); + runq->local=newvar(strdup("*"), runq->local); + runq->local->val=starval; + runq->local->changed=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(chdir(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\n", a->next->word); + break; + case 1: + a=vlook("home")->val; + if(count(a)>=1){ + if(chdir(a->word)>=0) + setstatus(""); + else + pfmt(err, "Can't cd %s\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 +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[letter[0]]=1; + break; + } + if(strcmp(val, "-")==0){ + flag[letter[0]]=0; + break; + } + } + default: + Xerror("Usage: flag [letter] [+-]"); + return; + } + poplist(); +} + +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; + free(star->val->word); + free(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; +} + +void +execeval(void) +{ + char *cmdline, *s, *t; + int len=0; + Word *ap; + + if(count(runq->argv->words)<=1){ + Xerror("Usage: eval cmd ..."); + return; + } + eflagok=1; + for(ap=runq->argv->words->next;ap;ap=ap->next) + len+=1+strlen(ap->word); + cmdline=malloc(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)); + free(cmdline); +} + +void +execdot(void) +{ + int iflag=0; + int fd; + List *av; + Thread *p=runq; + char *zero; + char file[512]; + Word *path; + static int first=1; + static Code dotcmds[14]; + + 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){ + Xerror("Usage: . [-i] file [arg ...]"); + return; + } + zero=strdup(p->argv->words->word); + popword(); + strcpy(file, "**No file name**"); + fd = -1; + if(strcmp(zero, "stdin$") == 0) + fd = dup(0); + else{ + 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(fd<0){ + Xperror(file); + return; + } + /* set up for a new command loop */ + start(dotcmds, 1, 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; + free(av); + /* push $0 value */ + pushlist(); + pushword(zero); + ndot++; +} + +void +execwhatis(void) +{ /* mildly wrong -- should fork before writing */ + Word *a, *b, *path; + Var *v; + Builtin *bp; + char file[512]; + Io out[1]; + int found, sep; + + a=runq->argv->words->next; + if(a==0){ + Xerror("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); +#ifdef XXX + if(Executable(file)){ + pfmt(out, "%s\n", file); + break; + } +#endif + } + if(!path && !found){ + pfmt(err, "%s: not found\n", a->word); + setstatus("not found"); + } + } + } + } + poplist(); + flush(err); +} + +void +execwait(void) +{ + fprint(2, "wait: not done yet"); + +#ifdef XXX + switch(count(runq->argv->words)){ + default: Xerror("Usage: wait [pid]"); return; + case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break; + case 1: Waitfor(-1, 0); break; + } + poplist(); +#endif +} + +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; +} |
