xref: /plan9/sys/src/cmd/qi/syscall.c (revision a84536681645e23c630ce4ef2e5c3b284d4c590b)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <bio.h>
5 #include <mach.h>
6 #define Extern extern
7 #include "power.h"
8 
9 
10 #define	REGSP	1
11 #define	REGRET	3
12 
13 #define	ODIRLEN	116	/* compatibility; used in _stat etc. */
14 #define	OERRLEN	64	/* compatibility; used in _stat etc. */
15 
16 char 	errbuf[ERRMAX];
17 ulong	nofunc;
18 
19 #include "/sys/src/libc/9syscall/sys.h"
20 
21 char *sysctab[]={
22 	[SYSR1]		"SYSR1",
23 	[_ERRSTR]	"_errstr",
24 	[BIND]		"Bind",
25 	[CHDIR]		"Chdir",
26 	[CLOSE]		"Close",
27 	[DUP]		"Dup",
28 	[ALARM]		"Alarm",
29 	[EXEC]		"Exec",
30 	[EXITS]		"Exits",
31 	[_FSESSION]	"_Fsession",
32 	[FAUTH]		"Fauth",
33 	[_FSTAT]	"_fstat",
34 	[SEGBRK]	"Segbrk",
35 	[_MOUNT]	"_Mount",
36 	[OPEN]		"Open",
37 	[_READ]		"_Read",
38 	[OSEEK]		"Oseek",
39 	[SLEEP]		"Sleep",
40 	[_STAT]		"_Stat",
41 	[RFORK]		"Rfork",
42 	[_WRITE]	"_Write",
43 	[PIPE]		"Pipe",
44 	[CREATE]	"Create",
45 	[FD2PATH]	"Fd2path",
46 	[BRK_]		"Brk_",
47 	[REMOVE]	"Remove",
48 	[_WSTAT]	"_Wstat",
49 	[_FWSTAT]	"_Fwstat",
50 	[NOTIFY]	"Notify",
51 	[NOTED]		"Noted",
52 	[SEGATTACH]	"Segattach",
53 	[SEGDETACH]	"Segdetach",
54 	[SEGFREE]	"Segfree",
55 	[SEGFLUSH]	"Segflush",
56 	[RENDEZVOUS]	"Rendezvous",
57 	[UNMOUNT]	"Unmount",
58 	[_WAIT]		"Wait",
59 	[SEEK]		"Seek",
60 	[FVERSION]	"Fversion",
61 	[ERRSTR]	"Errstr",
62 	[STAT]		"Stat",
63 	[FSTAT]		"Fstat",
64 	[WSTAT]		"Wstat",
65 	[FWSTAT]	"Fwstat",
66 	[MOUNT]		"Mount",
67 	[AWAIT]		"Await",
68 	[PREAD]		"Pread",
69 	[PWRITE]	"Pwrite",
70 };
71 
72 void sys1(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); }
73 
74 void
75 sys_errstr(void)
76 {
77 	ulong str;
78 	char tmp[OERRLEN];
79 
80 	str = getmem_w(reg.r[REGSP]+4);
81 	if(sysdbg)
82 		itrace("errstr(0x%lux)", str);
83 
84 	memio(tmp, str, OERRLEN, MemRead);
85 	memio(errbuf, str, OERRLEN, MemWrite);
86 	memmove(errbuf, tmp, OERRLEN);
87 	errbuf[OERRLEN-1] = 0;
88 	reg.r[REGRET] = 0;
89 }
90 
91 void
92 syserrstr(void)
93 {
94 	ulong str;
95 	uint n;
96 	char tmp[ERRMAX];
97 
98 	str = getmem_w(reg.r[REGSP]+4);
99 	n = getmem_w(reg.r[REGSP]+8);
100 	if(sysdbg)
101 		itrace("errstr(0x%lux, 0x%lux)", str, n);
102 
103 	if(n > strlen(errbuf)+1)
104 		n = strlen(errbuf)+1;
105 	if(n > ERRMAX)
106 		n = ERRMAX;
107 	memio(tmp, str, n, MemRead);
108 	memio(errbuf, str, n, MemWrite);
109 	memmove(errbuf, tmp, n);
110 	errbuf[ERRMAX-1] = 0;
111 	reg.r[REGRET] = n;
112 
113 }
114 
115 void
116 sysfd2path(void)
117 {
118 	ulong str;
119 	uint fd, n;
120 	char buf[1024];
121 
122 	fd = getmem_w(reg.r[REGSP]+4);
123 	str = getmem_w(reg.r[REGSP]+8);
124 	n = getmem_w(reg.r[REGSP]+12);
125 	if(sysdbg)
126 		itrace("fd2path(0x%lux, 0x%lux, 0x%lux)", fd, str, n);
127 	reg.r[REGRET] = -1;
128 	if(n > sizeof buf){
129 		strcpy(errbuf, "buffer too big");
130 		return;
131 	}
132 	n = fd2path(fd, buf, sizeof buf);
133 	if(n < 0)
134 		errstr(buf, sizeof buf);
135 	else
136 		memio(errbuf, str, n, MemWrite);
137 	reg.r[REGRET] = n;
138 
139 }
140 
141 void
142 sysbind(void)
143 {
144 	ulong pname, pold, flags;
145 	char name[1024], old[1024];
146 	int n;
147 
148 	pname = getmem_w(reg.r[REGSP]+4);
149 	pold = getmem_w(reg.r[REGSP]+8);
150 	flags = getmem_w(reg.r[REGSP]+12);
151 	memio(name, pname, sizeof(name), MemReadstring);
152 	memio(old, pold, sizeof(old), MemReadstring);
153 	if(sysdbg)
154 		itrace("bind(0x%lux='%s', 0x%lux='%s', 0x%lux)", name, old, flags);
155 
156 	n = bind(name, old, flags);
157 	if(n < 0)
158 		errstr(errbuf, sizeof errbuf);
159 
160 	reg.r[REGRET] = n;
161 }
162 
163 void
164 syschdir(void)
165 {
166 	char file[1024];
167 	int n;
168 	ulong name;
169 
170 	name = getmem_w(reg.r[REGSP]+4);
171 	memio(file, name, sizeof(file), MemReadstring);
172 	if(sysdbg)
173 		itrace("chdir(0x%lux='%s', 0x%lux)", name, file);
174 
175 	n = chdir(file);
176 	if(n < 0)
177 		errstr(errbuf, sizeof errbuf);
178 
179 	reg.r[REGRET] = n;
180 }
181 
182 void
183 sysclose(void)
184 {
185 	int n;
186 	ulong fd;
187 
188 	fd = getmem_w(reg.r[REGSP]+4);
189 	if(sysdbg)
190 		itrace("close(%d)", fd);
191 
192 	n = close(fd);
193 	if(n < 0)
194 		errstr(errbuf, sizeof errbuf);
195 	reg.r[REGRET] = n;
196 }
197 
198 void
199 sysdup(void)
200 {
201 	int oldfd, newfd;
202 	int n;
203 
204 	oldfd = getmem_w(reg.r[REGSP]+4);
205 	newfd = getmem_w(reg.r[REGSP]+8);
206 	if(sysdbg)
207 		itrace("dup(%d, %d)", oldfd, newfd);
208 
209 	n = dup(oldfd, newfd);
210 	if(n < 0)
211 		errstr(errbuf, sizeof errbuf);
212 	reg.r[REGRET] = n;
213 }
214 
215 void
216 sysexits(void)
217 {
218 	char buf[ERRMAX];
219 	ulong str;
220 
221 	str = getmem_w(reg.r[REGSP]+4);
222 	if(sysdbg)
223 		itrace("exits(0x%lux)", str);
224 
225 	count = 1;
226 	if(str != 0) {
227 		memio(buf, str, sizeof buf, MemRead);
228 		buf[ERRMAX-1] = 0;
229 		Bprint(bioout, "exits(%s)\n", buf);
230 	}
231 	else
232 		Bprint(bioout, "exits(0)\n");
233 }
234 
235 void
236 sysopen(void)
237 {
238 	char file[1024];
239 	int n;
240 	ulong mode, name;
241 
242 	name = getmem_w(reg.r[REGSP]+4);
243 	mode = getmem_w(reg.r[REGSP]+8);
244 	memio(file, name, sizeof(file), MemReadstring);
245 	if(sysdbg)
246 		itrace("open(0x%lux='%s', 0x%lux)", name, file, mode);
247 
248 	n = open(file, mode);
249 	if(n < 0)
250 		errstr(errbuf, sizeof errbuf);
251 
252 	reg.r[REGRET] = n;
253 };
254 
255 void
256 sysread(vlong offset)
257 {
258 	int fd;
259 	ulong size, a;
260 	char *buf, *p;
261 	int n, cnt, c;
262 
263 	fd = getmem_w(reg.r[REGSP]+4);
264 	a = getmem_w(reg.r[REGSP]+8);
265 	size = getmem_w(reg.r[REGSP]+12);
266 
267 	buf = emalloc(size);
268 	if(fd == 0) {
269 		print("\nstdin>>");
270 		p = buf;
271 		n = 0;
272 		cnt = size;
273 		while(cnt) {
274 			c = Bgetc(bin);
275 			if(c <= 0)
276 				break;
277 			*p++ = c;
278 			n++;
279 			cnt--;
280 			if(c == '\n')
281 				break;
282 		}
283 	}
284 	else
285 		n = pread(fd, buf, size, offset);
286 
287 	if(n < 0)
288 		errstr(errbuf, sizeof errbuf);
289 	else
290 		memio(buf, a, n, MemWrite);
291 
292 	if(sysdbg)
293 		itrace("read(%d, 0x%lux, %d, 0x%llx) = %d", fd, a, size, offset, n);
294 
295 	free(buf);
296 	reg.r[REGRET] = n;
297 }
298 
299 void
300 sys_read(void)
301 {
302 	sysread(-1LL);
303 }
304 
305 void
306 syspread(void)
307 {
308 	union {
309 		vlong v;
310 		ulong u[2];
311 	} o;
312 
313 	o.u[0] = getmem_w(reg.r[REGSP]+16);
314 	o.u[1] = getmem_w(reg.r[REGSP]+20);
315 	sysread(o.v);
316 }
317 
318 void
319 sysseek(void)
320 {
321 	int fd;
322 	ulong mode;
323 	ulong retp;
324 	union {
325 		vlong v;
326 		ulong u[2];
327 	} o;
328 
329 	retp = getmem_w(reg.r[REGSP]+4);
330 	fd = getmem_w(reg.r[REGSP]+8);
331 	o.u[0] = getmem_w(reg.r[REGSP]+12);
332 	o.u[1] = getmem_w(reg.r[REGSP]+16);
333 	mode = getmem_w(reg.r[REGSP]+20);
334 	if(sysdbg)
335 		itrace("seek(%d, %lld, %d)", fd, o.v, mode);
336 
337 	o.v = seek(fd, o.v, mode);
338 	if(o.v < 0)
339 		errstr(errbuf, sizeof errbuf);
340 
341 	memio((char*)o.u, retp, sizeof(vlong), MemWrite);
342 }
343 
344 void
345 sysoseek(void)
346 {
347 	int fd, n;
348 	ulong off, mode;
349 
350 	fd = getmem_w(reg.r[REGSP]+4);
351 	off = getmem_w(reg.r[REGSP]+8);
352 	mode = getmem_w(reg.r[REGSP]+12);
353 	if(sysdbg)
354 		itrace("seek(%d, %lud, %d)", fd, off, mode);
355 
356 	n = seek(fd, off, mode);
357 	if(n < 0)
358 		errstr(errbuf, sizeof errbuf);
359 
360 	reg.r[REGRET] = n;
361 }
362 
363 void
364 sysrfork(void)
365 {
366 	int flag;
367 
368 	flag = getmem_w(reg.r[REGSP]+4);
369 	if(sysdbg)
370 		itrace("rfork(%d)", flag);
371 	if(flag & RFPROC) {
372 		Bprint(bioout, "rfork: cannot create process, rfork(0x%.8ux)\n", flag);
373 		exits(0);
374 	}
375 	reg.r[REGRET] = rfork(flag);
376 }
377 
378 void
379 syssleep(void)
380 {
381 	ulong len;
382 	int n;
383 
384 	len = getmem_w(reg.r[REGSP]+4);
385 	if(sysdbg)
386 		itrace("sleep(%d)", len);
387 
388 	n = sleep(len);
389 	if(n < 0)
390 		errstr(errbuf, sizeof errbuf);
391 
392 	reg.r[REGRET] = n;
393 }
394 
395 void
396 sys_stat(void)
397 {
398 	char nambuf[1024];
399 	char buf[ODIRLEN];
400 	ulong edir, name;
401 	extern int _stat(char*, char*);	/* old system call */
402 	int n;
403 
404 	name = getmem_w(reg.r[REGSP]+4);
405 	edir = getmem_w(reg.r[REGSP]+8);
406 	memio(nambuf, name, sizeof(nambuf), MemReadstring);
407 	if(sysdbg)
408 		itrace("stat(0x%lux='%s', 0x%lux)", name, nambuf, edir);
409 
410 	n = _stat(nambuf, buf);
411 	if(n < 0)
412 		errstr(errbuf, sizeof errbuf);
413 	else
414 		memio(buf, edir, ODIRLEN, MemWrite);
415 
416 	reg.r[REGRET] = n;
417 }
418 
419 void
420 sysstat(void)
421 {
422 	char nambuf[1024];
423 	uchar buf[STATMAX];
424 	ulong edir, name;
425 	int n;
426 
427 	name = getmem_w(reg.r[REGSP]+4);
428 	edir = getmem_w(reg.r[REGSP]+8);
429 	n = getmem_w(reg.r[REGSP]+12);
430 	memio(nambuf, name, sizeof(nambuf), MemReadstring);
431 	if(sysdbg)
432 		itrace("stat(0x%lux='%s', 0x%lux, 0x%lux)", name, nambuf, edir, n);
433 	if(n > sizeof buf)
434 		errstr(errbuf, sizeof errbuf);
435 	else{
436 		n = stat(nambuf, buf, n);
437 		if(n < 0)
438 			errstr(errbuf, sizeof errbuf);
439 		else
440 			memio((char*)buf, edir, n, MemWrite);
441 	}
442 	reg.r[REGRET] = n;
443 }
444 
445 void
446 sys_fstat(void)
447 {
448 	char buf[ODIRLEN];
449 	ulong edir;
450 	extern int _fstat(int, char*);	/* old system call */
451 	int n, fd;
452 
453 	fd = getmem_w(reg.r[REGSP]+4);
454 	edir = getmem_w(reg.r[REGSP]+8);
455 	if(sysdbg)
456 		itrace("fstat(%d, 0x%lux)", fd, edir);
457 
458 	n = _fstat(fd, buf);
459 	if(n < 0)
460 		errstr(errbuf, sizeof errbuf);
461 	else
462 		memio(buf, edir, ODIRLEN, MemWrite);
463 
464 	reg.r[REGRET] = n;
465 }
466 
467 void
468 sysfstat(void)
469 {
470 	uchar buf[STATMAX];
471 	ulong edir;
472 	int n, fd;
473 
474 	fd = getmem_w(reg.r[REGSP]+4);
475 	edir = getmem_w(reg.r[REGSP]+8);
476 	n = getmem_w(reg.r[REGSP]+12);
477 	if(sysdbg)
478 		itrace("fstat(%d, 0x%lux, 0x%lux)", fd, edir, n);
479 
480 	reg.r[REGRET] = -1;
481 	if(n > sizeof buf){
482 		strcpy(errbuf, "stat buffer too big");
483 		return;
484 	}
485 	n = fstat(fd, buf, n);
486 	if(n < 0)
487 		errstr(errbuf, sizeof errbuf);
488 	else
489 		memio((char*)buf, edir, n, MemWrite);
490 	reg.r[REGRET] = n;
491 }
492 
493 void
494 syswrite(vlong offset)
495 {
496 	int fd;
497 	ulong size, a;
498 	char *buf;
499 	int n;
500 
501 	fd = getmem_w(reg.r[REGSP]+4);
502 	a = getmem_w(reg.r[REGSP]+8);
503 	size = getmem_w(reg.r[REGSP]+12);
504 
505 	Bflush(bioout);
506 	buf = memio(0, a, size, MemRead);
507 	n = pwrite(fd, buf, size, offset);
508 	if(n < 0)
509 		errstr(errbuf, sizeof errbuf);
510 	if(sysdbg)
511 		itrace("write(%d, %lux, %d, 0xllx) = %d", fd, a, size, offset, n);
512 	free(buf);
513 
514 	reg.r[REGRET] = n;
515 }
516 
517 void
518 sys_write(void)
519 {
520 	syswrite(-1LL);
521 }
522 
523 void
524 syspwrite(void)
525 {
526 	union {
527 		vlong v;
528 		ulong u[2];
529 	} o;
530 
531 	o.u[0] = getmem_w(reg.r[REGSP]+16);
532 	o.u[1] = getmem_w(reg.r[REGSP]+20);
533 	syswrite(o.v);
534 }
535 
536 void
537 syspipe(void)
538 {
539 	int n, p[2];
540 	ulong fd;
541 
542 	fd = getmem_w(reg.r[REGSP]+4);
543 	if(sysdbg)
544 		itrace("pipe(%lux)", fd);
545 
546 	n = pipe(p);
547 	if(n < 0)
548 		errstr(errbuf, sizeof errbuf);
549 	else {
550 		putmem_w(fd, p[0]);
551 		putmem_w(fd+4, p[1]);
552 	}
553 	reg.r[REGRET] = n;
554 }
555 
556 void
557 syscreate(void)
558 {
559 	char file[1024];
560 	int n;
561 	ulong mode, name, perm;
562 
563 	name = getmem_w(reg.r[REGSP]+4);
564 	mode = getmem_w(reg.r[REGSP]+8);
565 	perm = getmem_w(reg.r[REGSP]+12);
566 	memio(file, name, sizeof(file), MemReadstring);
567 	if(sysdbg)
568 		itrace("create(0x%lux='%s', 0x%lux, 0x%lux)", name, file, mode, perm);
569 
570 	n = create(file, mode, perm);
571 	if(n < 0)
572 		errstr(errbuf, sizeof errbuf);
573 
574 	reg.r[REGRET] = n;
575 }
576 
577 void
578 sysbrk_(void)
579 {
580 	ulong addr, osize, nsize;
581 	Segment *s;
582 
583 	addr = getmem_w(reg.r[REGSP]+4);
584 	if(sysdbg)
585 		itrace("brk_(0x%lux)", addr);
586 
587 	reg.r[REGRET] = -1;
588 	if(addr < memory.seg[Data].base+datasize) {
589 		strcpy(errbuf, "address below segment");
590 		return;
591 	}
592 	if(addr > memory.seg[Stack].base) {
593 		strcpy(errbuf, "segment too big");
594 		return;
595 	}
596 	s = &memory.seg[Bss];
597 	if(addr > s->end) {
598 		osize = ((s->end-s->base)/BY2PG)*BY2WD;
599 		addr = ((addr)+(BY2PG-1))&~(BY2PG-1);
600 		s->end = addr;
601 		nsize = ((s->end-s->base)/BY2PG)*BY2WD;
602 		s->table = erealloc(s->table, osize, nsize);
603 	}
604 
605 	reg.r[REGRET] = 0;
606 }
607 
608 void
609 sysremove(void)
610 {
611 	char nambuf[1024];
612 	ulong name;
613 	int n;
614 
615 	name = getmem_w(reg.r[REGSP]+4);
616 	memio(nambuf, name, sizeof(nambuf), MemReadstring);
617 	if(sysdbg)
618 		itrace("remove(0x%lux='%s')", name, nambuf);
619 
620 	n = remove(nambuf);
621 	if(n < 0)
622 		errstr(errbuf, sizeof errbuf);
623 	reg.r[REGRET] = n;
624 }
625 
626 void
627 sysnotify(void)
628 {
629 	nofunc = getmem_w(reg.r[REGSP]+4);
630 	if(sysdbg)
631 		itrace("notify(0x%lux)", nofunc);
632 
633 	reg.r[REGRET] = 0;
634 }
635 
636 void
637 syssegflush(void)
638 {
639 	ulong start, len;
640 
641 	start = getmem_w(reg.r[REGSP]+4);
642 	len = getmem_w(reg.r[REGSP]+8);
643 	if(sysdbg)
644 		itrace("segflush(va=0x%lux, n=%lud)", start, len);
645 	reg.r[REGRET] = 0;
646 }
647 
648 void sysfversion(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); }
649 void sysfsession(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); }
650 void sysfauth(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); }
651 void syswait(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0); }
652 void syswstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
653 void sys_wstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
654 void sysfwstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
655 void sys_fwstat(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
656 void sysnoted(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
657 void syssegattach(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
658 void syssegdetach(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
659 void syssegfree(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
660 void sysrendezvous(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
661 void sysunmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
662 void sysfork(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
663 void sysforkpgrp(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
664 void syssegbrk(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
665 void _sysmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
666 void sysalarm(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
667 void sysexec(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
668 void sysmount(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
669 void sysawait(void) { Bprint(bioout, "No system call %s\n", sysctab[reg.r[REGRET]]); exits(0);}
670 
671 void (*systab[])(void)	={
672 	[SYSR1]		sys1,
673 	[_ERRSTR]	sys_errstr,
674 	[BIND]		sysbind,
675 	[CHDIR]		syschdir,
676 	[CLOSE]		sysclose,
677 	[DUP]		sysdup,
678 	[ALARM]		sysalarm,
679 	[EXEC]		sysexec,
680 	[EXITS]		sysexits,
681 	[_FSESSION]	sysfsession,
682 	[FAUTH]		sysfauth,
683 	[_FSTAT]	sys_fstat,
684 	[SEGBRK]	syssegbrk,
685 	[_MOUNT]	_sysmount,
686 	[OPEN]		sysopen,
687 	[_READ]		sys_read,
688 	[OSEEK]		sysoseek,
689 	[SLEEP]		syssleep,
690 	[_STAT]		sys_stat,
691 	[RFORK]		sysrfork,
692 	[_WRITE]	sys_write,
693 	[PIPE]		syspipe,
694 	[CREATE]	syscreate,
695 	[FD2PATH]	sysfd2path,
696 	[BRK_]		sysbrk_,
697 	[REMOVE]	sysremove,
698 	[_WSTAT]	sys_wstat,
699 	[_FWSTAT]	sys_fwstat,
700 	[NOTIFY]	sysnotify,
701 	[NOTED]		sysnoted,
702 	[SEGATTACH]	syssegattach,
703 	[SEGDETACH]	syssegdetach,
704 	[SEGFREE]	syssegfree,
705 	[SEGFLUSH]	syssegflush,
706 	[RENDEZVOUS]	sysrendezvous,
707 	[UNMOUNT]	sysunmount,
708 	[_WAIT]		syswait,
709 	[SEEK]		sysseek,
710 	[FVERSION]	sysfversion,
711 	[ERRSTR]	syserrstr,
712 	[STAT]		sysstat,
713 	[FSTAT]		sysfstat,
714 	[WSTAT]		syswstat,
715 	[FWSTAT]	sysfwstat,
716 	[MOUNT]		sysmount,
717 	[AWAIT]		sysawait,
718 	[PREAD]		syspread,
719 	[PWRITE]	syspwrite,
720 };
721 
722 void
723 sc(ulong inst)
724 {
725 	int call;
726 
727 	if(inst != ((17<<26)|2))
728 		undef(inst);
729 	call = reg.r[REGRET];
730 	if(call < 0 || call > PWRITE || systab[call] == nil) {
731 		Bprint(bioout, "Bad system call\n");
732 		dumpreg();
733 	}
734 	if(trace)
735 		itrace("sc\t(%s)", sysctab[call]);
736 
737 	(*systab[call])();
738 	Bflush(bioout);
739 }
740