dots

Personal dotfiles
git clone git://git.gormless.xyz/dots.git
Log | Files | Refs

main.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] [-k] [pid] [file]\n");
     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 error */
    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" : "", (int)f->store.u.ival);
    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", buf);
    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 || 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);
    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 }