acid
diff --git a/src/cmd/acid/proc.c b/src/cmd/acid/proc.c
new file mode 100644
index 0000000..3b862aa
--- /dev/null
+++ b/src/cmd/acid/proc.c
@@ -0,0 +1,251 @@
+#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;
+
+	if(symmap == 0)
+		error("no map");
+
+	if(pid == xpid)
+		return;
+
+	if(xpid <= 0)
+		error("bad pid");
+
+	unmapproc(cormap);
+	unmapfile(corhdr, cormap);
+	free(correg);
+	correg = nil;
+
+	if(mapproc(xpid, cormap, &correg) < 0)
+		error("setproc %d: %r", pid);
+
+	/* XXX check text file here? */
+
+	pid = xpid;
+	s = look("pid");
+	s->v->store.u.ival = pid;
+
+	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";
+		}
+	install(pid);
+}
+
+int
+nproc(char **argv)
+{
+	char buf[128];
+	int pid, i, fd;
+
+	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);
+		exec(argv[0], argv);
+		fatal("new: exec %s: %r");
+	default:
+		install(pid);
+		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, &notes);
+	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;
+}
+
+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)
+{
+	int fd;
+	char *p;
+
+	static char buf[128];
+
+	sprint(buf, "/proc/%d/status", pid);
+	fd = open(buf, OREAD);
+	if(fd < 0)
+		error("open %s: %r", buf);
+	read(fd, buf, sizeof(buf));
+	close(fd);
+	p = buf+56+12;			/* Do better! */
+	while(*p == ' ')
+		p--;
+	p[1] = '\0';
+	return buf+56;			/* ditto */
+}
+
+Waitmsg*
+waitfor(int pid)
+{
+	Waitmsg *w;
+
+	for(;;) {
+		if((w = wait()) == nil)
+			error("wait %r");
+		if(w->pid == pid)
+			return w;
+		free(w);
+	}
+	return nil;	/* ken */
+}