]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/proc.c
grep: error if sbrk fails
[plan9front.git] / sys / src / cmd / 5e / proc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <bio.h>
5 #include <mach.h>
6 #include <ctype.h>
7 #include "dat.h"
8 #include "fns.h"
9
10 #pragma pack on
11 typedef struct Tos Tos;
12 struct Tos {
13         struct                  /* Per process profiling */
14         {
15                 ulong   pp;     /* known to be 0(ptr) */
16                 ulong   next;   /* known to be 4(ptr) */
17                 ulong   last;
18                 ulong   first;
19                 ulong   pid;
20                 ulong   what;
21         } prof;
22         uvlong  cyclefreq;      /* cycle clock frequency if there is one, 0 otherwise */
23         vlong   kcycles;        /* cycles spent in kernel */
24         vlong   pcycles;        /* cycles spent in process (kernel + user) */
25         ulong   pid;            /* might as well put the pid here */
26         ulong   clock;
27         /* top of stack is here */
28 };
29 #pragma pack off
30
31 Process plist;
32 Lock plistlock;
33
34 void
35 initproc(void)
36 {
37         P = emallocz(sizeof(Process));
38         P->pid = getpid();
39         P->fd = newfd();
40         incref(&nproc);
41         plist.prev = P;
42         plist.next = P;
43         P->prev = &plist;
44         P->next = &plist;
45         if(vfp)
46                 resetvfp();
47         else
48                 resetfpa();
49 }
50
51 void
52 addproc(Process *p)
53 {
54         lock(&plistlock);
55         p->prev = plist.prev;
56         p->next = &plist;
57         plist.prev->next = p;
58         plist.prev = p;
59         unlock(&plistlock);
60 }
61
62 void
63 remproc(Process *p)
64 {
65         lock(&plistlock);
66         p->prev->next = p->next;
67         p->next->prev = p->prev;
68         unlock(&plistlock);
69 }
70
71 Process *
72 findproc(int pid)
73 {
74         Process *p;
75
76         lock(&plistlock);
77         for(p = plist.next; p != &plist; p = p->next)
78                 if(p->pid == pid)
79                         break;
80         unlock(&plistlock);
81         if(p != &plist)
82                 return p;
83         return nil;
84 }
85
86 static void
87 copyname(char *file)
88 {
89         char *p;
90         
91         p = strrchr(file, '/');
92         if(p == nil)
93                 p = file;
94         else
95                 p++;
96         strncpy(P->name, p, NAMEMAX);
97
98         if(P->path != nil && decref(P->path) == 0)
99                 free(P->path);
100         P->path = emallocz(sizeof(Ref) + strlen(file)+1);
101         incref(P->path);
102         strcpy((char*)(P->path + 1), file);
103 }
104
105 static void
106 initstack(int argc, char **argv)
107 {
108         ulong tos, sp, ap, size, i, len;
109         
110         tos = (mach->utop & ~7) - sizeof(Tos) * 2;
111         sp = tos;
112         
113         size = 8;
114         for(i = 0; i < argc; i++)
115                 size += strlen(argv[i]) + 5;
116         
117         sp -= size;
118         sp &= ~7;
119         P->R[0] = tos;
120         P->R[1] = mach->utop - 4;
121         P->R[13] = sp;
122         
123         *(ulong *) vaddrnol(sp, 4) = argc;
124         sp += 4;
125         ap = sp + (argc + 1) * 4;
126         for(i = 0; i < argc; i++) {
127                 *(ulong *) vaddrnol(sp, 4) = ap;
128                 sp += 4;
129                 len = strlen(argv[i]) + 1;
130                 memcpy(vaddrnol(ap, len), argv[i], len);
131                 ap += len;
132         }
133         *(ulong *) vaddrnol(sp, 4) = 0;
134         inittos();
135 }
136
137 void
138 inittos(void)
139 {
140         ulong tos;
141
142         tos = (mach->utop & ~7) - sizeof(Tos) * 2;
143         ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid;
144 }
145
146 static int
147 loadscript(int fd, char *file, int argc, char **argv)
148 {
149         char buf[513], *p, **q, **nargv;
150         int rc, nargc, i;
151         
152         seek(fd, 0, 0);
153         rc = readn(fd, buf, 512);
154         if(rc <= 0)
155                 goto invalid;
156         close(fd);
157         buf[rc] = 0;
158         p = strchr(buf, '\n');
159         if(p == nil)
160                 goto invalid;
161         *p = 0;
162         while(isspace(*--p))
163                 *p = 0;
164         nargc = 0;
165         p = buf + 2;
166         while(*p) {
167                 while(*p && isspace(*p))
168                         p++;
169                 nargc++;
170                 while(*p && !isspace(*p))
171                         p++;
172         }
173         if(nargc == 0)
174                 goto invalid;
175         nargv = emallocz(sizeof(char *) * (nargc + argc));
176         q = nargv;
177         p = buf + 2;
178         while(*p) {
179                 while(*p && isspace(*p))
180                         p++;
181                 *(p-1) = 0;
182                 *q++ = p;
183                 while(*p && !isspace(*p))
184                         p++;
185         }
186         *q++ = file;
187         for(i = 1; i < argc; i++)
188                 *q++ = argv[i];
189         rc = loadtext(*nargv, argc + nargc, nargv);
190         free(nargv);
191         return rc;
192
193 invalid:
194         werrstr("exec header invalid");
195         return -1;
196 }
197
198 int
199 loadtext(char *file, int argc, char **argv)
200 {
201         int fd;
202         Fhdr fp;
203         Segment *text, *data, *bss;
204         char buf[2];
205         
206         fd = open(file, OREAD);
207         if(fd < 0) return -1;
208         if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
209                 return loadscript(fd, file, argc, argv);
210         seek(fd, 0, 0);
211         if(crackhdr(fd, &fp) == 0 || fp.magic != E_MAGIC) {
212                 werrstr("exec header invalid");
213                 return -1;
214         }
215         copyname(file);
216         P->notehandler = P->innote = P->notein = P->noteout = 0;
217         freesegs();
218         memset(P->R, 0, sizeof(P->R));
219         P->CPSR = 0;
220         text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
221         data = newseg(fp.dataddr, fp.datsz, SEGDATA);
222         bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
223         newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
224         seek(fd, fp.txtoff - fp.hdrsz, 0);
225         if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
226                 sysfatal("%r");
227         seek(fd, fp.datoff, 0);
228         if(readn(fd, data->data, fp.datsz) < fp.datsz)
229                 sysfatal("%r");
230         memset(bss->data, 0, bss->size);
231         P->R[15] = fp.entry;
232         if(havesymbols && syminit(fd, &fp) < 0)
233                 fprint(2, "initializing symbol table: %r\n");
234         close(fd);
235         fdclear(P->fd);
236         initstack(argc, argv);
237         if(vfp)
238                 resetvfp();
239         else
240                 resetfpa();
241         return 0;
242 }
243
244 void
245 cherrstr(char *str, ...)
246 {
247         va_list va;
248         
249         va_start(va, str);
250         vsnprint(P->errbuf, ERRMAX, str, va);
251         va_end(va);
252 }
253
254 u32int
255 noteerr(u32int x, u32int y)
256 {
257         if(((int)x) >= ((int)y))
258                 return x;
259         rerrstr(P->errbuf, ERRMAX);
260         return x;
261 }
262
263 Fd *
264 newfd(void)
265 {
266         Fd *fd;
267         
268         fd = emallocz(sizeof(*fd));
269         incref(fd);
270         return fd;
271 }
272
273 Fd *
274 copyfd(Fd *old)
275 {
276         Fd *new;
277         
278         rlock(old);
279         new = newfd();
280         if(old->nfds > 0) {
281                 new->nfds = old->nfds;
282                 new->fds = emalloc(old->nfds);
283                 memcpy(new->fds, old->fds, old->nfds);
284         }
285         runlock(old);
286         return new;
287 }
288
289 void
290 fddecref(Fd *fd)
291 {
292         if(decref(fd) == 0) {
293                 free(fd->fds);
294                 free(fd);
295         }
296 }
297
298 int
299 iscexec(Fd *fd, int n)
300 {
301         int r;
302
303         r = 0;
304         rlock(fd);
305         if(n / 8 < fd->nfds)
306                 r = (fd->fds[n / 8] & (1 << (n % 8))) != 0;
307         runlock(fd);
308         return r;
309 }
310
311 void
312 setcexec(Fd *fd, int n, int status)
313 {
314         int old;
315
316         wlock(fd);
317         if(n / 8 >= fd->nfds) {
318                 if(status == 0) {
319                         wunlock(fd);
320                         return;
321                 }
322                 old = fd->nfds;
323                 fd->nfds = (n / 8) + 1;
324                 fd->fds = erealloc(fd->fds, fd->nfds);
325                 memset(fd->fds + old, 0, fd->nfds - old);
326         }
327         if(status == 0)
328                 fd->fds[n / 8] &= ~(1 << (n % 8));
329         else
330                 fd->fds[n / 8] |= (1 << (n % 8));
331         wunlock(fd);
332 }
333
334 void
335 fdclear(Fd *fd)
336 {
337         int i, j, k;
338
339         wlock(fd);
340         if(fd->nfds == 0) {
341                 wunlock(fd);
342                 return;
343         }
344         for(i = 0; i < fd->nfds; i++) {
345                 j = fd->fds[i];
346                 for(k = 0; k < 8; k++)
347                         if(j & (1<<k))
348                                 close(8 * i + k);
349         }
350         free(fd->fds);
351         fd->nfds = 0;
352         fd->fds = nil;
353         wunlock(fd);
354 }
355
356 /* call this from a notehandler if you don't want the front to fall off */
357 void
358 addnote(char *msg)
359 {
360         int new;
361         
362         new = P->notein + 1;
363         if((new - P->noteout) % NNOTE == 0)
364                 return;
365
366         strncpy(P->notes[P->notein % NNOTE], msg, ERRMAX - 1);
367         P->notein = new;
368 }
369
370 /* the following code is not for the weak of heart */
371 void
372 donote(char *msg, ulong type)
373 {
374         int rc;
375         u32int *ureg, *sp, uregp, msgp;
376         char *msgb;
377
378         if(P->notehandler == 0)
379                 exits(msg);
380
381         clrex();
382         uregp = P->R[13] - 18 * 4;
383         ureg = vaddrnol(uregp, 18 * 4);
384         memcpy(ureg, P->R, 15 * 4);
385         ureg[15] = type;
386         ureg[16] = P->CPSR;
387         ureg[17] = P->R[15];
388         P->R[13] = uregp;
389         msgp = P->R[13] -= ERRMAX;
390         msgb = vaddrnol(msgp, ERRMAX);
391         strncpy(msgb, msg, ERRMAX);
392         P->R[13] -= 3 * 4;
393         sp = vaddrnol(P->R[13], 3 * 4);
394         sp[0] = 0;
395         sp[2] = msgp;
396         P->R[0] = uregp;
397         P->R[15] = P->notehandler;
398         P->innote = 1;
399         switch(rc = setjmp(P->notejmp) - 1) {
400         case -1:
401                 for(;;) {
402                         if(ultraverbose)
403                                 dump();
404                         step();
405                 }
406         case NDFLT:
407                 exits(msg);
408         case NCONT:
409                 break;
410         default:
411                 sysfatal("unhandled noted argument %d", rc);
412         }
413         P->innote = 0;
414         ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
415         memcpy(P->R, ureg, 15 * 4);
416         P->CPSR = ureg[16];
417         P->R[15] = ureg[17];
418 }