]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/rc/win32.c
rc: change plan9 envname limit to 128, cleanup
[plan9front.git] / sys / src / cmd / rc / win32.c
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 Rcmain[]="/rc/lib/rcmain";
28 char Fdprefix[]="/fd/";
29 void execfinit(void);
30 void execbind(void);
31
32 builtin Builtin[] = {
33         "cd",           execcd,
34         "whatis",       execwhatis,
35         "eval",         execeval,
36         "exec",         execexec,       /* but with popword first */
37         "exit",         execexit,
38         "shift",        execshift,
39         "wait",         execwait,
40         ".",            execdot,
41         "finit",        execfinit,
42         "flag",         execflag,
43         0
44 };
45
46 void
47 Vinit(void)
48 {
49         int dir, f, len;
50         word *val;
51         char *buf, *s;
52         Dir *ent;
53         int i, nent;
54         char envname[256];
55         dir = open("/env", OREAD);
56         if(dir<0){
57                 pfmt(err, "rc: can't open /env: %r\n");
58                 return;
59         }
60         ent = nil;
61         for(;;){
62                 nent = dirread(dir, &ent);
63                 if(nent <= 0)
64                         break;
65                 for(i = 0; i<nent; i++){
66                         len = ent[i].length;
67                         if(len && strncmp(ent[i].name, "fn#", 3)!=0){
68                                 snprint(envname, sizeof envname, "/env/%s", ent[i].name);
69                                 if((f = open(envname, 0))>=0){
70                                         buf = emalloc((int)len+1);
71                                         read(f, buf, (long)len);
72                                         val = 0;
73                                         /* Charitably add a 0 at the end if need be */
74                                         if(buf[len-1])
75                                                 buf[len++]='\0';
76                                         s = buf+len-1;
77                                         for(;;){
78                                                 while(s!=buf && s[-1]!='\0') --s;
79                                                 val = newword(s, val);
80                                                 if(s==buf)
81                                                         break;
82                                                 --s;
83                                         }
84                                         setvar(ent[i].name, val);
85                                         vlook(ent[i].name)->changed = 0;
86                                         close(f);
87                                         efree(buf);
88                                 }
89                         }
90                 }
91                 free(ent);
92         }
93         close(dir);
94 }
95 int envdir;
96
97 void
98 Xrdfn(void)
99 {
100         int f, len;
101         static Dir *ent, *allocent;
102         static int nent;
103         Dir *e;
104         char envname[256];
105
106         for(;;){
107                 if(nent == 0){
108                         free(allocent);
109                         nent = dirread(envdir, &allocent);
110                         ent = allocent;
111                 }
112                 if(nent <= 0)
113                         break;
114                 while(nent){
115                         e = ent++;
116                         nent--;
117                         len = e->length;
118                         if(len && strncmp(e->name, "fn#", 3)==0){
119                                 snprint(envname, sizeof envname, "/env/%s", e->name);
120                                 if((f = open(envname, 0))>=0){
121                                         execcmds(openfd(f));
122                                         return;
123                                 }
124                         }
125                 }
126         }
127         close(envdir);
128         Xreturn();
129 }
130 union code rdfns[4];
131
132 void
133 execfinit(void)
134 {
135         static int first = 1;
136         if(first){
137                 rdfns[0].i = 1;
138                 rdfns[1].f = Xrdfn;
139                 rdfns[2].f = Xjump;
140                 rdfns[3].i = 1;
141                 first = 0;
142         }
143         Xpopm();
144         envdir = open("/env", 0);
145         if(envdir<0){
146                 pfmt(err, "rc: can't open /env: %r\n");
147                 return;
148         }
149         start(rdfns, 1, runq->local);
150 }
151
152 int
153 Waitfor(int pid, int persist)
154 {
155         thread *p;
156         Waitmsg *w;
157         char errbuf[ERRMAX];
158
159         while((w = wait()) != nil){
160                 if(w->pid==pid){
161                         setstatus(w->msg);
162                         free(w);
163                         return 0;
164                 }
165                 for(p = runq->ret;p;p = p->ret)
166                         if(p->pid==w->pid){
167                                 p->pid=-1;
168                                 strcpy(p->status, w->msg);
169                         }
170                 free(w);
171         }
172
173         errstr(errbuf, sizeof errbuf);
174         if(strcmp(errbuf, "interrupted")==0) return -1;
175         return 0;
176 }
177
178 char*
179 *mkargv(word *a)
180 {
181         char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
182         char **argp = argv+1;   /* leave one at front for runcoms */
183         for(;a;a = a->next) *argp++=a->word;
184         *argp = 0;
185         return argv;
186 }
187
188 void
189 addenv(var *v)
190 {
191         char envname[256];
192         word *w;
193         int f;
194         io *fd;
195         if(v->changed){
196                 v->changed = 0;
197                 snprint(envname, sizeof envname, "/env/%s", v->name);
198                 if((f = Creat(envname))<0)
199                         pfmt(err, "rc: can't open %s: %r\n", envname);
200                 else{
201                         for(w = v->val;w;w = w->next)
202                                 write(f, w->word, strlen(w->word)+1L);
203                         close(f);
204                 }
205         }
206         if(v->fnchanged){
207                 v->fnchanged = 0;
208                 snprint(envname, sizeof envname, "/env/fn#%s", v->name);
209                 if((f = Creat(envname))<0)
210                         pfmt(err, "rc: can't open %s: %r\n", envname);
211                 else{
212                         if(v->fn){
213                                 fd = openfd(f);
214                                 pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
215                                 closeio(fd);
216                         }
217                         close(f);
218                 }
219         }
220 }
221
222 void
223 updenvlocal(var *v)
224 {
225         if(v){
226                 updenvlocal(v->next);
227                 addenv(v);
228         }
229 }
230
231 void
232 Updenv(void)
233 {
234         var *v, **h;
235         for(h = gvar;h!=&gvar[NVAR];h++)
236                 for(v=*h;v;v = v->next)
237                         addenv(v);
238         if(runq)
239                 updenvlocal(runq->local);
240 }
241
242 int
243 ForkExecute(char *file, char **argv, int sin, int sout, int serr)
244 {
245         int pid;
246
247 {int i;
248 fprint(2, "forkexec %s", file);
249 for(i = 0; argv[i]; i++)fprint(2, " %s", argv[i]);
250 fprint(2, " %d %d %d\n", sin, sout, serr);
251 }
252         if(access(file, 1) != 0)
253                 return -1;
254 fprint(2, "forking\n");
255         switch(pid = fork()){
256         case -1:
257                 return -1;
258         case 0:
259                 if(sin >= 0)
260                         dup(sin, 0);
261                 else
262                         close(0);
263                 if(sout >= 0)
264                         dup(sout, 1);
265                 else
266                         close(1);
267                 if(serr >= 0)
268                         dup(serr, 2);
269                 else
270                         close(2);
271 fprint(2, "execing\n");
272                 exec(file, argv);
273 fprint(2, "exec: %r\n");
274                 exits(file);
275         }
276         return pid;
277 }
278
279 void
280 Execute(word *args, word *path)
281 {
282         char **argv = mkargv(args);
283         char file[1024];
284         int nc;
285         Updenv();
286         for(;path;path = path->next){
287                 nc = strlen(path->word);
288                 if(nc<1024){
289                         strcpy(file, path->word);
290                         if(file[0]){
291                                 strcat(file, "/");
292                                 nc++;
293                         }
294                         if(nc+strlen(argv[1])<1024){
295                                 strcat(file, argv[1]);
296                                 exec(file, argv+1);
297                         }
298                         else werrstr("command name too long");
299                 }
300         }
301         rerrstr(file, sizeof file);
302         pfmt(err, "%s: %s\n", argv[1], file);
303         efree((char *)argv);
304 }
305 #define NDIR    256             /* shoud be a better way */
306
307 int
308 Globsize(char *p)
309 {
310         int isglob = 0, globlen = NDIR+1;
311         for(;*p;p++){
312                 if(*p==GLOB){
313                         p++;
314                         if(*p!=GLOB)
315                                 isglob++;
316                         globlen+=*p=='*'?NDIR:1;
317                 }
318                 else
319                         globlen++;
320         }
321         return isglob?globlen:0;
322 }
323 #define NFD     50
324 #define NDBUF   32
325 struct{
326         Dir     *dbuf;
327         int     i;
328         int     n;
329 }dir[NFD];
330
331 int
332 Opendir(char *name)
333 {
334         Dir *db;
335         int f;
336         f = open(name, 0);
337         if(f==-1)
338                 return f;
339         db = dirfstat(f);
340         if(db!=nil && (db->mode&DMDIR)){
341                 if(f<NFD){
342                         dir[f].i = 0;
343                         dir[f].n = 0;
344                 }
345                 free(db);
346                 return f;
347         }
348         free(db);
349         close(f);
350         return -1;
351 }
352
353 static int
354 trimdirs(Dir *d, int nd)
355 {
356         int r, w;
357
358         for(r=w=0; r<nd; r++)
359                 if(d[r].mode&DMDIR)
360                         d[w++] = d[r];
361         return w;
362 }
363
364 /*
365  * onlydirs is advisory -- it means you only
366  * need to return the directories.  it's okay to
367  * return files too (e.g., on unix where you can't
368  * tell during the readdir), but that just makes 
369  * the globber work harder.
370  */
371 int
372 Readdir(int f, void *p, int onlydirs)
373 {
374         int n;
375
376         if(f<0 || f>=NFD)
377                 return 0;
378 Again:
379         if(dir[f].i==dir[f].n){ /* read */
380                 free(dir[f].dbuf);
381                 dir[f].dbuf = 0;
382                 n = dirread(f, &dir[f].dbuf);
383                 if(n>0){
384                         if(onlydirs){
385                                 n = trimdirs(dir[f].dbuf, n);
386                                 if(n == 0)
387                                         goto Again;
388                         }       
389                         dir[f].n = n;
390                 }else
391                         dir[f].n = 0;
392                 dir[f].i = 0;
393         }
394         if(dir[f].i == dir[f].n)
395                 return 0;
396         strcpy(p, dir[f].dbuf[dir[f].i].name);
397         dir[f].i++;
398         return 1;
399 }
400
401 void
402 Closedir(int f)
403 {
404         if(f>=0 && f<NFD){
405                 free(dir[f].dbuf);
406                 dir[f].i = 0;
407                 dir[f].n = 0;
408                 dir[f].dbuf = 0;
409         }
410         close(f);
411 }
412 int interrupted = 0;
413 void
414 notifyf(void*, char *s)
415 {
416         int i;
417         for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
418                 if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
419                 goto Out;
420         }
421         pfmt(err, "rc: note: %s\n", s);
422         noted(NDFLT);
423         return;
424 Out:
425         if(strcmp(s, "interrupt")!=0 || trap[i]==0){
426                 trap[i]++;
427                 ntrap++;
428         }
429         if(ntrap>=32){  /* rc is probably in a trap loop */
430                 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
431                 abort();
432         }
433         noted(NCONT);
434 }
435
436 void
437 Trapinit(void)
438 {
439         notify(notifyf);
440 }
441
442 void
443 Unlink(char *name)
444 {
445         remove(name);
446 }
447
448 long
449 Write(int fd, void *buf, long cnt)
450 {
451         return write(fd, buf, (long)cnt);
452 }
453
454 long
455 Read(int fd, void *buf, long cnt)
456 {
457         return read(fd, buf, cnt);
458 }
459
460 long
461 Seek(int fd, long cnt, long whence)
462 {
463         return seek(fd, cnt, whence);
464 }
465
466 int
467 Executable(char *file)
468 {
469         Dir *statbuf;
470         int ret;
471
472         statbuf = dirstat(file);
473         if(statbuf == nil)
474                 return 0;
475         ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
476         free(statbuf);
477         return ret;
478 }
479
480 int
481 Creat(char *file)
482 {
483         return create(file, 1, 0666L);
484 }
485
486 int
487 Dup(int a, int b)
488 {
489         return dup(a, b);
490 }
491
492 int
493 Dup1(int)
494 {
495         return -1;
496 }
497
498 void
499 Exit(char *stat)
500 {
501         Updenv();
502         setstatus(stat);
503         exits(truestatus()?"":getstatus());
504 }
505
506 int
507 Eintr(void)
508 {
509         return interrupted;
510 }
511
512 void
513 Noerror(void)
514 {
515         interrupted = 0;
516 }
517
518 int
519 Isatty(int fd)
520 {
521         Dir *d1, *d2;
522         int ret;
523
524         d1 = dirfstat(fd);
525         if(d1 == nil)
526                 return 0;
527         if(strncmp(d1->name, "ptty", 4)==0){    /* fwd complaints to philw */
528                 free(d1);
529                 return 1;
530         }
531         d2 = dirstat("/dev/cons");
532         if(d2 == nil){
533                 free(d1);
534                 return 0;
535         }
536         ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path);
537         free(d1);
538         free(d2);
539         return ret;
540 }
541
542 void
543 Abort(void)
544 {
545         pfmt(err, "aborting\n");
546         flush(err);
547         Exit("aborting");
548 }
549
550 void
551 Memcpy(void *a, void *b, long n)
552 {
553         memmove(a, b, n);
554 }
555
556 void*
557 Malloc(ulong n)
558 {
559         return malloc(n);
560 }
561
562 void*
563 Realloc(void *p, ulong n)
564 {
565         return realloc(p, n);
566 }