]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/sys.c
5e: added FPA support
[plan9front.git] / sys / src / cmd / 5e / sys.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6 #include </sys/src/libc/9syscall/sys.h>
7
8 static u32int
9 arg(int n)
10 {
11         /* no locking necessary, since we're on the stack */
12         return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4);
13 }
14
15 static u64int
16 argv(int n)
17 {
18         return arg(n) | ((u64int)arg(n+1) << 32);
19 }
20
21 static void
22 sysopen(void)
23 {
24         u32int name, flags;
25         char *namet;
26         int fd, copied;
27         
28         name = arg(0);
29         flags = arg(1);
30         namet = copyifnec(name, -1, &copied);
31         if(systrace)
32                 fprint(2, "open(%#ux=\"%s\", %#o)\n", name, namet, flags);
33         fd = open(namet, flags);
34         if(copied)
35                 free(namet);
36         if(fd < 0) {
37                 noteerr(0, 1);
38                 P->R[0] = fd;
39                 return;
40         }
41         setcexec(P->fd, fd, flags & OCEXEC);
42         P->R[0] = fd;
43 }
44
45 static void
46 syscreate(void)
47 {
48         u32int name, flags, perm;
49         char *namet;
50         int fd, copied;
51         
52         name = arg(0);
53         flags = arg(1);
54         perm = arg(2);
55         namet = copyifnec(name, -1, &copied);
56         if(systrace)
57                 fprint(2, "create(%#ux=\"%s\", %#o, %o)\n", name, namet, flags, perm);
58         fd = create(namet, flags, perm);
59         if(copied)
60                 free(namet);
61         if(fd < 0) {
62                 noteerr(0, 1);
63                 P->R[0] = fd;
64                 return;
65         }
66         setcexec(P->fd, fd, flags & OCEXEC);
67         P->R[0] = fd;
68 }
69
70 static void
71 sysclose(void)
72 {
73         u32int fd;
74         
75         fd = arg(0);
76         if(systrace)
77                 fprint(2, "close(%d)\n", fd);
78         P->R[0] = noteerr(close(fd), 0);
79         if((fd & (1<<31)) == 0)
80                 setcexec(P->fd, fd, 0);
81 }
82
83 static void
84 syspread(void)
85 {
86         int buffered;
87         u32int fd, size, buf;
88         u64int off;
89         void *targ;
90         
91         fd = arg(0);
92         buf = arg(1);
93         size = arg(2);
94         off = argv(3);
95         if(systrace)
96                 fprint(2, "pread(%d, %#ux, %ud, %#ullx)\n", fd, buf, size, off);
97         targ = bufifnec(buf, size, &buffered);
98         P->R[0] = noteerr(pread(fd, targ, size, off), size);
99         if(buffered)
100                 copyback(buf, P->R[0], targ);
101 }
102
103 static void
104 syspwrite(void)
105 {
106         u32int fd, size, buf;
107         u64int off;
108         int copied;
109         void *buft;
110         
111         fd = arg(0);
112         buf = arg(1);
113         size = arg(2);
114         off = argv(3);
115         buft = copyifnec(buf, size, &copied);
116         if(systrace)
117                 fprint(2, "pwrite(%d, %#ux, %ud, %#ullx)\n", fd, buf, size, off);
118         P->R[0] = noteerr(pwrite(fd, buft, size, off), size);
119         if(copied)
120                 free(buft);
121 }
122
123 static void
124 sysseek(void)
125 {
126         u32int fd, type;
127         vlong n, *ret;
128         Segment *seg;
129         
130         ret = vaddr(arg(0), 8, &seg);
131         fd = arg(1);
132         n = argv(2);
133         type = arg(4);
134         if(systrace)
135                 fprint(2, "seek(%d, %lld, %d)\n", fd, n, type);
136         *ret = seek(fd, n, type);
137         if(*ret < 0) noteerr(0, 1);
138         segunlock(seg);
139 }
140
141 static void
142 sysfd2path(void)
143 {
144         u32int fd, buf, nbuf;
145         void *buft;
146         int buffered;
147         
148         fd = arg(0);
149         buf = arg(1);
150         nbuf = arg(2);
151         buft = bufifnec(buf, nbuf, &buffered);
152         if(systrace)
153                 fprint(2, "fd2path(%d, %#ux, %d)\n", fd, buf, nbuf);
154         P->R[0] = noteerr(fd2path(fd, buft, nbuf), 0);
155         if(buffered)
156                 copyback(buf, nbuf, buft);
157 }
158
159 static void
160 sysstat(void)
161 {
162         u32int name, edir, nedir;
163         char *namet;
164         void *edirt;
165         int copied, buffered;
166         
167         name = arg(0);
168         namet = copyifnec(name, -1, &copied);
169         edir = arg(1);
170         nedir = arg(2);
171         edirt = bufifnec(edir, nedir, &buffered);
172         if(systrace)
173                 fprint(2, "stat(%#ux=\"%s\", %#ux, %ud)\n", name, namet, edir, nedir);
174         P->R[0] = noteerr(stat(namet, edirt, nedir), nedir);
175         if(copied)
176                 free(namet);
177         if(buffered)
178                 copyback(edir, P->R[0], edirt);
179 }
180
181 static void
182 sysfstat(void)
183 {
184         u32int fd, edir, nedir;
185         void *edirt;
186         int buffered;
187         
188         fd = arg(0);
189         edir = arg(1);
190         nedir = arg(2);
191         edirt = bufifnec(edir, nedir, &buffered);
192         if(systrace)
193                 fprint(2, "fstat(%d, %#ux, %d)\n", fd, edir, nedir);
194         P->R[0] = noteerr(fstat(fd, edirt, nedir), nedir);
195         if(buffered)
196                 copyback(edir, P->R[0], edirt);
197 }
198
199 static void
200 syswstat(void)
201 {
202         u32int name, edir, nedir;
203         char *namet;
204         void *edirt;
205         int copied, copied2;
206         
207         name = arg(0);
208         namet = copyifnec(name, -1, &copied);
209         edir = arg(1);
210         nedir = arg(2);
211         edirt = copyifnec(edir, nedir, &copied2);
212         if(systrace)
213                 fprint(2, "wstat(%#ux=\"%s\", %#ux, %ud)\n", name, namet, edir, nedir);
214         P->R[0] = noteerr(wstat(namet, edirt, nedir), nedir);
215         if(copied)
216                 free(namet);
217         if(copied2)
218                 free(edirt);
219 }
220
221 static void
222 sysfwstat(void)
223 {
224         u32int fd, edir, nedir;
225         void *edirt;
226         int copied;
227         
228         fd = arg(0);
229         edir = arg(1);
230         nedir = arg(2);
231         edirt = copyifnec(edir, nedir, &copied);
232         if(systrace)
233                 fprint(2, "fwstat(%d, %#ux, %d)\n", fd, edir, nedir);
234         P->R[0] = noteerr(fwstat(fd, edirt, nedir), nedir);
235         if(copied)
236                 free(edirt);
237 }
238
239 static void
240 sysexits(void)
241 {
242         if(arg(0) == 0)
243                 exits(nil);
244         else
245                 exits(vaddrnol(arg(0), 0));
246 }
247
248 static void
249 sysbrk(void)
250 {
251         ulong v;
252         Segment *s;
253         
254         v = arg(0);
255         if(v >= P->S[SEGSTACK]->start)
256                 sysfatal("bss > stack, wtf?");
257         if(v < P->S[SEGBSS]->start)
258                 sysfatal("bss length < 0, wtf?");
259         s = P->S[SEGBSS];
260         wlock(&s->rw);
261         s->dref = realloc(s->dref, v - s->start + 4);
262         if(s->dref == nil)
263                 sysfatal("error reallocating");
264         s->data = s->dref + 1;
265         if(s->size < v - s->start)
266                 memset((char*)s->data + s->size, 0, v - s->start - s->size);
267         s->size = v - s->start;
268         P->R[0] = 0;
269         wunlock(&s->rw);
270 }
271
272 static void
273 syserrstr(void)
274 {
275         char buf[ERRMAX], *srct;
276         u32int src, len;
277         int copied;
278         
279         src = arg(0);
280         len = arg(1);
281         srct = copyifnec(src, len, &copied);
282         strcpy(buf, P->errbuf);
283         utfecpy(P->errbuf, P->errbuf + ERRMAX, srct);
284         utfecpy(srct, srct + len, buf);
285         if(copied)
286                 copyback(src, len, srct);
287         P->R[0] = 0;
288 }
289
290 static void
291 syschdir(void)
292 {
293         u32int dir;
294         char *dirt;
295         int copied;
296         
297         dir = arg(0);
298         dirt = copyifnec(dir, -1, &copied);
299         if(systrace)
300                 fprint(2, "chdir(%#ux=\"%s\")\n", dir, dirt);
301         P->R[0] = noteerr(chdir(dirt), 0);
302         if(copied)
303                 free(dirt);
304 }
305
306 static void
307 sysnotify(void)
308 {
309         u32int handler;
310         
311         handler = arg(0);
312         if(systrace)
313                 fprint(2, "notify(%#ux)\n", handler);
314         P->notehandler = handler;
315         P->R[0] = 0;
316 }
317
318 static void
319 sysnoted(void)
320 {
321         u32int v;
322         
323         v = arg(0);
324         if(systrace)
325                 fprint(2, "noted(%d)\n", v);
326         if(P->innote)
327                 longjmp(P->notejmp, v + 1);
328         cherrstr("the front fell off");
329         P->R[0] = -1;
330 }
331
332 static void
333 sysrfork(void)
334 {
335         u32int flags;
336         int rc, i;
337         Process *p;
338         Segment *s, *t;
339         Fd *old;
340         
341         flags = arg(0);
342         if(systrace)
343                 fprint(2, "rfork(%#o)\n", flags);
344         if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
345            (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
346            (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {
347                 P->R[0] = -1;
348                 cherrstr("bad arg in syscall");
349                 return;
350         }
351         if((flags & RFPROC) == 0) {
352                 if(flags & RFFDG) {
353                         old = P->fd;
354                         P->fd = copyfd(P->fd);
355                         fddecref(old);
356                 }
357                 if(flags & RFCFDG) {
358                         old = P->fd;
359                         P->fd = newfd();
360                         fddecref(old);
361                 }
362                 P->R[0] = noteerr(rfork(flags), 0);
363                 return;
364         }
365         incref(&nproc);
366         p = emallocz(sizeof(Process));
367         memcpy(p, P, sizeof(Process));
368         for(i = 0; i < SEGNUM; i++) {
369                 s = p->S[i];
370                 if(s == nil)
371                         continue;
372                 if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {
373                         t = emallocz(sizeof(Segment));
374                         incref(t);
375                         t->size = s->size;
376                         t->start = s->start;
377                         t->dref = emalloc(sizeof(Ref) + s->size);
378                         memset(t->dref, 0, sizeof(Ref));
379                         incref(t->dref);
380                         t->data = t->dref + 1;
381                         memcpy(t->data, s->data, s->size);
382                         p->S[i] = t;
383                 } else {
384                         incref(s->dref);
385                         incref(s);
386                 }
387         }
388         
389         if(flags & RFFDG)
390                 p->fd = copyfd(P->fd);
391         else if(flags & RFCFDG)
392                 p->fd = newfd();
393         else
394                 incref(P->fd);
395
396         incref(P->path);
397         rc = rfork(RFMEM | flags);
398         if(rc < 0) /* this should NEVER happen */
399                 sysfatal("rfork failed wtf: %r");
400         if(rc == 0) {
401                 P = p;
402                 atexit(cleanup);
403                 P->pid = getpid();
404                 addproc(P);
405         }
406         P->R[0] = rc;
407 }
408
409 static void
410 sysexec(void)
411 {
412         u32int name, argv, *argvt;
413         char *namet, **argvv;
414         int i, argc, rc;
415         Segment *seg1, *seg2;
416         
417         name = arg(0);
418         argv = arg(1);
419         namet = strdup(vaddr(name, 0, &seg1));
420         segunlock(seg1);
421         argvt = vaddr(argv, 0, &seg1);
422         if(systrace)
423                 fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
424         for(argc = 0; argvt[argc]; argc++)
425                 ;
426         argvv = emalloc(sizeof(char *) * argc);
427         for(i = 0; i < argc; i++) {
428                 argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
429                 segunlock(seg2);
430         }
431         segunlock(seg1);
432         rc = loadtext(namet, argc, argvv);
433         for(i = 0; i < argc; i++)
434                 free(argvv[i]);
435         free(argvv);
436         if(rc < 0)
437                 P->R[0] = noteerr(rc, 0);
438         free(namet);
439 }
440
441 static void
442 sysawait(void)
443 {
444         u32int s, n;
445         void *st;
446         int buffered;
447         
448         s = arg(0);
449         n = arg(1);
450         st = bufifnec(s, n, &buffered);
451         if(systrace)
452                 fprint(2, "await(%#ux, %d)\n", s, n);
453         P->R[0] = noteerr(await(st, n), 0);
454         if(buffered)
455                 copyback(s, P->R[0], st);
456 }
457
458 static void
459 syspipe(void)
460 {
461         u32int fd, *fdt;
462         int buffered;
463         
464         fd = arg(0);
465         if(systrace)
466                 fprint(2, "pipe(%#ux)\n", fd);
467         fdt = bufifnec(fd, 8, &buffered);
468         P->R[0] = noteerr(pipe((int *) fdt), 0);
469         if(buffered)
470                 copyback(fd, 8, fdt);
471 }
472
473 static void
474 sysdup(void)
475 {
476         u32int oldfd, newfd;
477         
478         oldfd = arg(0);
479         newfd = arg(1);
480         if(systrace)
481                 fprint(2, "dup(%d, %d)\n", oldfd, newfd);
482         P->R[0] = noteerr(dup(oldfd, newfd), 0);
483 }
484
485 static void
486 syssleep(void)
487 {
488         u32int n;
489         
490         n = arg(0);
491         if(systrace)
492                 fprint(2, "sleep(%d)\n", n);
493         P->R[0] = noteerr(sleep(n), 0);
494 }
495
496 static void
497 sysrendezvous(void)
498 {
499         u32int tag, value;
500         
501         tag = arg(0);
502         value = arg(1);
503         if(systrace)
504                 fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
505         P->R[0] = (u32int) rendezvous((void *) tag, (void *) value);
506         if(P->R[0] == ~0)
507                 noteerr(0, 1);
508 }
509
510 static void
511 sysmount(void)
512 {
513         u32int fd, afd, old, flag, aname;
514         char *oldt, *anamet;
515         int copiedold, copiedaname;
516         
517         fd = arg(0);
518         afd = arg(1);
519         old = arg(2);
520         flag = arg(3);
521         aname = arg(4);
522         oldt = copyifnec(old, -1, &copiedold);
523         if(aname) {
524                 anamet = copyifnec(aname, -1, &copiedaname);
525                 if(systrace)
526                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, %#x=\"%s\")\n", fd, afd, old, oldt, flag, aname, anamet);
527         } else {
528                 anamet = nil;
529                 copiedaname = 0;
530                 if(systrace)
531                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, nil)\n", fd, afd, old, oldt, flag);
532         }
533         P->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
534         if(copiedold)
535                 free(oldt);
536         if(copiedaname)
537                 free(anamet);
538 }
539
540 static void
541 sysbind(void)
542 {
543         u32int name, old, flags;
544         char *namet, *oldt;
545         int copiedname, copiedold;
546         
547         name = arg(0);
548         old = arg(1);
549         flags = arg(2);
550         namet = copyifnec(name, -1, &copiedname);
551         oldt = copyifnec(old, -1, &copiedold);
552         if(systrace)
553                 fprint(2, "bind(%#ux=\"%s\", %#ux=\"%s\", %#o)\n", name, namet, old, oldt, flags);
554         P->R[0] = noteerr(bind(namet, oldt, flags), 0);
555         if(copiedname)
556                 free(namet);
557         if(copiedold)
558                 free(oldt);
559 }
560
561 static void
562 sysunmount(void)
563 {
564         u32int name, old;
565         char *namet, *oldt;
566         int copiedname, copiedold;
567         
568         name = arg(0);
569         old = arg(1);
570         oldt = copyifnec(old, -1, &copiedold);
571         if(name == 0) {
572                 namet = nil;
573                 copiedname = 0;
574                 if(systrace)
575                         fprint(2, "unmount(nil, %#ux=\"%s\")\n", old, oldt);
576                 P->R[0] = noteerr(unmount(nil, oldt), 0);
577         } else {
578                 namet = copyifnec(name, -1, &copiedname);
579                 if(systrace)
580                         fprint(2, "unmount(%#ux=\"%s\", %#ux=\"%s\")\n", name, namet, old, oldt);
581                 P->R[0] = noteerr(unmount(namet, oldt), 0);
582         }
583         if(copiedold)
584                 free(oldt);
585         if(copiedname)
586                 free(namet);
587 }
588
589 static void
590 sysremove(void)
591 {
592         u32int file;
593         char *filet;
594         int copied;
595         
596         file = arg(0);
597         filet = copyifnec(file, -1, &copied);
598         if(systrace)
599                 fprint(2, "remove(%#ux=\"%s\")\n", file, filet);
600         P->R[0] = noteerr(remove(filet), 0);
601         if(copied)
602                 free(filet);
603 }
604
605 static void
606 sysalarm(void)
607 {
608         u32int msec;
609         
610         msec = arg(0);
611         if(systrace)
612                 fprint(2, "alarm(%d)\n", msec);
613         P->R[0] = alarm(msec);
614 }
615
616 void
617 syscall(void)
618 {
619         u32int n;
620         static void (*calls[])(void) = {
621                 [EXITS] sysexits,
622                 [CLOSE] sysclose,
623                 [OPEN] sysopen,
624                 [CREATE] syscreate,
625                 [PREAD] syspread,
626                 [PWRITE] syspwrite,
627                 [BRK_] sysbrk,
628                 [ERRSTR] syserrstr,
629                 [STAT] sysstat,
630                 [FSTAT] sysfstat,
631                 [WSTAT] syswstat,
632                 [FWSTAT] sysfwstat,
633                 [SEEK] sysseek,
634                 [CHDIR] syschdir,
635                 [FD2PATH] sysfd2path,
636                 [NOTIFY] sysnotify,
637                 [NOTED] sysnoted,
638                 [RFORK] sysrfork,
639                 [EXEC] sysexec,
640                 [AWAIT] sysawait,
641                 [PIPE] syspipe,
642                 [SLEEP] syssleep,
643                 [RENDEZVOUS] sysrendezvous,
644                 [BIND] sysbind,
645                 [UNMOUNT] sysunmount,
646                 [DUP] sysdup,
647                 [MOUNT] sysmount,
648                 [REMOVE] sysremove,
649                 [ALARM] sysalarm,
650         };
651         
652         n = P->R[0];
653         if(n >= nelem(calls) || calls[n] == nil)
654                 sysfatal("no such syscall %d @ %#ux", n, P->R[15] - 4);
655         calls[n]();
656 }