Logo Search packages:      
Sourcecode: 9base version File versions  Download package

simple.c

/*
 * 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, n;
      char buf[ERRMAX];
      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 */
                  switch(pid=fork()){
                  case -1:
                        Xerror("try again");
                        return;
                  case 0:
                        pushword("exec");
                        execexec();
                        strcpy(buf, "can't exec: ");
                        n = strlen(buf);
                        errstr(buf+n, ERRMAX-n);
                        Exit(buf);
                  default:
                        kidpid = pid;
                        poplist();
                        /* interrupts don't get us out */
                        while(Waitfor(pid, 1) < 0)
                              ;
                        kidpid = 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, (struct var *)0);
      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(strcmp(file, "/dev/stdin")==0){  /* for sun & ucb */
                  fd=Dup1(0);
                  if(fd>=0) break;
            }
            if((fd=open(file, 0))>=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();
}

Generated by  Doxygen 1.6.0   Back to index