Blob


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"
9 extern int __ifmt(Fmt*);
11 static Biobuf bioout;
12 static char* lm[16];
13 static int nlm;
14 static char* mtype;
16 static int attachfiles(int, char**);
17 int xfmt(Fmt*);
18 int isnumeric(char*);
19 void die(void);
20 void setcore(Fhdr*);
22 void
23 usage(void)
24 {
25 fprint(2, "usage: acid [-c core] [-l module] [-m machine] [-qrw] [-k] [pid] [file]\n");
26 exits("usage");
27 }
29 Map*
30 dumbmap(int fd)
31 {
32 Map *dumb;
33 Seg s;
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 }
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;
60 argv0 = argv[0];
61 pid = 0;
62 quiet = 1;
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
96 fmtinstall('Z', Zfmt);
97 fmtinstall('L', locfmt);
98 Binit(&bioout, 1, OWRITE);
99 bout = &bioout;
101 initexpr();
102 initprint();
103 kinit();
104 initialising = 1;
105 pushfile(0);
106 loadvars();
107 installbuiltin();
108 acidregs = mallocz(sizeof *acidregs, 1);
109 acidregs->rw = acidregsrw;
111 if(mtype && machbyname(mtype) == 0)
112 print("unknown machine %s", mtype);
114 if (attachfiles(argc, argv) < 0)
115 varreg(); /* use default register set on error */
116 if(mach == nil)
117 mach = machcpu;
119 symhdr = nil; /* not supposed to use this anymore */
121 l = mkvar("acid");
122 l->v->set = 1;
123 l->v->type = TLIST;
124 l->v->store.u.l = nil;
126 loadmodule(unsharp("#9/acid/port"));
127 for(i = 0; i < nlm; i++) {
128 if(access(lm[i], AREAD) >= 0)
129 loadmodule(lm[i]);
130 else {
131 sprint(buf, "#9/acid/%s", lm[i]);
132 loadmodule(unsharp(buf));
136 userinit();
137 varsym();
139 l = look("acidmap");
140 if(l && l->proc) {
141 if(setjmp(err) == 0){
142 n = an(ONAME, ZN, ZN);
143 n->sym = l;
144 n = an(OCALL, n, ZN);
145 execute(n);
149 interactive = 1;
150 initialising = 0;
151 line = 1;
153 notify(catcher);
155 for(;;) {
156 if(setjmp(err)) {
157 Binit(&bioout, 1, OWRITE);
158 unwind();
160 stacked = 0;
162 Bprint(bout, "acid; ");
164 if(yyparse() != 1)
165 die();
166 restartio();
168 unwind();
170 /*
171 Bputc(bout, '\n');
172 exits(0);
173 */
176 void
177 setstring(char *var, char *s)
179 Lsym *l;
180 Value *v;
182 l = mkvar(var);
183 v = l->v;
184 v->store.fmt = 's';
185 v->set = 1;
186 v->store.u.string = strnode(s ? s : "");
187 v->type = TSTRING;
190 static int
191 attachfiles(int argc, char **argv)
193 volatile int pid;
194 Lsym *l;
196 pid = 0;
197 interactive = 0;
199 if(setjmp(err))
200 return -1;
202 attachargs(argc, argv, wtflag?ORDWR:OREAD, 1);
204 setstring("objtype", mach->name);
205 setstring("textfile", symfil);
206 setstring("systype", symhdr ? symhdr->aname : "");
207 setstring("corefile", corfil);
209 l = mkvar("pids");
210 l->v->set = 1;
211 l->v->type = TLIST;
212 l->v->store.u.l = nil;
214 if(corpid)
215 sproc(corpid);
216 if(corhdr)
217 setcore(corhdr);
218 varreg();
219 return 0;
222 void
223 setcore(Fhdr *hdr)
225 int i;
226 Lsym *l;
227 Value *v;
228 List **tail, *tl;
230 unmapproc(cormap);
231 unmapfile(corhdr, cormap);
232 free(correg);
233 correg = nil;
235 if(hdr == nil)
236 error("no core");
237 if(mapfile(hdr, 0, cormap, &correg) < 0)
238 error("mapfile %s: %r", hdr->filename);
239 corhdr = hdr;
240 corfil = hdr->filename;
242 l = mkvar("pid");
243 v = l->v;
244 v->store.fmt = 'D';
245 v->set = 1;
246 v->store.u.ival = hdr->pid;
248 setstring("corefile", corfil);
249 setstring("cmdline", hdr->cmdline);
251 l = mkvar("pids");
252 l->v->set = 1;
253 l->v->type = TLIST;
254 l->v->store.u.l = nil;
255 tail = &l->v->store.u.l;
256 for(i=0; i<hdr->nthread; i++){
257 tl = al(TINT);
258 tl->store.u.ival = hdr->thread[i].id;
259 tl->store.fmt = 'X';
260 *tail = tl;
261 tail = &tl->next;
264 if(hdr->nthread)
265 sproc(hdr->thread[0].id);
268 void
269 die(void)
271 Lsym *s;
272 List *f;
273 int first;
275 Bprint(bout, "\n");
277 first = 1;
278 s = look("proclist");
279 if(s && s->v->type == TLIST) {
280 for(f = s->v->store.u.l; f; f = f->next){
281 detachproc((int)f->store.u.ival);
282 Bprint(bout, "%s %d", first ? "/bin/kill -9" : "", (int)f->store.u.ival);
283 first = 0;
286 if(!first)
287 Bprint(bout, "\n");
288 exits(0);
291 void
292 userinit(void)
294 Lsym *l;
295 Node *n;
296 char buf[128], *p;
298 sprint(buf, "#9/acid/%s", mach->name);
299 loadmodule(unsharp(buf));
300 p = getenv("HOME");
301 if(p != 0) {
302 sprint(buf, "%s/lib/acid", p);
303 silent = 1;
304 loadmodule(buf);
307 interactive = 0;
308 if(setjmp(err)) {
309 unwind();
310 return;
312 l = look("acidinit");
313 if(l && l->proc) {
314 n = an(ONAME, ZN, ZN);
315 n->sym = l;
316 n = an(OCALL, n, ZN);
317 execute(n);
321 void
322 loadmodule(char *s)
324 interactive = 0;
325 if(setjmp(err)) {
326 unwind();
327 return;
329 pushfile(s);
330 silent = 0;
331 yyparse();
332 popio();
333 return;
336 Node*
337 an(int op, Node *l, Node *r)
339 Node *n;
341 n = gmalloc(sizeof(Node));
342 memset(n, 0, sizeof(Node));
343 n->gc.gclink = gcl;
344 gcl = (Gc*)n;
345 n->op = op;
346 n->left = l;
347 n->right = r;
348 return n;
351 List*
352 al(int t)
354 List *l;
356 l = gmalloc(sizeof(List));
357 memset(l, 0, sizeof(List));
358 l->type = t;
359 l->gc.gclink = gcl;
360 gcl = (Gc*)l;
361 return l;
364 Node*
365 con(int v)
367 Node *n;
369 n = an(OCONST, ZN, ZN);
370 n->store.u.ival = v;
371 n->store.fmt = 'X';
372 n->type = TINT;
373 return n;
376 void
377 fatal(char *fmt, ...)
379 char buf[128];
380 va_list arg;
382 va_start(arg, fmt);
383 vseprint(buf, buf+sizeof(buf), fmt, arg);
384 va_end(arg);
385 fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf);
386 exits(buf);
389 void
390 yyerror(char *fmt, ...)
392 char buf[128];
393 va_list arg;
395 if(strcmp(fmt, "syntax error") == 0) {
396 yyerror("syntax error, near symbol '%s'", symbol);
397 return;
399 va_start(arg, fmt);
400 vseprint(buf, buf+sizeof(buf), fmt, arg);
401 va_end(arg);
402 print("%Z: %s\n", buf);
405 void
406 marktree(Node *n)
409 if(n == 0)
410 return;
412 marktree(n->left);
413 marktree(n->right);
415 n->gc.gcmark = 1;
416 if(n->op != OCONST)
417 return;
419 switch(n->type) {
420 case TSTRING:
421 n->store.u.string->gc.gcmark = 1;
422 break;
423 case TLIST:
424 marklist(n->store.u.l);
425 break;
426 case TCODE:
427 marktree(n->store.u.cc);
428 break;
432 void
433 marklist(List *l)
435 while(l) {
436 l->gc.gcmark = 1;
437 switch(l->type) {
438 case TSTRING:
439 l->store.u.string->gc.gcmark = 1;
440 break;
441 case TLIST:
442 marklist(l->store.u.l);
443 break;
444 case TCODE:
445 marktree(l->store.u.cc);
446 break;
448 l = l->next;
452 void
453 gc(void)
455 int i;
456 Lsym *f;
457 Value *v;
458 Gc *m, **p, *next;
460 if(dogc < Mempergc)
461 return;
462 dogc = 0;
464 /* Mark */
465 for(m = gcl; m; m = m->gclink)
466 m->gcmark = 0;
468 /* Scan */
469 for(i = 0; i < Hashsize; i++) {
470 for(f = hash[i]; f; f = f->hash) {
471 marktree(f->proc);
472 if(f->lexval != Tid)
473 continue;
474 for(v = f->v; v; v = v->pop) {
475 switch(v->type) {
476 case TSTRING:
477 v->store.u.string->gc.gcmark = 1;
478 break;
479 case TLIST:
480 marklist(v->store.u.l);
481 break;
482 case TCODE:
483 marktree(v->store.u.cc);
484 break;
485 case TCON:
486 marktree(v->store.u.con);
487 break;
493 /* Free */
494 p = &gcl;
495 for(m = gcl; m; m = next) {
496 next = m->gclink;
497 if(m->gcmark == 0) {
498 *p = next;
499 free(m); /* Sleazy reliance on my malloc */
501 else
502 p = &m->gclink;
506 void*
507 gmalloc(long l)
509 void *p;
511 dogc += l;
512 p = malloc(l);
513 if(p == 0)
514 fatal("out of memory");
515 return p;
518 void
519 checkqid(int f1, int pid)
521 int fd;
522 Dir *d1, *d2;
523 char buf[128];
525 if(kernel)
526 return;
528 d1 = dirfstat(f1);
529 if(d1 == nil){
530 print("checkqid: (qid not checked) dirfstat: %r\n");
531 return;
534 sprint(buf, "/proc/%d/text", pid);
535 fd = open(buf, OREAD);
536 if(fd < 0 || (d2 = dirfstat(fd)) == nil){
537 print("checkqid: (qid not checked) dirstat %s: %r\n", buf);
538 free(d1);
539 if(fd >= 0)
540 close(fd);
541 return;
544 close(fd);
546 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){
547 print("path %#llux %#llux vers %lud %lud type %d %d\n",
548 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);
549 print("warning: image does not match text for pid %d\n", pid);
551 free(d1);
552 free(d2);
555 void
556 catcher(void *junk, char *s)
558 USED(junk);
560 if(strstr(s, "interrupt")) {
561 gotint = 1;
562 noted(NCONT);
564 if(strstr(s, "child"))
565 noted(NCONT);
566 fprint(2, "note: %s\n", s);
567 noted(NDFLT);
570 char*
571 system(void)
573 char *cpu, *p, *q;
574 static char kernel[128];
576 cpu = getenv("cputype");
577 if(cpu == 0) {
578 cpu = "mips";
579 print("$cputype not set; assuming %s\n", cpu);
581 p = getenv("terminal");
582 if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0) {
583 p = "9power";
584 print("missing or bad $terminal; assuming %s\n", p);
586 else{
587 p++;
588 q = strchr(p, ' ');
589 if(q)
590 *q = 0;
591 sprint(kernel, "/%s/9%s", cpu, p);
593 return kernel;
596 int
597 isnumeric(char *s)
599 while(*s) {
600 if(*s < '0' || *s > '9')
601 return 0;
602 s++;
604 return 1;