Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include <mach.h>5 #define Extern6 #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 void23 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 void53 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 }ARGEND96 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));133 }134 }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);146 }147 }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();159 }160 stacked = 0;162 Bprint(bout, "acid; ");164 if(yyparse() != 1)165 die();166 restartio();168 unwind();169 }170 /*171 Bputc(bout, '\n');172 exits(0);173 */174 }176 void177 setstring(char *var, char *s)178 {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;188 }190 static int191 attachfiles(int argc, char **argv)192 {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;220 }222 void223 setcore(Fhdr *hdr)224 {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;262 }264 if(hdr->nthread)265 sproc(hdr->thread[0].id);266 }268 void269 die(void)270 {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;284 }285 }286 if(!first)287 Bprint(bout, "\n");288 exits(0);289 }291 void292 userinit(void)293 {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);305 }307 interactive = 0;308 if(setjmp(err)) {309 unwind();310 return;311 }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);318 }319 }321 void322 loadmodule(char *s)323 {324 interactive = 0;325 if(setjmp(err)) {326 unwind();327 return;328 }329 pushfile(s);330 silent = 0;331 yyparse();332 popio();333 return;334 }336 Node*337 an(int op, Node *l, Node *r)338 {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;349 }351 List*352 al(int t)353 {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;362 }364 Node*365 con(int v)366 {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;374 }376 void377 fatal(char *fmt, ...)378 {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);387 }389 void390 yyerror(char *fmt, ...)391 {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;398 }399 va_start(arg, fmt);400 vseprint(buf, buf+sizeof(buf), fmt, arg);401 va_end(arg);402 print("%Z: %s\n", buf);403 }405 void406 marktree(Node *n)407 {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;429 }430 }432 void433 marklist(List *l)434 {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;447 }448 l = l->next;449 }450 }452 void453 gc(void)454 {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;488 }489 }490 }491 }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 */500 }501 else502 p = &m->gclink;503 }504 }506 void*507 gmalloc(long l)508 {509 void *p;511 dogc += l;512 p = malloc(l);513 if(p == 0)514 fatal("out of memory");515 return p;516 }518 void519 checkqid(int f1, int pid)520 {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;532 }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;542 }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);550 }551 free(d1);552 free(d2);553 }555 void556 catcher(void *junk, char *s)557 {558 USED(junk);560 if(strstr(s, "interrupt")) {561 gotint = 1;562 noted(NCONT);563 }564 if(strstr(s, "child"))565 noted(NCONT);566 fprint(2, "note: %s\n", s);567 noted(NDFLT);568 }570 char*571 system(void)572 {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);580 }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);585 }586 else{587 p++;588 q = strchr(p, ' ');589 if(q)590 *q = 0;591 sprint(kernel, "/%s/9%s", cpu, p);592 }593 return kernel;594 }596 int597 isnumeric(char *s)598 {599 while(*s) {600 if(*s < '0' || *s > '9')601 return 0;602 s++;603 }604 return 1;605 }