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