]> 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);
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), &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 sysexits(void)
201 {
202         if(arg(0) == 0)
203                 exits(nil);
204         else
205                 exits(vaddrnol(arg(0)));
206 }
207
208 static void
209 sysbrk(void)
210 {
211         ulong v;
212         Segment *s;
213         
214         v = arg(0);
215         if(v >= P->S[SEGSTACK]->start)
216                 sysfatal("bss > stack, wtf?");
217         if(v < P->S[SEGBSS]->start)
218                 sysfatal("bss length < 0, wtf?");
219         s = P->S[SEGBSS];
220         wlock(&s->rw);
221         s->ref = realloc(s->ref, v - s->start + 4);
222         if(s->ref == nil)
223                 sysfatal("error reallocating");
224         s->data = s->ref + 1;
225         if(s->size < v - s->start)
226                 memset((char*)s->data + s->size, 0, v - s->start - s->size);
227         s->size = v - s->start;
228         P->R[0] = 0;
229         wunlock(&s->rw);
230 }
231
232 static void
233 syserrstr(void)
234 {
235         char buf[ERRMAX], *srct;
236         u32int src, len;
237         int copied;
238         
239         src = arg(0);
240         len = arg(1);
241         srct = copyifnec(src, len, &copied);
242         strcpy(buf, P->errbuf);
243         utfecpy(P->errbuf, P->errbuf + ERRMAX, srct);
244         utfecpy(srct, srct + len, buf);
245         if(copied)
246                 copyback(src, len, srct);
247         P->R[0] = 0;
248 }
249
250 static void
251 syschdir(void)
252 {
253         u32int dir;
254         char *dirt;
255         int copied;
256         
257         dir = arg(0);
258         dirt = copyifnec(dir, -1, &copied);
259         if(systrace)
260                 fprint(2, "chdir(%#ux=\"%s\")\n", dir, dirt);
261         P->R[0] = noteerr(chdir(dirt), 0);
262         if(copied)
263                 free(dirt);
264 }
265
266 static void
267 sysnotify(void)
268 {
269 }
270
271 static void
272 sysrfork(void)
273 {
274         u32int flags;
275         int rc, i;
276         Process *p;
277         Segment *s, *t;
278         Fd *old;
279         enum {
280                 RFORKPASS = RFENVG | RFCENVG | RFNOTEG | RFNOMNT | RFNAMEG | RFCNAMEG | RFNOWAIT | RFREND | RFFDG | RFCFDG,
281                 RFORKHANDLED = RFPROC | RFMEM,
282         };
283         
284         flags = arg(0);
285         if(systrace)
286                 fprint(2, "rfork(%#o)\n", flags);
287         if(flags & ~(RFORKPASS | RFORKHANDLED))
288                 sysfatal("rfork with unhandled flags %#o", flags & ~(RFORKPASS | RFORKHANDLED));
289         if((flags & RFPROC) == 0) {
290                 if(flags & RFFDG) {
291                         old = P->fd;
292                         P->fd = copyfd(P->fd);
293                         fddecref(old);
294                 }
295                 if(flags & RFCFDG) {
296                         old = P->fd;
297                         P->fd = newfd();
298                         fddecref(old);
299                 }
300                 P->R[0] = noteerr(rfork(flags & RFORKPASS), 0);
301                 return;
302         }
303         p = emallocz(sizeof(Process));
304         memcpy(p, P, sizeof(Process));
305         for(i = 0; i < SEGNUM; i++) {
306                 s = p->S[i];
307                 if(s == nil)
308                         continue;
309                 if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {
310                         t = emallocz(sizeof(Segment));
311                         incref(t);
312                         t->size = s->size;
313                         t->start = s->start;
314                         t->ref = emalloc(sizeof(Ref) + s->size);
315                         memset(t->ref, 0, sizeof(Ref));
316                         incref(t->ref);
317                         t->data = t->ref + 1;
318                         memcpy(t->data, s->data, s->size);
319                         p->S[i] = t;
320                 } else {
321                         incref(s);
322                         incref(s->ref);
323                 }
324         }
325         
326         if(flags & RFFDG)
327                 p->fd = copyfd(P->fd);
328         else if(flags & RFCFDG)
329                 p->fd = newfd();
330         else
331                 incref(&P->fd->ref);
332
333         rc = rfork(RFPROC | RFMEM | (flags & RFORKPASS));
334         if(rc < 0)
335                 sysfatal("rfork: %r");
336         if(rc == 0) {
337                 P = p;
338                 atexit(cleanup);
339                 P->pid = getpid();
340         }
341         P->R[0] = rc;
342 }
343
344 static void
345 sysexec(void)
346 {
347         u32int name, argv, *argvt;
348         char *namet, **argvv;
349         int i, argc, rc;
350         Segment *seg1, *seg2;
351         
352         name = arg(0);
353         argv = arg(1);
354         namet = strdup(vaddr(name, &seg1));
355         segunlock(seg1);
356         argvt = vaddr(argv, &seg1);
357         if(systrace)
358                 fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
359         for(argc = 0; argvt[argc]; argc++)
360                 ;
361         argvv = emalloc(sizeof(char *) * argc);
362         for(i = 0; i < argc; i++) {
363                 argvv[i] = strdup(vaddr(argvt[i], &seg2));
364                 segunlock(seg2);
365         }
366         segunlock(seg1);
367         rc = loadtext(namet, argc, argvv);
368         for(i = 0; i < argc; i++)
369                 free(argvv[i]);
370         free(argvv);
371         if(rc < 0)
372                 P->R[0] = noteerr(rc, 0);
373         free(namet);
374 }
375
376 static void
377 sysawait(void)
378 {
379         u32int s, n;
380         void *st;
381         int buffered;
382         
383         s = arg(0);
384         n = arg(1);
385         st = bufifnec(s, n, &buffered);
386         if(systrace)
387                 fprint(2, "await(%#ux, %d)\n", s, n);
388         P->R[0] = noteerr(await(st, n), 0);
389         if(buffered)
390                 copyback(s, P->R[0], st);
391 }
392
393 static void
394 syspipe(void)
395 {
396         u32int fd, *fdt;
397         int buffered;
398         
399         fd = arg(0);
400         if(systrace)
401                 fprint(2, "pipe(%#ux)\n", fd);
402         fdt = bufifnec(fd, 8, &buffered);
403         P->R[0] = noteerr(pipe((int *) fdt), 0);
404         if(buffered)
405                 copyback(fd, 8, fdt);
406 }
407
408 static void
409 sysdup(void)
410 {
411         u32int oldfd, newfd;
412         
413         oldfd = arg(0);
414         newfd = arg(1);
415         if(systrace)
416                 fprint(2, "dup(%d, %d)\n", oldfd, newfd);
417         P->R[0] = noteerr(dup(oldfd, newfd), 0);
418 }
419
420 static void
421 syssleep(void)
422 {
423         u32int n;
424         
425         n = arg(0);
426         if(systrace)
427                 fprint(2, "sleep(%d)\n", n);
428         P->R[0] = noteerr(sleep(n), 0);
429 }
430
431 static void
432 sysrendezvous(void)
433 {
434         u32int tag, value;
435         
436         tag = arg(0);
437         value = arg(1);
438         if(systrace)
439                 fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
440         P->R[0] = (u32int) rendezvous((void *) tag, (void *) value);
441         if(P->R[0] == ~0)
442                 noteerr(0, 1);
443 }
444
445 static void
446 sysmount(void)
447 {
448         u32int fd, afd, old, flag, aname;
449         char *oldt, *anamet;
450         int copiedold, copiedaname;
451         
452         fd = arg(0);
453         afd = arg(1);
454         old = arg(2);
455         flag = arg(3);
456         aname = arg(4);
457         oldt = copyifnec(old, -1, &copiedold);
458         if(aname) {
459                 anamet = copyifnec(aname, -1, &copiedaname);
460                 if(systrace)
461                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, %#x=\"%s\")\n", fd, afd, old, oldt, flag, aname, anamet);
462         } else {
463                 anamet = nil;
464                 copiedaname = 0;
465                 if(systrace)
466                         fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, nil)\n", fd, afd, old, oldt, flag);
467         }
468         P->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
469         if(copiedold)
470                 free(oldt);
471         if(copiedaname)
472                 free(anamet);
473 }
474
475 static void
476 sysbind(void)
477 {
478         u32int name, old, flags;
479         char *namet, *oldt;
480         int copiedname, copiedold;
481         
482         name = arg(0);
483         old = arg(1);
484         flags = arg(2);
485         namet = copyifnec(name, -1, &copiedname);
486         oldt = copyifnec(old, -1, &copiedold);
487         if(systrace)
488                 fprint(2, "bind(%#ux=\"%s\", %#ux=\"%s\", %#o)\n", name, namet, old, oldt, flags);
489         P->R[0] = noteerr(bind(namet, oldt, flags), 0);
490         if(copiedname)
491                 free(namet);
492         if(copiedold)
493                 free(oldt);
494 }
495
496 static void
497 sysunmount(void)
498 {
499         u32int name, old;
500         char *namet, *oldt;
501         int copiedname, copiedold;
502         
503         name = arg(0);
504         old = arg(1);
505         oldt = copyifnec(old, -1, &copiedold);
506         if(name == 0) {
507                 namet = nil;
508                 copiedname = 0;
509                 if(systrace)
510                         fprint(2, "unmount(nil, %#ux=\"%s\")\n", old, oldt);
511                 P->R[0] = noteerr(unmount(nil, oldt), 0);
512         } else {
513                 namet = copyifnec(name, -1, &copiedname);
514                 if(systrace)
515                         fprint(2, "unmount(%#ux=\"%s\", %#ux=\"%s\")\n", name, namet, old, oldt);
516                 P->R[0] = noteerr(unmount(namet, oldt), 0);
517         }
518         if(copiedold)
519                 free(oldt);
520         if(copiedname)
521                 free(namet);
522 }
523
524 static void
525 sysremove(void)
526 {
527         u32int file;
528         char *filet;
529         int copied;
530         
531         file = arg(0);
532         filet = copyifnec(file, -1, &copied);
533         if(systrace)
534                 fprint(2, "remove(%#ux=\"%s\")\n", file, filet);
535         P->R[0] = noteerr(remove(filet), 0);
536         if(copied)
537                 free(filet);
538 }
539
540 void
541 syscall(void)
542 {
543         u32int n;
544         static void (*calls[])(void) = {
545                 [EXITS] sysexits,
546                 [CLOSE] sysclose,
547                 [OPEN] sysopen,
548                 [CREATE] syscreate,
549                 [PREAD] syspread,
550                 [PWRITE] syspwrite,
551                 [BRK_] sysbrk,
552                 [ERRSTR] syserrstr,
553                 [STAT] sysstat,
554                 [FSTAT] sysfstat,
555                 [SEEK] sysseek,
556                 [CHDIR] syschdir,
557                 [FD2PATH] sysfd2path,
558                 [NOTIFY] sysnotify,
559                 [RFORK] sysrfork,
560                 [EXEC] sysexec,
561                 [AWAIT] sysawait,
562                 [PIPE] syspipe,
563                 [SLEEP] syssleep,
564                 [RENDEZVOUS] sysrendezvous,
565                 [BIND] sysbind,
566                 [UNMOUNT] sysunmount,
567                 [DUP] sysdup,
568                 [MOUNT] sysmount,
569                 [REMOVE] sysremove,
570         };
571         
572         n = P->R[0];
573         if(n >= nelem(calls) || calls[n] == nil)
574                 sysfatal("no such syscall %d @ %#ux", n, P->R[15] - 4);
575         calls[n]();
576 }