blob: 632e753f91ef032096ec0ddf07fa0d6940997826 [file] [log] [blame]
rscf08fded2003-11-23 18:04:08 +00001/*
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"
11char *Signame[]={
12 "sigexit", "sighup", "sigint", "sigquit",
13 "sigalrm", "sigkill", "sigfpe", "sigterm",
14 0
15};
16char *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};
27char*
28Rcmain(void)
29{
rsc8ad51792004-03-25 23:03:57 +000030 return unsharp("#9/rcmain");
rscf08fded2003-11-23 18:04:08 +000031}
32
rsc8ad51792004-03-25 23:03:57 +000033char Fdprefix[]="/dev/fd/";
rscf08fded2003-11-23 18:04:08 +000034void execfinit(void);
35void execbind(void);
36void execmount(void);
rsc39cff6e2004-10-17 05:19:53 +000037void execulimit(void);
38void execumask(void);
rscf08fded2003-11-23 18:04:08 +000039builtin Builtin[]={
40 "cd", execcd,
41 "whatis", execwhatis,
42 "eval", execeval,
43 "exec", execexec, /* but with popword first */
44 "exit", execexit,
45 "shift", execshift,
46 "wait", execwait,
47 ".", execdot,
48 "finit", execfinit,
49 "flag", execflag,
rsc39cff6e2004-10-17 05:19:53 +000050 "ulimit", execulimit,
51 "umask", execumask,
rscf08fded2003-11-23 18:04:08 +000052 0
53};
54#define SEP '\1'
55char **environp;
56struct word *enval(s)
57register char *s;
58{
59 register char *t, c;
60 register struct word *v;
61 for(t=s;*t && *t!=SEP;t++);
62 c=*t;
63 *t='\0';
64 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
65 *t=c;
66 return v;
67}
68void Vinit(void){
69 extern char **environ;
70 register char *s;
71 register char **env=environ;
72 environp=env;
73 for(;*env;env++){
74 for(s=*env;*s && *s!='(' && *s!='=';s++);
75 switch(*s){
76 case '\0':
rscc4097c22004-05-11 17:51:27 +000077 // pfmt(err, "rc: odd environment %q?\n", *env);
rscf08fded2003-11-23 18:04:08 +000078 break;
79 case '=':
80 *s='\0';
81 setvar(*env, enval(s+1));
82 *s='=';
83 break;
84 case '(': /* ignore functions for now */
85 break;
86 }
87 }
88}
89char **envp;
90void Xrdfn(void){
91 char *p;
92 register char *s;
93 register int len;
94 for(;*envp;envp++){
95 s = *envp;
96 if(strncmp(s, "fn#", 3) == 0){
97 p = strchr(s, '=');
98 if(p == nil)
99 continue;
100 *p = ' ';
101 s[2] = ' ';
102 len = strlen(s);
103 execcmds(opencore(s, len));
104 s[len] = '\0';
105 return;
106 }
107#if 0
108 for(s=*envp;*s && *s!='(' && *s!='=';s++);
109 switch(*s){
110 case '\0':
111 pfmt(err, "environment %q?\n", *envp);
112 break;
113 case '=': /* ignore variables */
114 break;
115 case '(': /* Bourne again */
116 s=*envp+3;
117 envp++;
118 len=strlen(s);
119 s[len]='\n';
120 execcmds(opencore(s, len+1));
121 s[len]='\0';
122 return;
123 }
124#endif
125 }
126 Xreturn();
127}
128union code rdfns[4];
129void execfinit(void){
130 static int first=1;
131 if(first){
132 rdfns[0].i=1;
133 rdfns[1].f=Xrdfn;
134 rdfns[2].f=Xjump;
135 rdfns[3].i=1;
136 first=0;
137 }
138 Xpopm();
139 envp=environp;
140 start(rdfns, 1, runq->local);
141}
rscf002cc12004-10-17 05:29:53 +0000142extern int mapfd(int);
rscf08fded2003-11-23 18:04:08 +0000143int Waitfor(int pid, int unused0){
144 thread *p;
145 Waitmsg *w;
146 char errbuf[ERRMAX];
147
148 while((w = wait()) != nil){
149 if(w->pid==pid){
rscf002cc12004-10-17 05:29:53 +0000150 if(strncmp(w->msg, "signal: ", 8) == 0)
151 fprint(mapfd(2), "%d: %s\n", w->pid, w->msg);
rscf08fded2003-11-23 18:04:08 +0000152 setstatus(w->msg);
153 free(w);
154 return 0;
155 }
rscf002cc12004-10-17 05:29:53 +0000156 if(strncmp(w->msg, "signal: ", 8) == 0)
157 fprint(2, "%d: %s\n", w->pid, w->msg);
rscf08fded2003-11-23 18:04:08 +0000158 for(p=runq->ret;p;p=p->ret)
159 if(p->pid==w->pid){
160 p->pid=-1;
161 strcpy(p->status, w->msg);
162 }
163 free(w);
164 }
165
166 errstr(errbuf, sizeof errbuf);
167 if(strcmp(errbuf, "interrupted")==0) return -1;
168 return 0;
169}
170char **mkargv(word *a)
171{
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;
175 *argp=0;
176 return argv;
177}
178/*
179void addenv(var *v)
180{
181 char envname[256];
182 word *w;
183 int f;
184 io *fd;
185 if(v->changed){
186 v->changed=0;
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);
190 else{
191 for(w=v->val;w;w=w->next)
192 write(f, w->word, strlen(w->word)+1L);
193 close(f);
194 }
195 }
196 if(v->fnchanged){
197 v->fnchanged=0;
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);
201 else{
202 if(v->fn){
203 fd=openfd(f);
204 pfmt(fd, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
205 closeio(fd);
206 }
207 close(f);
208 }
209 }
210}
211void updenvlocal(var *v)
212{
213 if(v){
214 updenvlocal(v->next);
215 addenv(v);
216 }
217}
218void Updenv(void){
219 var *v, **h;
220 for(h=gvar;h!=&gvar[NVAR];h++)
221 for(v=*h;v;v=v->next)
222 addenv(v);
223 if(runq) updenvlocal(runq->local);
224}
225*/
226int
rscbe22ae22004-03-26 01:59:35 +0000227cmpenv(const void *a, const void *b)
rscf08fded2003-11-23 18:04:08 +0000228{
rscbe22ae22004-03-26 01:59:35 +0000229 return strcmp(*(char**)a, *(char**)b);
rscf08fded2003-11-23 18:04:08 +0000230}
231char **mkenv(){
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;
236 /*
237 * Slightly kludgy loops look at locals then globals
238 */
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){
241 nvar++;
242 nchr+=strlen(v->name)+1;
243 for(a=v->val;a;a=a->next)
244 nchr+=strlen(a->word)+1;
245 }
246 if(v->fn){
247 nvar++;
248 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
249 }
250 }
251 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
252 ep=env;
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){
256 *ep++=p;
257 q=v->name;
258 while(*q) *p++=*q++;
259 sep='=';
260 for(a=v->val;a;a=a->next){
261 *p++=sep;
262 sep=SEP;
263 q=a->word;
264 while(*q) *p++=*q++;
265 }
266 *p++='\0';
267 }
268 if(v->fn){
269 *ep++=p;
270#if 0
271 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
272 *p++='f'; *p++='n'; *p++=' ';
273 q=v->name;
274 while(*q) *p++=*q++;
275 *p++=' ';
276#endif
277 *p++='f'; *p++='n'; *p++='#';
278 q=v->name;
279 while(*q) *p++=*q++;
280 *p++='=';
281 q=v->fn[v->pc-1].s;
282 while(*q) *p++=*q++;
283 *p++='\n';
284 *p++='\0';
285 }
286 }
287 *ep=0;
288 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
289 return env;
290}
291void Updenv(void){}
292void Execute(word *args, word *path)
293{
294 char **argv=mkargv(args);
295 char **env=mkenv();
296 char file[1024];
297 int nc;
298 Updenv();
299 for(;path;path=path->next){
300 nc=strlen(path->word);
301 if(nc<1024){
302 strcpy(file, path->word);
303 if(file[0]){
304 strcat(file, "/");
305 nc++;
306 }
307 if(nc+strlen(argv[1])<1024){
308 strcat(file, argv[1]);
309 execve(file, argv+1, env);
310 }
311 else werrstr("command name too long");
312 }
313 }
314 rerrstr(file, sizeof file);
315 pfmt(err, "%s: %s\n", argv[1], file);
316 efree((char *)argv);
317}
318#define NDIR 256 /* shoud be a better way */
319int Globsize(char *p)
320{
321 ulong isglob=0, globlen=NDIR+1;
322 for(;*p;p++){
323 if(*p==GLOB){
324 p++;
325 if(*p!=GLOB) isglob++;
326 globlen+=*p=='*'?NDIR:1;
327 }
328 else
329 globlen++;
330 }
331 return isglob?globlen:0;
332}
333#define NFD 50
334#define NDBUF 32
335struct{
336 Dir *dbuf;
337 int i;
338 int n;
339}dir[NFD];
340int Opendir(char *name)
341{
342 Dir *db;
343 int f;
344 f=open(name, 0);
345 if(f==-1)
346 return f;
347 db = dirfstat(f);
348 if(db!=nil && (db->mode&DMDIR)){
349 if(f<NFD){
350 dir[f].i=0;
351 dir[f].n=0;
352 }
353 free(db);
354 return f;
355 }
356 free(db);
357 close(f);
358 return -1;
359}
360int Readdir(int f, char *p)
361{
362 int n;
363 if(f<0 || f>=NFD)
364 return 0;
365 if(dir[f].i==dir[f].n){ /* read */
366 free(dir[f].dbuf);
367 dir[f].dbuf=0;
368 n=dirread(f, &dir[f].dbuf);
369 if(n>=0)
370 dir[f].n=n;
371 else
372 dir[f].n=0;
373 dir[f].i=0;
374 }
375 if(dir[f].i==dir[f].n)
376 return 0;
377 strcpy(p, dir[f].dbuf[dir[f].i].name);
378 dir[f].i++;
379 return 1;
380}
381void Closedir(int f){
382 if(f>=0 && f<NFD){
383 free(dir[f].dbuf);
384 dir[f].i=0;
385 dir[f].n=0;
386 dir[f].dbuf=0;
387 }
388 close(f);
389}
390int interrupted = 0;
391void
392notifyf(void *unused0, char *s)
393{
394 int i;
rsc669250d2003-12-03 22:50:48 +0000395 for(i=0;syssigname[i];i++)
396 if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
rsc69ab5d32004-03-26 17:30:36 +0000397 if(strncmp(s, "sys: ", 5)!=0){
398 if(kidpid && !interrupted){
399 interrupted=1;
400 postnote(PNGROUP, kidpid, s);
401 }
402 interrupted = 1;
403 }
rsc669250d2003-12-03 22:50:48 +0000404 goto Out;
405 }
rscc6f92062005-07-14 12:48:02 +0000406 if(strcmp(s, "sys: window size change") != 0)
rsc4ee543e2005-03-18 19:03:25 +0000407 if(strcmp(s, "sys: write on closed pipe") != 0)
rsc0b917992004-03-04 02:36:36 +0000408 if(strcmp(s, "sys: child") != 0)
409 pfmt(err, "rc: note: %s\n", s);
rscf08fded2003-11-23 18:04:08 +0000410 noted(NDFLT);
411 return;
412Out:
413 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
414 trap[i]++;
415 ntrap++;
416 }
417 if(ntrap>=32){ /* rc is probably in a trap loop */
418 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
419 abort();
420 }
421 noted(NCONT);
422}
423void Trapinit(void){
424 notify(notifyf);
425}
426void Unlink(char *name)
427{
428 remove(name);
429}
430long Write(int fd, char *buf, long cnt)
431{
432 return write(fd, buf, (long)cnt);
433}
434long Read(int fd, char *buf, long cnt)
435{
rsc669250d2003-12-03 22:50:48 +0000436 int i;
437
438 i = read(fd, buf, cnt);
439 if(ntrap) dotrap();
440 return i;
rscf08fded2003-11-23 18:04:08 +0000441}
442long Seek(int fd, long cnt, long whence)
443{
444 return seek(fd, cnt, whence);
445}
446int Executable(char *file)
447{
448 Dir *statbuf;
449 int ret;
450
451 statbuf = dirstat(file);
452 if(statbuf == nil) return 0;
453 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
454 free(statbuf);
455 return ret;
456}
457int Creat(char *file)
458{
459 return create(file, 1, 0666L);
460}
461int Dup(int a, int b){
462 return dup(a, b);
463}
rsc134c20c2005-02-13 21:38:32 +0000464int Dup1(int a){
465 return dup(a, -1);
rscf08fded2003-11-23 18:04:08 +0000466}
467void Exit(char *stat)
468{
469 Updenv();
470 setstatus(stat);
471 exits(truestatus()?"":getstatus());
472}
473int Eintr(void){
474 return interrupted;
475}
476void Noerror(void){
477 interrupted=0;
478}
479int
rscbe22ae22004-03-26 01:59:35 +0000480Isatty(int fd){
rscf08fded2003-11-23 18:04:08 +0000481 return isatty(fd);
482}
483void Abort(void){
484 pfmt(err, "aborting\n");
485 flush(err);
486 Exit("aborting");
487}
488void Memcpy(char *a, char *b, long n)
489{
490 memmove(a, b, (long)n);
491}
492void *Malloc(ulong n){
493 return malloc(n);
494}