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/";
37 void execulimit(void);
44 "exec", execexec, /* but with popword first */
63 switch(count(runq->argv->words)){
65 arg = RFENVG|RFNOTEG|RFNAMEG;
69 for(s = runq->argv->words->next->word;*s;s++) switch(*s){
78 /* arg|=RFENVG; */ break;
91 pfmt(err, "Usage: %s [nNeEsfF]\n", runq->argv->words->word);
92 setstatus("rfork usage");
97 pfmt(err, "rc: %s failed\n", runq->argv->words->word);
98 setstatus("rfork failed");
109 struct word *enval(s)
113 register struct word *v;
114 for(t=s;*t && *t!=SEP;t++);
117 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
122 extern char **environ;
124 register char **env=environ;
127 for(s=*env;*s && *s!='(' && *s!='=';s++);
130 /* pfmt(err, "rc: odd environment %q?\n", *env); */
134 setvar(*env, enval(s+1));
137 case '(': /* ignore functions for now */
149 if(strncmp(s, "fn#", 3) == 0){
156 execcmds(opencore(s, len));
161 for(s=*envp;*s && *s!='(' && *s!='=';s++);
164 pfmt(err, "environment %q?\n", *envp);
166 case '=': /* ignore variables */
168 case '(': /* Bourne again */
173 execcmds(opencore(s, len+1));
182 void execfinit(void){
193 start(rdfns, 1, runq->local);
195 extern int mapfd(int);
196 int Waitfor(int pid, int unused0){
201 while((w = wait()) != nil){
203 if(strncmp(w->msg, "signal: ", 8) == 0)
204 fprint(mapfd(2), "%d: %s\n", w->pid, w->msg);
209 if(runq->iflag && strncmp(w->msg, "signal: ", 8) == 0)
210 fprint(2, "%d: %s\n", w->pid, w->msg);
211 for(p=runq->ret;p;p=p->ret)
214 strcpy(p->status, w->msg);
219 errstr(errbuf, sizeof errbuf);
220 if(strcmp(errbuf, "interrupted")==0) return -1;
223 char **mkargv(word *a)
225 char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
226 char **argp=argv+1; /* leave one at front for runcoms */
227 for(;a;a=a->next) *argp++=a->word;
240 snprint(envname, sizeof envname, "/env/%s", v->name);
241 if((f=Creat(envname))<0)
242 pfmt(err, "rc: can't open %s: %r\n", envname);
244 for(w=v->val;w;w=w->next)
245 write(f, w->word, strlen(w->word)+1L);
251 snprint(envname, sizeof envname, "/env/fn#%s", v->name);
252 if((f=Creat(envname))<0)
253 pfmt(err, "rc: can't open %s: %r\n", envname);
257 pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
264 void updenvlocal(var *v)
267 updenvlocal(v->next);
273 for(h=gvar;h!=&gvar[NVAR];h++)
274 for(v=*h;v;v=v->next)
276 if(runq) updenvlocal(runq->local);
280 cmpenv(const void *a, const void *b)
282 return strcmp(*(char**)a, *(char**)b);
285 register char **env, **ep, *p, *q;
286 register struct var **h, *v;
287 register struct word *a;
288 register int nvar=0, nchr=0, sep;
290 * Slightly kludgy loops look at locals then globals
292 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
293 if((v==vlook(v->name)) && v->val){
295 nchr+=strlen(v->name)+1;
296 for(a=v->val;a;a=a->next)
297 nchr+=strlen(a->word)+1;
301 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
304 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
306 p=(char *)&env[nvar+1];
307 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
308 if((v==vlook(v->name)) && v->val){
313 for(a=v->val;a;a=a->next){
324 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
325 *p++='f'; *p++='n'; *p++=' ';
330 *p++='f'; *p++='n'; *p++='#';
341 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
345 void Execute(word *args, word *path)
347 char **argv=mkargv(args);
352 for(;path;path=path->next){
353 nc=strlen(path->word);
355 strcpy(file, path->word);
360 if(nc+strlen(argv[1])<1024){
361 strcat(file, argv[1]);
362 execve(file, argv+1, env);
364 else werrstr("command name too long");
367 rerrstr(file, sizeof file);
368 pfmt(err, "%s: %s\n", argv[1], file);
371 #define NDIR 256 /* shoud be a better way */
372 int Globsize(char *p)
374 ulong isglob=0, globlen=NDIR+1;
378 if(*p!=GLOB) isglob++;
379 globlen+=*p=='*'?NDIR:1;
384 return isglob?globlen:0;
393 int Opendir(char *name)
401 if(db!=nil && (db->mode&DMDIR)){
413 int Readdir(int f, char *p)
418 if(dir[f].i==dir[f].n){ /* read */
421 n=dirread(f, &dir[f].dbuf);
428 if(dir[f].i==dir[f].n)
430 strcpy(p, dir[f].dbuf[dir[f].i].name);
434 void Closedir(int f){
445 notifyf(void *unused0, char *s)
448 for(i=0;syssigname[i];i++)
449 if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
450 if(strncmp(s, "sys: ", 5)!=0){
451 if(kidpid && !interrupted){
453 postnote(PNGROUP, kidpid, s);
459 if(strcmp(s, "sys: window size change") != 0)
460 if(strcmp(s, "sys: write on closed pipe") != 0)
461 if(strcmp(s, "sys: child") != 0)
462 pfmt(err, "rc: note: %s\n", s);
466 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
470 if(ntrap>=32){ /* rc is probably in a trap loop */
471 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
479 void Unlink(char *name)
483 long Write(int fd, char *buf, long cnt)
485 return write(fd, buf, (long)cnt);
487 long Read(int fd, char *buf, long cnt)
491 i = read(fd, buf, cnt);
495 long Seek(int fd, long cnt, long whence)
497 return seek(fd, cnt, whence);
499 int Executable(char *file)
504 statbuf = dirstat(file);
505 if(statbuf == nil) return 0;
506 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
510 int Creat(char *file)
512 return create(file, 1, 0666L);
514 int Dup(int a, int b){
520 void Exit(char *stat)
524 exits(truestatus()?"":getstatus());
537 pfmt(err, "aborting\n");
541 void Memcpy(char *a, char *b, long n)
543 memmove(a, b, (long)n);
545 void *Malloc(ulong n){