]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/acid/proc.c
etheriwl: don't break controller on command flush timeout
[plan9front.git] / sys / src / cmd / acid / proc.c
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         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
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", argv[0]);
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
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
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
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         callhook("procattach");
194 }
195
196 void
197 deinstall(int pid)
198 {
199         int i;
200         Lsym *s;
201         List *f, **d;
202
203         for(i = 0; i < Maxproc; i++) {
204                 if(ptab[i].pid == pid) {
205                         close(ptab[i].ctl);
206                         ptab[i].pid = 0;
207                         s = look("proclist");
208                         d = &s->v->l;
209                         for(f = *d; f; f = f->next) {
210                                 if(f->ival == pid) {
211                                         *d = f->next;
212                                         break;
213                                 }
214                         }
215                         s = look("pid");
216                         if(s->v->ival == pid)
217                                 s->v->ival = 0;
218                         return;
219                 }
220         }
221 }
222
223 void
224 msg(int pid, char *msg)
225 {
226         int i;
227         int l;
228         char err[ERRMAX];
229
230         for(i = 0; i < Maxproc; i++) {
231                 if(ptab[i].pid == pid) {
232                         l = strlen(msg);
233                         if(write(ptab[i].ctl, msg, l) != l) {
234                                 errstr(err, sizeof err);
235                                 if(strcmp(err, "process exited") == 0)
236                                         deinstall(pid);
237                                 error("msg: pid=%d %s: %s", pid, msg, err);
238                         }
239                         return;
240                 }
241         }
242         error("msg: pid=%d: not found for %s", pid, msg);
243 }
244
245 char *
246 getstatus(int pid)
247 {
248         int fd, n;
249         char *argv[16], buf[64];
250         static char status[128];
251
252         snprint(buf, sizeof(buf), "/proc/%d/status", pid);
253         fd = open(buf, OREAD);
254         if(fd < 0)
255                 error("open %s: %r", buf);
256
257         n = read(fd, status, sizeof(status)-1);
258         close(fd);
259         if(n <= 0)
260                 error("read %s: %r", buf);
261         status[n] = '\0';
262
263         if(tokenize(status, argv, nelem(argv)-1) < 3)
264                 error("tokenize %s: %r", buf);
265
266         return argv[2];
267 }
268
269 Waitmsg*
270 waitfor(int pid)
271 {
272         Waitmsg *w;
273
274         for(;;) {
275                 if((w = wait()) == nil)
276                         error("wait %r");
277                 if(w->pid == pid)
278                         return w;
279                 free(w);
280         }
281 }