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