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

plan9ish.c

/*
 * Plan 9 versions of system-specific functions
 *    By convention, exported routines herein have names beginning with an
 *    upper case letter.
 */
#include "rc.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
#include "getflags.h"
char *Signame[]={
      "sigexit",  "sighup",   "sigint",   "sigquit",
      "sigalrm",  "sigkill",  "sigfpe",   "sigterm",
      0
};
char *syssigname[]={
      "exit",           /* can't happen */
      "hangup",
      "interrupt",
      "quit",           /* can't happen */
      "alarm",
      "kill",
      "sys: fp: ",
      "term",
      0
};
char*
Rcmain(void)
{
    static char Rcmain[] = PREFIX"/etc/rcmain";
    char *rcmain = getenv("RCMAIN");
    return rcmain ? rcmain : Rcmain;
}

char Fdprefix[]="/dev/fd/";
void execfinit(void);
void execbind(void);
void execmount(void);
void execulimit(void);
void execumask(void);
void execrfork(void);
builtin Builtin[]={
      "cd",       execcd,
      "whatis",   execwhatis,
      "eval",           execeval,
      "exec",           execexec,   /* but with popword first */
      "exit",           execexit,
      "shift",    execshift,
      "wait",           execwait,
      ".",        execdot,
      "finit",    execfinit,
      "flag",           execflag,
      "ulimit",   execulimit,
      "umask",    execumask,
      "rfork",    execrfork,
      0
};

void
execrfork(void)
{
      int arg;
      char *s;

      switch(count(runq->argv->words)){
      case 1:
            arg = RFENVG|RFNOTEG|RFNAMEG;
            break;
      case 2:
            arg = 0;
            for(s = runq->argv->words->next->word;*s;s++) switch(*s){
            default:
                  goto Usage;
            case 'n':
                  arg|=RFNAMEG;  break;
            case 'N':
                  arg|=RFCNAMEG;
                  break;
            case 'e':
                  /* arg|=RFENVG; */  break;
            case 'E':
                  arg|=RFCENVG;  break;
            case 's':
                  arg|=RFNOTEG;  break;
            case 'f':
                  arg|=RFFDG;    break;
            case 'F':
                  arg|=RFCFDG;   break;
            }
            break;
      default:
      Usage:
            pfmt(err, "Usage: %s [nNeEsfF]\n", runq->argv->words->word);
            setstatus("rfork usage");
            poplist();
            return;
      }
      if(rfork(arg)==-1){
            pfmt(err, "rc: %s failed\n", runq->argv->words->word);
            setstatus("rfork failed");
      }
      else
            setstatus("");
      poplist();
}



