]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/sys.c
merge
[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(systrace)
256                 fprint(2, "brk(%#lux)\n", v);
257         if(v >= P->S[SEGSTACK]->start)
258                 sysfatal("bss > stack, wtf?");
259         if(v < P->S[SEGBSS]->start)
260                 sysfatal("bss length < 0, wtf?");
261         s = P->S[SEGBSS];
262         wlock(&s->rw);
263         s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
264         if(s->dref == nil)
265                 sysfatal("error reallocating");
266         s->data = s->dref + 1;
267         if(s->size < v - s->start)
268                 memset((char*)s->data + s->size, 0, v - s->start - s->size);
269         s->size = v - s->start;
270         P->R[0] = 0;
271         wunlock(&s->rw);
272 }
273
274 static void
275 syserrstr(void)
276 {
277         char buf[ERRMAX], *srct;
278         u32int src, len;
279         int copied;
280         
281         src = arg(0);
282         len = arg(1);
283         srct = copyifnec(src, len, &copied);
284         strcpy(buf, P->errbuf);
285         utfecpy(P->errbuf, P->errbuf + ERRMAX, srct);
286         utfecpy(srct, srct + len, buf);
287         if(copied)
288                 copyback(src, len, srct);
289         P->R[0] = 0;
290 }
291
292 static void
293 syschdir(void)
294 {
295         u32int dir;
296         char *dirt;
297         int copied;
298         
299         dir = arg(0);
300         dirt = copyifnec(dir, -1, &copied);
301         if(systrace)
302                 fprint(2, "chdir(%#ux=\"%s\")\n", dir, dirt);
303         P->R[0] = noteerr(chdir(dirt), 0);
304         if(copied)
305                 free(dirt);
306 }
307
308 static void
309 sysnotify(void)
310 {
311         u32int handler;
312         
313         handler = arg(0);
314         if(systrace)
315                 fprint(2, "notify(%#ux)\n", handler);
316         P->notehandler = handler;
317         P->R[0] = 0;
318 }
319
320 static void
321 sysnoted(void)
322 {
323         u32int v;
324         
325         v = arg(0);
326         if(systrace)
327                 fprint(2, "noted(%d)\n", v);
328         if(P->innote)
329                 longjmp(P->notejmp, v + 1);
330         cherrstr("the front fell off");
331         P->R[0] = -1;
332 }
333
334 static void
335 sysrfork(void)
336 {
337         u32int flags;
338         int rc, i;
339         Process *p;
340         Segment *s, *t;
341         Fd *old;
342         
343         flags = arg(0);
344         if(systrace)
345                 fprint(2, "rfork(%#o)\n", flags);
346         if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
347            (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
348            (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {
349                 P->R[0] = -1;
350                 cherrstr("bad arg in syscall");
351                 return;
352         }
353         if((flags & RFPROC) == 0) {
354                 if(flags & RFFDG) {
355                         old = P->fd;
356                         P->fd = copyfd(P->fd);
357                         fddecref(old);
358                 }
359                 if(flags & RFCFDG) {
360                         old = P->fd;
361                         P->fd = newfd();
362                         fddecref(old);
363                 }
364                 P->R[0] = noteerr(rfork(flags), 0);
365                 return;
366         }
367         incref(&nproc);
368         p = emallocz(sizeof(Process));
369         memcpy(p, P, sizeof(Process));
370         for(i = 0; i < SEGNUM; i++) {
371                 s = p->S[i];
372                 if(s == nil)
373                         continue;
374                 if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {
375                         t = emallocz(sizeof(Segment));
376                         incref(t);
377                         t->size = s->size;
378                         t->start = s->start;
379                         t->dref = emalloc(sizeof(Ref) + s->size);
380                         memset(t->dref, 0, sizeof(Ref));
381                         incref(t->dref);
382                         t->data = t->dref + 1;
383                         memcpy(t->data, s->data, s->size);
384                         p->S[i] = t;
385                 } else {
386                         incref(s->dref);
387                         incref(s);
388                 }
389         }
390         
391         if(flags & RFFDG)
392                 p->fd = copyfd(P->fd);
393         else if(flags & RFCFDG)
394                 p->fd = newfd();
395         else
396                 incref(P->fd);
397
398         incref(P->path);
399         rc = rfork(RFMEM | flags);
400         if(rc < 0) /* this should NEVER happen */
401                 sysfatal("rfork failed wtf: %r");
402         if(rc == 0) {
403                 P = p;
404                 atexit(cleanup);
405                 P->pid = getpid();
406                 inittos();
407                 addproc(P);
408         }
409         P->R[0] = rc;
410 }
411
412 static void
413 sysexec(void)
414 {
415         u32int name, argv, *argvt;
416         char *namet, **argvv;
417         int i, argc, rc;
418         Segment *seg1, *seg2;
419         
420         name = arg(0);
421         argv = arg(1);
422         namet = strdup(vaddr(name, 0, &seg1));
423         segunlock(seg1);
424         argvt = vaddr(argv, 0, &seg1);
425         if(systrace)
426                 fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
427         for(argc = 0; argvt[argc]; argc++)
428                 ;
429         argvv = emalloc(sizeof(char *) * argc);
430         for(i = 0; i < argc; i++) {
431                 argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
432                 segunlock(seg2);
433         }
434         segunlock(seg1);
435         rc = loadtext(namet, argc, argvv);
436         for(i = 0; i < argc; i++)
437                 free(argvv[i]);
438         free(argvv);
439         if(rc < 0)
440                 P->R[0] = noteerr(rc, 0);
441         free(namet);
442 }
443
444 static void
445 sysawait(void)
446 {
447         u32int s, n;
448         void *st;
449         int buffered;
450         
451         s = arg(0);
452         n = arg(1);
453         st = bufifnec(s, n, &buffered);
454         if(systrace)
455                 fprint(2, "await(%#ux, %d)\n", s, n);
456         P->R[0] = noteerr(await(st, n), 0);
457         if(buffered)
458                 copyback(s, P->R[0], st);
459 }
460
461 static void
462 syspipe(void)
463 {
464         u32int fd, *fdt;
465         int buffered;
466         
467         fd = arg(0);
468         if(systrace)
469                 fprint(2, "pipe(%#ux)\n", fd);
470         fdt = bufifnec(fd, 8, &buffered);
471         P->R[0] = noteerr(pipe((int *) fdt), 0);
472         if(buffered)
473                 copyback(fd, 8, fdt);
474 }
475
476 static void
477 sysdup(void)
478 {
479         u32int oldfd, newfd;
480         
481         oldfd = arg(0);
482         newfd = arg(1);
483         if(systrace)
484                 fprint(2, "dup(%d, %d)\n", oldfd, newfd);
485         P->R[0] = noteerr(dup(oldfd, newfd), 0);
486 }
487
488 static void
489 syssleep(void)
490 {
491         u32int n;
492         
493         n = arg(0);
494         if(systrace)
495                 fprint(2, "sleep(%d)\n", n);
496         P->R[0] = noteerr(sleep(n), 0);
497 }
498
499 static void
500 sysrendezvous(void)
501 {
502         u32int tag, value;
503         
504         tag = arg(0);
505         value = arg(1);
506         if(systrace)
507                 fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
508         P->R[0] = (u32int) (uintptr)rendezvous((void *) tag, (void *) value);
509         if(P->R[0] == ~0)
510                 noteerr(0, 1);
511 }
512
513 static void
514 sysmount(void)
515 {
516         u32int fd, afd, old, flag, aname;
517         char *oldt, *anamet;
518         int copiedold, copiedaname;
519         
520         fd = arg(0);
521         afd = arg(1);
522         old = arg(2);
523         flag = arg(3);
524         aname = arg(4);
525         oldt = copyifnec(old, -1, &copiedold);
526         if(aname) {
527                 anamet = copyifnec(aname, -1, &copiedaname);
528                 if(systrace)
529                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, %#x=\"%s\")\n", fd, afd, old, oldt, flag, aname, anamet);
530         } else {
531                 anamet = nil;
532                 copiedaname = 0;
533                 if(systrace)
534                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, nil)\n", fd, afd, old, oldt, flag);
535         }
536         P->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
537         if(copiedold)
538                 free(oldt);
539         if(copiedaname)
540                 free(anamet);
541 }
542
543 static void
544 sysbind(void)
545 {
546         u32int name, old, flags;
547         char *namet, *oldt;
548         int copiedname, copiedold;
549         
550         name = arg(0);
551         old = arg(1);
552         flags = arg(2);
553         namet = copyifnec(name, -1, &copiedname);
554         oldt = copyifnec(old, -1, &copiedold);
555         if(systrace)
556                 fprint(2, "bind(%#ux=\"%s\", %#ux=\"%s\", %#o)\n", name, namet, old, oldt, flags);
557         P->R[0] = noteerr(bind(namet, oldt, flags), 0);
558         if(copiedname)
559                 free(namet);
560         if(copiedold)
561                 free(oldt);
562 }
563
564 static void
565 sysunmount(void)
566 {
567         u32int name, old;
568         char *namet, *oldt;
569         int copiedname, copiedold;
570         
571         name = arg(0);
572         old = arg(1);
573         oldt = copyifnec(old, -1, &copiedold);
574         if(name == 0) {
575                 namet = nil;
576                 copiedname = 0;
577                 if(systrace)
578                         fprint(2, "unmount(nil, %#ux=\"%s\")\n", old, oldt);
579                 P->R[0] = noteerr(unmount(nil, oldt), 0);
580         } else {
581                 namet = copyifnec(name, -1, &copiedname);
582                 if(systrace)
583                         fprint(2, "unmount(%#ux=\"%s\", %#ux=\"%s\")\n", name, namet, old, oldt);
584                 P->R[0] = noteerr(unmount(namet, oldt), 0);
585         }
586         if(copiedold)
587                 free(oldt);
588         if(copiedname)
589                 free(namet);
590 }
591
592 static void
593 sysremove(void)
594 {
595         u32int file;
596         char *filet;
597         int copied;
598         
599         file = arg(0);
600         filet = copyifnec(file, -1, &copied);
601         if(systrace)
602                 fprint(2, "remove(%#ux=\"%s\")\n", file, filet);
603         P->R[0] = noteerr(remove(filet), 0);
604         if(copied)
605                 free(filet);
606 }
607
608 static void
609 sysalarm(void)
610 {
611         u32int msec;
612         
613         msec = arg(0);
614         if(systrace)
615                 fprint(2, "alarm(%d)\n", msec);
616         P->R[0] = alarm(msec);
617 }
618
619 static void
620 syssemacquire(void)
621 {
622         u32int addr, block;
623         long *addrt;
624
625         addr = arg(0);
626         block = arg(1);
627         if(systrace)
628                 fprint(2, "semacquire(%#ux, %ud)\n", addr, block);
629         addrt = vaddrnol(addr, 4);
630         P->R[0] = noteerr(semacquire(addrt, block), 0);
631 }
632
633 static void
634 syssemrelease(void)
635 {
636         u32int addr, count;
637         long *addrt;
638         Segment *seg;
639
640         addr = arg(0);
641         count = arg(1);
642         if(systrace)
643                 fprint(2, "semrelease(%#ux, %ud)\n", addr, count);
644         addrt = vaddr(addr, 4, &seg);
645         P->R[0] = noteerr(semrelease(addrt, count), 0);
646         segunlock(seg);
647 }
648
649 void
650 syscall(void)
651 {
652         u32int n;
653         static void (*calls[])(void) = {
654                 [EXITS] sysexits,
655                 [CLOSE] sysclose,
656                 [OPEN] sysopen,
657                 [CREATE] syscreate,
658                 [PREAD] syspread,
659                 [PWRITE] syspwrite,
660                 [BRK_] sysbrk,
661                 [ERRSTR] syserrstr,
662                 [STAT] sysstat,
663                 [FSTAT] sysfstat,
664                 [WSTAT] syswstat,
665                 [FWSTAT] sysfwstat,
666                 [SEEK] sysseek,
667                 [CHDIR] syschdir,
668                 [FD2PATH] sysfd2path,
669                 [NOTIFY] sysnotify,
670                 [NOTED] sysnoted,
671                 [RFORK] sysrfork,
672                 [EXEC] sysexec,
673                 [AWAIT] sysawait,
674                 [PIPE] syspipe,
675                 [SLEEP] syssleep,
676                 [RENDEZVOUS] sysrendezvous,
677                 [BIND] sysbind,
678                 [UNMOUNT] sysunmount,
679                 [DUP] sysdup,
680                 [MOUNT] sysmount,
681                 [REMOVE] sysremove,
682                 [ALARM] sysalarm,
683                 [SEMACQUIRE] syssemacquire,
684                 [SEMRELEASE] syssemrelease,
685         };
686         
687         n = P->R[0];
688         if(n >= nelem(calls) || calls[n] == nil)
689                 sysfatal("no such syscall %d @ %#ux", n, P->R[15] - 4);
690         calls[n]();
691 }