summaryrefslogtreecommitdiff
path: root/utils/rcsh/simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rcsh/simple.c')
-rw-r--r--utils/rcsh/simple.c528
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;
+}