xref: /plan9-contrib/sys/src/cmd/acid/proc.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5 #include <mach.h>
6 #define Extern extern
7 #include "acid.h"
8 #include "y.tab.h"
9 
10 static void install(int);
11 
12 static void
13 fixregs(Map *map)
14 {
15 	Reglist *rp;
16 	Lsym *l;
17 	long flen;
18 
19 	static int doneonce;
20 
21 	switch(mach->mtype) {
22 	default:
23 	case MMIPS:
24 	case MSPARC:
25 		return;
26 	case MI386:
27 		if (doneonce)
28 			return;
29 		doneonce = 1;
30 		flen = 0;
31 		break;
32 	case M68020:
33 		if (machdata->ufixup(map, &flen) < 0)
34 			error("fixregs: %r\n");
35 		break;
36 	}
37 	for (rp = mach->reglist; rp->rname; rp++) {
38 		if ((rp->rflags&RFLT))
39 			continue;
40 		l = look(rp->rname);
41 		if(l == 0)
42 			print("lost register %s\n", rp->rname);
43 		else
44 			l->v->ival = mach->kbase+rp->roffs-flen;
45 	}
46 }
47 
48 void
49 sproc(int pid)
50 {
51 	Lsym *s;
52 	ulong ksp;
53 	char buf[64];
54 	int fd, fcor;
55 
56 	if(symmap == 0)
57 		error("no map");
58 
59 	sprint(buf, "/proc/%d/mem", pid);
60 	fcor = open(buf, ORDWR);
61 	if(fcor < 0)
62 		error("setproc: open %s: %r", buf);
63 
64 	checkqid(symmap->fd, pid);
65 
66 	if(cormap)
67 		close(cormap->fd);
68 
69 	s = look("pid");
70 	s->v->ival = pid;
71 
72 	sprint(buf, "/proc/%d/proc", pid);
73 	fd = open(buf, 0);
74 	if(fd >= 0){
75 		seek(fd, mach->kspoff, 0);
76 		if(read(fd, (char *)&ksp, 4L) == 4)
77 			mach->kbase = machdata->swal(ksp) & ~(mach->pgsize-1);
78 		close(fd);
79 	}
80 
81 	cormap = newmap(cormap, fcor, 3);
82 	if (cormap == 0)
83 		error("setproc: cant make coremap");
84 
85 	setmap(cormap, fhdr.txtaddr, fhdr.txtaddr+fhdr.txtsz, fhdr.txtaddr, "*text");
86 	setmap(cormap, fhdr.dataddr, mach->kbase&~mach->ktmask, fhdr.dataddr, "*data");
87 	setmap(cormap, mach->kbase, mach->kbase+mach->pgsize, mach->kbase, "*ublock");
88 	install(pid);
89 	fixregs(cormap);
90 }
91 
92 int
93 nproc(char **argv)
94 {
95 	char buf[128];
96 	int pid, i, fd;
97 
98 	pid = fork();
99 	switch(pid) {
100 	case -1:
101 		error("new: fork %r");
102 	case 0:
103 		rfork(RFNAMEG|RFNOTEG);
104 
105 		sprint(buf, "/proc/%d/ctl", getpid());
106 		fd = open(buf, ORDWR);
107 		if(fd < 0)
108 			fatal("new: open %s: %r", buf);
109 		write(fd, "hang", 4);
110 		close(fd);
111 
112 		close(0);
113 		close(1);
114 		close(2);
115 		for(i = 3; i < NFD; i++)
116 			close(i);
117 
118 		open("/dev/cons", OREAD);
119 		open("/dev/cons", OWRITE);
120 		open("/dev/cons", OWRITE);
121 		exec(argv[0], argv);
122 		fatal("new: exec %s: %r");
123 	default:
124 		install(pid);
125 		msg(pid, "waitstop");
126 		notes(pid);
127 		sproc(pid);
128 		dostop(pid);
129 		break;
130 	}
131 
132 	return pid;
133 }
134 
135 void
136 notes(int pid)
137 {
138 	Lsym *s;
139 	Value *v;
140 	int i, fd;
141 	char buf[128];
142 	List *l, **tail;
143 
144 	s = look("notes");
145 	if(s == 0)
146 		return;
147 	v = s->v;
148 
149 	sprint(buf, "/proc/%d/note", pid);
150 	fd = open(buf, OREAD);
151 	if(fd < 0)
152 		error("pid=%d: open note: %r", pid);
153 
154 	v->set = 1;
155 	v->type = TLIST;
156 	v->l = 0;
157 	tail = &v->l;
158 	for(;;) {
159 		i = read(fd, buf, sizeof(buf));
160 		if(i <= 0)
161 			break;
162 		buf[i] = '\0';
163 		l = al(TSTRING);
164 		l->string = strnode(buf);
165 		l->fmt = 's';
166 		*tail = l;
167 		tail = &l->next;
168 	}
169 	close(fd);
170 }
171 
172 void
173 dostop(int pid)
174 {
175 	Lsym *s;
176 	Node *np, *p;
177 
178 	fixregs(cormap);
179 
180 	s = look("stopped");
181 	if(s && s->proc) {
182 		np = an(ONAME, ZN, ZN);
183 		np->sym = s;
184 		np->fmt = 'D';
185 		np->type = TINT;
186 		p = con(pid);
187 		p->fmt = 'D';
188 		np = an(OCALL, np, p);
189 		execute(np);
190 	}
191 }
192 
193 static void
194 install(int pid)
195 {
196 	Lsym *s;
197 	List *l;
198 	char buf[128];
199 	int i, fd, new, p;
200 
201 	new = -1;
202 	for(i = 0; i < Maxproc; i++) {
203 		p = ptab[i].pid;
204 		if(p == pid)
205 			return;
206 		if(p == 0 && new == -1)
207 			new = i;
208 	}
209 	if(new == -1)
210 		error("no free process slots");
211 
212 	sprint(buf, "/proc/%d/ctl", pid);
213 	fd = open(buf, OWRITE);
214 	if(fd < 0)
215 		error("pid=%d: open ctl: %r", pid);
216 
217 	ptab[new].pid = pid;
218 	ptab[new].ctl = fd;
219 
220 	s = look("proclist");
221 	l = al(TINT);
222 	l->fmt = 'D';
223 	l->ival = pid;
224 	l->next = s->v->l;
225 	s->v->l = l;
226 	s->v->set = 1;
227 }
228 
229 void
230 deinstall(int pid)
231 {
232 	int i;
233 	Lsym *s;
234 	List *f, **d;
235 
236 	for(i = 0; i < Maxproc; i++) {
237 		if(ptab[i].pid == pid) {
238 			close(ptab[i].ctl);
239 			ptab[i].pid = 0;
240 			s = look("proclist");
241 			d = &s->v->l;
242 			for(f = *d; f; f = f->next) {
243 				if(f->ival == pid) {
244 					*d = f->next;
245 					break;
246 				}
247 			}
248 			s = look("pid");
249 			if(s->v->ival == pid)
250 				s->v->ival = 0;
251 			return;
252 		}
253 	}
254 }
255 
256 void
257 msg(int pid, char *msg)
258 {
259 	int i;
260 	int l;
261 	char err[ERRLEN];
262 
263 	for(i = 0; i < Maxproc; i++) {
264 		if(ptab[i].pid == pid) {
265 			l = strlen(msg);
266 			if(write(ptab[i].ctl, msg, l) != l) {
267 				errstr(err);
268 				if(strcmp(err, "process exited") == 0)
269 					deinstall(pid);
270 				error("msg: pid=%d %s: %s", pid, msg, err);
271 			}
272 			return;
273 		}
274 	}
275 	error("msg: pid=%d: not found for %s", pid, msg);
276 }
277 
278 char *
279 getstatus(int pid)
280 {
281 	int fd;
282 	char *p;
283 
284 	static char buf[128];
285 
286 	sprint(buf, "/proc/%d/status", pid);
287 	fd = open(buf, OREAD);
288 	if(fd < 0)
289 		error("open %s: %r", buf);
290 	read(fd, buf, sizeof(buf));
291 	close(fd);
292 	p = buf+56+12;			/* Do better! */
293 	while(*p == ' ')
294 		p--;
295 	p[1] = '\0';
296 	return buf+56;			/* ditto */
297 }
298 
299 char *
300 waitfor(int pid)
301 {
302 	int n;
303 
304 	static Waitmsg w;
305 
306 	for(;;) {
307 		n = wait(&w);
308 		if(n < 0)
309 			error("wait %r");
310 		if(n == pid)
311 			return w.msg;
312 	}
313 }
314