From f08fdedcee12c06e3ce9ac9bec363915978e8289 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 23 Nov 2003 18:04:08 +0000 Subject: Plan 9's rc. not a clear win over byron's, but at least it has the right syntax. --- src/cmd/rc/plan9ish.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 src/cmd/rc/plan9ish.c (limited to 'src/cmd/rc/plan9ish.c') diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c new file mode 100644 index 00000000..0c3076ec --- /dev/null +++ b/src/cmd/rc/plan9ish.c @@ -0,0 +1,480 @@ +/* + * 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 buf[256]; + char *root; + + root = getenv("PLAN9"); + if(root == nil) + root = "/usr/local/plan9"; + snprint(buf, sizeof buf, "%s/rcmain", root); + return buf; +} + +char Fdprefix[]="/dev/fd/"; +void execfinit(void); +void execbind(void); +void execmount(void); +void execnewpgrp(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, + 0 +}; +#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, "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); +} +int Waitfor(int pid, int unused0){ + thread *p; + Waitmsg *w; + char errbuf[ERRMAX]; + + while((w = wait()) != nil){ + if(w->pid==pid){ + setstatus(w->msg); + free(w); + return 0; + } + 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(a, b) +char **a, **b; +{ + return strcmp(*a, *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) + 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=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) +{ + return read(fd, buf, cnt); +} +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 unused0){ + return -1; +} +void Exit(char *stat) +{ + Updenv(); + setstatus(stat); + exits(truestatus()?"":getstatus()); +} +int Eintr(void){ + return interrupted; +} +void Noerror(void){ + interrupted=0; +} +int +Isatty(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); +} -- cgit v1.2.3