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);
43 "exec", execexec, /* but with popword first */
60 register struct word *v;
61 for(t=s;*t && *t!=SEP;t++);
64 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
69 extern char **environ;
71 register char **env=environ;
74 for(s=*env;*s && *s!='(' && *s!='=';s++);
77 // pfmt(err, "rc: odd environment %q?\n", *env);
81 setvar(*env, enval(s+1));
84 case '(': /* ignore functions for now */
96 if(strncmp(s, "fn#", 3) == 0){
103 execcmds(opencore(s, len));
108 for(s=*envp;*s && *s!='(' && *s!='=';s++);
111 pfmt(err, "environment %q?\n", *envp);
113 case '=': /* ignore variables */
115 case '(': /* Bourne again */
120 execcmds(opencore(s, len+1));
129 void execfinit(void){
140 start(rdfns, 1, runq->local);
142 extern int mapfd(int);
143 int Waitfor(int pid, int unused0){
148 while((w = wait()) != nil){
150 if(strncmp(w->msg, "signal: ", 8) == 0)
151 fprint(mapfd(2), "%d: %s\n", w->pid, w->msg);
156 if(strncmp(w->msg, "signal: ", 8) == 0)
157 fprint(2, "%d: %s\n", w->pid, w->msg);
158 for(p=runq->ret;p;p=p->ret)
161 strcpy(p->status, w->msg);
166 errstr(errbuf, sizeof errbuf);
167 if(strcmp(errbuf, "interrupted")==0) return -1;
170 char **mkargv(word *a)
172 char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
173 char **argp=argv+1; /* leave one at front for runcoms */
174 for(;a;a=a->next) *argp++=a->word;
187 snprint(envname, sizeof envname, "/env/%s", v->name);
188 if((f=Creat(envname))<0)
189 pfmt(err, "rc: can't open %s: %r\n", envname);
191 for(w=v->val;w;w=w->next)
192 write(f, w->word, strlen(w->word)+1L);
198 snprint(envname, sizeof envname, "/env/fn#%s", v->name);
199 if((f=Creat(envname))<0)
200 pfmt(err, "rc: can't open %s: %r\n", envname);
204 pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
211 void updenvlocal(var *v)
214 updenvlocal(v->next);
220 for(h=gvar;h!=&gvar[NVAR];h++)
221 for(v=*h;v;v=v->next)
223 if(runq) updenvlocal(runq->local);
227 cmpenv(const void *a, const void *b)
229 return strcmp(*(char**)a, *(char**)b);
232 register char **env, **ep, *p, *q;
233 register struct var **h, *v;
234 register struct word *a;
235 register int nvar=0, nchr=0, sep;
237 * Slightly kludgy loops look at locals then globals
239 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
240 if((v==vlook(v->name)) && v->val){
242 nchr+=strlen(v->name)+1;
243 for(a=v->val;a;a=a->next)
244 nchr+=strlen(a->word)+1;
248 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
251 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
253 p=(char *)&env[nvar+1];
254 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;v=v->next){
255 if((v==vlook(v->name)) && v->val){
260 for(a=v->val;a;a=a->next){
271 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
272 *p++='f'; *p++='n'; *p++=' ';
277 *p++='f'; *p++='n'; *p++='#';
288 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
292 void Execute(word *args, word *path)
294 char **argv=mkargv(args);
299 for(;path;path=path->next){
300 nc=strlen(path->word);
302 strcpy(file, path->word);
307 if(nc+strlen(argv[1])<1024){
308 strcat(file, argv[1]);
309 execve(file, argv+1, env);
311 else werrstr("command name too long");
314 rerrstr(file, sizeof file);
315 pfmt(err, "%s: %s\n", argv[1], file);
318 #define NDIR 256 /* shoud be a better way */
319 int Globsize(char *p)
321 ulong isglob=0, globlen=NDIR+1;
325 if(*p!=GLOB) isglob++;
326 globlen+=*p=='*'?NDIR:1;
331 return isglob?globlen:0;
340 int Opendir(char *name)
348 if(db!=nil && (db->mode&DMDIR)){
360 int Readdir(int f, char *p)
365 if(dir[f].i==dir[f].n){ /* read */
368 n=dirread(f, &dir[f].dbuf);
375 if(dir[f].i==dir[f].n)
377 strcpy(p, dir[f].dbuf[dir[f].i].name);
381 void Closedir(int f){
392 notifyf(void *unused0, char *s)
395 for(i=0;syssigname[i];i++)
396 if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
397 if(strncmp(s, "sys: ", 5)!=0){
398 if(kidpid && !interrupted){
400 postnote(PNGROUP, kidpid, s);
406 if(strcmp(s, "sys: write on closed pipe") != 0)
407 if(strcmp(s, "sys: child") != 0)
408 pfmt(err, "rc: note: %s\n", s);
412 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
416 if(ntrap>=32){ /* rc is probably in a trap loop */
417 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
425 void Unlink(char *name)
429 long Write(int fd, char *buf, long cnt)
431 return write(fd, buf, (long)cnt);
433 long Read(int fd, char *buf, long cnt)
437 i = read(fd, buf, cnt);
441 long Seek(int fd, long cnt, long whence)
443 return seek(fd, cnt, whence);
445 int Executable(char *file)
450 statbuf = dirstat(file);
451 if(statbuf == nil) return 0;
452 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
456 int Creat(char *file)
458 return create(file, 1, 0666L);
460 int Dup(int a, int b){
466 void Exit(char *stat)
470 exits(truestatus()?"":getstatus());
483 pfmt(err, "aborting\n");
487 void Memcpy(char *a, char *b, long n)
489 memmove(a, b, (long)n);
491 void *Malloc(ulong n){