2 * Plan 9 versions of system-specific functions
3 * By convention, exported routines herein have names beginning with an
12 "sigexit", "sighup", "sigint", "sigquit",
13 "sigalrm", "sigkill", "sigfpe", "sigterm",
17 "exit", /* can't happen */
20 "quit", /* can't happen */
30 return unsharp("#9/rcmain");
33 char Fdprefix[]="/dev/fd/";
41 "exec", execexec, /* but with popword first */
56 register struct word *v;
57 for(t=s;*t && *t!=SEP;t++);
60 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
65 extern char **environ;
67 register char **env=environ;
70 for(s=*env;*s && *s!='(' && *s!='=';s++);
73 // pfmt(err, "rc: odd environment %q?\n", *env);
77 setvar(*env, enval(s+1));
80 case '(': /* ignore functions for now */
92 if(strncmp(s, "fn#", 3) == 0){
99 execcmds(opencore(s, len));
104 for(s=*envp;*s && *s!='(' && *s!='=';s++);
107 pfmt(err, "environment %q?\n", *envp);
109 case '=': /* ignore variables */
111 case '(': /* Bourne again */
116 execcmds(opencore(s, len+1));
125 void execfinit(void){
136 start(rdfns, 1, runq->local);
138 int Waitfor(int pid, int unused0){
143 while((w = wait()) != nil){
149 for(p=runq->ret;p;p=p->ret)
152 strcpy(p->status, w->msg);
157 errstr(errbuf, sizeof errbuf);
158 if(strcmp(errbuf, "interrupted")==0) return -1;
161 char **mkargv(word *a)
163 char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
164 char **argp=argv+1; /* leave one at front for runcoms */
165 for(;a;a=a->next) *argp++=a->word;
178 snprint(envname, sizeof envname, "/env/%s", v->name);
179 if((f=Creat(envname))<0)
180 pfmt(err, "rc: can't open %s: %r\n", envname);
182 for(w=v->val;w;w=w->next)
183 write(f, w->word, strlen(w->word)+1L);
189 snprint(envname, sizeof envname, "/env/fn#%s", v->name);
190 if((f=Creat(envname))<0)
191 pfmt(err, "rc: can't open %s: %r\n", envname);
195 pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
202 void updenvlocal(var *v)
205 updenvlocal(v->next);
211 for(h=gvar;h!=&gvar[NVAR];h++)
212 for(v=*h;v;v=v->next)
214 if(runq) updenvlocal(runq->local);
218 cmpenv(const void *a, const void *b)
220 return strcmp(*(char**)a, *(char**)b);
223 register char **env, **ep, *p, *q;
224 register struct var **h, *v;
225 register struct word *a;
226 register int nvar=0, nchr=0, sep;
228 * Slightly kludgy loops look at locals then globals
230 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
231 if((v==vlook(v->name)) && v->val){
233 nchr+=strlen(v->name)+1;
234 for(a=v->val;a;a=a->next)
235 nchr+=strlen(a->word)+1;
239 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
242 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
244 p=(char *)&env[nvar+1];
245 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
246 if((v==vlook(v->name)) && v->val){
251 for(a=v->val;a;a=a->next){
262 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
263 *p++='f'; *p++='n'; *p++=' ';
268 *p++='f'; *p++='n'; *p++='#';
279 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
283 void Execute(word *args, word *path)
285 char **argv=mkargv(args);
290 for(;path;path=path->next){
291 nc=strlen(path->word);
293 strcpy(file, path->word);
298 if(nc+strlen(argv[1])<1024){
299 strcat(file, argv[1]);
300 execve(file, argv+1, env);
302 else werrstr("command name too long");
305 rerrstr(file, sizeof file);
306 pfmt(err, "%s: %s\n", argv[1], file);
309 #define NDIR 256 /* shoud be a better way */
310 int Globsize(char *p)
312 ulong isglob=0, globlen=NDIR+1;
316 if(*p!=GLOB) isglob++;
317 globlen+=*p=='*'?NDIR:1;
322 return isglob?globlen:0;
331 int Opendir(char *name)
339 if(db!=nil && (db->mode&DMDIR)){
351 int Readdir(int f, char *p)
356 if(dir[f].i==dir[f].n){ /* read */
359 n=dirread(f, &dir[f].dbuf);
366 if(dir[f].i==dir[f].n)
368 strcpy(p, dir[f].dbuf[dir[f].i].name);
372 void Closedir(int f){
383 notifyf(void *unused0, char *s)
386 for(i=0;syssigname[i];i++)
387 if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
388 if(strncmp(s, "sys: ", 5)!=0){
389 if(kidpid && !interrupted){
391 postnote(PNGROUP, kidpid, s);
397 if(strcmp(s, "sys: child") != 0)
398 pfmt(err, "rc: note: %s\n", s);
402 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
406 if(ntrap>=32){ /* rc is probably in a trap loop */
407 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
415 void Unlink(char *name)
419 long Write(int fd, char *buf, long cnt)
421 return write(fd, buf, (long)cnt);
423 long Read(int fd, char *buf, long cnt)
427 i = read(fd, buf, cnt);
431 long Seek(int fd, long cnt, long whence)
433 return seek(fd, cnt, whence);
435 int Executable(char *file)
440 statbuf = dirstat(file);
441 if(statbuf == nil) return 0;
442 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
446 int Creat(char *file)
448 return create(file, 1, 0666L);
450 int Dup(int a, int b){
453 int Dup1(int unused0){
456 void Exit(char *stat)
460 exits(truestatus()?"":getstatus());
473 pfmt(err, "aborting\n");
477 void Memcpy(char *a, char *b, long n)
479 memmove(a, b, (long)n);
481 void *Malloc(ulong n){