📄 plan9.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[]="/rc/lib/rcmain";char Fdprefix[]="/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, "rfork", execnewpgrp, 0};voidexecnewpgrp(void){ int arg; char *s; switch(count(runq->argv->words)){ case 1: arg = RFENVG|RFNAMEG|RFNOTEG; 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 'm': arg|=RFNOMNT; 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 [fnesFNEm]\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();}voidVinit(void){ int dir, f, len; word *val; char *buf, *s; Dir *ent; int i, nent; char envname[256]; dir = open("/env", OREAD); if(dir<0){ pfmt(err, "rc: can't open /env: %r\n"); return; } ent = nil; for(;;){ nent = dirread(dir, &ent); if(nent <= 0) break; for(i = 0; i<nent; i++){ len = ent[i].length; if(len && strncmp(ent[i].name, "fn#", 3)!=0){ snprint(envname, sizeof envname, "/env/%s", ent[i].name); if((f = open(envname, 0))>=0){ buf = emalloc((int)len+1); read(f, buf, (long)len); val = 0; /* Charitably add a 0 at the end if need be */ if(buf[len-1]) buf[len++]='\0'; s = buf+len-1; for(;;){ while(s!=buf && s[-1]!='\0') --s; val = newword(s, val); if(s==buf) break; --s; } setvar(ent[i].name, val); vlook(ent[i].name)->changed = 0; close(f); efree(buf); } } } free(ent); } close(dir);}int envdir;voidXrdfn(void){ int f, len; static Dir *ent, *allocent; static int nent; Dir *e; char envname[256]; for(;;){ if(nent == 0){ free(allocent); nent = dirread(envdir, &allocent); ent = allocent; } if(nent <= 0) break; while(nent){ e = ent++; nent--; len = e->length; if(len && strncmp(e->name, "fn#", 3)==0){ snprint(envname, sizeof envname, "/env/%s", e->name); if((f = open(envname, 0))>=0){ execcmds(openfd(f)); return; } } } } close(envdir); Xreturn();}union code rdfns[4];voidexecfinit(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(); envdir = open("/env", 0); if(envdir<0){ pfmt(err, "rc: can't open /env: %r\n"); return; } start(rdfns, 1, runq->local);}intWaitfor(int pid, int){ 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;}voidaddenv(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); } }}voidupdenvlocal(var *v){ if(v){ updenvlocal(v->next); addenv(v); }}voidUpdenv(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);}intForkExecute(char *file, char **argv, int sin, int sout, int serr){ int pid; if(access(file, 1) != 0) return -1; switch(pid = fork()){ case -1: return -1; case 0: if(sin >= 0) dup(sin, 0); else close(0); if(sout >= 0) dup(sout, 1); else close(1); if(serr >= 0) dup(serr, 2); else close(2); exec(file, argv); exits(file); } return pid;}voidExecute(word *args, word *path){ char **argv = mkargv(args); 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]); exec(file, argv+1); } 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 */intGlobsize(char *p){ int 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 32struct{ Dir *dbuf; int i; int n;}dir[NFD];intOpendir(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;}static inttrimdirs(Dir *d, int nd){ int r, w; for(r=w=0; r<nd; r++) if(d[r].mode&DMDIR) d[w++] = d[r]; return w;}/* * onlydirs is advisory -- it means you only * need to return the directories. it's okay to * return files too (e.g., on unix where you can't * tell during the readdir), but that just makes * the globber work harder. */intReaddir(int f, char *p, int onlydirs){ int n; if(f<0 || f>=NFD) return 0;Again: 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){ if(onlydirs){ n = trimdirs(dir[f].dbuf, n); if(n == 0) goto Again; } 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;}voidClosedir(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;voidnotifyf(void*, 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);}voidTrapinit(void){ notify(notifyf);}voidUnlink(char *name){ remove(name);}longWrite(int fd, char *buf, long cnt){ return write(fd, buf, (long)cnt);}longRead(int fd, char *buf, long cnt){ return read(fd, buf, cnt);}longSeek(int fd, long cnt, long whence){ return seek(fd, cnt, whence);}intExecutable(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;}intCreat(char *file){ return create(file, 1, 0666L);}intDup(int a, int b){ return dup(a, b);}intDup1(int){ return -1;}voidExit(char *stat){ Updenv(); setstatus(stat); exits(truestatus()?"":getstatus());}intEintr(void){ return interrupted;}voidNoerror(void){ interrupted = 0;}intIsatty(int fd){ char buf[64]; if(fd2path(fd, buf, sizeof buf) != 0) return 0; /* might be #c/cons during boot - fixed 22 april 2005, remove this later */ if(strcmp(buf, "#c/cons") == 0) return 1; /* might be /mnt/term/dev/cons */ return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0;}voidAbort(void){ pfmt(err, "aborting\n"); flush(err); Exit("aborting");}voidMemcpy(char *a, char *b, long n){ memmove(a, b, (long)n);}void*Malloc(ulong n){ return malloc(n);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -