ref: 2c9e3861a54e22498fb2e3226defe4393b20b202
dir: /sys/src/cmd/acid/proc.c/
#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 nocore(void) { int i; if(cormap == 0) return; for (i = 0; i < cormap->nsegs; i++) if (cormap->seg[i].inuse && cormap->seg[i].fd >= 0) close(cormap->seg[i].fd); free(cormap); cormap = 0; } void sproc(int pid) { Lsym *s; char buf[64]; int i, fcor; if(symmap == 0) error("no map"); snprint(buf, sizeof(buf), "/proc/%d/mem", pid); fcor = open(buf, ORDWR); if(fcor < 0) error("setproc: open %s: %r", buf); checkqid(symmap->seg[0].fd, pid); s = look("pid"); s->v->ival = pid; nocore(); cormap = attachproc(pid, kernel, fcor, &fhdr); if (cormap == 0) error("setproc: can't make coremap: %r"); i = findseg(cormap, "text"); if (i > 0) cormap->seg[i].name = "*text"; i = findseg(cormap, "data"); if (i > 0) cormap->seg[i].name = "*data"; 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); snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid()); fd = open(buf, ORDWR); if(fd < 0) fatal("new: open %s: %r", buf); write(fd, "hang", 4); close(fd); close(0); close(1); close(2); for(i = 3; i < NFD; i++) close(i); open("/dev/cons", OREAD); open("/dev/cons", OWRITE); open("/dev/cons", OWRITE); exec(argv[0], argv); fatal("new: exec %s: %r", argv[0]); 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, fd; char buf[128]; List *l, **tail; s = look("notes"); if(s == 0) return; v = s->v; snprint(buf, sizeof(buf), "/proc/%d/note", pid); fd = open(buf, OREAD); if(fd < 0) error("pid=%d: open note: %r", pid); v->set = 1; v->type = TLIST; v->l = 0; tail = &v->l; for(;;) { i = read(fd, buf, sizeof(buf)); if(i <= 0) break; buf[i] = '\0'; l = al(TSTRING); l->string = strnode(buf); l->fmt = 's'; *tail = l; tail = &l->next; } close(fd); } 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->fmt = 'D'; np->type = TINT; p = con(pid); p->fmt = 'D'; np = an(OCALL, np, p); execute(np); } } static void install(int pid) { Lsym *s; List *l; char buf[128]; int i, fd, 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"); snprint(buf, sizeof(buf), "/proc/%d/ctl", pid); fd = open(buf, OWRITE); if(fd < 0) error("pid=%d: open ctl: %r", pid); ptab[new].pid = pid; ptab[new].ctl = fd; s = look("proclist"); l = al(TINT); l->fmt = 'D'; l->ival = pid; l->next = s->v->l; s->v->l = l; s->v->set = 1; callhook("procattach"); } void deinstall(int pid) { int i; Lsym *s; List *f, **d; for(i = 0; i < Maxproc; i++) { if(ptab[i].pid == pid) { close(ptab[i].ctl); ptab[i].pid = 0; s = look("proclist"); d = &s->v->l; for(f = *d; f; f = f->next) { if(f->ival == pid) { *d = f->next; break; } } s = look("pid"); if(s->v->ival == pid) s->v->ival = 0; return; } } } void msg(int pid, char *msg) { int i; int l; char err[ERRMAX]; for(i = 0; i < Maxproc; i++) { if(ptab[i].pid == pid) { l = strlen(msg); if(write(ptab[i].ctl, msg, l) != l) { 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, n; char *argv[16], buf[64]; static char status[128]; snprint(buf, sizeof(buf), "/proc/%d/status", pid); fd = open(buf, OREAD); if(fd < 0) error("open %s: %r", buf); n = read(fd, status, sizeof(status)-1); close(fd); if(n <= 0) error("read %s: %r", buf); status[n] = '\0'; if(tokenize(status, argv, nelem(argv)-1) < 3) error("tokenize %s: %r", buf); return argv[2]; } Waitmsg* waitfor(int pid) { Waitmsg *w; for(;;) { if((w = wait()) == nil) error("wait %r"); if(w->pid == pid) return w; free(w); } }