Introduction
Introduction Statistics Contact Development Disclaimer Help
plan9ish.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
plan9ish.c (10617B)
---
1 /*
2 * Plan 9 versions of system-specific functions
3 * By convention, exported routines herein have names beginning w…
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/etc/rcmain");
31 }
32
33 char Fdprefix[]="/dev/fd/";
34 long readnb(int, char *, long);
35 void execfinit(void);
36 void execbind(void);
37 void execmount(void);
38 void execulimit(void);
39 void execumask(void);
40 void execrfork(void);
41 builtin Builtin[]={
42 "cd", execcd,
43 "whatis", execwhatis,
44 "eval", execeval,
45 "exec", execexec, /* but with popword firs…
46 "exit", execexit,
47 "shift", execshift,
48 "wait", execwait,
49 ".", execdot,
50 "finit", execfinit,
51 "flag", execflag,
52 "ulimit", execulimit,
53 "umask", execumask,
54 "rfork", execrfork,
55 0
56 };
57
58 void
59 execrfork(void)
60 {
61 int arg;
62 char *s;
63
64 switch(count(runq->argv->words)){
65 case 1:
66 arg = RFENVG|RFNOTEG|RFNAMEG;
67 break;
68 case 2:
69 arg = 0;
70 for(s = runq->argv->words->next->word;*s;s++) switch(*s){
71 default:
72 goto Usage;
73 case 'n':
74 arg|=RFNAMEG; break;
75 case 'N':
76 arg|=RFCNAMEG;
77 break;
78 case 'e':
79 /* arg|=RFENVG; */ break;
80 case 'E':
81 arg|=RFCENVG; break;
82 case 's':
83 arg|=RFNOTEG; break;
84 case 'f':
85 arg|=RFFDG; break;
86 case 'F':
87 arg|=RFCFDG; break;
88 }
89 break;
90 default:
91 Usage:
92 pfmt(err, "Usage: %s [nNeEsfF]\n", runq->argv->words->wo…
93 setstatus("rfork usage");
94 poplist();
95 return;
96 }
97 if(rfork(arg)==-1){
98 pfmt(err, "rc: %s failed\n", runq->argv->words->word);
99 setstatus("rfork failed");
100 }
101 else
102 setstatus("");
103 poplist();
104 }
105
106
107
108 #define SEP '\1'
109 char **environp;
110 struct word *enval(s)
111 register char *s;
112 {
113 register char *t, c;
114 register struct word *v;
115 for(t=s;*t && *t!=SEP;t++);
116 c=*t;
117 *t='\0';
118 v=newword(s, c=='\0'?(struct word *)0:enval(t+1));
119 *t=c;
120 return v;
121 }
122 void Vinit(void){
123 extern char **environ;
124 register char *s;
125 register char **env=environ;
126 environp=env;
127 for(;*env;env++){
128 for(s=*env;*s && *s!='(' && *s!='=';s++);
129 switch(*s){
130 case '\0':
131 /* pfmt(err, "rc: odd environment %q?\n", *env); …
132 break;
133 case '=':
134 *s='\0';
135 setvar(*env, enval(s+1));
136 *s='=';
137 break;
138 case '(': /* ignore functions for now */
139 break;
140 }
141 }
142 }
143 char **envp;
144 void Xrdfn(void){
145 char *p;
146 register char *s;
147 register int len;
148 for(;*envp;envp++){
149 s = *envp;
150 if(strncmp(s, "fn#", 3) == 0){
151 p = strchr(s, '=');
152 if(p == nil)
153 continue;
154 *p = ' ';
155 s[2] = ' ';
156 len = strlen(s);
157 execcmds(opencore(s, len));
158 s[len] = '\0';
159 return;
160 }
161 #if 0
162 for(s=*envp;*s && *s!='(' && *s!='=';s++);
163 switch(*s){
164 case '\0':
165 pfmt(err, "environment %q?\n", *envp);
166 break;
167 case '=': /* ignore variables */
168 break;
169 case '(': /* Bourne again */
170 s=*envp+3;
171 envp++;
172 len=strlen(s);
173 s[len]='\n';
174 execcmds(opencore(s, len+1));
175 s[len]='\0';
176 return;
177 }
178 #endif
179 }
180 Xreturn();
181 }
182 union code rdfns[4];
183 void execfinit(void){
184 static int first=1;
185 if(first){
186 rdfns[0].i=1;
187 rdfns[1].f=Xrdfn;
188 rdfns[2].f=Xjump;
189 rdfns[3].i=1;
190 first=0;
191 }
192 Xpopm();
193 envp=environp;
194 start(rdfns, 1, runq->local);
195 }
196 extern int mapfd(int);
197 int Waitfor(int pid, int unused0){
198 thread *p;
199 Waitmsg *w;
200 char errbuf[ERRMAX];
201
202 if(pid >= 0 && !havewaitpid(pid))
203 return 0;
204 while((w = wait()) != nil){
205 delwaitpid(w->pid);
206 if(w->pid==pid){
207 if(strncmp(w->msg, "signal: ", 8) == 0)
208 fprint(mapfd(2), "%d: %s\n", w->pid, w->…
209 setstatus(w->msg);
210 free(w);
211 return 0;
212 }
213 if(runq->iflag && strncmp(w->msg, "signal: ", 8) == 0)
214 fprint(2, "%d: %s\n", w->pid, w->msg);
215 for(p=runq->ret;p;p=p->ret)
216 if(p->pid==w->pid){
217 p->pid=-1;
218 strcpy(p->status, w->msg);
219 }
220 free(w);
221 }
222
223 rerrstr(errbuf, sizeof errbuf);
224 if(strcmp(errbuf, "interrupted")==0) return -1;
225 return 0;
226 }
227 char **mkargv(word *a)
228 {
229 char **argv=(char **)emalloc((count(a)+2)*sizeof(char *));
230 char **argp=argv+1; /* leave one at front for runcoms */
231 for(;a;a=a->next) *argp++=a->word;
232 *argp=0;
233 return argv;
234 }
235 /*
236 void addenv(var *v)
237 {
238 char envname[256];
239 word *w;
240 int f;
241 io *fd;
242 if(v->changed){
243 v->changed=0;
244 snprint(envname, sizeof envname, "/env/%s", v->name);
245 if((f=Creat(envname))<0)
246 pfmt(err, "rc: can't open %s: %r\n", envname);
247 else{
248 for(w=v->val;w;w=w->next)
249 write(f, w->word, strlen(w->word)+1L);
250 close(f);
251 }
252 }
253 if(v->fnchanged){
254 v->fnchanged=0;
255 snprint(envname, sizeof envname, "/env/fn#%s", v->name);
256 if((f=Creat(envname))<0)
257 pfmt(err, "rc: can't open %s: %r\n", envname);
258 else{
259 if(v->fn){
260 fd=openfd(f);
261 pfmt(fd, "fn %s %s\n", v->name, v->fn[v-…
262 closeio(fd);
263 }
264 close(f);
265 }
266 }
267 }
268 void updenvlocal(var *v)
269 {
270 if(v){
271 updenvlocal(v->next);
272 addenv(v);
273 }
274 }
275 void Updenv(void){
276 var *v, **h;
277 for(h=gvar;h!=&gvar[NVAR];h++)
278 for(v=*h;v;v=v->next)
279 addenv(v);
280 if(runq) updenvlocal(runq->local);
281 }
282 */
283 int
284 cmpenv(const void *a, const void *b)
285 {
286 return strcmp(*(char**)a, *(char**)b);
287 }
288 char **mkenv(){
289 register char **env, **ep, *p, *q;
290 register struct var **h, *v;
291 register struct word *a;
292 register int nvar=0, nchr=0, sep;
293 /*
294 * Slightly kludgy loops look at locals then globals
295 */
296 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;…
297 if((v==vlook(v->name)) && v->val){
298 nvar++;
299 nchr+=strlen(v->name)+1;
300 for(a=v->val;a;a=a->next)
301 nchr+=strlen(a->word)+1;
302 }
303 if(v->fn){
304 nvar++;
305 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
306 }
307 }
308 env=(char **)emalloc((nvar+1)*sizeof(char *)+nchr);
309 ep=env;
310 p=(char *)&env[nvar+1];
311 for(h=gvar-1;h!=&gvar[NVAR];h++) for(v=h>=gvar?*h:runq->local;v;…
312 if((v==vlook(v->name)) && v->val){
313 *ep++=p;
314 q=v->name;
315 while(*q) *p++=*q++;
316 sep='=';
317 for(a=v->val;a;a=a->next){
318 *p++=sep;
319 sep=SEP;
320 q=a->word;
321 while(*q) *p++=*q++;
322 }
323 *p++='\0';
324 }
325 if(v->fn){
326 *ep++=p;
327 #if 0
328 *p++='#'; *p++='('; *p++=')'; /* to fool …
329 *p++='f'; *p++='n'; *p++=' ';
330 q=v->name;
331 while(*q) *p++=*q++;
332 *p++=' ';
333 #endif
334 *p++='f'; *p++='n'; *p++='#';
335 q=v->name;
336 while(*q) *p++=*q++;
337 *p++='=';
338 q=v->fn[v->pc-1].s;
339 while(*q) *p++=*q++;
340 *p++='\n';
341 *p++='\0';
342 }
343 }
344 *ep=0;
345 qsort((char *)env, nvar, sizeof ep[0], cmpenv);
346 return env;
347 }
348 void Updenv(void){}
349 void Execute(word *args, word *path)
350 {
351 char **argv=mkargv(args);
352 char **env=mkenv();
353 char file[1024];
354 int nc;
355 Updenv();
356 for(;path;path=path->next){
357 nc=strlen(path->word);
358 if(nc<1024){
359 strcpy(file, path->word);
360 if(file[0]){
361 strcat(file, "/");
362 nc++;
363 }
364 if(nc+strlen(argv[1])<1024){
365 strcat(file, argv[1]);
366 execve(file, argv+1, env);
367 }
368 else werrstr("command name too long");
369 }
370 }
371 rerrstr(file, sizeof file);
372 pfmt(err, "%s: %s\n", argv[1], file);
373 efree((char *)argv);
374 }
375 #define NDIR 256 /* shoud be a better way */
376 int Globsize(char *p)
377 {
378 ulong isglob=0, globlen=NDIR+1;
379 for(;*p;p++){
380 if(*p==GLOB){
381 p++;
382 if(*p!=GLOB) isglob++;
383 globlen+=*p=='*'?NDIR:1;
384 }
385 else
386 globlen++;
387 }
388 return isglob?globlen:0;
389 }
390 #define NFD 50
391 #define NDBUF 32
392 struct{
393 Dir *dbuf;
394 int i;
395 int n;
396 }dir[NFD];
397 int Opendir(char *name)
398 {
399 Dir *db;
400 int f;
401 f=open(name, 0);
402 if(f==-1)
403 return f;
404 db = dirfstat(f);
405 if(db!=nil && (db->mode&DMDIR)){
406 if(f<NFD){
407 dir[f].i=0;
408 dir[f].n=0;
409 }
410 free(db);
411 return f;
412 }
413 free(db);
414 close(f);
415 return -1;
416 }
417 int Readdir(int f, char *p, int onlydirs)
418 {
419 int n;
420 USED(onlydirs); /* only advisory */
421
422 if(f<0 || f>=NFD)
423 return 0;
424 if(dir[f].i==dir[f].n){ /* read */
425 free(dir[f].dbuf);
426 dir[f].dbuf=0;
427 n=dirread(f, &dir[f].dbuf);
428 if(n>=0)
429 dir[f].n=n;
430 else
431 dir[f].n=0;
432 dir[f].i=0;
433 }
434 if(dir[f].i==dir[f].n)
435 return 0;
436 strcpy(p, dir[f].dbuf[dir[f].i].name);
437 dir[f].i++;
438 return 1;
439 }
440 void Closedir(int f){
441 if(f>=0 && f<NFD){
442 free(dir[f].dbuf);
443 dir[f].i=0;
444 dir[f].n=0;
445 dir[f].dbuf=0;
446 }
447 close(f);
448 }
449 int interrupted = 0;
450 void
451 notifyf(void *unused0, char *s)
452 {
453 int i;
454 for(i=0;syssigname[i];i++)
455 if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
456 if(strncmp(s, "sys: ", 5)!=0){
457 if(kidpid && !interrupted){
458 interrupted=1;
459 postnote(PNGROUP, kidpid, s);
460 }
461 interrupted = 1;
462 }
463 goto Out;
464 }
465 if(strcmp(s, "sys: window size change") != 0)
466 if(strcmp(s, "sys: write on closed pipe") != 0)
467 if(strcmp(s, "sys: child") != 0)
468 pfmt(err, "rc: note: %s\n", s);
469 noted(NDFLT);
470 return;
471 Out:
472 if(strcmp(s, "interrupt")!=0 || trap[i]==0){
473 trap[i]++;
474 ntrap++;
475 }
476 if(ntrap>=32){ /* rc is probably in a trap loop */
477 pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
478 abort();
479 }
480 noted(NCONT);
481 }
482 void Trapinit(void){
483 notify(notifyf);
484 }
485 void Unlink(char *name)
486 {
487 remove(name);
488 }
489 long Write(int fd, char *buf, long cnt)
490 {
491 return write(fd, buf, (long)cnt);
492 }
493 long Read(int fd, char *buf, long cnt)
494 {
495 int i;
496
497 i = readnb(fd, buf, cnt);
498 if(ntrap) dotrap();
499 return i;
500 }
501 long Seek(int fd, long cnt, long whence)
502 {
503 return seek(fd, cnt, whence);
504 }
505 int Executable(char *file)
506 {
507 Dir *statbuf;
508 int ret;
509
510 statbuf = dirstat(file);
511 if(statbuf == nil) return 0;
512 ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
513 free(statbuf);
514 return ret;
515 }
516 int Creat(char *file)
517 {
518 return create(file, 1, 0666L);
519 }
520 int Dup(int a, int b){
521 return dup(a, b);
522 }
523 int Dup1(int a){
524 return dup(a, -1);
525 }
526 void Exit(char *stat)
527 {
528 Updenv();
529 setstatus(stat);
530 exits(truestatus()?"":getstatus());
531 }
532 int Eintr(void){
533 return interrupted;
534 }
535 void Noerror(void){
536 interrupted=0;
537 }
538 int
539 Isatty(int fd){
540 return isatty(fd);
541 }
542 void Abort(void){
543 pfmt(err, "aborting\n");
544 flush(err);
545 Exit("aborting");
546 }
547 void Memcpy(char *a, char *b, long n)
548 {
549 memmove(a, b, (long)n);
550 }
551 void *Malloc(ulong n){
552 return malloc(n);
553 }
554
555 int
556 exitcode(char *msg)
557 {
558 int n;
559
560 n = atoi(msg);
561 if(n == 0)
562 n = 1;
563 return n;
564 }
565
566 int *waitpids;
567 int nwaitpids;
568
569 void
570 addwaitpid(int pid)
571 {
572 waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
573 if(waitpids == 0)
574 panic("Can't realloc %d waitpids", nwaitpids+1);
575 waitpids[nwaitpids++] = pid;
576 }
577
578 void
579 delwaitpid(int pid)
580 {
581 int r, w;
582
583 for(r=w=0; r<nwaitpids; r++)
584 if(waitpids[r] != pid)
585 waitpids[w++] = waitpids[r];
586 nwaitpids = w;
587 }
588
589 void
590 clearwaitpids(void)
591 {
592 nwaitpids = 0;
593 }
594
595 int
596 havewaitpid(int pid)
597 {
598 int i;
599
600 for(i=0; i<nwaitpids; i++)
601 if(waitpids[i] == pid)
602 return 1;
603 return 0;
604 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.