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 USED(pid);
98 fmtinstall('Z', Zfmt);
99 fmtinstall('L', locfmt);
100 Binit(&bioout, 1, OWRITE);
101 bout = &bioout;
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;
113 if(mtype && machbyname(mtype) == 0)
114 print("unknown machine %s", mtype);
116 if (attachfiles(argc, argv) < 0)
117 varreg(); /* use default register set on error */
118 if(mach == nil)
119 mach = machcpu;
121 symhdr = nil; /* not supposed to use this anymore */
123 l = mkvar("acid");
124 l->v->set = 1;
125 l->v->type = TLIST;
126 l->v->store.u.l = nil;
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));
138 userinit();
139 varsym();
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);
151 interactive = 1;
152 initialising = 0;
153 line = 1;
155 notify(catcher);
157 for(;;) {
158 if(setjmp(err)) {
159 Binit(&bioout, 1, OWRITE);
160 unwind();
162 stacked = 0;
164 Bprint(bout, "acid; ");
166 if(yyparse() != 1)
167 die();
168 restartio();
170 unwind();
172 /*
173 Bputc(bout, '\n');
174 exits(0);
175 */
178 void
179 setstring(char *var, char *s)
181 Lsym *l;
182 Value *v;
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;
192 static int
193 attachfiles(int argc, char **argv)
195 volatile int pid;
196 Lsym *l;
198 pid = 0;
199 interactive = 0;
200 USED(pid);
202 if(setjmp(err))
203 return -1;
205 attachargs(argc, argv, wtflag?ORDWR:OREAD, 1);
207 setstring("objtype", mach->name);
208 setstring("textfile", symfil);
209 setstring("systype", symhdr ? symhdr->aname : "");
210 setstring("corefile", corfil);
212 l = mkvar("pids");
213 l->v->set = 1;
214 l->v->type = TLIST;
215 l->v->store.u.l = nil;
217 if(corpid)
218 sproc(corpid);
219 if(corhdr)
220 setcore(corhdr);
221 varreg();
222 return 0;
225 void
226 setcore(Fhdr *hdr)
228 int i;
229 Lsym *l;
230 Value *v;
231 List **tail, *tl;
233 unmapproc(cormap);
234 unmapfile(corhdr, cormap);
235 free(correg);
236 correg = nil;
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;
245 l = mkvar("pid");
246 v = l->v;
247 v->store.fmt = 'D';
248 v->set = 1;
249 v->store.u.ival = hdr->pid;
251 setstring("corefile", corfil);
252 setstring("cmdline", hdr->cmdline);
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;
267 if(hdr->nthread)
268 sproc(hdr->thread[0].id);
271 void
272 die(void)
274 Lsym *s;
275 List *f;
276 int first;
278 Bprint(bout, "\n");
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" : "", (int)f->store.u.ival);
286 first = 0;
289 if(!first)
290 Bprint(bout, "\n");
291 exits(0);
294 void
295 userinit(void)
297 Lsym *l;
298 Node *n;
299 char buf[128], *p;
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);
310 interactive = 0;
311 if(setjmp(err)) {
312 unwind();
313 return;
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);
324 void
325 loadmodule(char *s)
327 interactive = 0;
328 if(setjmp(err)) {
329 unwind();
330 return;
332 pushfile(s);
333 silent = 0;
334 yyparse();
335 popio();
336 return;
339 Node*
340 an(int op, Node *l, Node *r)
342 Node *n;
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;
354 List*
355 al(int t)
357 List *l;
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;
367 Node*
368 con(s64int v)
370 Node *n;
372 n = an(OCONST, ZN, ZN);
373 n->store.u.ival = v;
374 n->store.fmt = 'X';
375 n->type = TINT;
376 return n;
379 void
380 fatal(char *fmt, ...)
382 char buf[128];
383 va_list arg;
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);
392 void
393 yyerror(char *fmt, ...)
395 char buf[128];
396 va_list arg;
398 if(strcmp(fmt, "syntax error") == 0) {
399 yyerror("syntax error, near symbol '%s'", symbol);
400 return;
402 va_start(arg, fmt);
403 vseprint(buf, buf+sizeof(buf), fmt, arg);
404 va_end(arg);
405 print("%Z: %s\n", buf);
408 void
409 marktree(Node *n)
412 if(n == 0)
413 return;
415 marktree(n->left);
416 marktree(n->right);
418 n->gc.gcmark = 1;
419 if(n->op != OCONST)
420 return;
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;
435 void
436 marklist(List *l)
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;
451 l = l->next;
455 void
456 gc(void)
458 int i;
459 Lsym *f;
460 Value *v;
461 Gc *m, **p, *next;
463 if(dogc < Mempergc)
464 return;
465 dogc = 0;
467 /* Mark */
468 for(m = gcl; m; m = m->gclink)
469 m->gcmark = 0;
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;
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 */
504 else
505 p = &m->gclink;
509 void*
510 gmalloc(long l)
512 void *p;
514 dogc += l;
515 p = malloc(l);
516 if(p == 0)
517 fatal("out of memory");
518 return p;
521 void
522 checkqid(int f1, int pid)
524 int fd;
525 Dir *d1, *d2;
526 char buf[128];
528 if(kernel)
529 return;
531 d1 = dirfstat(f1);
532 if(d1 == nil){
533 print("checkqid: (qid not checked) dirfstat: %r\n");
534 return;
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", buf);
541 free(d1);
542 if(fd >= 0)
543 close(fd);
544 return;
547 close(fd);
549 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){
550 print("path %#llux %#llux vers %lud %lud type %d %d\n",
551 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);
552 print("warning: image does not match text for pid %d\n", pid);
554 free(d1);
555 free(d2);
558 void
559 catcher(void *junk, char *s)
561 USED(junk);
563 if(strstr(s, "interrupt")) {
564 gotint = 1;
565 noted(NCONT);
567 if(strstr(s, "child"))
568 noted(NCONT);
569 fprint(2, "note: %s\n", s);
570 noted(NDFLT);
573 char*
574 system(void)
576 char *cpu, *p, *q;
577 static char kernel[128];
579 cpu = getenv("cputype");
580 if(cpu == 0) {
581 cpu = "mips";
582 print("$cputype not set; assuming %s\n", cpu);
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);
589 else{
590 p++;
591 q = strchr(p, ' ');
592 if(q)
593 *q = 0;
594 sprint(kernel, "/%s/9%s", cpu, p);
596 return kernel;
599 int
600 isnumeric(char *s)
602 while(*s) {
603 if(*s < '0' || *s > '9')
604 return 0;
605 s++;
607 return 1;