1
0
mirror of https://github.com/DoctorWkt/unix-jun72.git synced 2026-02-14 20:07:17 +00:00
Files
DoctorWkt.unix-jun72/tools/apout/bsdtrap.c
2008-05-06 23:25:22 +00:00

878 lines
27 KiB
C

/* bsdtrap.c - Deal with 2.11BSD trap instructions.
*
* $Revision: 1.65 $
* $Date: 2002/06/10 11:43:24 $
*/
#ifdef EMU211
/* NOTE NOTE NOTE NOTE
* Grep for the word DONE in this file to see the implemented syscalls.
*/
#define BSDTRAP_NAME
#include "defines.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/wait.h>
#include <signal.h>
#include <utime.h>
#include <sys/file.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include "bsdtrap.h"
#ifdef __linux__
#include <grp.h> /* setgroups() */
#endif
#define MAX_BLKSIZE 1024 /* Maximum block size from stat/fstat */
#undef STREAM_BUFFERING /* This works, but doesn't seem to give */
/* any speed improvement */
arglist *A; /* Pointer to various arguments on stack */
/* Forward prototypes */
#ifdef __STDC__
#define P(s) s
#else
#define P(s) ()
#endif
static int trap_execve P((int));
static int bsdopen_dir P((char *name));
#ifdef NEED_MAP_FCNTL
static int16_t map_fcntl P((int16_t f));
#endif
#undef P
void
bsdtrap()
{
int i, j, len, pid, pfd[2];
char *buf, *buf2;
int16_t *shortptr;
long larg1;
char *fmode; /* used with fdopen only */
struct stat stbuf; /* used in STAT */
struct tr_stat *tr_stbuf; /* used in STAT */
struct tr_timeval *tr_del, *tr_oldel; /* used in ADJTIME */
struct timeval del, oldel; /* used in ADJTIME */
struct timeval utv[2]; /* used in UTIMES */
struct tr_timezone *tr_zone; /* used in GETTIMEOFDAY */
struct timezone zone; /* used in GETTIMEOFDAY */
struct tr_itimerval *tr_tval, *tr_oltval; /* used in itimer calls */
struct itimerval tval, oltval; /* used in itimer calls */
struct tr_sockaddr *tr_sock; /* used in socket calls */
struct sockaddr sock; /* used in socket calls */
gid_t *gidset; /* used in GETGROUPS */
struct tr_rlimit *tr_rlp; /* used in rlimit calls */
struct rlimit rlp; /* used in rlimit calls */
struct tr_rusage *tr_use; /* used in getrusage */
struct rusage use; /* used in getrusage */
struct iovec *ivec; /* used in writev, readv */
struct tr_iovec *trivec; /* used in writev, readv */
TrapDebug((dbg_file, "pid %d %s: ", (int)getpid(),bsdtrap_name[ir & 0xff]));
A= (arglist *)&dspace[(regs[SP]+2)];
i=errno=0;
switch (ir & 0xff) {
case S_INDIR:
(void)printf("Does 2.11BSD use INDIR? I don't think so\n");
exit(EXIT_FAILURE);
case S_QUOTA: /* DONE - for now */
case S_SETQUOTA: /* DONE - for now */
i=-1; errno=EINVAL; break;
/* These syscalls are not implemented, and */
/* always return EPERM to the caller */
case S_PTRACE: /* DONE - bad syscall */
case S_MOUNT: /* DONE - bad syscall */
case S_UMOUNT: /* DONE - bad syscall */
case S_PROFIL: /* DONE - bad syscall */
case S_NOSYS147: /* DONE - bad syscall */
case S_SYSCTL:
i=-1; errno=EPERM; break;
/* These syscalls are ignored, and */
/* always return C=0 to the caller */
case S_OLDLOCK: /* DONE - ok syscall */
case S_OLDPHYS: /* DONE - ok syscall */
case S_FSTATFS: /* DONE - ok syscall */
case S_SIGPROCMASK: /* DONE - ok syscall */
case S_SIGRETURN: /* DONE - ok syscall */
case S_SIGALTSTACK: /* DONE - ok syscall */
case S_VHANGUP: /* DONE - ok syscall */
i=0; break;
case S_SIGACTION: /* DONE */
#define NO_SIGNALS_YET
#ifdef NO_SIGNALS_YET
i=0;
#else
i= do_sigaction(uarg1, uarg2, uarg3);
#endif
break;
case S_IOCTL: /* DONE a bit */
i=trap_ioctl(); break;
case S_SBRK: /* DONE */
if (uarg1<regs[SP]) {
i=0;
TrapDebug((dbg_file, "set break to %d ", uarg1));
} else {
i=-1; errno=ENOMEM;
TrapDebug((dbg_file, "break %d > SP %d", uarg1, regs[SP]));
}
break;
case S_SYNC: /* DONE */
sync(); i=0; break;
case S_FSYNC: /* DONE */
i= fsync(sarg1); break;
case S_GETDTABLESIZE: /* DONE */
i= getdtablesize(); break;
case S_EXIT: /* DONE */
#ifdef DEBUG
TrapDebug((dbg_file, "val %d\n",sarg1)); fflush(dbg_file);
#endif
exit(sarg1);
case S_DUP: /* DONE */
TrapDebug((dbg_file, "on %d ",sarg1));
i = dup(sarg1);
#ifdef STREAM_BUFFERING
if ((i!=-1) && ValidFD(sarg1) && stream[sarg1]) {
fmode= streammode[sarg1];
stream[i] = fdopen(i, fmode);
streammode[i]=fmode;
}
#endif
break;
case S_DUP2: /* DONE */
TrapDebug((dbg_file, "on %d %d ",sarg1,sarg2));
i = dup2(sarg1,sarg2);
#ifdef STREAM_BUFFERING
if ((i!=-1) && ValidFD(sarg2) && ValidFD(sarg1) && stream[sarg1]) {
fmode= streammode[sarg1];
stream[sarg2] = fdopen(sarg2, fmode);
streammode[sarg2]=fmode;
}
#endif
break;
case S_REBOOT: /* DONE */
(void)Reboot(sarg1); break;
case S_UMASK: /* DONE */
i = umask((mode_t)sarg1); break;
case S_GETPAGESIZE: /* DONE */
i = getpagesize(); break;
case S_GETHOSTNAME: /* DONE */
buf = (char *)&dspace[uarg1];
i= gethostname(buf,sarg2); break;
case S_SETHOSTNAME: /* DONE */
buf = (char *)&dspace[uarg1];
sethostname(buf,sarg2); break;
case S_LSEEK: /* DONE */
larg1 = (sarg2 << 16) | uarg3;
#ifdef STREAM_BUFFERING
if (ValidFD(sarg1) && stream[sarg1]) {
i = fseek(stream[sarg1], larg1, sarg4);
if (i == 0) i = ftell(stream[sarg1]);
} else
#endif
i = lseek(sarg1, larg1, sarg4);
if (i == -1) break;
else {
regs[1] = i & 0xffff;
i= (i >> 16) & 0xffff;
break;
}
case S_READ: /* DONE */
TrapDebug((dbg_file, "%d bytes on %d ",uarg3,sarg1));
buf = &dspace[uarg2];
#ifdef STREAM_BUFFERING
if (ValidFD(sarg1) && stream[sarg1])
i = fread(buf, 1, uarg3, stream[sarg1]);
else
#endif
i = read(sarg1, buf, uarg3); break;
case S_LINK: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
buf2 = xlate_filename(&dspace[uarg2]);
i = link(buf, buf2); break;
case S_SYMLINK: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
buf2 = xlate_filename(&dspace[uarg2]);
i = symlink(buf, buf2); break;
case S_RENAME: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
buf2 = xlate_filename(&dspace[uarg2]);
i = rename(buf, buf2); break;
case S_READLINK: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = readlink(buf, &dspace[uarg2], sarg3); break;
case S_ACCESS: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = access(buf, sarg2); break;
case S_MKDIR: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = mkdir(buf, sarg2); break;
case S_RMDIR: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = rmdir(buf); break;
case S_ACCT: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = acct(buf); break;
case S_WRITEV: /* DONE */
case S_READV: /* DONE */
ivec= (struct iovec *)malloc(uarg3 * sizeof(struct iovec));
if (ivec==NULL) { i=-1; errno=EINVAL; break; }
trivec= (struct tr_iovec *)&dspace[uarg2];
for (j=0; j<uarg3; j++) {
ivec[j].iov_len= trivec[j].iov_len;
ivec[j].iov_base= (char *)&dspace[trivec[j].iov_base];
}
if ((ir & 0xff)==S_READV) i= readv(sarg1, ivec, uarg3);
else i= writev(sarg1, ivec, uarg3);
free(ivec);
break;
case S_WRITE: /* DONE */
buf = &dspace[uarg2];
TrapDebug((dbg_file, "%d bytes on %d ",uarg3,sarg1));
#ifdef STREAM_BUFFERING
if (ValidFD(sarg1) && stream[sarg1])
i = fwrite(buf, 1, uarg3, stream[sarg1]);
else
#endif
i = write(sarg1, buf, uarg3); break;
case S_CLOSE: /* DONE */
#ifdef DEBUG
TrapDebug((dbg_file, "on %d ",sarg1));
if ((dbg_file!=NULL) && (sarg1==fileno(dbg_file))) {
i=0; break; /* Don't close our debug file! */
}
#endif
#ifdef STREAM_BUFFERING
if (ValidFD(sarg1) && stream[sarg1]) {
i = fclose(stream[sarg1]);
stream[sarg1] = NULL;
} else
#endif
i = close(sarg1); break;
case S_FCNTL:
TrapDebug((dbg_file, "on %d %d %d ",sarg1,sarg2, sarg3));
i = fcntl(sarg1,sarg2,sarg3); break;
case S_FLOCK:
i = flock(sarg1,sarg2); break;
case S_LSTAT: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
i = lstat(buf, &stbuf);
TrapDebug((dbg_file, "on %s ",buf));
goto dostat;
case S_STAT: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
i = stat(buf, &stbuf);
TrapDebug((dbg_file, "on %s ",buf));
goto dostat;
case S_FSTAT: /* DONE */
tr_stbuf = (struct tr_stat *) &dspace[uarg2];
i = fstat(uarg1, &stbuf);
TrapDebug((dbg_file, "on fd %d ",uarg1));
dostat:
if (i == -1) break;
else {
/* The following stops blksize equalling 64K,
* which becomes 0 in a 16-bit int. This then
* causes 2.11BSD flsbuf() to malloc(0), which
* then causes malloc to go crazy - wkt.
*/
if (stbuf.st_blksize>MAX_BLKSIZE) stbuf.st_blksize=MAX_BLKSIZE;
tr_stbuf->st_dev = stbuf.st_dev;
tr_stbuf->st_ino = stbuf.st_ino;
tr_stbuf->st_mode = stbuf.st_mode;
tr_stbuf->st_nlink = stbuf.st_nlink;
tr_stbuf->st_uid = stbuf.st_uid;
tr_stbuf->st_gid = stbuf.st_gid;
tr_stbuf->st_rdev = stbuf.st_rdev;
#ifndef NO_STFLAGS
tr_stbuf->st_flags = stbuf.st_flags;
#endif
copylong(tr_stbuf->st_size, stbuf.st_size);
copylong(tr_stbuf->st_atim, stbuf.st_atime);
copylong(tr_stbuf->st_mtim, stbuf.st_mtime);
copylong(tr_stbuf->st_ctim, stbuf.st_ctime);
copylong(tr_stbuf->st_blksize, stbuf.st_blksize);
larg1= stbuf.st_blocks; copylong(tr_stbuf->st_blocks, larg1);
}
break;
case S_UTIMES: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
tr_del = (struct tr_timeval *) &dspace[uarg2];
tr_oldel = (struct tr_timeval *) &dspace[uarg4];
i= utimes(buf, utv);
if (i==-1) break;
copylong(tr_del->tv_sec, utv[0].tv_sec);
copylong(tr_del->tv_usec, utv[0].tv_usec);
copylong(tr_oldel->tv_sec, utv[1].tv_sec);
copylong(tr_oldel->tv_usec, utv[1].tv_usec);
break;
case S_ADJTIME: /* DONE */
tr_del = (struct tr_timeval *) &dspace[uarg1];
/* Convert tr_del to del */
copylong(del.tv_sec, tr_del->tv_sec);
copylong(del.tv_usec, tr_del->tv_usec);
i= adjtime(&del, &oldel);
if (uarg2) {
tr_oldel = (struct tr_timeval *) &dspace[uarg2];
copylong(tr_oldel->tv_sec, oldel.tv_sec);
copylong(tr_oldel->tv_usec, oldel.tv_usec);
}
break;
case S_GETTIMEOFDAY: /* DONE */
tr_del = (struct tr_timeval *) &dspace[uarg1];
tr_zone = (struct tr_timezone *) &dspace[uarg2];
i= gettimeofday(&del, &zone);
copylong(tr_del->tv_sec, del.tv_sec);
copylong(tr_del->tv_usec, del.tv_usec);
tr_zone->tz_minuteswest= zone.tz_minuteswest;
tr_zone->tz_dsttime= zone.tz_dsttime;
break;
case S_SETTIMEOFDAY: /* DONE */
tr_del = (struct tr_timeval *) &dspace[uarg1];
tr_zone = (struct tr_timezone *) &dspace[uarg2];
copylong(del.tv_sec, tr_del->tv_sec);
copylong(del.tv_usec, tr_del->tv_usec);
zone.tz_minuteswest= tr_zone->tz_minuteswest;
zone.tz_dsttime= tr_zone->tz_dsttime;
i= settimeofday(&del, &zone);
break;
case S_GETITIMER: /* DONE */
tr_tval = (struct tr_itimerval *) &dspace[uarg2];
i= getitimer(sarg1, &tval);
copylong(tr_tval->it_interval.tv_sec, tval.it_interval.tv_sec);
copylong(tr_tval->it_interval.tv_usec, tval.it_interval.tv_usec);
copylong(tr_tval->it_value.tv_sec, tval.it_value.tv_sec);
copylong(tr_tval->it_value.tv_usec, tval.it_value.tv_usec);
break;
case S_SETITIMER: /* DONE */
tr_tval = (struct tr_itimerval *) &dspace[uarg2];
tr_oltval = (struct tr_itimerval *) &dspace[uarg2];
copylong(tval.it_interval.tv_sec, tr_tval->it_interval.tv_sec);
copylong(tval.it_interval.tv_usec, tr_tval->it_interval.tv_usec);
copylong(tval.it_value.tv_sec, tr_tval->it_value.tv_sec);
copylong(tval.it_value.tv_usec, tr_tval->it_value.tv_usec);
i= setitimer(sarg1, &tval, &oltval);
if (i == -1) break;
copylong(tr_oltval->it_interval.tv_sec, oltval.it_interval.tv_sec);
copylong(tr_oltval->it_interval.tv_usec, oltval.it_interval.tv_usec);
copylong(tr_oltval->it_value.tv_sec, oltval.it_value.tv_sec);
copylong(tr_oltval->it_value.tv_usec, oltval.it_value.tv_usec);
break;
case S_UNLINK: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = unlink(buf); break;
case S_OPEN: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = stat(buf, &stbuf); /* If file is a directory */
if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
i = bsdopen_dir(buf);
fmode = "w+";
TrapDebug((dbg_file, "(dir) on %s ",buf));
} else {
#ifdef NEED_MAP_FCNTL
sarg2= map_fcntl(sarg2);
#endif
switch (sarg2 & O_ACCMODE) {
case O_RDONLY: fmode = "r"; break;
case O_WRONLY: fmode = "w"; break;
default: fmode = "w+"; break;
}
i = open(buf, sarg2, sarg3);
TrapDebug((dbg_file, "on %s ",buf));
TrapDebug((dbg_file, "sarg2 is %d, sarg3 is 0x%x ",sarg2,sarg3));
}
#ifdef STREAM_BUFFERING
if (i==-1) break;
/* Now get its stream pointer if possible */
/* Can someone explain why fdopen doesn't work for O_RDWR? */
# if 0
if (ValidFD(i) && !isatty(i) && (sarg2!=O_RDWR)) {
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
}
# endif
stream[i] = fdopen(i, fmode); streammode[i]=fmode;
#endif
break;
case S_MKNOD: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = mknod(buf, sarg2, sarg3); break;
case S_CHMOD: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = chmod(buf, sarg2); break;
case S_FCHMOD: /* DONE */
i = fchmod(sarg1, sarg2); break;
case S_TRUNCATE: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
larg1 = (sarg2 << 16) | uarg3;
i = truncate(buf, larg1); break;
case S_FTRUNCATE: /* DONE */
larg1 = (sarg2 << 16) | uarg3;
i = ftruncate(sarg1, larg1); break;
case S_KILL: /* DONE */
i = kill(sarg1, sarg2); break;
case S_KILLPG: /* DONE */
i = killpg(sarg1, sarg2); break;
case S_CHOWN: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = chown(buf, sarg2, sarg3); break;
case S_PIPE: /* DONE */
i = pipe(pfd);
#ifdef STREAM_BUFFERING
if (ValidFD(pfd[0])) {
stream[pfd[0]] = fdopen(pfd[0], "r");
streammode[pfd[0]]= "r";
}
if (ValidFD(pfd[1])) {
stream[pfd[1]] = fdopen(pfd[1], "w");
streammode[pfd[1]]= "w";
}
#endif
if (i == -1) break;
i = pfd[0]; regs[1] = pfd[1]; break;
case S_CHROOT: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
if (buf == NULL) {
errno=ENOENT; i=-1; break;
}
set_apout_root(buf);
i=0; break;
case S_CHDIR: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = chdir(buf); break;
case S_FCHDIR: /* DONE */
i = fchdir(sarg1); break;
#ifndef NO_CHFLAGS
case S_CHFLAGS: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = chflags(buf,uarg2); break;
case S_FCHFLAGS: /* DONE */
i = fchflags(sarg1,uarg2); break;
#endif
case S_CREAT: /* DONE */
buf = xlate_filename(&dspace[uarg1]);
i = creat(buf, sarg2);
#ifdef STREAM_BUFFERING
if (ValidFD(i)) {
stream[i] = fdopen(i, "w");
streammode[i]= "w";
}
#endif
break;
case S_EXECVE: /* DONE, I think */
i= trap_execve(1); break;
case S_EXECV: /* Not sure here */
i= trap_execve(0); break;
case S_WAIT: /* Not sure here */
i = wait(&pid);
if (i == -1) break;
regs[1] = pid;
break;
case S_WAIT4: /* Definitely incomplete */
TrapDebug((dbg_file, "on pid %d options %d ",sarg1,uarg3));
if (uarg4) TrapDebug((dbg_file, " rusage on!!! "));
shortptr = (int16_t *)&dspace[uarg2];
i= wait4(sarg1, &j, uarg3, 0);
*shortptr= j;
break;
case S_FORK: /* DONE */
case S_VFORK: /* DONE */
i = fork();
if (i!=0) { regs[PC]+=2; } /* Took ages to find this! */
else ov_changes=0;
break;
case S_GETHOSTID: /* DONE */
i = gethostid();
regs[1] = i & 0xffff;
i= (i >> 16) & 0xffff;
break;
case S_SETHOSTID: /* DONE */
larg1 = (sarg2 << 16) | uarg3;
sethostid(larg1); i=0; break;
case S_GETUID: /* DONE */
i = getuid(); break;
case S_SETUID: /* DONE */
i = setuid(uarg1); break;
case S_GETEUID: /* DONE */
i = geteuid(); break;
case S_GETPID: /* DONE */
i = getpid(); break;
case S_GETPPID: /* DONE */
i = getppid(); break;
case S_GETGID: /* DONE */
i = getgid(); break;
case S_GETEGID: /* DONE */
i = getegid(); break;
#ifndef NO_GETPGID
case S_GETPGRP: /* DONE */
i = getpgid(sarg1); break;
#endif
case S_SETPGRP: /* DONE */
i = setpgid(sarg1,sarg2); break;
case S_SETREGID: /* DONE */
i = setregid(sarg1,sarg2); break;
case S_SETREUID: /* DONE */
i = setreuid(sarg1,sarg2); break;
case S_GETPRIORITY: /* DONE */
i = getpriority(sarg1,sarg2); break;
case S_SETPRIORITY: /* DONE */
i = setpriority(sarg1,sarg2,sarg3); break;
case S_LISTEN: /* DONE */
i = listen(sarg1,sarg2); break;
case S_SHUTDOWN: /* DONE */
i = shutdown(sarg1,sarg2); break;
case S_SOCKET: /* DONE */
i = socket(sarg1,sarg2,sarg3); break;
case S_SOCKETPAIR: /* DONE */
i = socketpair(sarg1,sarg2,sarg3, pfd); break;
shortptr= (int16_t *)&dspace[uarg4];
*shortptr= pfd[0]; shortptr+=2;
*shortptr= pfd[1];
break;
case S_RECV: /* DONE */
buf = &dspace[uarg2];
i = recv(sarg1, buf, sarg3, sarg4); break;
case S_SEND: /* DONE */
buf = &dspace[uarg2];
i = send(sarg1, buf, sarg3, sarg4); break;
case S_ACCEPT: /* DONE */
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
sock.sa_family= tr_sock->sa_family;
ll_word(uarg3, len);
#ifndef __linux__
sock.sa_len=len;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
i= accept(sarg1, &sock, &len);
if (i != -1) {
sl_word(uarg3,len);
memcpy(tr_sock->sa_data, sock.sa_data, len);
}
break;
case S_GETPEERNAME: /* DONE */
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
sock.sa_family= tr_sock->sa_family;
ll_word(uarg3, len);
#ifndef __linux__
sock.sa_len=len;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
i= getpeername(sarg1, &sock, &len);
if (i != -1) {
sl_word(uarg3,len);
memcpy(tr_sock->sa_data, sock.sa_data, len);
}
break;
case S_GETSOCKNAME: /* DONE */
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
sock.sa_family= tr_sock->sa_family;
ll_word(uarg3, len);
#ifndef __linux__
sock.sa_len=len;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
i= getsockname(sarg1, &sock, &len);
if (i != -1) {
sl_word(uarg3,len);
memcpy(tr_sock->sa_data, sock.sa_data, len);
}
break;
case S_BIND: /* DONE */
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
sock.sa_family= tr_sock->sa_family;
len= sarg3;
#ifndef __linux__
sock.sa_len= sarg3;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
i= bind(sarg1, &sock, len);
break;
case S_CONNECT: /* DONE */
tr_sock= (struct tr_sockaddr *)&dspace[uarg2];
sock.sa_family= tr_sock->sa_family;
len= sarg3;
#ifndef __linux__
sock.sa_len= sarg3;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
i= connect(sarg1, &sock, len);
break;
case S_RECVFROM: /* DONE I think */
tr_sock= (struct tr_sockaddr *)&dspace[uarg5];
sock.sa_family= tr_sock->sa_family;
ll_word(uarg6, len);
#ifndef __linux__
sock.sa_len=len;
#endif
memcpy(sock.sa_data, tr_sock->sa_data, len);
buf = &dspace[uarg2];
i= recvfrom(sarg1, buf, sarg3, sarg4, &sock, &len);
if (i != -1) {
sl_word(uarg6,len);
memcpy(tr_sock->sa_data, sock.sa_data, len);
}
break;
case S_GETGROUPS:
len= sarg1;
gidset= (gid_t *)malloc(len * sizeof(gid_t));
if (gidset==NULL) { i=-1; errno=EINVAL; break; }
i= getgroups(len, gidset);
shortptr= (int16_t *)&dspace[uarg2];
for (j=0; j<i; j++) shortptr[j]= gidset[j];
free(gidset);
break;
case S_SETGROUPS:
len= sarg1;
if (len>16) { i=-1; errno=EFAULT; break; }
gidset= (gid_t *)malloc(len * sizeof(gid_t));
if (gidset==NULL) { i=-1; errno=EINVAL; break; }
shortptr= (int16_t *)&dspace[uarg2];
for (j=0; j<len; j++) gidset[j]= shortptr[j];
i= setgroups(len, gidset);
free(gidset);
break;
case S_GETRLIMIT: /* DONE */
tr_rlp= (struct tr_rlimit *)&dspace[uarg2];
i= getrlimit(sarg1, &rlp);
if (i== -1) break;
copylong(tr_rlp->rlim_cur, rlp.rlim_cur);
copylong(tr_rlp->rlim_max, rlp.rlim_max);
break;
case S_SETRLIMIT: /* DONE */
tr_rlp= (struct tr_rlimit *)&dspace[uarg2];
copylong(rlp.rlim_cur, tr_rlp->rlim_cur);
copylong(rlp.rlim_max, tr_rlp->rlim_max);
i= setrlimit(sarg1, &rlp);
break;
case S_GETRUSAGE:
TrapDebug((dbg_file, "arg1 %d pointer 0%o ",sarg1,uarg2));
tr_use = (struct tr_rusage *) &dspace[uarg2];
i= getrusage(sarg1, &use);
if (i==-1) break;
/* Should do tr_use->ru_utime; user time used */
/* Should do tr_use->ru_stime; system time used */
copylong(tr_use->ru_maxrss, use.ru_maxrss);
copylong(tr_use->ru_ixrss, use.ru_ixrss);
copylong(tr_use->ru_idrss, use.ru_idrss);
copylong(tr_use->ru_isrss, use.ru_isrss);
copylong(tr_use->ru_minflt, use.ru_minflt);
copylong(tr_use->ru_majflt, use.ru_majflt);
copylong(tr_use->ru_ovly, ov_changes);
copylong(tr_use->ru_nswap, use.ru_nswap);
copylong(tr_use->ru_inblock, use.ru_inblock);
copylong(tr_use->ru_oublock, use.ru_oublock);
copylong(tr_use->ru_msgsnd, use.ru_msgsnd);
copylong(tr_use->ru_msgrcv, use.ru_msgrcv);
copylong(tr_use->ru_nsignals, use.ru_nsignals);
copylong(tr_use->ru_nvcsw, use.ru_nvcsw);
copylong(tr_use->ru_nivcsw, use.ru_nivcsw);
break;
default:
if ((ir & 0xff)>S_GETSOCKNAME) {
TrapDebug((stderr,"Apout - unknown syscall %d at PC 0%o\n",
ir & 0xff,regs[PC]));
} else {
(void)fprintf(stderr,
"Apout - the 2.11BSD %s syscall is not yet implemented\n",
bsdtrap_name[ir & 0xff]);
}
exit(EXIT_FAILURE);
}
/* Set r0 to either errno or i, */
/* and clear/set C bit */
if (i == -1) {
SET_CC_C(); regs[0] = errno;
TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
} else {
CLR_CC_C(); regs[0]=i;
TrapDebug((dbg_file, "return %d\n", i));
}
return;
}
static int
trap_execve(int want_env)
{
u_int16_t cptr, cptr2;
char *buf, *name, *origpath;
origpath = strdup(&dspace[uarg1]);
name = xlate_filename(origpath);
TrapDebug((dbg_file, "%s Execing %s (%s) ", progname, name, origpath));
set_bsdsig_dfl(); /* Set signals to default values */
cptr=uarg2;
Argc=0; Envc=0;
while (Argc < MAX_ARGS) {
ll_word(cptr, cptr2);
if (cptr2 == 0)
break;
buf = &dspace[cptr2];
Argv[Argc++] = strdup(buf);
cptr += 2;
TrapDebug((dbg_file, "%s ", buf));
}
Argv[Argc] = NULL;
TrapDebug((dbg_file, "\n"));
if (want_env)
{ cptr=uarg3;
while (Envc < MAX_ARGS) {
ll_word(cptr, cptr2);
if (cptr2 == 0)
break;
buf = &dspace[cptr2];
Envp[Envc++] = strdup(buf);
cptr += 2;
}
Envp[Envc] = NULL;
}
if (load_a_out(name,origpath,want_env) == -1) {
for (Argc--; Argc >= 0; Argc--)
free(Argv[Argc]);
if (want_env) for (Envc--; Envc >= 0; Envc--)
free(Envp[Envc]);
errno= ENOENT; return(-1);
}
run(); /* Ok, so it's recursive, I dislike setjmp */
return(0); /* Just to shut the compiler up */
}
/* 2.11BSD reads directories as if they were ordinary files.
* The solution is to read the directory entries, and build a
* real file, which is passed back to the open call.
*
* A directory consists of some number of blocks of DIRBLKSIZ
* bytes, where DIRBLKSIZ is chosen such that it can be transferred
* to disk in a single atomic operation (e.g. 512 bytes on most machines).
*
* Each DIRBLKSIZ byte block contains some number of directory entry
* structures, which are of variable length. Each directory entry has
* a struct direct at the front of it, containing its inode number,
* the length of the entry, and the length of the name contained in
* the entry. These are followed by the name padded to a 4 byte boundary
* with null bytes. All names are guaranteed null terminated.
* The maximum length of a name in a directory is MAXNAMLEN.
*
* The macro DIRSIZ(dp) gives the amount of space required to represent
* a directory entry. Free space in a directory is represented by
* entries which have dp->d_reclen > DIRSIZ(dp). All DIRBLKSIZ bytes
* in a directory block are claimed by the directory entries. This
* usually results in the last entry in a directory having a large
* dp->d_reclen. When entries are deleted from a directory, the
* space is returned to the previous entry in the same directory
* block by increasing its dp->d_reclen. If the first entry of
* a directory block is free, then its dp->d_ino is set to 0.
* Entries other than the first in a directory do not normally have
* dp->d_ino set to 0.
*/
static int
bsdopen_dir(char *name)
{
DIR *d;
char *tmpname;
int i, nlen, total_left;
struct dirent *dent;
struct tr_direct odent, empty;
d = opendir(name);
if (d == NULL) return (-1);
tmpname= strdup(TMP_PLATE);
i= mkstemp(tmpname);
if (i == -1) {
(void)fprintf(stderr,"Apout - open_dir couldn't open %s\n", tmpname);
exit(EXIT_FAILURE);
}
unlink(tmpname); free(tmpname);
total_left=TR_DIRBLKSIZ;
empty.d_ino=0; empty.d_namlen=0; empty.d_name[0]='\0';
empty.d_name[1]='\0'; empty.d_name[2]='\0'; empty.d_name[3]='\0';
while ((dent = readdir(d)) != NULL) {
memset(odent.d_name, 0, TR_MAXNAMLEN+1); /* Null name */
nlen= strlen(dent->d_name) +1; /* Name length */
if (nlen>TR_MAXNAMLEN+1) nlen=TR_MAXNAMLEN+1;
strncpy(odent.d_name, dent->d_name, nlen);
odent.d_ino = dent->d_fileno;
/* Nasty hack: ensure inode */
/* is never 0 */
if (odent.d_ino==0) odent.d_ino=1;
odent.d_namlen= nlen;
nlen+= (nlen & 3); /* Round up to mult of 4 */
odent.d_reclen= nlen+6; /* Name + 3 u_int16_ts */
/* Not enough room, write */
/* a blank entry */
if ( (total_left - odent.d_reclen) < 10) {
empty.d_reclen=total_left;
write(i, &empty, empty.d_reclen);
total_left=TR_DIRBLKSIZ;
}
write(i, &odent, odent.d_reclen);
total_left-= odent.d_reclen;
}
closedir(d);
if (total_left) {
empty.d_reclen=total_left; write(i, &empty, empty.d_reclen);
}
lseek(i, 0, SEEK_SET);
return (i);
}
#ifdef NEED_MAP_FCNTL
/* Map the 2.11BSD fcntl mode bits to the underlying
* system's bits. We have to do this for Linux
*/
static int16_t map_fcntl(int16_t f)
{
int16_t out=0;
if (f & BSD_RDONLY) out |= O_RDONLY;
if (f & BSD_WRONLY) out |= O_WRONLY;
if (f & BSD_RDWR) out |= O_RDWR;
if (f & BSD_NONBLOCK) out |= O_NONBLOCK;
if (f & BSD_APPEND) out |= O_APPEND;
if (f & BSD_SHLOCK) out |= O_SHLOCK;
if (f & BSD_EXLOCK) out |= O_EXLOCK;
if (f & BSD_ASYNC) out |= O_ASYNC;
if (f & BSD_FSYNC) out |= O_FSYNC;
if (f & BSD_CREAT) out |= O_CREAT;
if (f & BSD_TRUNC) out |= O_TRUNC;
if (f & BSD_EXCL) out |= O_EXCL;
TrapDebug((dbg_file, "map_fcntl: 0x%x -> 0x%x, ",f,out));
return(out);
}
#endif
#endif /* EMU211 */