Blob


1 /*
2 * Plan 9 versions of system-specific functions
3 * By convention, exported routines herein have names beginning with an
4 * upper case letter.
5 */
6 #include "rc.h"
7 #include "exec.h"
8 #include "io.h"
9 #include "fns.h"
10 #include "getflags.h"
11 char *Signame[]={
12 "sigexit", "sighup", "sigint", "sigquit",
13 "sigalrm", "sigkill", "sigfpe", "sigterm",
14 0
15 };
16 char *syssigname[]={
17 "exit", /* can't happen */
18 "hangup",
19 "interrupt",
20 "quit", /* can't happen */
21 "alarm",
22 "kill",
23 "sys: fp: ",
24 "term",
25 0
26 };
27 char*
28 Rcmain(void)
29 {
30 return unsharp("#9/rcmain");
31 }
33 char Fdprefix[]="/dev/fd/";
34 void execfinit(void);
35 void execbind(void);
36 void execmount(void);
37 builtin Builtin[]={
38 "cd", execcd,
39 "whatis", execwhatis,
40 "eval", execeval,
41 "exec", execexec, /* but with popword first */
42 "exit", execexit,
43 "shift", execshift,
44 "wait", execwait,
45 ".", execdot,
46 "finit", execfinit,
47 "flag", execflag,
48 0
49 };
50 #define SEP '\1'
51 char **environp;
52 struct word *enval(s)
53 register char *s;
54 {
55 register char *t, c;
56 register struct word *v;
57 for(t=s;*t && *t!=SEP;t++);
58 c=*t;
59 *t='\0';
60 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
61 *t=c;
62 return v;
63 }
64 void Vinit(void){
65 extern char **environ;
66 register char *s;
67 register char **env=environ;
68 environp=env;
69 for(;*env;env++){
70 for(s=*env;*s && *s!='(' && *s!='=';s++);
71 switch(*s){
72 case '\0':
73 // pfmt(err, "rc: odd environment %q?\n", *env);
74 break;
75 case '=':
76 *s='\0';
77 setvar(*env, enval(s+1));
78 *s='=';
79 break;
80 case '(': /* ignore functions for now */
81 break;
82 }
83 }
84 }
85 char **envp;
86 void Xrdfn(void){
87 char *p;
88 register char *s;
89 register int len;
90 for(;*envp;envp++){
91 s = *envp;
92 if(strncmp(s, "fn#", 3) == 0){
93 p = strchr(s, '=');
94 if(p == nil)
95 continue;
96 *p = ' ';
97 s[2] = ' ';
98 len = strlen(s);
99 execcmds(opencore(s, len));
100 s[len] = '\0';
101 return;
103 #if 0
104 for(s=*envp;*s && *s!='(' && *s!='=';s++);
105 switch(*s){
106 case '\0':
107 pfmt(err, "environment %q?\n", *envp);
108 break;
109 case '=': /* ignore variables */
110 break;
111 case '(': /* Bourne again */
112 s=*envp+3;
113 envp++;
114 len=strlen(s);
115 s[len]='\n';
116 execcmds(opencore(s, len+1));
117 s[len]='\0';
118 return;
120 #endif
122 Xreturn();
124 union code rdfns[4];
125 void execfinit(void){
126 static int first=1;
127 if(first){
128 rdfns[0].i=1;
129 rdfns[1].f=Xrdfn;
130 rdfns[2].f=Xjump;
131 rdfns[3].i=1;
132 first=0;
134 Xpopm();
135 envp=environp;
136 start(rdfns, 1, runq->local);
138 int Waitfor(int pid, int unused0){
139 thread *p;
140 Waitmsg *w;
141 char errbuf[ERRMAX];
143 while((w = wait()) != nil){
144 if(w->pid==pid){
145 setstatus(w->msg);
146 free(w);
147 return 0;
149 for(p=runq->ret;p;p=p->ret)
150 if(p->pid==w->pid){
151 p->pid=-1;
152 strcpy(p->status, w->msg);
154 free(w);
157 errstr(errbuf, sizeof errbuf);
158 if(strcmp(errbuf, "interrupted")==0) return -1;
159 return 0;
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;
166 *argp=0;
167 return argv;
169 /*
170 void addenv(var *v)
172 char envname[256];
173 word *w;
174 int f;
175 io *fd;
176 if(v->changed){
177 v->changed=0;
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);
181 else{
182 for(w=v->val;w;w=w->next)
183 write(f, w->word, strlen(w->word)+1L);
184 close(f);
187 if(v->fnchanged){
188 v->fnchanged=0;
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);
192 else{
193 if(v->fn){
194 fd=openfd(f);
195 pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
196 closeio(fd);
198 close(f);
202 void updenvlocal(var *v)
204 if(v){
205 updenvlocal(v->next);
206 addenv(v);
209 void Updenv(void){
210 var *v, **h;
211 for(h=gvar;h!=&gvar[NVAR];h++)
212 for(v=*h;v;v=v->next)
213 addenv(v);
214 if(runq) updenvlocal(runq->local);
216 */
217 int
218 cmpenv(const void *a, const void *b)
220 return strcmp(*(char**)a, *(char**)b);
222 char **mkenv(){
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;
227 /*
228 * Slightly kludgy loops look at locals then globals
229 */
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){
232 nvar++;
233 nchr+=strlen(v->name)+1;
234 for(a=v->val;a;a=a->next)
235 nchr+=strlen(a->word)+1;
237 if(v->fn){
238 nvar++;
239 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
242 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
243 ep=env;
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){
247 *ep++=p;
248 q=v->name;
249 while(*q) *p++=*q++;
250 sep='=';
251 for(a=v->val;a;a=a->next){
252 *p++=sep;
253 sep=SEP;
254 q=a->word;
255 while(*q) *p++=*q++;
257 *p++='\0';
259 if(v->fn){
260 *ep++=p;
261 #if 0
262 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
263 *p++='f'; *p++='n'; *p++=' ';
264 q=v->name;
265 while(*q) *p++=*q++;
266 *p++=' ';
267 #endif
268 *p++='f'; *p++='n'; *p++='#';
269 q=v->name;
270 while(*q) *p++=*q++;
271 *p++='=';
272 q=v->fn[v->pc-1].s;
273 while(*q) *p++=*q++;
274 *p++='\n';
275 *p++='\0';
278 *ep=0;
279 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
280 return env;
282 void Updenv(void){}
283 void Execute(word *args, word *path)
285 char **argv=mkargv(args);
286 char **env=mkenv();
287 char file[1024];
288 int nc;
289 Updenv();
290 for(;path;path=path->next){
291 nc=strlen(path->word);
292 if(nc<1024){
293 strcpy(file, path->word);
294 if(file[0]){
295 strcat(file, "/");
296 nc++;
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);
307 efree((char *)argv);
309 #define NDIR 256 /* shoud be a better way */
310 int Globsize(char *p)
312 ulong isglob=0, globlen=NDIR+1;
313 for(;*p;p++){
314 if(*p==GLOB){
315 p++;
316 if(*p!=GLOB) isglob++;
317 globlen+=*p=='*'?NDIR:1;
319 else
320 globlen++;
322 return isglob?globlen:0;
324 #define NFD 50
325 #define NDBUF 32
326 struct{
327 Dir *dbuf;
328 int i;
329 int n;
330 }dir[NFD];
331 int Opendir(char *name)
333 Dir *db;
334 int f;
335 f=open(name, 0);
336 if(f==-1)
337 return f;
338 db = dirfstat(f);
339 if(db!=nil && (db->mode&DMDIR)){
340 if(f<NFD){
341 dir[f].i=0;
342 dir[f].n=0;
344 free(db);
345 return f;
347 free(db);
348 close(f);
349 return -1;
351 int Readdir(int f, char *p)
353 int n;
354 if(f<0 || f>=NFD)
355 return 0;
356 if(dir[f].i==dir[f].n){ /* read */
357 free(dir[f].dbuf);
358 dir[f].dbuf=0;
359 n=dirread(f, &dir[f].dbuf);
360 if(n>=0)
361 dir[f].n=n;
362 else
363 dir[f].n=0;
364 dir[f].i=0;
366 if(dir[f].i==dir[f].n)
367 return 0;
368 strcpy(p, dir[f].dbuf[dir[f].i].name);
369 dir[f].i++;
370 return 1;
372 void Closedir(int f){
373 if(f>=0 && f<NFD){
374 free(dir[f].dbuf);
375 dir[f].i=0;
376 dir[f].n=0;
377 dir[f].dbuf=0;
379 close(f);
381 int interrupted = 0;
382 void
383 notifyf(void *unused0, char *s)
385 int i;
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){
390 interrupted=1;
391 postnote(PNGROUP, kidpid, s);
393 interrupted = 1;
395 goto Out;
397 if(strcmp(s, "sys: child") != 0)
398 pfmt(err, "rc: note: %s\n", s);
399 noted(NDFLT);
400 return;
401 Out:
402 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
403 trap[i]++;
404 ntrap++;
406 if(ntrap>=32){ /* rc is probably in a trap loop */
407 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
408 abort();
410 noted(NCONT);
412 void Trapinit(void){
413 notify(notifyf);
415 void Unlink(char *name)
417 remove(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)
425 int i;
427 i = read(fd, buf, cnt);
428 if(ntrap) dotrap();
429 return i;
431 long Seek(int fd, long cnt, long whence)
433 return seek(fd, cnt, whence);
435 int Executable(char *file)
437 Dir *statbuf;
438 int ret;
440 statbuf = dirstat(file);
441 if(statbuf == nil) return 0;
442 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
443 free(statbuf);
444 return ret;
446 int Creat(char *file)
448 return create(file, 1, 0666L);
450 int Dup(int a, int b){
451 return dup(a, b);
453 int Dup1(int unused0){
454 return -1;
456 void Exit(char *stat)
458 Updenv();
459 setstatus(stat);
460 exits(truestatus()?"":getstatus());
462 int Eintr(void){
463 return interrupted;
465 void Noerror(void){
466 interrupted=0;
468 int
469 Isatty(int fd){
470 return isatty(fd);
472 void Abort(void){
473 pfmt(err, "aborting\n");
474 flush(err);
475 Exit("aborting");
477 void Memcpy(char *a, char *b, long n)
479 memmove(a, b, (long)n);
481 void *Malloc(ulong n){
482 return malloc(n);