aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rc/plan9ish.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-11-23 18:04:08 +0000
committerrsc <devnull@localhost>2003-11-23 18:04:08 +0000
commitf08fdedcee12c06e3ce9ac9bec363915978e8289 (patch)
treed67a27473be1e8f98d3694028104d9ddf915345b /src/cmd/rc/plan9ish.c
parent5993a8f2756bc455101a8c9ce95347d5050e7883 (diff)
downloadplan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.tar.gz
plan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.tar.bz2
plan9port-f08fdedcee12c06e3ce9ac9bec363915978e8289.zip
Plan 9's rc.
not a clear win over byron's, but at least it has the right syntax.
Diffstat (limited to 'src/cmd/rc/plan9ish.c')
-rw-r--r--src/cmd/rc/plan9ish.c480
1 files changed, 480 insertions, 0 deletions
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){
+ 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) interrupted=1;
+ goto Out;
+ }
+ 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)
+{
+ 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);
+}