#define     SEP   '\1'
char **environp;
struct word *enval(s)
register char *s;
{
      register char *t, c;
      register struct word *v;
      for(t=s;*t && *t!=SEP;t++);
      c=*t;
      *t='\0';
      v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
      *t=c;
      return v;
}
void Vinit(void){
      extern char **environ;
      register char *s;
      register char **env=environ;
      environp=env;
      for(;*env;env++){
            for(s=*env;*s && *s!='(' && *s!='=';s++);
            switch(*s){
            case '\0':
            //    pfmt(err, "rc: odd environment %q?\n", *env);
                  break;
            case '=':
                  *s='\0';
                  setvar(*env, enval(s+1));
                  *s='=';
                  break;
            case '(':   /* ignore functions for now */
                  break;
            }
      }
}
char **envp;
void Xrdfn(void){
      char *p;
      register char *s;
      register int len;
      for(;*envp;envp++){
            s = *envp;
            if(strncmp(s, "fn#", 3) == 0){
                  p = strchr(s, '=');
                  if(p == nil)
                        continue;
                  *p = ' ';
                  s[2] = ' ';
                  len = strlen(s);
                  execcmds(opencore(s, len));
                  s[len] = '\0';
                  return;
            }
#if 0
            for(s=*envp;*s && *s!='(' && *s!='=';s++);
            switch(*s){
            case '\0':
                  pfmt(err, "environment %q?\n", *envp);
                  break;
            case '=':   /* ignore variables */
                  break;
            case '(':         /* Bourne again */
                  s=*envp+3;
                  envp++;
                  len=strlen(s);
                  s[len]='\n';
                  execcmds(opencore(s, len+1));
                  s[len]='\0';
                  return;
            }
#endif
      }
      Xreturn();
}
union code rdfns[4];
void execfinit(void){
      static int first=1;
      if(first){
            rdfns[0].i=1;
            rdfns[1].f=Xrdfn;
            rdfns[2].f=Xjump;
            rdfns[3].i=1;
            first=0;
      }
      Xpopm();
      envp=environp;
      start(rdfns, 1, runq->local);
}
extern int mapfd(int);
int Waitfor(int pid, int unused0){
      thread *p;
      Waitmsg *w;
      char errbuf[ERRMAX];

      while((w = wait()) != nil){
            if(w->pid==pid){
                  if(strncmp(w->msg, "signal: ", 8) == 0)
                        fprint(mapfd(2), "%d: %s\n", w->pid, w->msg);
                  setstatus(w->msg);
                  free(w);
                  return 0;
            }
            if(strncmp(w->msg, "signal: ", 8) == 0)
                  fprint(2, "%d: %s\n", w->pid, w->msg);
            for(p=runq->ret;p;p=p->ret)
                  if(p->pid==w->pid){
                        p->pid=-1;
                        strcpy(p->status, w->msg);
                  }
            free(w);
      }

      errstr(errbuf, sizeof errbuf);
      if(strcmp(errbuf, "interrupted")==0) return -1;
      return 0;
}
char **mkargv(word *a)
{
      char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
      char **argp=argv+1;     /* leave one at front for runcoms */
      for(;a;a=a->next) *argp++=a->word;
      *argp=0;
      return argv;
}
/*
void addenv(var *v)
{
      char envname[256];
      word *w;
      int f;
      io *fd;
      if(v->changed){
            v->changed=0;
            snprint(envname, sizeof envname, "/env/%s", v->name);
            if((f=Creat(envname))<0)
                  pfmt(err, "rc: can't open %s: %r\n", envname);
            else{
                  for(w=v->val;w;w=w->next)
                        write(f, w->word, strlen(w->word)+1L);
                  close(f);
            }
      }
      if(v->fnchanged){
            v->fnchanged=0;
            snprint(envname, sizeof envname, "/env/fn#%s", v->name);
            if((f=Creat(envname))<0)
                  pfmt(err, "rc: can't open %s: %r\n", envname);
            else{
                  if(v->fn){
                        fd=openfd(f);
                        pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
                        closeio(fd);
                  }
                  close(f);
            }
      }
}
void updenvlocal(var *v)
{
      if(v){
            updenvlocal(v->next);
            addenv(v);
      }
}
void Updenv(void){
      var *v, **h;
      for(h=gvar;h!=&gvar[NVAR];h++)
            for(v=*h;v;v=v->next)
                  addenv(v);
      if(runq) updenvlocal(runq->local);
}
*/
int
cmpenv(const void *a, const void *b)
{
      return strcmp(*(char**)a, *(char**)b);
}
char **mkenv(){
      register char **env, **ep, *p, *q;
      register struct var **h, *v;
      register struct word *a;
      register int nvar=0, nchr=0, sep;
      /*
       * Slightly kludgy loops look at locals then globals
       */
      for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
            if((v==vlook(v->name)) && v->val){
                  nvar++;
                  nchr+=strlen(v->name)+1;
                  for(a=v->val;a;a=a->next)
                        nchr+=strlen(a->word)+1;
            }
            if(v->fn){
                  nvar++;
                  nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
            }
      }
      env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
      ep=env;
      p=(char *)&env[nvar+1];
      for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
            if((v==vlook(v->name)) && v->val){
                  *ep++=p;
                  q=v->name;
                  while(*q) *p++=*q++;
                  sep='=';
                  for(a=v->val;a;a=a->next){
                        *p++=sep;
                        sep=SEP;
                        q=a->word;
                        while(*q) *p++=*q++;
                  }
                  *p++='\0';
            }
            if(v->fn){
                  *ep++=p;
#if 0
                  *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
                  *p++='f'; *p++='n'; *p++=' ';
                  q=v->name;
                  while(*q) *p++=*q++;
                  *p++=' ';
#endif
                  *p++='f'; *p++='n'; *p++='#';
                  q=v->name;
                  while(*q) *p++=*q++;
                  *p++='=';
                  q=v->fn[v->pc-1].s;
                  while(*q) *p++=*q++;
                  *p++='\n';
                  *p++='\0';
            }
      }
      *ep=0;
      qsort((char *)env, nvar, sizeof ep[0], cmpenv);
      return env; 
}
void Updenv(void){}
void Execute(word *args, word *path)
{
      char **argv=mkargv(args);
      char **env=mkenv();
      char file[1024];
      int nc;
      Updenv();
      for(;path;path=path->next){
            nc=strlen(path->word);
            if(nc<1024){
                  strcpy(file, path->word);
                  if(file[0]){
                        strcat(file, "/");
                        nc++;
                  }
                  if(nc+strlen(argv[1])<1024){
                        strcat(file, argv[1]);
                        execve(file, argv+1, env);
                  }
                  else werrstr("command name too long");
            }
      }
      rerrstr(file, sizeof file);
      pfmt(err, "%s: %s\n", argv[1], file);
      efree((char *)argv);
}
#define     NDIR  256         /* shoud be a better way */
int Globsize(char *p)
{
      ulong isglob=0, globlen=NDIR+1;
      for(;*p;p++){
            if(*p==GLOB){
                  p++;
                  if(*p!=GLOB) isglob++;
                  globlen+=*p=='*'?NDIR:1;
            }
            else
                  globlen++;
      }
      return isglob?globlen:0;
}
#define     NFD   50
#define     NDBUF 32
struct{
      Dir   *dbuf;
      int   i;
      int   n;
}dir[NFD];
int Opendir(char *name)
{
      Dir *db;
      int f;
      f=open(name, 0);
      if(f==-1)
            return f;
      db = dirfstat(f);
      if(db!=nil && (db->mode&DMDIR)){
            if(f<NFD){
                  dir[f].i=0;
                  dir[f].n=0;
            }
            free(db);
            return f;
      }
      free(db);
      close(f);
      return -1;
}
int Readdir(int f, char *p)
{
      int n;
      if(f<0 || f>=NFD)
            return 0;
      if(dir[f].i==dir[f].n){ /* read */
            free(dir[f].dbuf);
            dir[f].dbuf=0;
            n=dirread(f, &dir[f].dbuf);
            if(n>=0)
                  dir[f].n=n;
            else
                  dir[f].n=0;
            dir[f].i=0;
      }
      if(dir[f].i==dir[f].n)
            return 0;
      strcpy(p, dir[f].dbuf[dir[f].i].name);
      dir[f].i++;
      return 1;
}
void Closedir(int f){
      if(f>=0 && f<NFD){
            free(dir[f].dbuf);
            dir[f].i=0;
            dir[f].n=0;
            dir[f].dbuf=0;
      }
      close(f);
}
int interrupted = 0;
void
notifyf(void *unused0, char *s)
{
      int i;
      for(i=0;syssigname[i];i++)
            if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
                  if(strncmp(s, "sys: ", 5)!=0){
                        if(kidpid && !interrupted){
                              interrupted=1;
                              postnote(PNGROUP, kidpid, s);
                        }
                        interrupted = 1;
                  }
                  goto Out;
            }
      if(strcmp(s, "sys: window size change") != 0)
      if(strcmp(s, "sys: write on closed pipe") != 0)
      if(strcmp(s, "sys: child") != 0)
            pfmt(err, "rc: note: %s\n", s);
      noted(NDFLT);
      return;
