tmain.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tmain.c (9006B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <bio.h> | |
4 #include <mach.h> | |
5 #define Extern | |
6 #include "acid.h" | |
7 #include "y.tab.h" | |
8 | |
9 extern int __ifmt(Fmt*); | |
10 | |
11 static Biobuf bioout; | |
12 static char* lm[16]; | |
13 static int nlm; | |
14 static char* mtype; | |
15 | |
16 static int attachfiles(int, char**); | |
17 int xfmt(Fmt*); | |
18 int isnumeric(char*); | |
19 void die(void); | |
20 void setcore(Fhdr*); | |
21 | |
22 void | |
23 usage(void) | |
24 { | |
25 fprint(2, "usage: acid [-c core] [-l module] [-m machine] [-qrw]… | |
26 exits("usage"); | |
27 } | |
28 | |
29 Map* | |
30 dumbmap(int fd) | |
31 { | |
32 Map *dumb; | |
33 Seg s; | |
34 | |
35 dumb = allocmap(); | |
36 memset(&s, 0, sizeof s); | |
37 s.fd = fd; | |
38 s.base = 0; | |
39 s.offset = 0; | |
40 s.size = 0xFFFFFFFF; | |
41 s.name = "data"; | |
42 s.file = "<dumb>"; | |
43 if(addseg(dumb, s) < 0){ | |
44 freemap(dumb); | |
45 return nil; | |
46 } | |
47 if(mach == nil) | |
48 mach = machcpu; | |
49 return dumb; | |
50 } | |
51 | |
52 void | |
53 main(int argc, char *argv[]) | |
54 { | |
55 Lsym *volatile l; | |
56 Node *n; | |
57 char buf[128], *s; | |
58 int pid, i; | |
59 | |
60 argv0 = argv[0]; | |
61 pid = 0; | |
62 quiet = 1; | |
63 | |
64 mtype = 0; | |
65 ARGBEGIN{ | |
66 case 'A': | |
67 abort(); | |
68 break; | |
69 case 'm': | |
70 mtype = ARGF(); | |
71 break; | |
72 case 'w': | |
73 wtflag = 1; | |
74 break; | |
75 case 'l': | |
76 s = ARGF(); | |
77 if(s == 0) | |
78 usage(); | |
79 lm[nlm++] = s; | |
80 break; | |
81 case 'k': | |
82 kernel++; | |
83 break; | |
84 case 'q': | |
85 quiet = 0; | |
86 break; | |
87 case 'r': | |
88 pid = 1; | |
89 remote++; | |
90 kernel++; | |
91 break; | |
92 default: | |
93 usage(); | |
94 }ARGEND | |
95 | |
96 USED(pid); | |
97 | |
98 fmtinstall('Z', Zfmt); | |
99 fmtinstall('L', locfmt); | |
100 Binit(&bioout, 1, OWRITE); | |
101 bout = &bioout; | |
102 | |
103 initexpr(); | |
104 initprint(); | |
105 kinit(); | |
106 initialising = 1; | |
107 pushfile(0); | |
108 loadvars(); | |
109 installbuiltin(); | |
110 acidregs = mallocz(sizeof *acidregs, 1); | |
111 acidregs->rw = acidregsrw; | |
112 | |
113 if(mtype && machbyname(mtype) == 0) | |
114 print("unknown machine %s", mtype); | |
115 | |
116 if (attachfiles(argc, argv) < 0) | |
117 varreg(); /* use default register set on … | |
118 if(mach == nil) | |
119 mach = machcpu; | |
120 | |
121 symhdr = nil; /* not supposed to use this anymore */ | |
122 | |
123 l = mkvar("acid"); | |
124 l->v->set = 1; | |
125 l->v->type = TLIST; | |
126 l->v->store.u.l = nil; | |
127 | |
128 loadmodule(unsharp("#9/acid/port")); | |
129 for(i = 0; i < nlm; i++) { | |
130 if(access(lm[i], AREAD) >= 0) | |
131 loadmodule(lm[i]); | |
132 else { | |
133 sprint(buf, "#9/acid/%s", lm[i]); | |
134 loadmodule(unsharp(buf)); | |
135 } | |
136 } | |
137 | |
138 userinit(); | |
139 varsym(); | |
140 | |
141 l = look("acidmap"); | |
142 if(l && l->proc) { | |
143 if(setjmp(err) == 0){ | |
144 n = an(ONAME, ZN, ZN); | |
145 n->sym = l; | |
146 n = an(OCALL, n, ZN); | |
147 execute(n); | |
148 } | |
149 } | |
150 | |
151 interactive = 1; | |
152 initialising = 0; | |
153 line = 1; | |
154 | |
155 notify(catcher); | |
156 | |
157 for(;;) { | |
158 if(setjmp(err)) { | |
159 Binit(&bioout, 1, OWRITE); | |
160 unwind(); | |
161 } | |
162 stacked = 0; | |
163 | |
164 Bprint(bout, "acid; "); | |
165 | |
166 if(yyparse() != 1) | |
167 die(); | |
168 restartio(); | |
169 | |
170 unwind(); | |
171 } | |
172 /* | |
173 Bputc(bout, '\n'); | |
174 exits(0); | |
175 */ | |
176 } | |
177 | |
178 void | |
179 setstring(char *var, char *s) | |
180 { | |
181 Lsym *l; | |
182 Value *v; | |
183 | |
184 l = mkvar(var); | |
185 v = l->v; | |
186 v->store.fmt = 's'; | |
187 v->set = 1; | |
188 v->store.u.string = strnode(s ? s : ""); | |
189 v->type = TSTRING; | |
190 } | |
191 | |
192 static int | |
193 attachfiles(int argc, char **argv) | |
194 { | |
195 volatile int pid; | |
196 Lsym *l; | |
197 | |
198 pid = 0; | |
199 interactive = 0; | |
200 USED(pid); | |
201 | |
202 if(setjmp(err)) | |
203 return -1; | |
204 | |
205 attachargs(argc, argv, wtflag?ORDWR:OREAD, 1); | |
206 | |
207 setstring("objtype", mach->name); | |
208 setstring("textfile", symfil); | |
209 setstring("systype", symhdr ? symhdr->aname : ""); | |
210 setstring("corefile", corfil); | |
211 | |
212 l = mkvar("pids"); | |
213 l->v->set = 1; | |
214 l->v->type = TLIST; | |
215 l->v->store.u.l = nil; | |
216 | |
217 if(corpid) | |
218 sproc(corpid); | |
219 if(corhdr) | |
220 setcore(corhdr); | |
221 varreg(); | |
222 return 0; | |
223 } | |
224 | |
225 void | |
226 setcore(Fhdr *hdr) | |
227 { | |
228 int i; | |
229 Lsym *l; | |
230 Value *v; | |
231 List **tail, *tl; | |
232 | |
233 unmapproc(cormap); | |
234 unmapfile(corhdr, cormap); | |
235 free(correg); | |
236 correg = nil; | |
237 | |
238 if(hdr == nil) | |
239 error("no core"); | |
240 if(mapfile(hdr, 0, cormap, &correg) < 0) | |
241 error("mapfile %s: %r", hdr->filename); | |
242 corhdr = hdr; | |
243 corfil = hdr->filename; | |
244 | |
245 l = mkvar("pid"); | |
246 v = l->v; | |
247 v->store.fmt = 'D'; | |
248 v->set = 1; | |
249 v->store.u.ival = hdr->pid; | |
250 | |
251 setstring("corefile", corfil); | |
252 setstring("cmdline", hdr->cmdline); | |
253 | |
254 l = mkvar("pids"); | |
255 l->v->set = 1; | |
256 l->v->type = TLIST; | |
257 l->v->store.u.l = nil; | |
258 tail = &l->v->store.u.l; | |
259 for(i=0; i<hdr->nthread; i++){ | |
260 tl = al(TINT); | |
261 tl->store.u.ival = hdr->thread[i].id; | |
262 tl->store.fmt = 'X'; | |
263 *tail = tl; | |
264 tail = &tl->next; | |
265 } | |
266 | |
267 if(hdr->nthread) | |
268 sproc(hdr->thread[0].id); | |
269 } | |
270 | |
271 void | |
272 die(void) | |
273 { | |
274 Lsym *s; | |
275 List *f; | |
276 int first; | |
277 | |
278 Bprint(bout, "\n"); | |
279 | |
280 first = 1; | |
281 s = look("proclist"); | |
282 if(s && s->v->type == TLIST) { | |
283 for(f = s->v->store.u.l; f; f = f->next){ | |
284 detachproc((int)f->store.u.ival); | |
285 Bprint(bout, "%s %d", first ? "/bin/kill -9" : "… | |
286 first = 0; | |
287 } | |
288 } | |
289 if(!first) | |
290 Bprint(bout, "\n"); | |
291 exits(0); | |
292 } | |
293 | |
294 void | |
295 userinit(void) | |
296 { | |
297 Lsym *l; | |
298 Node *n; | |
299 char buf[128], *p; | |
300 | |
301 sprint(buf, "#9/acid/%s", mach->name); | |
302 loadmodule(unsharp(buf)); | |
303 p = getenv("HOME"); | |
304 if(p != 0) { | |
305 sprint(buf, "%s/lib/acid", p); | |
306 silent = 1; | |
307 loadmodule(buf); | |
308 } | |
309 | |
310 interactive = 0; | |
311 if(setjmp(err)) { | |
312 unwind(); | |
313 return; | |
314 } | |
315 l = look("acidinit"); | |
316 if(l && l->proc) { | |
317 n = an(ONAME, ZN, ZN); | |
318 n->sym = l; | |
319 n = an(OCALL, n, ZN); | |
320 execute(n); | |
321 } | |
322 } | |
323 | |
324 void | |
325 loadmodule(char *s) | |
326 { | |
327 interactive = 0; | |
328 if(setjmp(err)) { | |
329 unwind(); | |
330 return; | |
331 } | |
332 pushfile(s); | |
333 silent = 0; | |
334 yyparse(); | |
335 popio(); | |
336 return; | |
337 } | |
338 | |
339 Node* | |
340 an(int op, Node *l, Node *r) | |
341 { | |
342 Node *n; | |
343 | |
344 n = gmalloc(sizeof(Node)); | |
345 memset(n, 0, sizeof(Node)); | |
346 n->gc.gclink = gcl; | |
347 gcl = (Gc*)n; | |
348 n->op = op; | |
349 n->left = l; | |
350 n->right = r; | |
351 return n; | |
352 } | |
353 | |
354 List* | |
355 al(int t) | |
356 { | |
357 List *l; | |
358 | |
359 l = gmalloc(sizeof(List)); | |
360 memset(l, 0, sizeof(List)); | |
361 l->type = t; | |
362 l->gc.gclink = gcl; | |
363 gcl = (Gc*)l; | |
364 return l; | |
365 } | |
366 | |
367 Node* | |
368 con(s64int v) | |
369 { | |
370 Node *n; | |
371 | |
372 n = an(OCONST, ZN, ZN); | |
373 n->store.u.ival = v; | |
374 n->store.fmt = 'X'; | |
375 n->type = TINT; | |
376 return n; | |
377 } | |
378 | |
379 void | |
380 fatal(char *fmt, ...) | |
381 { | |
382 char buf[128]; | |
383 va_list arg; | |
384 | |
385 va_start(arg, fmt); | |
386 vseprint(buf, buf+sizeof(buf), fmt, arg); | |
387 va_end(arg); | |
388 fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf); | |
389 exits(buf); | |
390 } | |
391 | |
392 void | |
393 yyerror(char *fmt, ...) | |
394 { | |
395 char buf[128]; | |
396 va_list arg; | |
397 | |
398 if(strcmp(fmt, "syntax error") == 0) { | |
399 yyerror("syntax error, near symbol '%s'", symbol); | |
400 return; | |
401 } | |
402 va_start(arg, fmt); | |
403 vseprint(buf, buf+sizeof(buf), fmt, arg); | |
404 va_end(arg); | |
405 print("%Z: %s\n", buf); | |
406 } | |
407 | |
408 void | |
409 marktree(Node *n) | |
410 { | |
411 | |
412 if(n == 0) | |
413 return; | |
414 | |
415 marktree(n->left); | |
416 marktree(n->right); | |
417 | |
418 n->gc.gcmark = 1; | |
419 if(n->op != OCONST) | |
420 return; | |
421 | |
422 switch(n->type) { | |
423 case TSTRING: | |
424 n->store.u.string->gc.gcmark = 1; | |
425 break; | |
426 case TLIST: | |
427 marklist(n->store.u.l); | |
428 break; | |
429 case TCODE: | |
430 marktree(n->store.u.cc); | |
431 break; | |
432 } | |
433 } | |
434 | |
435 void | |
436 marklist(List *l) | |
437 { | |
438 while(l) { | |
439 l->gc.gcmark = 1; | |
440 switch(l->type) { | |
441 case TSTRING: | |
442 l->store.u.string->gc.gcmark = 1; | |
443 break; | |
444 case TLIST: | |
445 marklist(l->store.u.l); | |
446 break; | |
447 case TCODE: | |
448 marktree(l->store.u.cc); | |
449 break; | |
450 } | |
451 l = l->next; | |
452 } | |
453 } | |
454 | |
455 void | |
456 gc(void) | |
457 { | |
458 int i; | |
459 Lsym *f; | |
460 Value *v; | |
461 Gc *m, **p, *next; | |
462 | |
463 if(dogc < Mempergc) | |
464 return; | |
465 dogc = 0; | |
466 | |
467 /* Mark */ | |
468 for(m = gcl; m; m = m->gclink) | |
469 m->gcmark = 0; | |
470 | |
471 /* Scan */ | |
472 for(i = 0; i < Hashsize; i++) { | |
473 for(f = hash[i]; f; f = f->hash) { | |
474 marktree(f->proc); | |
475 if(f->lexval != Tid) | |
476 continue; | |
477 for(v = f->v; v; v = v->pop) { | |
478 switch(v->type) { | |
479 case TSTRING: | |
480 v->store.u.string->gc.gcmark = 1; | |
481 break; | |
482 case TLIST: | |
483 marklist(v->store.u.l); | |
484 break; | |
485 case TCODE: | |
486 marktree(v->store.u.cc); | |
487 break; | |
488 case TCON: | |
489 marktree(v->store.u.con); | |
490 break; | |
491 } | |
492 } | |
493 } | |
494 } | |
495 | |
496 /* Free */ | |
497 p = &gcl; | |
498 for(m = gcl; m; m = next) { | |
499 next = m->gclink; | |
500 if(m->gcmark == 0) { | |
501 *p = next; | |
502 free(m); /* Sleazy reliance on my malloc … | |
503 } | |
504 else | |
505 p = &m->gclink; | |
506 } | |
507 } | |
508 | |
509 void* | |
510 gmalloc(long l) | |
511 { | |
512 void *p; | |
513 | |
514 dogc += l; | |
515 p = malloc(l); | |
516 if(p == 0) | |
517 fatal("out of memory"); | |
518 return p; | |
519 } | |
520 | |
521 void | |
522 checkqid(int f1, int pid) | |
523 { | |
524 int fd; | |
525 Dir *d1, *d2; | |
526 char buf[128]; | |
527 | |
528 if(kernel) | |
529 return; | |
530 | |
531 d1 = dirfstat(f1); | |
532 if(d1 == nil){ | |
533 print("checkqid: (qid not checked) dirfstat: %r\n"); | |
534 return; | |
535 } | |
536 | |
537 sprint(buf, "/proc/%d/text", pid); | |
538 fd = open(buf, OREAD); | |
539 if(fd < 0 || (d2 = dirfstat(fd)) == nil){ | |
540 print("checkqid: (qid not checked) dirstat %s: %r\n", bu… | |
541 free(d1); | |
542 if(fd >= 0) | |
543 close(fd); | |
544 return; | |
545 } | |
546 | |
547 close(fd); | |
548 | |
549 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers … | |
550 print("path %#llux %#llux vers %lud %lud type %d %d\n", | |
551 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qi… | |
552 print("warning: image does not match text for pid %d\n",… | |
553 } | |
554 free(d1); | |
555 free(d2); | |
556 } | |
557 | |
558 void | |
559 catcher(void *junk, char *s) | |
560 { | |
561 USED(junk); | |
562 | |
563 if(strstr(s, "interrupt")) { | |
564 gotint = 1; | |
565 noted(NCONT); | |
566 } | |
567 if(strstr(s, "child")) | |
568 noted(NCONT); | |
569 fprint(2, "note: %s\n", s); | |
570 noted(NDFLT); | |
571 } | |
572 | |
573 char* | |
574 system(void) | |
575 { | |
576 char *cpu, *p, *q; | |
577 static char kernel[128]; | |
578 | |
579 cpu = getenv("cputype"); | |
580 if(cpu == 0) { | |
581 cpu = "mips"; | |
582 print("$cputype not set; assuming %s\n", cpu); | |
583 } | |
584 p = getenv("terminal"); | |
585 if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0… | |
586 p = "9power"; | |
587 print("missing or bad $terminal; assuming %s\n", p); | |
588 } | |
589 else{ | |
590 p++; | |
591 q = strchr(p, ' '); | |
592 if(q) | |
593 *q = 0; | |
594 sprint(kernel, "/%s/9%s", cpu, p); | |
595 } | |
596 return kernel; | |
597 } | |
598 | |
599 int | |
600 isnumeric(char *s) | |
601 { | |
602 while(*s) { | |
603 if(*s < '0' || *s > '9') | |
604 return 0; | |
605 s++; | |
606 } | |
607 return 1; | |
608 } |