1 /* bsdtrap.c - Deal with 2.11BSD trap instructions.
4 * $Date: 2008/05/19 13:26:42 $
9 * Grep for the word DONE in this file to see the implemented syscalls.
24 #include <sys/resource.h>
25 #include <sys/socket.h>
29 #include <grp.h> /* setgroups() */
32 #define MAX_BLKSIZE 1024 /* Maximum block size from stat/fstat */
34 #undef STREAM_BUFFERING /* This works, but doesn't seem to give */
35 /* any speed improvement */
37 arglist *A; /* Pointer to various arguments on stack */
40 /* Forward prototypes */
46 static int trap_execve P((int));
47 static int bsdopen_dir P((char *name));
49 static int16_t map_fcntl P((int16_t f));
55 int i, j, len, pid, pfd[2];
59 char *fmode; /* used with fdopen only */
60 struct stat stbuf; /* used in STAT */
61 struct tr_stat *tr_stbuf; /* used in STAT */
62 struct tr_timeval *tr_del, *tr_oldel; /* used in ADJTIME */
63 struct timeval del, oldel; /* used in ADJTIME */
64 struct timeval utv[2]; /* used in UTIMES */
65 struct tr_timezone *tr_zone; /* used in GETTIMEOFDAY */
66 struct timezone zone; /* used in GETTIMEOFDAY */
67 struct tr_itimerval *tr_tval, *tr_oltval; /* used in itimer calls */
68 struct itimerval tval, oltval; /* used in itimer calls */
69 struct tr_sockaddr *tr_sock; /* used in socket calls */
70 struct sockaddr sock; /* used in socket calls */
71 gid_t *gidset; /* used in GETGROUPS */
72 struct tr_rlimit *tr_rlp; /* used in rlimit calls */
73 struct rlimit rlp; /* used in rlimit calls */
74 struct tr_rusage *tr_use; /* used in getrusage */
75 struct rusage use; /* used in getrusage */
76 struct iovec *ivec; /* used in writev, readv */
77 struct tr_iovec *trivec; /* used in writev, readv */
79 TrapDebug((dbg_file, "pid %d %s: ", (int) getpid(),
80 bsdtrap_name[ir & 0xff]));
82 A = (arglist *) & dspace[(regs[SP] + 2)];
87 (void) printf("Does 2.11BSD use INDIR? I don't think so\n");
90 case S_QUOTA: /* DONE - for now */
91 case S_SETQUOTA: /* DONE - for now */
96 /* These syscalls are not implemented, and */
97 /* always return EPERM to the caller */
98 case S_PTRACE: /* DONE - bad syscall */
99 case S_MOUNT: /* DONE - bad syscall */
100 case S_UMOUNT: /* DONE - bad syscall */
101 case S_PROFIL: /* DONE - bad syscall */
102 case S_NOSYS147: /* DONE - bad syscall */
107 /* These syscalls are ignored, and */
108 /* always return C=0 to the caller */
109 case S_OLDLOCK: /* DONE - ok syscall */
110 case S_OLDPHYS: /* DONE - ok syscall */
111 case S_FSTATFS: /* DONE - ok syscall */
112 case S_SIGPROCMASK: /* DONE - ok syscall */
113 case S_SIGRETURN: /* DONE - ok syscall */
114 case S_SIGALTSTACK: /* DONE - ok syscall */
115 case S_VHANGUP: /* DONE - ok syscall */
118 case S_SIGACTION: /* DONE */
119 #define NO_SIGNALS_YET
120 #ifdef NO_SIGNALS_YET
123 i = do_sigaction(uarg1, uarg2, uarg3);
126 case S_IOCTL: /* DONE a bit */
129 case S_SBRK: /* DONE */
130 if (uarg1 < regs[SP]) {
132 TrapDebug((dbg_file, "set break to %d ", uarg1));
136 TrapDebug((dbg_file, "break %d > SP %d", uarg1, regs[SP]));
139 case S_SYNC: /* DONE */
143 case S_FSYNC: /* DONE */
146 case S_GETDTABLESIZE: /* DONE */
149 case S_EXIT: /* DONE */
151 TrapDebug((dbg_file, "val %d\n", sarg1));
155 case S_DUP: /* DONE */
156 TrapDebug((dbg_file, "on %d ", sarg1));
158 #ifdef STREAM_BUFFERING
159 if ((i != -1) && ValidFD(sarg1) && stream[sarg1]) {
160 fmode = streammode[sarg1];
161 stream[i] = fdopen(i, fmode);
162 streammode[i] = fmode;
166 case S_DUP2: /* DONE */
167 TrapDebug((dbg_file, "on %d %d ", sarg1, sarg2));
168 i = dup2(sarg1, sarg2);
169 #ifdef STREAM_BUFFERING
170 if ((i != -1) && ValidFD(sarg2) && ValidFD(sarg1)
172 fmode = streammode[sarg1];
173 stream[sarg2] = fdopen(sarg2, fmode);
174 streammode[sarg2] = fmode;
178 case S_REBOOT: /* DONE */
179 (void) Reboot(sarg1);
181 case S_UMASK: /* DONE */
182 i = umask((mode_t) sarg1);
184 case S_GETPAGESIZE: /* DONE */
187 case S_GETHOSTNAME: /* DONE */
188 buf = (char *) &dspace[uarg1];
189 i = gethostname(buf, sarg2);
191 case S_SETHOSTNAME: /* DONE */
192 buf = (char *) &dspace[uarg1];
193 sethostname(buf, sarg2);
195 case S_LSEEK: /* DONE */
196 larg1 = (sarg2 << 16) | uarg3;
197 #ifdef STREAM_BUFFERING
198 if (ValidFD(sarg1) && stream[sarg1]) {
199 i = fseek(stream[sarg1], larg1, sarg4);
201 i = ftell(stream[sarg1]);
204 i = lseek(sarg1, larg1, sarg4);
208 regs[1] = i & 0xffff;
209 i = (i >> 16) & 0xffff;
212 case S_READ: /* DONE */
213 TrapDebug((dbg_file, "%d bytes on %d ", uarg3, sarg1));
214 buf = (char *) &dspace[uarg2];
215 #ifdef STREAM_BUFFERING
216 if (ValidFD(sarg1) && stream[sarg1])
217 i = fread(buf, 1, uarg3, stream[sarg1]);
220 i = read(sarg1, buf, uarg3);
222 case S_LINK: /* DONE */
223 buf = xlate_filename((char *) &dspace[uarg1]);
224 buf2 = xlate_filename((char *) &dspace[uarg2]);
227 case S_SYMLINK: /* DONE */
228 buf = xlate_filename((char *) &dspace[uarg1]);
229 buf2 = xlate_filename((char *) &dspace[uarg2]);
230 i = symlink(buf, buf2);
232 case S_RENAME: /* DONE */
233 buf = xlate_filename((char *) &dspace[uarg1]);
234 buf2 = xlate_filename((char *) &dspace[uarg2]);
235 i = rename(buf, buf2);
237 case S_READLINK: /* DONE */
238 buf = xlate_filename((char *) &dspace[uarg1]);
239 i = readlink(buf, (char *) &dspace[uarg2], sarg3);
241 case S_ACCESS: /* DONE */
242 buf = xlate_filename((char *) &dspace[uarg1]);
243 i = access(buf, sarg2);
245 case S_MKDIR: /* DONE */
246 buf = xlate_filename((char *) &dspace[uarg1]);
247 i = mkdir(buf, sarg2);
249 case S_RMDIR: /* DONE */
250 buf = xlate_filename((char *) &dspace[uarg1]);
253 case S_ACCT: /* DONE */
254 buf = xlate_filename((char *) &dspace[uarg1]);
257 case S_WRITEV: /* DONE */
258 case S_READV: /* DONE */
259 ivec = (struct iovec *) malloc(uarg3 * sizeof(struct iovec));
265 trivec = (struct tr_iovec *) &dspace[uarg2];
267 for (j = 0; j < uarg3; j++) {
268 ivec[j].iov_len = trivec[j].iov_len;
269 ivec[j].iov_base = (char *) &dspace[trivec[j].iov_base];
271 if ((ir & 0xff) == S_READV)
272 i = readv(sarg1, ivec, uarg3);
274 i = writev(sarg1, ivec, uarg3);
277 case S_WRITE: /* DONE */
278 buf = (char *) &dspace[uarg2];
279 TrapDebug((dbg_file, "%d bytes on %d ", uarg3, sarg1));
280 #ifdef STREAM_BUFFERING
281 if (ValidFD(sarg1) && stream[sarg1])
282 i = fwrite(buf, 1, uarg3, stream[sarg1]);
285 i = write(sarg1, buf, uarg3);
287 case S_CLOSE: /* DONE */
289 TrapDebug((dbg_file, "on %d ", sarg1));
290 if ((dbg_file != NULL) && (sarg1 == fileno(dbg_file))) {
292 break; /* Don't close our debug file! */
295 #ifdef STREAM_BUFFERING
296 if (ValidFD(sarg1) && stream[sarg1]) {
297 i = fclose(stream[sarg1]);
298 stream[sarg1] = NULL;
304 TrapDebug((dbg_file, "on %d %d %d ", sarg1, sarg2, sarg3));
305 i = fcntl(sarg1, sarg2, sarg3);
308 i = flock(sarg1, sarg2);
310 case S_LSTAT: /* DONE */
311 buf = xlate_filename((char *) &dspace[uarg1]);
312 tr_stbuf = (struct tr_stat *) &dspace[uarg2];
313 i = lstat(buf, &stbuf);
314 TrapDebug((dbg_file, "on %s ", buf));
316 case S_STAT: /* DONE */
317 buf = xlate_filename((char *) &dspace[uarg1]);
318 tr_stbuf = (struct tr_stat *) &dspace[uarg2];
319 i = stat(buf, &stbuf);
320 TrapDebug((dbg_file, "on %s ", buf));
322 case S_FSTAT: /* DONE */
323 tr_stbuf = (struct tr_stat *) &dspace[uarg2];
324 i = fstat(uarg1, &stbuf);
325 TrapDebug((dbg_file, "on fd %d ", uarg1));
331 /* The following stops blksize equalling 64K,
332 * which becomes 0 in a 16-bit int. This then
333 * causes 2.11BSD flsbuf() to malloc(0), which
334 * then causes malloc to go crazy - wkt.
336 if (stbuf.st_blksize > MAX_BLKSIZE)
337 stbuf.st_blksize = MAX_BLKSIZE;
339 tr_stbuf->st_dev = stbuf.st_dev;
340 tr_stbuf->st_ino = stbuf.st_ino;
341 tr_stbuf->st_mode = stbuf.st_mode;
342 tr_stbuf->st_nlink = stbuf.st_nlink;
343 tr_stbuf->st_uid = stbuf.st_uid;
344 tr_stbuf->st_gid = stbuf.st_gid;
345 tr_stbuf->st_rdev = stbuf.st_rdev;
347 tr_stbuf->st_flags = stbuf.st_flags;
349 copylong(tr_stbuf->st_size, stbuf.st_size);
350 copylong(tr_stbuf->st_atim, stbuf.st_atime);
351 copylong(tr_stbuf->st_mtim, stbuf.st_mtime);
352 copylong(tr_stbuf->st_ctim, stbuf.st_ctime);
353 copylong(tr_stbuf->st_blksize, stbuf.st_blksize);
354 larg1 = stbuf.st_blocks;
355 copylong(tr_stbuf->st_blocks, larg1);
358 case S_UTIMES: /* DONE */
359 buf = xlate_filename((char *) &dspace[uarg1]);
360 tr_del = (struct tr_timeval *) &dspace[uarg2];
361 tr_oldel = (struct tr_timeval *) &dspace[uarg4];
362 i = utimes(buf, utv);
365 copylong(tr_del->tv_sec, utv[0].tv_sec);
366 copylong(tr_del->tv_usec, utv[0].tv_usec);
367 copylong(tr_oldel->tv_sec, utv[1].tv_sec);
368 copylong(tr_oldel->tv_usec, utv[1].tv_usec);
370 case S_ADJTIME: /* DONE */
371 tr_del = (struct tr_timeval *) &dspace[uarg1];
372 /* Convert tr_del to del */
373 copylong(del.tv_sec, tr_del->tv_sec);
374 copylong(del.tv_usec, tr_del->tv_usec);
375 i = adjtime(&del, &oldel);
378 tr_oldel = (struct tr_timeval *) &dspace[uarg2];
379 copylong(tr_oldel->tv_sec, oldel.tv_sec);
380 copylong(tr_oldel->tv_usec, oldel.tv_usec);
383 case S_GETTIMEOFDAY: /* DONE */
384 tr_del = (struct tr_timeval *) &dspace[uarg1];
385 tr_zone = (struct tr_timezone *) &dspace[uarg2];
386 i = gettimeofday(&del, &zone);
387 copylong(tr_del->tv_sec, del.tv_sec);
388 copylong(tr_del->tv_usec, del.tv_usec);
389 tr_zone->tz_minuteswest = zone.tz_minuteswest;
390 tr_zone->tz_dsttime = zone.tz_dsttime;
392 case S_SETTIMEOFDAY: /* DONE */
393 tr_del = (struct tr_timeval *) &dspace[uarg1];
394 tr_zone = (struct tr_timezone *) &dspace[uarg2];
395 copylong(del.tv_sec, tr_del->tv_sec);
396 copylong(del.tv_usec, tr_del->tv_usec);
397 zone.tz_minuteswest = tr_zone->tz_minuteswest;
398 zone.tz_dsttime = tr_zone->tz_dsttime;
399 i = settimeofday(&del, &zone);
401 case S_GETITIMER: /* DONE */
402 tr_tval = (struct tr_itimerval *) &dspace[uarg2];
403 i = getitimer(sarg1, &tval);
404 copylong(tr_tval->it_interval.tv_sec, tval.it_interval.tv_sec);
405 copylong(tr_tval->it_interval.tv_usec,
406 tval.it_interval.tv_usec);
407 copylong(tr_tval->it_value.tv_sec, tval.it_value.tv_sec);
408 copylong(tr_tval->it_value.tv_usec, tval.it_value.tv_usec);
410 case S_SETITIMER: /* DONE */
411 tr_tval = (struct tr_itimerval *) &dspace[uarg2];
412 tr_oltval = (struct tr_itimerval *) &dspace[uarg2];
413 copylong(tval.it_interval.tv_sec, tr_tval->it_interval.tv_sec);
414 copylong(tval.it_interval.tv_usec,
415 tr_tval->it_interval.tv_usec);
416 copylong(tval.it_value.tv_sec, tr_tval->it_value.tv_sec);
417 copylong(tval.it_value.tv_usec, tr_tval->it_value.tv_usec);
418 i = setitimer(sarg1, &tval, &oltval);
421 copylong(tr_oltval->it_interval.tv_sec,
422 oltval.it_interval.tv_sec);
423 copylong(tr_oltval->it_interval.tv_usec,
424 oltval.it_interval.tv_usec);
425 copylong(tr_oltval->it_value.tv_sec, oltval.it_value.tv_sec);
426 copylong(tr_oltval->it_value.tv_usec, oltval.it_value.tv_usec);
428 case S_UNLINK: /* DONE */
429 buf = xlate_filename((char *) &dspace[uarg1]);
432 case S_OPEN: /* DONE */
433 buf = xlate_filename((char *) &dspace[uarg1]);
435 i = stat(buf, &stbuf); /* If file is a directory */
436 if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
437 i = bsdopen_dir(buf);
439 TrapDebug((dbg_file, "(dir) on %s ", buf));
441 #ifdef NEED_MAP_FCNTL
442 sarg2 = map_fcntl(sarg2);
444 switch (sarg2 & O_ACCMODE) {
455 i = open(buf, sarg2, sarg3);
456 TrapDebug((dbg_file, "on %s ", buf));
457 TrapDebug((dbg_file, "sarg2 is %d, sarg3 is 0x%x ", sarg2,
460 #ifdef STREAM_BUFFERING
463 /* Now get its stream pointer if possible */
464 /* Can someone explain why fdopen doesn't work for O_RDWR? */
466 if (ValidFD(i) && !isatty(i) && (sarg2 != O_RDWR)) {
467 stream[i] = fdopen(i, fmode);
468 streammode[i] = fmode;
471 stream[i] = fdopen(i, fmode);
472 streammode[i] = fmode;
475 case S_MKNOD: /* DONE */
476 buf = xlate_filename((char *) &dspace[uarg1]);
477 i = mknod(buf, sarg2, sarg3);
479 case S_CHMOD: /* DONE */
480 buf = xlate_filename((char *) &dspace[uarg1]);
481 i = chmod(buf, sarg2);
483 case S_FCHMOD: /* DONE */
484 i = fchmod(sarg1, sarg2);
486 case S_TRUNCATE: /* DONE */
487 buf = xlate_filename((char *) &dspace[uarg1]);
488 larg1 = (sarg2 << 16) | uarg3;
489 i = truncate(buf, larg1);
491 case S_FTRUNCATE: /* DONE */
492 larg1 = (sarg2 << 16) | uarg3;
493 i = ftruncate(sarg1, larg1);
495 case S_KILL: /* DONE */
496 i = kill(sarg1, sarg2);
498 case S_KILLPG: /* DONE */
499 i = killpg(sarg1, sarg2);
501 case S_CHOWN: /* DONE */
502 buf = xlate_filename((char *) &dspace[uarg1]);
503 i = chown(buf, sarg2, sarg3);
505 case S_PIPE: /* DONE */
507 #ifdef STREAM_BUFFERING
508 if (ValidFD(pfd[0])) {
509 stream[pfd[0]] = fdopen(pfd[0], "r");
510 streammode[pfd[0]] = "r";
512 if (ValidFD(pfd[1])) {
513 stream[pfd[1]] = fdopen(pfd[1], "w");
514 streammode[pfd[1]] = "w";
522 case S_CHROOT: /* DONE */
523 buf = xlate_filename((char *) &dspace[uarg1]);
532 case S_CHDIR: /* DONE */
533 buf = xlate_filename((char *) &dspace[uarg1]);
536 case S_FCHDIR: /* DONE */
541 case S_CHFLAGS: /* DONE */
542 buf = xlate_filename((char *) &dspace[uarg1]);
543 i = chflags(buf, uarg2);
545 case S_FCHFLAGS: /* DONE */
546 i = fchflags(sarg1, uarg2);
550 case S_CREAT: /* DONE */
551 buf = xlate_filename((char *) &dspace[uarg1]);
552 i = creat(buf, sarg2);
553 #ifdef STREAM_BUFFERING
555 stream[i] = fdopen(i, "w");
560 case S_EXECVE: /* DONE, I think */
563 case S_EXECV: /* Not sure here */
566 case S_WAIT: /* Not sure here */
572 case S_WAIT4: /* Definitely incomplete */
573 TrapDebug((dbg_file, "on pid %d options %d ", sarg1, uarg3));
575 TrapDebug((dbg_file, " rusage on!!! "));
576 shortptr = (int16_t *) & dspace[uarg2];
577 i = wait4(sarg1, &j, uarg3, 0);
580 case S_FORK: /* DONE */
581 case S_VFORK: /* DONE */
585 } /* Took ages to find this! */
589 case S_GETHOSTID: /* DONE */
591 regs[1] = i & 0xffff;
592 i = (i >> 16) & 0xffff;
594 case S_SETHOSTID: /* DONE */
595 larg1 = (sarg2 << 16) | uarg3;
599 case S_GETUID: /* DONE */
602 case S_SETUID: /* DONE */
605 case S_GETEUID: /* DONE */
608 case S_GETPID: /* DONE */
611 case S_GETPPID: /* DONE */
614 case S_GETGID: /* DONE */
617 case S_GETEGID: /* DONE */
621 case S_GETPGRP: /* DONE */
625 case S_SETPGRP: /* DONE */
626 i = setpgid(sarg1, sarg2);
628 case S_SETREGID: /* DONE */
629 i = setregid(sarg1, sarg2);
631 case S_SETREUID: /* DONE */
632 i = setreuid(sarg1, sarg2);
634 case S_GETPRIORITY: /* DONE */
635 i = getpriority(sarg1, sarg2);
637 case S_SETPRIORITY: /* DONE */
638 i = setpriority(sarg1, sarg2, sarg3);
640 case S_LISTEN: /* DONE */
641 i = listen(sarg1, sarg2);
643 case S_SHUTDOWN: /* DONE */
644 i = shutdown(sarg1, sarg2);
646 case S_SOCKET: /* DONE */
647 i = socket(sarg1, sarg2, sarg3);
649 case S_SOCKETPAIR: /* DONE */
650 i = socketpair(sarg1, sarg2, sarg3, pfd);
652 shortptr = (int16_t *) & dspace[uarg4];
657 case S_RECV: /* DONE */
658 buf = (char *) &dspace[uarg2];
659 i = recv(sarg1, buf, sarg3, sarg4);
661 case S_SEND: /* DONE */
662 buf = (char *) &dspace[uarg2];
663 i = send(sarg1, buf, sarg3, sarg4);
665 case S_ACCEPT: /* DONE */
666 tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
667 sock.sa_family = tr_sock->sa_family;
672 memcpy(sock.sa_data, tr_sock->sa_data, len);
673 i = accept(sarg1, &sock, (socklen_t *) & len);
676 memcpy(tr_sock->sa_data, sock.sa_data, len);
679 case S_GETPEERNAME: /* DONE */
680 tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
681 sock.sa_family = tr_sock->sa_family;
686 memcpy(sock.sa_data, tr_sock->sa_data, len);
687 i = getpeername(sarg1, &sock, (socklen_t *) & len);
690 memcpy(tr_sock->sa_data, sock.sa_data, len);
693 case S_GETSOCKNAME: /* DONE */
694 tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
695 sock.sa_family = tr_sock->sa_family;
700 memcpy(sock.sa_data, tr_sock->sa_data, len);
701 i = getsockname(sarg1, &sock, (socklen_t *) & len);
704 memcpy(tr_sock->sa_data, sock.sa_data, len);
707 case S_BIND: /* DONE */
708 tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
709 sock.sa_family = tr_sock->sa_family;
714 memcpy(sock.sa_data, tr_sock->sa_data, len);
715 i = bind(sarg1, &sock, len);
717 case S_CONNECT: /* DONE */
718 tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
719 sock.sa_family = tr_sock->sa_family;
724 memcpy(sock.sa_data, tr_sock->sa_data, len);
725 i = connect(sarg1, &sock, len);
727 case S_RECVFROM: /* DONE I think */
728 tr_sock = (struct tr_sockaddr *) &dspace[uarg5];
729 sock.sa_family = tr_sock->sa_family;
734 memcpy(sock.sa_data, tr_sock->sa_data, len);
735 buf = (char *) &dspace[uarg2];
736 i = recvfrom(sarg1, buf, sarg3, sarg4, &sock,
737 (socklen_t *) & len);
740 memcpy(tr_sock->sa_data, sock.sa_data, len);
745 gidset = (gid_t *) malloc(len * sizeof(gid_t));
746 if (gidset == NULL) {
751 i = getgroups(len, gidset);
752 shortptr = (int16_t *) & dspace[uarg2];
753 for (j = 0; j < i; j++)
754 shortptr[j] = gidset[j];
764 gidset = (gid_t *) malloc(len * sizeof(gid_t));
765 if (gidset == NULL) {
770 shortptr = (int16_t *) & dspace[uarg2];
771 for (j = 0; j < len; j++)
772 gidset[j] = shortptr[j];
773 i = setgroups(len, gidset);
776 case S_GETRLIMIT: /* DONE */
777 tr_rlp = (struct tr_rlimit *) &dspace[uarg2];
778 i = getrlimit(sarg1, &rlp);
781 copylong(tr_rlp->rlim_cur, rlp.rlim_cur);
782 copylong(tr_rlp->rlim_max, rlp.rlim_max);
784 case S_SETRLIMIT: /* DONE */
785 tr_rlp = (struct tr_rlimit *) &dspace[uarg2];
786 copylong(rlp.rlim_cur, tr_rlp->rlim_cur);
787 copylong(rlp.rlim_max, tr_rlp->rlim_max);
788 i = setrlimit(sarg1, &rlp);
791 TrapDebug((dbg_file, "arg1 %d pointer 0%o ", sarg1, uarg2));
792 tr_use = (struct tr_rusage *) &dspace[uarg2];
793 i = getrusage(sarg1, &use);
797 /* Should do tr_use->ru_utime; user time used */
798 /* Should do tr_use->ru_stime; system time used */
799 copylong(tr_use->ru_maxrss, use.ru_maxrss);
800 copylong(tr_use->ru_ixrss, use.ru_ixrss);
801 copylong(tr_use->ru_idrss, use.ru_idrss);
802 copylong(tr_use->ru_isrss, use.ru_isrss);
803 copylong(tr_use->ru_minflt, use.ru_minflt);
804 copylong(tr_use->ru_majflt, use.ru_majflt);
805 copylong(tr_use->ru_ovly, ov_changes);
806 copylong(tr_use->ru_nswap, use.ru_nswap);
807 copylong(tr_use->ru_inblock, use.ru_inblock);
808 copylong(tr_use->ru_oublock, use.ru_oublock);
809 copylong(tr_use->ru_msgsnd, use.ru_msgsnd);
810 copylong(tr_use->ru_msgrcv, use.ru_msgrcv);
811 copylong(tr_use->ru_nsignals, use.ru_nsignals);
812 copylong(tr_use->ru_nvcsw, use.ru_nvcsw);
813 copylong(tr_use->ru_nivcsw, use.ru_nivcsw);
816 if ((ir & 0xff) > S_GETSOCKNAME) {
818 "Apout - unknown syscall %d at PC 0%o\n",
819 ir & 0xff, regs[PC]));
821 (void) fprintf(stderr,
822 "Apout - the 2.11BSD %s syscall is not yet implemented\n",
823 bsdtrap_name[ir & 0xff]);
828 /* Set r0 to either errno or i, */
829 /* and clear/set C bit */
834 TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
838 TrapDebug((dbg_file, "return %d\n", i));
845 static int trap_execve(int want_env)
847 u_int16_t cptr, cptr2;
848 char *buf, *name, *origpath;
850 origpath = strdup((char *) &dspace[uarg1]);
851 name = xlate_filename(origpath);
852 TrapDebug((dbg_file, "%s Execing %s (%s) ", progname, name, origpath));
854 set_bsdsig_dfl(); /* Set signals to default values */
859 while (Argc < MAX_ARGS) {
860 ll_word(cptr, cptr2);
863 buf = (char *) &dspace[cptr2];
864 Argv[Argc++] = strdup(buf);
866 TrapDebug((dbg_file, "%s ", buf));
869 TrapDebug((dbg_file, "\n"));
873 while (Envc < MAX_ARGS) {
874 ll_word(cptr, cptr2);
877 buf = (char *) &dspace[cptr2];
878 Envp[Envc++] = strdup(buf);
884 if (load_a_out(name, origpath, want_env) == -1) {
885 for (Argc--; Argc >= 0; Argc--)
888 for (Envc--; Envc >= 0; Envc--)
893 run(); /* Ok, so it's recursive, I dislike setjmp */
894 return (0); /* Just to shut the compiler up */
897 /* 2.11BSD reads directories as if they were ordinary files.
898 * The solution is to read the directory entries, and build a
899 * real file, which is passed back to the open call.
901 * A directory consists of some number of blocks of DIRBLKSIZ
902 * bytes, where DIRBLKSIZ is chosen such that it can be transferred
903 * to disk in a single atomic operation (e.g. 512 bytes on most machines).
905 * Each DIRBLKSIZ byte block contains some number of directory entry
906 * structures, which are of variable length. Each directory entry has
907 * a struct direct at the front of it, containing its inode number,
908 * the length of the entry, and the length of the name contained in
909 * the entry. These are followed by the name padded to a 4 byte boundary
910 * with null bytes. All names are guaranteed null terminated.
911 * The maximum length of a name in a directory is MAXNAMLEN.
913 * The macro DIRSIZ(dp) gives the amount of space required to represent
914 * a directory entry. Free space in a directory is represented by
915 * entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes
916 * in a directory block are claimed by the directory entries. This
917 * usually results in the last entry in a directory having a large
918 * dp->d_reclen. When entries are deleted from a directory, the
919 * space is returned to the previous entry in the same directory
920 * block by increasing its dp->d_reclen. If the first entry of
921 * a directory block is free, then its dp->d_ino is set to 0.
922 * Entries other than the first in a directory do not normally have
923 * dp->d_ino set to 0.
926 static int bsdopen_dir(char *name)
930 int i, nlen, total_left;
932 struct tr_direct odent, empty;
937 tmpname = strdup(TMP_PLATE);
938 i = mkstemp(tmpname);
940 (void) fprintf(stderr, "Apout - open_dir couldn't open %s\n",
947 total_left = TR_DIRBLKSIZ;
950 empty.d_name[0] = '\0';
951 empty.d_name[1] = '\0';
952 empty.d_name[2] = '\0';
953 empty.d_name[3] = '\0';
955 while ((dent = readdir(d)) != NULL) {
956 memset(odent.d_name, 0, TR_MAXNAMLEN + 1); /* Null name */
957 nlen = strlen(dent->d_name) + 1; /* Name length */
958 if (nlen > TR_MAXNAMLEN + 1)
959 nlen = TR_MAXNAMLEN + 1;
960 strncpy(odent.d_name, dent->d_name, nlen);
961 odent.d_ino = dent->d_fileno;
962 /* Nasty hack: ensure inode */
964 if (odent.d_ino == 0)
966 odent.d_namlen = nlen;
967 nlen += (nlen & 3); /* Round up to mult of 4 */
968 odent.d_reclen = nlen + 6; /* Name + 3 u_int16_ts */
970 /* Not enough room, write */
972 if ((total_left - odent.d_reclen) < 10) {
973 empty.d_reclen = total_left;
974 write(i, &empty, empty.d_reclen);
975 total_left = TR_DIRBLKSIZ;
977 write(i, &odent, odent.d_reclen);
978 total_left -= odent.d_reclen;
983 empty.d_reclen = total_left;
984 write(i, &empty, empty.d_reclen);
986 lseek(i, 0, SEEK_SET);
990 #ifdef NEED_MAP_FCNTL
991 /* Map the 2.11BSD fcntl mode bits to the underlying
992 * system's bits. We have to do this for Linux
994 static int16_t map_fcntl(int16_t f)
1004 if (f & BSD_NONBLOCK)
1023 TrapDebug((dbg_file, "map_fcntl: 0x%x -> 0x%x, ", f, out));