Out:
      if(strcmp(s, "interrupt")!=0 || trap[i]==0){
            trap[i]++;
            ntrap++;
      }
      if(ntrap>=32){    /* rc is probably in a trap loop */
            pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
            abort();
      }
      noted(NCONT);
}
void Trapinit(void){
      notify(notifyf);
}
void Unlink(char *name)
{
      remove(name);
}
long Write(int fd, char *buf, long cnt)
{
      return write(fd, buf, (long)cnt);
}
long Read(int fd, char *buf, long cnt)
{
      int i;

      i = read(fd, buf, cnt);
      if(ntrap) dotrap();
      return i;
}
long Seek(int fd, long cnt, long whence)
{
      return seek(fd, cnt, whence);
}
int Executable(char *file)
{
      Dir *statbuf;
      int ret;

      statbuf = dirstat(file);
      if(statbuf == nil) return 0;
      ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
      free(statbuf);
      return ret;
}
int Creat(char *file)
{
      return create(file, 1, 0666L);
}
int Dup(int a, int b){
      return dup(a, b);
}
int Dup1(int a){
      return dup(a, -1);
}
void Exit(char *stat)
{
      Updenv();
      setstatus(stat);
      exits(truestatus()?"":getstatus());
}
int Eintr(void){
      return interrupted;
}
void Noerror(void){
      interrupted=0;
}
int
Isatty(int fd){
      return isatty(fd);
}
void Abort(void){
      pfmt(err, "aborting\n");
      flush(err);
      Exit("aborting");
}
void Memcpy(char *a, char *b, long n)
{
      memmove(a, b, (long)n);
}
void *Malloc(ulong n){
      return malloc(n);
}

Generated by  Doxygen 1.6.0   Back to index