]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5e/sys.c
merge with jpathy
[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                 inittos();
405                 addproc(P);
406         }
407         P->R[0] = rc;
408 }
409
410 static void
411 sysexec(void)
412 {
413         u32int name, argv, *argvt;
414         char *namet, **argvv;
415         int i, argc, rc;
416         Segment *seg1, *seg2;
417         
418         name = arg(0);
419         argv = arg(1);
420         namet = strdup(vaddr(name, 0, &seg1));
421         segunlock(seg1);
422         argvt = vaddr(argv, 0, &seg1);
423         if(systrace)
424                 fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
425         for(argc = 0; argvt[argc]; argc++)
426                 ;
427         argvv = emalloc(sizeof(char *) * argc);
428         for(i = 0; i < argc; i++) {
429                 argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
430                 segunlock(seg2);
431         }
432         segunlock(seg1);
433         rc = loadtext(namet, argc, argvv);
434         for(i = 0; i < argc; i++)
435                 free(argvv[i]);
436         free(argvv);
437         if(rc < 0)
438                 P->R[0] = noteerr(rc, 0);
439         free(namet);
440 }
441
442 static void
443 sysawait(void)
444 {
445         u32int s, n;
446         void *st;
447         int buffered;
448         
449         s = arg(0);
450         n = arg(1);
451         st = bufifnec(s, n, &buffered);
452         if(systrace)
453                 fprint(2, "await(%#ux, %d)\n", s, n);
454         P->R[0] = noteerr(await(st, n), 0);
455         if(buffered)
456                 copyback(s, P->R[0], st);
457 }
458
459 static void
460 syspipe(void)
461 {
462         u32int fd, *fdt;
463         int buffered;
464         
465         fd = arg(0);
466         if(systrace)
467                 fprint(2, "pipe(%#ux)\n", fd);
468         fdt = bufifnec(fd, 8, &buffered);
469         P->R[0] = noteerr(pipe((int *) fdt), 0);
470         if(buffered)
471                 copyback(fd, 8, fdt);
472 }
473
474 static void
475 sysdup(void)
476 {
477         u32int oldfd, newfd;
478         
479         oldfd = arg(0);
480         newfd = arg(1);
481         if(systrace)
482                 fprint(2, "dup(%d, %d)\n", oldfd, newfd);
483         P->R[0] = noteerr(dup(oldfd, newfd), 0);
484 }
485
486 static void
487 syssleep(void)
488 {
489         u32int n;
490         
491         n = arg(0);
492         if(systrace)
493                 fprint(2, "sleep(%d)\n", n);
494         P->R[0] = noteerr(sleep(n), 0);
495 }
496
497 static void
498 sysrendezvous(void)
499 {
500         u32int tag, value;
501         
502         tag = arg(0);
503         value = arg(1);
504         if(systrace)
505                 fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
506         P->R[0] = (u32int) rendezvous((void *) tag, (void *) value);
507         if(P->R[0] == ~0)
508                 noteerr(0, 1);
509 }
510
511 static void
512 sysmount(void)
513 {
514         u32int fd, afd, old, flag, aname;
515         char *oldt, *anamet;
516         int copiedold, copiedaname;
517         
518         fd = arg(0);
519         afd = arg(1);
520         old = arg(2);
521         flag = arg(3);
522         aname = arg(4);
523         oldt = copyifnec(old, -1, &copiedold);
524         if(aname) {
525                 anamet = copyifnec(aname, -1, &copiedaname);
526                 if(systrace)
527                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, %#x=\"%s\")\n", fd, afd, old, oldt, flag, aname, anamet);
528         } else {
529                 anamet = nil;
530                 copiedaname = 0;
531                 if(systrace)
532                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, nil)\n", fd, afd, old, oldt, flag);
533         }
534         P->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
535         if(copiedold)
536                 free(oldt);
537         if(copiedaname)
538                 free(anamet);
539 }
540
541 static void
542 sysbind(void)
543 {
544         u32int name, old, flags;
545         char *namet, *oldt;
546         int copiedname, copiedold;
547         
548         name = arg(0);
549         old = arg(1);
550         flags = arg(2);
551         namet = copyifnec(name, -1, &copiedname);
552         oldt = copyifnec(old, -1, &copiedold);
553         if(systrace)
554                 fprint(2, "bind(%#ux=\"%s\", %#ux=\"%s\", %#o)\n", name, namet, old, oldt, flags);
555         P->R[0] = noteerr(bind(namet, oldt, flags), 0);
556         if(copiedname)
557                 free(namet);
558         if(copiedold)
559                 free(oldt);
560 }
561
562 static void
563 sysunmount(void)
564 {
565         u32int name, old;
566         char *namet, *oldt;
567         int copiedname, copiedold;
568         
569         name = arg(0);
570         old = arg(1);
571         oldt = copyifnec(old, -1, &copiedold);
572         if(name == 0) {
573                 namet = nil;
574                 copiedname = 0;
575                 if(systrace)
576                         fprint(2, "unmount(nil, %#ux=\"%s\")\n", old, oldt);
577                 P->R[0] = noteerr(unmount(nil, oldt), 0);
578         } else {
579                 namet = copyifnec(name, -1, &copiedname);
580                 if(systrace)
581                         fprint(2, "unmount(%#ux=\"%s\", %#ux=\"%s\")\n", name, namet, old, oldt);
582                 P->R[0] = noteerr(unmount(namet, oldt), 0);
583         }
584         if(copiedold)
585                 free(oldt);
586         if(copiedname)
587                 free(namet);
588 }
589
590 static void
591 sysremove(void)
592 {
593         u32int file;
594         char *filet;
595         int copied;
596         
597         file = arg(0);
598         filet = copyifnec(file, -1, &copied);
599         if(systrace)
600                 fprint(2, "remove(%#ux=\"%s\")\n", file, filet);
601         P->R[0] = noteerr(remove(filet), 0);
602         if(copied)
603                 free(filet);
604 }
605
606 static void
607 sysalarm(void)
608 {
609         u32int msec;
610         
611         msec = arg(0);
612         if(systrace)
613                 fprint(2, "alarm(%d)\n", msec);
614         P->R[0] = alarm(msec);
615 }
616
617 static void
618 syssemacquire(void)
619 {
620         u32int addr, block;
621         long *addrt;
622
623         addr = arg(0);
624         block = arg(1);
625         if(systrace)
626                 fprint(2, "semacquire(%#ux, %ud)\n", addr, block);
627         addrt = vaddrnol(addr, 4);
628         P->R[0] = noteerr(semacquire(addrt, block), 0);
629 }
630
631 static void
632 syssemrelease(void)
633 {
634         u32int addr, count;
635         long *addrt;
636         Segment *seg;
637
638         addr = arg(0);
639         count = arg(1);
640         if(systrace)
641                 fprint(2, "semrelease(%#ux, %ud)\n", addr, count);
642         addrt = vaddr(addr, 4, &seg);
643         P->R[0] = noteerr(semrelease(addrt, count), 0);
644         segunlock(seg);
645 }
646
647 void
648 syscall(void)
649 {
650         u32int n;
651         static void (*calls[])(void) = {
652                 [EXITS] sysexits,
653                 [CLOSE] sysclose,
654                 [OPEN] sysopen,
655                 [CREATE] syscreate,
656                 [PREAD] syspread,
657                 [PWRITE] syspwrite,
658                 [BRK_] sysbrk,
659                 [ERRSTR] syserrstr,
660                 [STAT] sysstat,
661                 [FSTAT] sysfstat,
662                 [WSTAT] syswstat,
663                 [FWSTAT] sysfwstat,
664                 [SEEK] sysseek,
665                 [CHDIR] syschdir,
666                 [FD2PATH] sysfd2path,
667                 [NOTIFY] sysnotify,
668                 [NOTED] sysnoted,
669                 [RFORK] sysrfork,
670                 [EXEC] sysexec,
671                 [AWAIT] sysawait,
672                 [PIPE] syspipe,
673                 [SLEEP] syssleep,
674                 [RENDEZVOUS] sysrendezvous,
675                 [BIND] sysbind,
676                 [UNMOUNT] sysunmount,
677                 [DUP] sysdup,
678                 [MOUNT] sysmount,
679                 [REMOVE] sysremove,
680                 [ALARM] sysalarm,
681                 [SEMACQUIRE] syssemacquire,
682                 [SEMRELEASE] syssemrelease,
683         };
684         
685         n = P->R[0];
686         if(n >= nelem(calls) || calls[n] == nil)
687                 sysfatal("no such syscall %d @ %#ux", n, P->R[15] - 4);
688         calls[n]();
689 }