| #include <u.h> | 
 | #include <libc.h> | 
 | #include <bio.h> | 
 | #include <ctype.h> | 
 | #include <mach.h> | 
 | #define Extern extern | 
 | #include "acid.h" | 
 | #include "y.tab.h" | 
 |  | 
 | static void install(int); | 
 |  | 
 | void | 
 | sproc(int xpid) | 
 | { | 
 | 	Lsym *s; | 
 | 	int i; | 
 | 	Regs *regs; | 
 |  | 
 | 	if(symmap == 0) | 
 | 		error("no map"); | 
 |  | 
 | 	if(pid == xpid) | 
 | 		return; | 
 |  | 
 | 	if(corhdr){ | 
 | 		regs = coreregs(corhdr, xpid); | 
 | 		if(regs == nil) | 
 | 			error("no such pid in core dump"); | 
 | 		free(correg); | 
 | 		correg = regs; | 
 | 	}else{ | 
 | 		/* XXX should only change register set here if cormap already mapped */		 | 
 | 		if(xpid <= 0) | 
 | 			error("bad pid"); | 
 | 		unmapproc(cormap); | 
 | 		unmapfile(corhdr, cormap); | 
 | 		free(correg); | 
 | 		correg = nil; | 
 | 		pid = -1; | 
 | 		corpid = -1; | 
 |  | 
 | 		if(mapproc(xpid, cormap, &correg) < 0) | 
 | 			error("setproc %d: %r", xpid); | 
 |  | 
 | 		/* XXX check text file here? */ | 
 |  | 
 | 		for(i=0; i<cormap->nseg; i++){ | 
 | 			if(cormap->seg[i].file == nil){ | 
 | 				if(strcmp(cormap->seg[i].name, "data") == 0) | 
 | 					cormap->seg[i].name = "*data"; | 
 | 				if(strcmp(cormap->seg[i].name, "text") == 0) | 
 | 					cormap->seg[i].name = "*text"; | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	pid = xpid; | 
 | 	corpid = pid; | 
 | 	s = look("pid"); | 
 | 	s->v->store.u.ival = pid; | 
 |  | 
 | 	install(pid); | 
 | } | 
 |  | 
 | int | 
 | nproc(char **argv) | 
 | { | 
 | 	int pid, i; | 
 |  | 
 | 	pid = fork(); | 
 | 	switch(pid) { | 
 | 	case -1: | 
 | 		error("new: fork %r"); | 
 | 	case 0: | 
 | 		rfork(RFNAMEG|RFNOTEG); | 
 | 		if(ctlproc(getpid(), "hang") < 0) | 
 | 			fatal("new: hang %d: %r", getpid()); | 
 |  | 
 | 		close(0); | 
 | 		close(1); | 
 | 		close(2); | 
 | 		for(i = 3; i < NFD; i++) | 
 | 			close(i); | 
 |  | 
 | 		open("/dev/tty", OREAD); | 
 | 		open("/dev/tty", OWRITE); | 
 | 		open("/dev/tty", OWRITE); | 
 | 		execv(argv[0], argv); | 
 | 		fatal("new: exec %s: %r", argv[0]); | 
 | 	default: | 
 | 		install(pid); | 
 | 		msg(pid, "attached"); | 
 | 		msg(pid, "waitstop"); | 
 | 		notes(pid); | 
 | 		sproc(pid); | 
 | 		dostop(pid); | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	return pid; | 
 | } | 
 |  | 
 | void | 
 | notes(int pid) | 
 | { | 
 | 	Lsym *s; | 
 | 	Value *v; | 
 | 	int i, n; | 
 | 	char **notes; | 
 | 	List *l, **tail; | 
 |  | 
 | 	s = look("notes"); | 
 | 	if(s == 0) | 
 | 		return; | 
 |  | 
 | 	v = s->v; | 
 | 	n = procnotes(pid, ¬es); | 
 | 	if(n < 0) | 
 | 		error("procnotes pid=%d: %r", pid); | 
 |  | 
 | 	v->set = 1; | 
 | 	v->type = TLIST; | 
 | 	v->store.u.l = 0; | 
 | 	tail = &v->store.u.l; | 
 | 	for(i=0; i<n; i++) { | 
 | 		l = al(TSTRING); | 
 | 		l->store.u.string = strnode(notes[i]); | 
 | 		l->store.fmt = 's'; | 
 | 		*tail = l; | 
 | 		tail = &l->next; | 
 | 	} | 
 | 	free(notes); | 
 | } | 
 |  | 
 | void | 
 | dostop(int pid) | 
 | { | 
 | 	Lsym *s; | 
 | 	Node *np, *p; | 
 |  | 
 | 	s = look("stopped"); | 
 | 	if(s && s->proc) { | 
 | 		np = an(ONAME, ZN, ZN); | 
 | 		np->sym = s; | 
 | 		np->store.fmt = 'D'; | 
 | 		np->type = TINT; | 
 | 		p = con(pid); | 
 | 		p->store.fmt = 'D'; | 
 | 		np = an(OCALL, np, p); | 
 | 		execute(np); | 
 | 	} | 
 | } | 
 |  | 
 | static void | 
 | install(int pid) | 
 | { | 
 | 	Lsym *s; | 
 | 	List *l; | 
 | 	int i, new, p; | 
 |  | 
 | 	new = -1; | 
 | 	for(i = 0; i < Maxproc; i++) { | 
 | 		p = ptab[i].pid; | 
 | 		if(p == pid) | 
 | 			return; | 
 | 		if(p == 0 && new == -1) | 
 | 			new = i; | 
 | 	} | 
 | 	if(new == -1) | 
 | 		error("no free process slots"); | 
 |  | 
 | 	ptab[new].pid = pid; | 
 |  | 
 | 	s = look("proclist"); | 
 | 	l = al(TINT); | 
 | 	l->store.fmt = 'D'; | 
 | 	l->store.u.ival = pid; | 
 | 	l->next = s->v->store.u.l; | 
 | 	s->v->store.u.l = l; | 
 | 	s->v->set = 1; | 
 | } | 
 |  | 
 | /* | 
 | static int | 
 | installed(int pid) | 
 | { | 
 | 	int i; | 
 |  | 
 | 	for(i=0; i<Maxproc; i++) | 
 | 		if(ptab[i].pid == pid) | 
 | 			return 1; | 
 | 	return 0; | 
 | } | 
 | */ | 
 |  | 
 | void | 
 | deinstall(int pid) | 
 | { | 
 | 	int i; | 
 | 	Lsym *s; | 
 | 	List *f, **d; | 
 |  | 
 | 	for(i = 0; i < Maxproc; i++) { | 
 | 		if(ptab[i].pid == pid) { | 
 | 			detachproc(pid); | 
 | 			/* close(ptab[i].ctl); */ | 
 | 			ptab[i].pid = 0; | 
 | 			s = look("proclist"); | 
 | 			d = &s->v->store.u.l; | 
 | 			for(f = *d; f; f = f->next) { | 
 | 				if(f->store.u.ival == pid) { | 
 | 					*d = f->next; | 
 | 					break; | 
 | 				} | 
 | 			} | 
 | 			s = look("pid"); | 
 | 			if(s->v->store.u.ival == pid) | 
 | 				s->v->store.u.ival = 0; | 
 | 			return; | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | void | 
 | msg(int pid, char *msg) | 
 | { | 
 | 	int i; | 
 | 	char err[ERRMAX]; | 
 |  | 
 | 	for(i = 0; i < Maxproc; i++) { | 
 | 		if(ptab[i].pid == pid) { | 
 | 			if(ctlproc(pid, msg) < 0){ | 
 | 				errstr(err, sizeof err); | 
 | 				if(strcmp(err, "process exited") == 0) | 
 | 					deinstall(pid); | 
 | 				error("msg: pid=%d %s: %s", pid, msg, err); | 
 | 			} | 
 | 			return; | 
 | 		} | 
 | 	} | 
 | 	error("msg: pid=%d: not found for %s", pid, msg); | 
 | } | 
 |  | 
 | char * | 
 | getstatus(int pid) | 
 | { | 
 | 	return "unknown"; | 
 | } | 
 |  |