summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/Makefile15
-rw-r--r--sys/compat/freebsd32/freebsd32.h103
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c1339
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h264
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h288
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c413
-rw-r--r--sys/compat/freebsd32/freebsd32_util.h94
-rw-r--r--sys/compat/freebsd32/syscalls.conf12
-rw-r--r--sys/compat/freebsd32/syscalls.master563
-rw-r--r--sys/compat/ia32/ia32_sysvec.c365
-rw-r--r--sys/compat/ia32/ia32_util.h94
-rw-r--r--sys/compat/linprocfs/linprocfs.c861
-rw-r--r--sys/compat/linux/linux_file.c1197
-rw-r--r--sys/compat/linux/linux_getcwd.c473
-rw-r--r--sys/compat/linux/linux_ioctl.c2379
-rw-r--r--sys/compat/linux/linux_ioctl.h668
-rw-r--r--sys/compat/linux/linux_ipc.c528
-rw-r--r--sys/compat/linux/linux_ipc.h131
-rw-r--r--sys/compat/linux/linux_mib.c354
-rw-r--r--sys/compat/linux/linux_mib.h43
-rw-r--r--sys/compat/linux/linux_misc.c1349
-rw-r--r--sys/compat/linux/linux_signal.c438
-rw-r--r--sys/compat/linux/linux_signal.h38
-rw-r--r--sys/compat/linux/linux_socket.c971
-rw-r--r--sys/compat/linux/linux_socket.h52
-rw-r--r--sys/compat/linux/linux_stats.c499
-rw-r--r--sys/compat/linux/linux_sysctl.c120
-rw-r--r--sys/compat/linux/linux_uid16.c297
-rw-r--r--sys/compat/linux/linux_util.c186
-rw-r--r--sys/compat/linux/linux_util.h108
-rw-r--r--sys/compat/netbsd/dvcfg.h65
-rw-r--r--sys/compat/netbsd/physio_proc.h56
-rw-r--r--sys/compat/pecoff/imgact_pecoff.c650
-rw-r--r--sys/compat/pecoff/imgact_pecoff.h142
-rw-r--r--sys/compat/svr4/Makefile19
-rw-r--r--sys/compat/svr4/imgact_svr4.c241
-rw-r--r--sys/compat/svr4/svr4.h53
-rw-r--r--sys/compat/svr4/svr4_acl.h46
-rw-r--r--sys/compat/svr4/svr4_dirent.h53
-rw-r--r--sys/compat/svr4/svr4_errno.h172
-rw-r--r--sys/compat/svr4/svr4_exec.h70
-rw-r--r--sys/compat/svr4/svr4_fcntl.c736
-rw-r--r--sys/compat/svr4/svr4_fcntl.h134
-rw-r--r--sys/compat/svr4/svr4_filio.c234
-rw-r--r--sys/compat/svr4/svr4_filio.h45
-rw-r--r--sys/compat/svr4/svr4_fuser.h97
-rw-r--r--sys/compat/svr4/svr4_hrt.h87
-rw-r--r--sys/compat/svr4/svr4_ioctl.c167
-rw-r--r--sys/compat/svr4/svr4_ioctl.h62
-rw-r--r--sys/compat/svr4/svr4_ipc.c821
-rw-r--r--sys/compat/svr4/svr4_ipc.h176
-rw-r--r--sys/compat/svr4/svr4_misc.c1744
-rw-r--r--sys/compat/svr4/svr4_mman.h47
-rw-r--r--sys/compat/svr4/svr4_proto.h477
-rw-r--r--sys/compat/svr4/svr4_resource.c324
-rw-r--r--sys/compat/svr4/svr4_resource.h109
-rw-r--r--sys/compat/svr4/svr4_siginfo.h111
-rw-r--r--sys/compat/svr4/svr4_signal.c676
-rw-r--r--sys/compat/svr4/svr4_signal.h143
-rw-r--r--sys/compat/svr4/svr4_socket.c193
-rw-r--r--sys/compat/svr4/svr4_socket.h56
-rw-r--r--sys/compat/svr4/svr4_sockio.c164
-rw-r--r--sys/compat/svr4/svr4_sockio.h93
-rw-r--r--sys/compat/svr4/svr4_sockmod.h83
-rw-r--r--sys/compat/svr4/svr4_stat.c775
-rw-r--r--sys/compat/svr4/svr4_stat.h105
-rw-r--r--sys/compat/svr4/svr4_statvfs.h72
-rw-r--r--sys/compat/svr4/svr4_stream.c2295
-rw-r--r--sys/compat/svr4/svr4_stropts.h175
-rw-r--r--sys/compat/svr4/svr4_syscall.h145
-rw-r--r--sys/compat/svr4/svr4_syscallnames.c264
-rw-r--r--sys/compat/svr4/svr4_sysconfig.h62
-rw-r--r--sys/compat/svr4/svr4_sysent.c276
-rw-r--r--sys/compat/svr4/svr4_systeminfo.h50
-rw-r--r--sys/compat/svr4/svr4_sysvec.c413
-rw-r--r--sys/compat/svr4/svr4_termios.c607
-rw-r--r--sys/compat/svr4/svr4_termios.h224
-rw-r--r--sys/compat/svr4/svr4_time.h41
-rw-r--r--sys/compat/svr4/svr4_timod.h87
-rw-r--r--sys/compat/svr4/svr4_ttold.c366
-rw-r--r--sys/compat/svr4/svr4_ttold.h122
-rw-r--r--sys/compat/svr4/svr4_types.h81
-rw-r--r--sys/compat/svr4/svr4_ucontext.h74
-rw-r--r--sys/compat/svr4/svr4_ulimit.h41
-rw-r--r--sys/compat/svr4/svr4_ustat.h43
-rw-r--r--sys/compat/svr4/svr4_util.h87
-rw-r--r--sys/compat/svr4/svr4_utsname.h44
-rw-r--r--sys/compat/svr4/svr4_wait.h56
-rw-r--r--sys/compat/svr4/syscalls.conf12
-rw-r--r--sys/compat/svr4/syscalls.master366
90 files changed, 29471 insertions, 0 deletions
diff --git a/sys/compat/freebsd32/Makefile b/sys/compat/freebsd32/Makefile
new file mode 100644
index 0000000..1184ef4
--- /dev/null
+++ b/sys/compat/freebsd32/Makefile
@@ -0,0 +1,15 @@
+# Makefile for syscall tables
+#
+# $FreeBSD$
+
+all:
+ @echo "make sysent only"
+
+sysent: ia32_sysent.c ia32_syscall.h ia32_proto.h
+
+ia32_sysent.c ia32_syscall.h ia32_proto.h: ../../kern/makesyscalls.sh \
+ syscalls.master syscalls.conf
+ -mv -f ia32_sysent.c ia32_sysent.c.bak
+ -mv -f ia32_syscall.h ia32_syscall.h.bak
+ -mv -f ia32_proto.h ia32_proto.h.bak
+ sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
new file mode 100644
index 0000000..943b24c
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _IA64_IA32_IA32_H_
+#define _IA64_IA32_IA32_H_
+
+#define PTRIN(v) (void *)(uintptr_t) (v)
+#define PTROUT(v) (u_int32_t)(uintptr_t) (v)
+
+#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0)
+#define PTRIN_CP(src,dst,fld) \
+ do { (dst).fld = PTRIN((src).fld); } while (0)
+#define PTROUT_CP(src,dst,fld) \
+ do { (dst).fld = PTROUT((src).fld); } while (0)
+
+struct timeval32 {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+#define TV_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_usec); \
+} while (0);
+
+struct timespec32 {
+ u_int32_t tv_sec;
+ u_int32_t tv_nsec;
+};
+#define TS_CP(src,dst,fld) do { \
+ CP((src).fld,(dst).fld,tv_sec); \
+ CP((src).fld,(dst).fld,tv_nsec); \
+} while (0);
+
+struct rusage32 {
+ struct timeval32 ru_utime;
+ struct timeval32 ru_stime;
+ int32_t ru_maxrss;
+ int32_t ru_ixrss;
+ int32_t ru_idrss;
+ int32_t ru_isrss;
+ int32_t ru_minflt;
+ int32_t ru_majflt;
+ int32_t ru_nswap;
+ int32_t ru_inblock;
+ int32_t ru_oublock;
+ int32_t ru_msgsnd;
+ int32_t ru_msgrcv;
+ int32_t ru_nsignals;
+ int32_t ru_nvcsw;
+ int32_t ru_nivcsw;
+};
+
+struct statfs32 {
+ int32_t f_spare2;
+ int32_t f_bsize;
+ int32_t f_iosize;
+ int32_t f_blocks;
+ int32_t f_bfree;
+ int32_t f_bavail;
+ int32_t f_files;
+ int32_t f_ffree;
+ fsid_t f_fsid;
+ uid_t f_owner;
+ int32_t f_type;
+ int32_t f_flags;
+ int32_t f_syncwrites;
+ int32_t f_asyncwrites;
+ char f_fstypename[MFSNAMELEN];
+ char f_mntonname[MNAMELEN];
+ int32_t f_syncreads;
+ int32_t f_asyncreads;
+ int16_t f_spares1;
+ char f_mntfromname[MNAMELEN];
+ int16_t f_spares2;
+ int32_t f_spare[2];
+};
+
+#endif /* !_IA64_IA32_IA32_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
new file mode 100644
index 0000000..8b28bce
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -0,0 +1,1339 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/module.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/selinfo.h>
+#include <sys/pipe.h> /* Must come after sys/selinfo.h */
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/systm.h>
+#include <sys/unistd.h>
+#include <sys/user.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+static const char ia32_emul_path[] = "/compat/ia32";
+/*
+ * [ taken from the linux emulator ]
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+ia32_emul_find(td, sgp, prefix, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ int error;
+ size_t len, sz;
+ char *buf, *cp, *ptr;
+ struct ucred *ucred;
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--)
+ ;
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ } else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the ia32_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ ucred = td->td_ucred;
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred,
+ td)) != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+
+ return error;
+
+bad:
+ vrele(ndroot.ni_vp);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
+
+int
+ia32_open(struct thread *td, struct ia32_open_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return open(td, (struct open_args *) uap);
+}
+
+int
+ia32_wait4(struct thread *td, struct ia32_wait4_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *rusage32, ru32;
+ struct rusage *rusage = NULL, ru;
+
+ rusage32 = SCARG(uap, rusage);
+ if (rusage32) {
+ sg = stackgap_init();
+ rusage = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)rusage;
+ }
+ error = wait4(td, (struct wait_args *)uap);
+ if (error)
+ return (error);
+ if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) {
+ TV_CP(ru, ru32, ru_utime);
+ TV_CP(ru, ru32, ru_stime);
+ CP(ru, ru32, ru_maxrss);
+ CP(ru, ru32, ru_ixrss);
+ CP(ru, ru32, ru_idrss);
+ CP(ru, ru32, ru_isrss);
+ CP(ru, ru32, ru_minflt);
+ CP(ru, ru32, ru_majflt);
+ CP(ru, ru32, ru_nswap);
+ CP(ru, ru32, ru_inblock);
+ CP(ru, ru32, ru_oublock);
+ CP(ru, ru32, ru_msgsnd);
+ CP(ru, ru32, ru_msgrcv);
+ CP(ru, ru32, ru_nsignals);
+ CP(ru, ru32, ru_nvcsw);
+ CP(ru, ru32, ru_nivcsw);
+ error = copyout(&ru32, rusage32, sizeof(ru32));
+ }
+ return (error);
+}
+
+static void
+copy_statfs(struct statfs *in, struct statfs32 *out)
+{
+ CP(*in, *out, f_bsize);
+ CP(*in, *out, f_iosize);
+ CP(*in, *out, f_blocks);
+ CP(*in, *out, f_bfree);
+ CP(*in, *out, f_bavail);
+ CP(*in, *out, f_files);
+ CP(*in, *out, f_ffree);
+ CP(*in, *out, f_fsid);
+ CP(*in, *out, f_owner);
+ CP(*in, *out, f_type);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_flags);
+ CP(*in, *out, f_syncwrites);
+ CP(*in, *out, f_asyncwrites);
+ bcopy(in->f_fstypename,
+ out->f_fstypename, MFSNAMELEN);
+ bcopy(in->f_mntonname,
+ out->f_mntonname, MNAMELEN);
+ CP(*in, *out, f_syncreads);
+ CP(*in, *out, f_asyncreads);
+ bcopy(in->f_mntfromname,
+ out->f_mntfromname, MNAMELEN);
+}
+
+int
+ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *sp32, stat32;
+ struct statfs *sp = NULL, stat;
+ int maxcount, count, i;
+
+ sp32 = SCARG(uap, buf);
+ maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32);
+
+ if (sp32) {
+ sg = stackgap_init();
+ sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount);
+ SCARG(uap, buf) = (struct statfs32 *)sp;
+ }
+ error = getfsstat(td, (struct getfsstat_args *) uap);
+ if (sp32 && !error) {
+ count = td->td_retval[0];
+ for (i = 0; i < count; i++) {
+ error = copyin(&sp[i], &stat, sizeof(stat));
+ if (error)
+ return (error);
+ copy_statfs(&stat, &stat32);
+ error = copyout(&stat32, &sp32[i], sizeof(stat32));
+ if (error)
+ return (error);
+ }
+ }
+ return (error);
+}
+
+int
+ia32_access(struct thread *td, struct ia32_access_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return access(td, (struct access_args *)uap);
+}
+
+int
+ia32_chflags(struct thread *td, struct ia32_chflags_args *uap)
+{
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ return chflags(td, (struct chflags_args *)uap);
+}
+
+struct sigaltstack32 {
+ u_int32_t ss_sp;
+ u_int32_t ss_size;
+ int ss_flags;
+};
+
+int
+ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaltstack32 *p32, *op32, s32;
+ struct sigaltstack *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, ss);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, ss) = (struct sigaltstack32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ PTRIN_CP(s32, s, ss_sp);
+ CP(s32, s, ss_size);
+ CP(s32, s, ss_flags);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oss);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ SCARG(uap, oss) = (struct sigaltstack32 *)op;
+ }
+ error = sigaltstack(td, (struct sigaltstack_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ PTROUT_CP(s, s32, ss_sp);
+ CP(s, s32, ss_size);
+ CP(s, s32, ss_flags);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_execve(struct thread *td, struct ia32_execve_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct execve_args ap;
+ u_int32_t *p32, arg;
+ char **p;
+ int count;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, fname));
+ SCARG(&ap, fname) = SCARG(uap, fname);
+
+ if (SCARG(uap, argv)) {
+ count = 0;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, argv) = p;
+ p32 = SCARG(uap, argv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+ if (SCARG(uap, envv)) {
+ count = 0;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ count++;
+ } while (arg != 0);
+ p = stackgap_alloc(&sg, count * sizeof(char *));
+ SCARG(&ap, envv) = p;
+ p32 = SCARG(uap, envv);
+ do {
+ error = copyin(p32++, &arg, sizeof(arg));
+ if (error)
+ return error;
+ *p++ = PTRIN(arg);
+ } while (arg != 0);
+ }
+
+ return execve(td, &ap);
+}
+
+static int
+ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end,
+ int prot, int fd, off_t pos)
+{
+ vm_map_t map;
+ vm_map_entry_t entry;
+ int rv;
+
+ map = &td->td_proc->p_vmspace->vm_map;
+ if (fd != -1)
+ prot |= VM_PROT_WRITE;
+
+ if (vm_map_lookup_entry(map, start, &entry)) {
+ if ((entry->protection & prot) != prot) {
+ rv = vm_map_protect(map,
+ trunc_page(start),
+ round_page(end),
+ entry->protection | prot,
+ FALSE);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+ } else {
+ vm_offset_t addr = trunc_page(start);
+ rv = vm_map_find(map, 0, 0,
+ &addr, PAGE_SIZE, FALSE, prot,
+ VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ }
+
+ if (fd != -1) {
+ struct pread_args r;
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ return (pread(td, &r));
+ } else {
+ while (start < end) {
+ subyte((void *) start, 0);
+ start++;
+ }
+ return (0);
+ }
+}
+
+int
+ia32_mmap(struct thread *td, struct ia32_mmap_args *uap)
+{
+ struct mmap_args ap;
+ vm_offset_t addr = (vm_offset_t) SCARG(uap, addr);
+ vm_size_t len = SCARG(uap, len);
+ int prot = SCARG(uap, prot);
+ int flags = SCARG(uap, flags);
+ int fd = SCARG(uap, fd);
+ off_t pos = (SCARG(uap, poslo)
+ | ((off_t)SCARG(uap, poshi) << 32));
+ vm_size_t pageoff;
+ int error;
+
+ /*
+ * Attempt to handle page size hassles.
+ */
+ pageoff = (pos & PAGE_MASK);
+ if (flags & MAP_FIXED) {
+ vm_offset_t start, end;
+ start = addr;
+ end = addr + len;
+
+ if (start != trunc_page(start)) {
+ error = ia32_mmap_partial(td, start, round_page(start),
+ prot, fd, pos);
+ if (fd != -1)
+ pos += round_page(start) - start;
+ start = round_page(start);
+ }
+ if (end != round_page(end)) {
+ vm_offset_t t = trunc_page(end);
+ error = ia32_mmap_partial(td, t, end,
+ prot, fd,
+ pos + t - start);
+ end = trunc_page(end);
+ }
+ if (end > start && fd != -1 && (pos & PAGE_MASK)) {
+ /*
+ * We can't map this region at all. The specified
+ * address doesn't have the same alignment as the file
+ * position. Fake the mapping by simply reading the
+ * entire region into memory. First we need to make
+ * sure the region exists.
+ */
+ vm_map_t map;
+ struct pread_args r;
+ int rv;
+
+ prot |= VM_PROT_WRITE;
+ map = &td->td_proc->p_vmspace->vm_map;
+ rv = vm_map_remove(map, start, end);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ rv = vm_map_find(map, 0, 0,
+ &start, end - start, FALSE,
+ prot, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS)
+ return (EINVAL);
+ SCARG(&r, fd) = fd;
+ SCARG(&r, buf) = (void *) start;
+ SCARG(&r, nbyte) = end - start;
+ SCARG(&r, offset) = pos;
+ error = pread(td, &r);
+ if (error)
+ return (error);
+
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ if (end == start) {
+ /*
+ * After dealing with the ragged ends, there
+ * might be none left.
+ */
+ td->td_retval[0] = addr;
+ return (0);
+ }
+ addr = start;
+ len = end - start;
+ }
+
+ SCARG(&ap, addr) = (void *) addr;
+ SCARG(&ap, len) = len;
+ SCARG(&ap, prot) = prot;
+ SCARG(&ap, flags) = flags;
+ SCARG(&ap, fd) = fd;
+ SCARG(&ap, pos) = pos;
+
+ return (mmap(td, &ap));
+}
+
+struct itimerval32 {
+ struct timeval32 it_interval;
+ struct timeval32 it_value;
+};
+
+int
+ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct itimerval32 *p32, *op32, s32;
+ struct itimerval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, itv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, itv) = (struct itimerval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ TV_CP(s32, s, it_interval);
+ TV_CP(s32, s, it_value);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oitv);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct itimerval));
+ SCARG(uap, oitv) = (struct itimerval32 *)op;
+ }
+ error = setitimer(td, (struct setitimer_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, it_interval);
+ TV_CP(s, s32, it_value);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_select(struct thread *td, struct ia32_select_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ /*
+ * XXX big-endian needs to convert the fd_sets too.
+ */
+ return (select(td, (struct select_args *) uap));
+}
+
+int
+ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tp);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tp) = (struct timeval32 *)p;
+ }
+ error = gettimeofday(td, (struct gettimeofday_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, p32, sizeof(s32));
+ if (error)
+ return (error);
+ }
+ return (error);
+}
+
+int
+ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct rusage32 *p32, s32;
+ struct rusage *p = NULL, s;
+
+ p32 = SCARG(uap, rusage);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct rusage));
+ SCARG(uap, rusage) = (struct rusage32 *)p;
+ }
+ error = getrusage(td, (struct getrusage_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ TV_CP(s, s32, ru_utime);
+ TV_CP(s, s32, ru_stime);
+ CP(s, s32, ru_maxrss);
+ CP(s, s32, ru_ixrss);
+ CP(s, s32, ru_idrss);
+ CP(s, s32, ru_isrss);
+ CP(s, s32, ru_minflt);
+ CP(s, s32, ru_majflt);
+ CP(s, s32, ru_nswap);
+ CP(s, s32, ru_inblock);
+ CP(s, s32, ru_oublock);
+ CP(s, s32, ru_msgsnd);
+ CP(s, s32, ru_msgrcv);
+ CP(s, s32, ru_nsignals);
+ CP(s, s32, ru_nvcsw);
+ CP(s, s32, ru_nivcsw);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+struct iovec32 {
+ u_int32_t iov_base;
+ int iov_len;
+};
+#define STACKGAPLEN 400
+
+int
+ia32_readv(struct thread *td, struct ia32_readv_args *uap)
+{
+ int error, osize, nsize, i;
+ caddr_t sg;
+ struct readv_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = readv(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_writev(struct thread *td, struct ia32_writev_args *uap)
+{
+ int error, i, nsize, osize;
+ caddr_t sg;
+ struct writev_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct iovec *) iovp;
+ syscallarg(u_int) iovcnt;
+ } */ a;
+ struct iovec32 *oio;
+ struct iovec *nio;
+
+ sg = stackgap_init();
+
+ if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec)))
+ return (EINVAL);
+
+ osize = SCARG(uap, iovcnt) * sizeof (struct iovec32);
+ nsize = SCARG(uap, iovcnt) * sizeof (struct iovec);
+
+ oio = malloc(osize, M_TEMP, M_WAITOK);
+ nio = malloc(nsize, M_TEMP, M_WAITOK);
+
+ error = 0;
+ if ((error = copyin(SCARG(uap, iovp), oio, osize)))
+ goto punt;
+ for (i = 0; i < SCARG(uap, iovcnt); i++) {
+ nio[i].iov_base = PTRIN(oio[i].iov_base);
+ nio[i].iov_len = oio[i].iov_len;
+ }
+
+ SCARG(&a, fd) = SCARG(uap, fd);
+ SCARG(&a, iovp) = stackgap_alloc(&sg, nsize);
+ SCARG(&a, iovcnt) = SCARG(uap, iovcnt);
+
+ if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize)))
+ goto punt;
+ error = writev(td, &a);
+
+punt:
+ free(oio, M_TEMP);
+ free(nio, M_TEMP);
+ return (error);
+}
+
+int
+ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32;
+ struct timeval *p = NULL, s;
+
+ p32 = SCARG(uap, tv);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, tv) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (settimeofday(td, (struct settimeofday_args *) uap));
+}
+
+int
+ia32_utimes(struct thread *td, struct ia32_utimes_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, s32[2];
+ struct timeval *p = NULL, s[2];
+
+ p32 = SCARG(uap, tptr);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, 2*sizeof(struct timeval));
+ SCARG(uap, tptr) = (struct timeval32 *)p;
+ error = copyin(p32, s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32[0], s[0], tv_sec);
+ CP(s32[0], s[0], tv_usec);
+ CP(s32[1], s[1], tv_sec);
+ CP(s32[1], s[1], tv_usec);
+ error = copyout(s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ return (utimes(td, (struct utimes_args *) uap));
+}
+
+int
+ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct timeval32 *p32, *op32, s32;
+ struct timeval *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, delta);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, delta) = (struct timeval32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ CP(s32, s, tv_sec);
+ CP(s32, s, tv_usec);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, olddelta);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct timeval));
+ SCARG(uap, olddelta) = (struct timeval32 *)op;
+ }
+ error = utimes(td, (struct utimes_args *) uap);
+ if (error)
+ return error;
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ CP(s, s32, tv_sec);
+ CP(s, s32, tv_usec);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_statfs(struct thread *td, struct ia32_statfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = statfs(td, (struct statfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct statfs32 *p32, s32;
+ struct statfs *p = NULL, s;
+
+ p32 = SCARG(uap, buf);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct statfs));
+ SCARG(uap, buf) = (struct statfs32 *)p;
+ }
+ error = fstatfs(td, (struct fstatfs_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_statfs(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_semsys(struct thread *td, struct ia32_semsys_args *uap)
+{
+ /*
+ * Vector through to semsys if it is loaded.
+ */
+ return sysent[169].sy_call(td, uap);
+}
+
+int
+ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap)
+{
+ /*
+ * Vector through to msgsys if it is loaded.
+ */
+ return sysent[170].sy_call(td, uap);
+}
+
+int
+ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap)
+{
+ /*
+ * Vector through to shmsys if it is loaded.
+ */
+ return sysent[171].sy_call(td, uap);
+}
+
+int
+ia32_pread(struct thread *td, struct ia32_pread_args *uap)
+{
+ struct pread_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pread(td, &ap));
+}
+
+int
+ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap)
+{
+ struct pwrite_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, buf) = SCARG(uap, buf);
+ SCARG(&ap, nbyte) = SCARG(uap, nbyte);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ return (pwrite(td, &ap));
+}
+
+int
+ia32_lseek(struct thread *td, struct ia32_lseek_args *uap)
+{
+ int error;
+ struct lseek_args ap;
+ off_t pos;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, whence) = SCARG(uap, whence);
+ error = lseek(td, &ap);
+ /* Expand the quad return into two parts for eax and edx */
+ pos = *(off_t *)(td->td_retval);
+ td->td_retval[0] = pos & 0xffffffff; /* %eax */
+ td->td_retval[1] = pos >> 32; /* %edx */
+ return error;
+}
+
+int
+ia32_truncate(struct thread *td, struct ia32_truncate_args *uap)
+{
+ struct truncate_args ap;
+
+ SCARG(&ap, path) = SCARG(uap, path);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (truncate(td, &ap));
+}
+
+int
+ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap)
+{
+ struct ftruncate_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, length) = (SCARG(uap, lengthlo)
+ | ((off_t)SCARG(uap, lengthhi) << 32));
+ return (ftruncate(td, &ap));
+}
+
+int
+ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap)
+{
+ struct sendfile_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+ SCARG(&ap, s) = SCARG(uap, s);
+ SCARG(&ap, offset) = (SCARG(uap, offsetlo)
+ | ((off_t)SCARG(uap, offsethi) << 32));
+ SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */
+ SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */
+ SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */
+ SCARG(&ap, flags) = SCARG(uap, flags);
+ return (sendfile(td, &ap));
+}
+
+struct stat32 {
+ udev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ udev_t st_rdev;
+ struct timespec32 st_atimespec;
+ struct timespec32 st_mtimespec;
+ struct timespec32 st_ctimespec;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int32_t st_gen;
+};
+
+static void
+copy_stat( struct stat *in, struct stat32 *out)
+{
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atimespec);
+ TS_CP(*in, *out, st_mtimespec);
+ TS_CP(*in, *out, st_ctimespec);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+}
+
+int
+ia32_stat(struct thread *td, struct ia32_stat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = stat(td, (struct stat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_fstat(struct thread *td, struct ia32_fstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = fstat(td, (struct fstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+int
+ia32_lstat(struct thread *td, struct ia32_lstat_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct stat32 *p32, s32;
+ struct stat *p = NULL, s;
+
+ p32 = SCARG(uap, ub);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct stat));
+ SCARG(uap, ub) = (struct stat32 *)p;
+ }
+ error = lstat(td, (struct lstat_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ copy_stat(&s, &s32);
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+/*
+ * MPSAFE
+ */
+int
+ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j, oldlen;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+
+ error = copyin(uap->name, &name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+
+ mtx_lock(&Giant);
+
+ if (uap->oldlenp)
+ oldlen = fuword32(uap->oldlenp);
+ else
+ oldlen = 0;
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, &oldlen, 1,
+ uap->new, uap->newlen, &j);
+ if (error && error != ENOMEM)
+ goto done2;
+ if (uap->oldlenp) {
+ suword32(uap->oldlenp, j);
+ }
+done2:
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+struct sigaction32 {
+ u_int32_t sa_u;
+ int sa_flags;
+ sigset_t sa_mask;
+};
+
+int
+ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct sigaction32 *p32, *op32, s32;
+ struct sigaction *p = NULL, *op = NULL, s;
+
+ p32 = SCARG(uap, act);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, act) = (struct sigaction32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ s.sa_handler = PTRIN(s32.sa_u);
+ CP(s32, s, sa_flags);
+ CP(s32, s, sa_mask);
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ op32 = SCARG(uap, oact);
+ if (op32) {
+ sg = stackgap_init();
+ op = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(uap, oact) = (struct sigaction32 *)op;
+ }
+ error = sigaction(td, (struct sigaction_args *) uap);
+ if (error)
+ return (error);
+ if (op32) {
+ error = copyin(op, &s, sizeof(s));
+ if (error)
+ return (error);
+ s32.sa_u = PTROUT(s.sa_handler);
+ CP(s, s32, sa_flags);
+ CP(s, s32, sa_mask);
+ error = copyout(&s32, op32, sizeof(s32));
+ }
+ return (error);
+}
+
+#if 0
+
+int
+ia32_xxx(struct thread *td, struct ia32_xxx_args *uap)
+{
+ int error;
+ caddr_t sg;
+ struct yyy32 *p32, s32;
+ struct yyy *p = NULL, s;
+
+ p32 = SCARG(uap, zzz);
+ if (p32) {
+ sg = stackgap_init();
+ p = stackgap_alloc(&sg, sizeof(struct yyy));
+ SCARG(uap, zzz) = (struct yyy32 *)p;
+ error = copyin(p32, &s32, sizeof(s32));
+ if (error)
+ return (error);
+ /* translate in */
+ error = copyout(&s, p, sizeof(s));
+ if (error)
+ return (error);
+ }
+ error = xxx(td, (struct xxx_args *) uap);
+ if (error)
+ return (error);
+ if (p32) {
+ error = copyin(p, &s, sizeof(s));
+ if (error)
+ return (error);
+ /* translate out */
+ error = copyout(&s32, p32, sizeof(s32));
+ }
+ return (error);
+}
+
+#endif
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
new file mode 100644
index 0000000..36b9e73
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -0,0 +1,264 @@
+/*
+ * System call prototypes.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp
+ */
+
+#ifndef _IA32_SYSPROTO_H_
+#define _IA32_SYSPROTO_H_
+
+#include <sys/signal.h>
+
+#include <sys/acl.h>
+
+struct proc;
+
+struct thread;
+
+#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
+ 0 : sizeof(register_t) - sizeof(t))
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define PADL_(t) 0
+#define PADR_(t) PAD_(t)
+#else
+#define PADL_(t) PAD_(t)
+#define PADR_(t) 0
+#endif
+
+struct ia32_open_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)];
+};
+struct ia32_wait4_args {
+ char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)];
+};
+struct ia32_getfsstat_args {
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+ char bufsize_l_[PADL_(long)]; long bufsize; char bufsize_r_[PADR_(long)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct ia32_access_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct ia32_chflags_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct ia32_sigaltstack_args {
+ char ss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * ss; char ss_r_[PADR_(struct sigaltstack32 *)];
+ char oss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * oss; char oss_r_[PADR_(struct sigaltstack32 *)];
+};
+struct ia32_execve_args {
+ char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)];
+ char argv_l_[PADL_(u_int32_t *)]; u_int32_t * argv; char argv_r_[PADR_(u_int32_t *)];
+ char envv_l_[PADL_(u_int32_t *)]; u_int32_t * envv; char envv_r_[PADR_(u_int32_t *)];
+};
+struct ia32_setitimer_args {
+ char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)];
+ char itv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * itv; char itv_r_[PADR_(struct itimerval32 *)];
+ char oitv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * oitv; char oitv_r_[PADR_(struct itimerval32 *)];
+};
+struct ia32_select_args {
+ char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)];
+ char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)];
+ char ou_l_[PADL_(fd_set *)]; fd_set * ou; char ou_r_[PADR_(fd_set *)];
+ char ex_l_[PADL_(fd_set *)]; fd_set * ex; char ex_r_[PADR_(fd_set *)];
+ char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)];
+};
+struct ia32_gettimeofday_args {
+ char tp_l_[PADL_(struct timeval32 *)]; struct timeval32 * tp; char tp_r_[PADR_(struct timeval32 *)];
+ char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)];
+};
+struct ia32_getrusage_args {
+ char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)];
+ char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)];
+};
+struct ia32_readv_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+};
+struct ia32_writev_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)];
+ char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)];
+};
+struct ia32_settimeofday_args {
+ char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)];
+ char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)];
+};
+struct ia32_utimes_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char tptr_l_[PADL_(struct timeval32 *)]; struct timeval32 * tptr; char tptr_r_[PADR_(struct timeval32 *)];
+};
+struct ia32_adjtime_args {
+ char delta_l_[PADL_(struct timeval32 *)]; struct timeval32 * delta; char delta_r_[PADR_(struct timeval32 *)];
+ char olddelta_l_[PADL_(struct timeval32 *)]; struct timeval32 * olddelta; char olddelta_r_[PADR_(struct timeval32 *)];
+};
+struct ia32_statfs_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+};
+struct ia32_fstatfs_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)];
+};
+struct ia32_semsys_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+};
+struct ia32_msgsys_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+ char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)];
+ char a6_l_[PADL_(int)]; int a6; char a6_r_[PADR_(int)];
+};
+struct ia32_shmsys_args {
+ char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
+ char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
+ char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)];
+ char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)];
+};
+struct ia32_pread_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)];
+ char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)];
+};
+struct ia32_pwrite_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)];
+ char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)];
+ char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)];
+};
+struct ia32_stat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct ia32_fstat_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct ia32_lstat_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)];
+};
+struct ia32_mmap_args {
+ char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)];
+ char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
+ char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char poslo_l_[PADL_(u_int32_t)]; u_int32_t poslo; char poslo_r_[PADR_(u_int32_t)];
+ char poshi_l_[PADL_(u_int32_t)]; u_int32_t poshi; char poshi_r_[PADR_(u_int32_t)];
+};
+struct ia32_lseek_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)];
+ char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)];
+ char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)];
+};
+struct ia32_truncate_args {
+ char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char lengthlo_l_[PADL_(u_int32_t)]; u_int32_t lengthlo; char lengthlo_r_[PADR_(u_int32_t)];
+ char lengthhi_l_[PADL_(u_int32_t)]; u_int32_t lengthhi; char lengthhi_r_[PADR_(u_int32_t)];
+};
+struct ia32_ftruncate_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)];
+ char lengthlo_l_[PADL_(u_int32_t)]; u_int32_t lengthlo; char lengthlo_r_[PADR_(u_int32_t)];
+ char lengthhi_l_[PADL_(u_int32_t)]; u_int32_t lengthhi; char lengthhi_r_[PADR_(u_int32_t)];
+};
+struct ia32_sysctl_args {
+ char name_l_[PADL_(int *)]; int * name; char name_r_[PADR_(int *)];
+ char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)];
+ char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)];
+ char oldlenp_l_[PADL_(u_int32_t *)]; u_int32_t * oldlenp; char oldlenp_r_[PADR_(u_int32_t *)];
+ char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)];
+ char newlen_l_[PADL_(u_int32_t)]; u_int32_t newlen; char newlen_r_[PADR_(u_int32_t)];
+};
+struct ia32_sendfile_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)];
+ char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)];
+ char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)];
+ char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)];
+ char hdtr_l_[PADL_(struct sf_hdtr *)]; struct sf_hdtr * hdtr; char hdtr_r_[PADR_(struct sf_hdtr *)];
+ char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct ia32_sigaction_args {
+ char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)];
+ char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)];
+ char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)];
+};
+int ia32_open(struct thread *, struct ia32_open_args *);
+int ia32_wait4(struct thread *, struct ia32_wait4_args *);
+int ia32_getfsstat(struct thread *, struct ia32_getfsstat_args *);
+int ia32_access(struct thread *, struct ia32_access_args *);
+int ia32_chflags(struct thread *, struct ia32_chflags_args *);
+int ia32_sigaltstack(struct thread *, struct ia32_sigaltstack_args *);
+int ia32_execve(struct thread *, struct ia32_execve_args *);
+int ia32_setitimer(struct thread *, struct ia32_setitimer_args *);
+int ia32_select(struct thread *, struct ia32_select_args *);
+int ia32_gettimeofday(struct thread *, struct ia32_gettimeofday_args *);
+int ia32_getrusage(struct thread *, struct ia32_getrusage_args *);
+int ia32_readv(struct thread *, struct ia32_readv_args *);
+int ia32_writev(struct thread *, struct ia32_writev_args *);
+int ia32_settimeofday(struct thread *, struct ia32_settimeofday_args *);
+int ia32_utimes(struct thread *, struct ia32_utimes_args *);
+int ia32_adjtime(struct thread *, struct ia32_adjtime_args *);
+int ia32_statfs(struct thread *, struct ia32_statfs_args *);
+int ia32_fstatfs(struct thread *, struct ia32_fstatfs_args *);
+int ia32_semsys(struct thread *, struct ia32_semsys_args *);
+int ia32_msgsys(struct thread *, struct ia32_msgsys_args *);
+int ia32_shmsys(struct thread *, struct ia32_shmsys_args *);
+int ia32_pread(struct thread *, struct ia32_pread_args *);
+int ia32_pwrite(struct thread *, struct ia32_pwrite_args *);
+int ia32_stat(struct thread *, struct ia32_stat_args *);
+int ia32_fstat(struct thread *, struct ia32_fstat_args *);
+int ia32_lstat(struct thread *, struct ia32_lstat_args *);
+int ia32_mmap(struct thread *, struct ia32_mmap_args *);
+int ia32_lseek(struct thread *, struct ia32_lseek_args *);
+int ia32_truncate(struct thread *, struct ia32_truncate_args *);
+int ia32_ftruncate(struct thread *, struct ia32_ftruncate_args *);
+int ia32_sysctl(struct thread *, struct ia32_sysctl_args *);
+int ia32_sendfile(struct thread *, struct ia32_sendfile_args *);
+int ia32_sigaction(struct thread *, struct ia32_sigaction_args *);
+
+#ifdef COMPAT_43
+
+
+#endif /* COMPAT_43 */
+
+
+#ifdef COMPAT_FREEBSD4
+
+
+#endif /* COMPAT_FREEBSD4 */
+
+#undef PAD_
+#undef PADL_
+#undef PADR_
+
+#endif /* !_IA32_SYSPROTO_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
new file mode 100644
index 0000000..e457152
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -0,0 +1,288 @@
+/*
+ * System call numbers.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp
+ */
+
+#define IA32_SYS_syscall 0
+#define IA32_SYS_exit 1
+#define IA32_SYS_fork 2
+#define IA32_SYS_read 3
+#define IA32_SYS_write 4
+#define IA32_SYS_ia32_open 5
+#define IA32_SYS_close 6
+#define IA32_SYS_ia32_wait4 7
+ /* 8 is obsolete old creat */
+#define IA32_SYS_link 9
+#define IA32_SYS_unlink 10
+ /* 11 is obsolete execv */
+#define IA32_SYS_chdir 12
+#define IA32_SYS_fchdir 13
+#define IA32_SYS_mknod 14
+#define IA32_SYS_chmod 15
+#define IA32_SYS_chown 16
+#define IA32_SYS_break 17
+#define IA32_SYS_ia32_getfsstat 18
+ /* 19 is obsolete olseek */
+#define IA32_SYS_getpid 20
+#define IA32_SYS_mount 21
+#define IA32_SYS_unmount 22
+#define IA32_SYS_setuid 23
+#define IA32_SYS_getuid 24
+#define IA32_SYS_geteuid 25
+#define IA32_SYS_ptrace 26
+#define IA32_SYS_sendmsg 28
+#define IA32_SYS_recvfrom 29
+#define IA32_SYS_accept 30
+#define IA32_SYS_getpeername 31
+#define IA32_SYS_getsockname 32
+#define IA32_SYS_ia32_access 33
+#define IA32_SYS_ia32_chflags 34
+#define IA32_SYS_fchflags 35
+#define IA32_SYS_sync 36
+#define IA32_SYS_kill 37
+#define IA32_SYS_getppid 39
+#define IA32_SYS_dup 41
+#define IA32_SYS_pipe 42
+#define IA32_SYS_getegid 43
+#define IA32_SYS_profil 44
+#define IA32_SYS_ktrace 45
+#define IA32_SYS_getgid 47
+#define IA32_SYS_getlogin 49
+#define IA32_SYS_setlogin 50
+#define IA32_SYS_acct 51
+#define IA32_SYS_sigpending 52
+#define IA32_SYS_ia32_sigaltstack 53
+#define IA32_SYS_ioctl 54
+#define IA32_SYS_reboot 55
+#define IA32_SYS_revoke 56
+#define IA32_SYS_symlink 57
+#define IA32_SYS_readlink 58
+#define IA32_SYS_ia32_execve 59
+#define IA32_SYS_umask 60
+#define IA32_SYS_chroot 61
+ /* 62 is obsolete ofstat */
+ /* 63 is obsolete ogetkerninfo */
+ /* 64 is obsolete ogetpagesize */
+ /* 65 is obsolete omsync */
+ /* 66 is obsolete ovfork */
+ /* 67 is obsolete vread */
+ /* 68 is obsolete vwrite */
+#define IA32_SYS_sbrk 69
+#define IA32_SYS_sstk 70
+ /* 71 is obsolete ommap */
+#define IA32_SYS_vadvise 72
+#define IA32_SYS_munmap 73
+#define IA32_SYS_mprotect 74
+#define IA32_SYS_madvise 75
+ /* 76 is obsolete vhangup */
+ /* 77 is obsolete vlimit */
+#define IA32_SYS_mincore 78
+#define IA32_SYS_getgroups 79
+#define IA32_SYS_setgroups 80
+#define IA32_SYS_getpgrp 81
+#define IA32_SYS_setpgid 82
+#define IA32_SYS_ia32_setitimer 83
+ /* 84 is obsolete owait */
+ /* 85 is obsolete oswapon */
+ /* 86 is obsolete ogetitimer */
+ /* 87 is obsolete ogethostname */
+ /* 88 is obsolete osethostname */
+#define IA32_SYS_getdtablesize 89
+#define IA32_SYS_dup2 90
+#define IA32_SYS_fcntl 92
+#define IA32_SYS_ia32_select 93
+#define IA32_SYS_fsync 95
+#define IA32_SYS_setpriority 96
+#define IA32_SYS_socket 97
+#define IA32_SYS_connect 98
+#define IA32_SYS_accept 99
+#define IA32_SYS_getpriority 100
+ /* 101 is obsolete osend */
+ /* 102 is obsolete orecv */
+ /* 103 is obsolete osigreturn */
+#define IA32_SYS_bind 104
+#define IA32_SYS_setsockopt 105
+#define IA32_SYS_listen 106
+ /* 107 is obsolete vtimes */
+ /* 108 is obsolete osigvec */
+ /* 109 is obsolete osigblock */
+ /* 110 is obsolete osigsetmask */
+ /* 111 is obsolete osigsuspend */
+ /* 112 is obsolete osigstack */
+ /* 113 is obsolete orecvmsg */
+ /* 114 is obsolete osendmsg */
+ /* 115 is obsolete vtrace */
+#define IA32_SYS_ia32_gettimeofday 116
+#define IA32_SYS_ia32_getrusage 117
+#define IA32_SYS_getsockopt 118
+#define IA32_SYS_ia32_readv 120
+#define IA32_SYS_ia32_writev 121
+#define IA32_SYS_ia32_settimeofday 122
+#define IA32_SYS_fchown 123
+#define IA32_SYS_fchmod 124
+#define IA32_SYS_recvfrom 125
+#define IA32_SYS_setreuid 126
+#define IA32_SYS_setregid 127
+#define IA32_SYS_rename 128
+ /* 129 is obsolete otruncate */
+ /* 130 is obsolete ftruncate */
+#define IA32_SYS_flock 131
+#define IA32_SYS_mkfifo 132
+#define IA32_SYS_sendto 133
+#define IA32_SYS_shutdown 134
+#define IA32_SYS_socketpair 135
+#define IA32_SYS_mkdir 136
+#define IA32_SYS_rmdir 137
+#define IA32_SYS_ia32_utimes 138
+ /* 139 is obsolete 4.2 sigreturn */
+#define IA32_SYS_ia32_adjtime 140
+ /* 141 is obsolete ogetpeername */
+ /* 142 is obsolete ogethostid */
+ /* 143 is obsolete sethostid */
+ /* 144 is obsolete getrlimit */
+ /* 145 is obsolete setrlimit */
+ /* 146 is obsolete killpg */
+#define IA32_SYS_setsid 147
+#define IA32_SYS_quotactl 148
+ /* 149 is obsolete oquota */
+ /* 150 is obsolete ogetsockname */
+#define IA32_SYS_getdirentries 156
+#define IA32_SYS_ia32_statfs 157
+#define IA32_SYS_ia32_fstatfs 158
+#define IA32_SYS_getfh 161
+#define IA32_SYS_getdomainname 162
+#define IA32_SYS_setdomainname 163
+#define IA32_SYS_uname 164
+#define IA32_SYS_sysarch 165
+#define IA32_SYS_rtprio 166
+#define IA32_SYS_ia32_semsys 169
+#define IA32_SYS_ia32_msgsys 170
+#define IA32_SYS_ia32_shmsys 171
+#define IA32_SYS_ia32_pread 173
+#define IA32_SYS_ia32_pwrite 174
+#define IA32_SYS_ntp_adjtime 176
+#define IA32_SYS_setgid 181
+#define IA32_SYS_setegid 182
+#define IA32_SYS_seteuid 183
+#define IA32_SYS_ia32_stat 188
+#define IA32_SYS_ia32_fstat 189
+#define IA32_SYS_ia32_lstat 190
+#define IA32_SYS_pathconf 191
+#define IA32_SYS_fpathconf 192
+#define IA32_SYS_getrlimit 194
+#define IA32_SYS_setrlimit 195
+#define IA32_SYS_getdirentries 196
+#define IA32_SYS_ia32_mmap 197
+#define IA32_SYS___syscall 198
+#define IA32_SYS_ia32_lseek 199
+#define IA32_SYS_ia32_truncate 200
+#define IA32_SYS_ia32_ftruncate 201
+#define IA32_SYS_ia32_sysctl 202
+#define IA32_SYS_mlock 203
+#define IA32_SYS_munlock 204
+#define IA32_SYS_undelete 205
+#define IA32_SYS_futimes 206
+#define IA32_SYS_getpgid 207
+#define IA32_SYS_poll 209
+#define IA32_SYS___semctl 220
+#define IA32_SYS_semget 221
+#define IA32_SYS_semop 222
+#define IA32_SYS_msgctl 224
+#define IA32_SYS_msgget 225
+#define IA32_SYS_msgsnd 226
+#define IA32_SYS_msgrcv 227
+#define IA32_SYS_shmat 228
+#define IA32_SYS_shmctl 229
+#define IA32_SYS_shmdt 230
+#define IA32_SYS_shmget 231
+#define IA32_SYS_clock_gettime 232
+#define IA32_SYS_clock_settime 233
+#define IA32_SYS_clock_getres 234
+#define IA32_SYS_nanosleep 240
+#define IA32_SYS_minherit 250
+#define IA32_SYS_rfork 251
+#define IA32_SYS_openbsd_poll 252
+#define IA32_SYS_issetugid 253
+#define IA32_SYS_lchown 254
+#define IA32_SYS_getdents 272
+#define IA32_SYS_lchmod 274
+#define IA32_SYS_netbsd_lchown 275
+#define IA32_SYS_lutimes 276
+#define IA32_SYS_netbsd_msync 277
+#define IA32_SYS_nstat 278
+#define IA32_SYS_nfstat 279
+#define IA32_SYS_nlstat 280
+#define IA32_SYS_fhstatfs 297
+#define IA32_SYS_fhopen 298
+#define IA32_SYS_fhstat 299
+#define IA32_SYS_modnext 300
+#define IA32_SYS_modstat 301
+#define IA32_SYS_modfnext 302
+#define IA32_SYS_modfind 303
+#define IA32_SYS_kldload 304
+#define IA32_SYS_kldunload 305
+#define IA32_SYS_kldfind 306
+#define IA32_SYS_kldnext 307
+#define IA32_SYS_kldstat 308
+#define IA32_SYS_kldfirstmod 309
+#define IA32_SYS_getsid 310
+#define IA32_SYS_setresuid 311
+#define IA32_SYS_setresgid 312
+ /* 313 is obsolete signanosleep */
+#define IA32_SYS_yield 321
+ /* 322 is obsolete thr_sleep */
+ /* 323 is obsolete thr_wakeup */
+#define IA32_SYS_mlockall 324
+#define IA32_SYS_munlockall 325
+#define IA32_SYS___getcwd 326
+#define IA32_SYS_sched_setparam 327
+#define IA32_SYS_sched_getparam 328
+#define IA32_SYS_sched_setscheduler 329
+#define IA32_SYS_sched_getscheduler 330
+#define IA32_SYS_sched_yield 331
+#define IA32_SYS_sched_get_priority_max 332
+#define IA32_SYS_sched_get_priority_min 333
+#define IA32_SYS_sched_rr_get_interval 334
+#define IA32_SYS_utrace 335
+#define IA32_SYS_ia32_sendfile 336
+#define IA32_SYS_kldsym 337
+#define IA32_SYS_jail 338
+#define IA32_SYS_sigprocmask 340
+#define IA32_SYS_sigsuspend 341
+#define IA32_SYS_ia32_sigaction 342
+#define IA32_SYS_sigpending 343
+#define IA32_SYS_sigreturn 344
+#define IA32_SYS___acl_get_file 347
+#define IA32_SYS___acl_set_file 348
+#define IA32_SYS___acl_get_fd 349
+#define IA32_SYS___acl_set_fd 350
+#define IA32_SYS___acl_delete_file 351
+#define IA32_SYS___acl_delete_fd 352
+#define IA32_SYS___acl_aclcheck_file 353
+#define IA32_SYS___acl_aclcheck_fd 354
+#define IA32_SYS_extattrctl 355
+#define IA32_SYS_extattr_set_file 356
+#define IA32_SYS_extattr_get_file 357
+#define IA32_SYS_extattr_delete_file 358
+#define IA32_SYS_getresuid 360
+#define IA32_SYS_getresgid 361
+#define IA32_SYS_kqueue 362
+#define IA32_SYS_kevent 363
+#define IA32_SYS_extattr_set_fd 371
+#define IA32_SYS_extattr_get_fd 372
+#define IA32_SYS_extattr_delete_fd 373
+#define IA32_SYS___setugid 374
+#define IA32_SYS_eaccess 376
+#define IA32_SYS_nmount 378
+#define IA32_SYS_kse_exit 379
+#define IA32_SYS_kse_wakeup 380
+#define IA32_SYS_kse_new 381
+#define IA32_SYS_thread_wakeup 382
+#define IA32_SYS_kse_yield 383
+#define IA32_SYS_kenv 390
+#define IA32_SYS_lchflags 391
+#define IA32_SYS_uuidgen 392
+#define IA32_SYS_MAXSYSCALL 393
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
new file mode 100644
index 0000000..a385596
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -0,0 +1,413 @@
+/*
+ * System call switch table.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp
+ */
+
+#include <sys/param.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+#define AS(name) (sizeof(struct name) / sizeof(register_t))
+
+/* The casts are bogus but will do for now. */
+struct sysent ia32_sysent[] = {
+ { SYF_MPSAFE | 0, (sy_call_t *)nosys }, /* 0 = syscall */
+ { SYF_MPSAFE | AS(sys_exit_args), (sy_call_t *)sys_exit }, /* 1 = exit */
+ { SYF_MPSAFE | 0, (sy_call_t *)fork }, /* 2 = fork */
+ { SYF_MPSAFE | AS(read_args), (sy_call_t *)read }, /* 3 = read */
+ { SYF_MPSAFE | AS(write_args), (sy_call_t *)write }, /* 4 = write */
+ { AS(ia32_open_args), (sy_call_t *)ia32_open }, /* 5 = ia32_open */
+ { SYF_MPSAFE | AS(close_args), (sy_call_t *)close }, /* 6 = close */
+ { SYF_MPSAFE | AS(ia32_wait4_args), (sy_call_t *)ia32_wait4 }, /* 7 = ia32_wait4 */
+ { 0, (sy_call_t *)nosys }, /* 8 = obsolete old creat */
+ { AS(link_args), (sy_call_t *)link }, /* 9 = link */
+ { AS(unlink_args), (sy_call_t *)unlink }, /* 10 = unlink */
+ { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */
+ { AS(chdir_args), (sy_call_t *)chdir }, /* 12 = chdir */
+ { AS(fchdir_args), (sy_call_t *)fchdir }, /* 13 = fchdir */
+ { AS(mknod_args), (sy_call_t *)mknod }, /* 14 = mknod */
+ { AS(chmod_args), (sy_call_t *)chmod }, /* 15 = chmod */
+ { AS(chown_args), (sy_call_t *)chown }, /* 16 = chown */
+ { SYF_MPSAFE | AS(obreak_args), (sy_call_t *)obreak }, /* 17 = break */
+ { AS(ia32_getfsstat_args), (sy_call_t *)ia32_getfsstat }, /* 18 = ia32_getfsstat */
+ { 0, (sy_call_t *)nosys }, /* 19 = obsolete olseek */
+ { SYF_MPSAFE | 0, (sy_call_t *)getpid }, /* 20 = getpid */
+ { AS(mount_args), (sy_call_t *)mount }, /* 21 = mount */
+ { AS(unmount_args), (sy_call_t *)unmount }, /* 22 = unmount */
+ { SYF_MPSAFE | AS(setuid_args), (sy_call_t *)setuid }, /* 23 = setuid */
+ { SYF_MPSAFE | 0, (sy_call_t *)getuid }, /* 24 = getuid */
+ { SYF_MPSAFE | 0, (sy_call_t *)geteuid }, /* 25 = geteuid */
+ { AS(ptrace_args), (sy_call_t *)ptrace }, /* 26 = ptrace */
+ { 0, (sy_call_t *)nosys }, /* 27 = recvmsg */
+ { SYF_MPSAFE | AS(sendmsg_args), (sy_call_t *)sendmsg }, /* 28 = sendmsg */
+ { SYF_MPSAFE | AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 29 = recvfrom */
+ { SYF_MPSAFE | AS(accept_args), (sy_call_t *)accept }, /* 30 = accept */
+ { SYF_MPSAFE | AS(getpeername_args), (sy_call_t *)getpeername }, /* 31 = getpeername */
+ { SYF_MPSAFE | AS(getsockname_args), (sy_call_t *)getsockname }, /* 32 = getsockname */
+ { AS(ia32_access_args), (sy_call_t *)ia32_access }, /* 33 = ia32_access */
+ { AS(ia32_chflags_args), (sy_call_t *)ia32_chflags }, /* 34 = ia32_chflags */
+ { AS(fchflags_args), (sy_call_t *)fchflags }, /* 35 = fchflags */
+ { 0, (sy_call_t *)sync }, /* 36 = sync */
+ { SYF_MPSAFE | AS(kill_args), (sy_call_t *)kill }, /* 37 = kill */
+ { 0, (sy_call_t *)nosys }, /* 38 = ostat */
+ { SYF_MPSAFE | 0, (sy_call_t *)getppid }, /* 39 = getppid */
+ { 0, (sy_call_t *)nosys }, /* 40 = olstat */
+ { AS(dup_args), (sy_call_t *)dup }, /* 41 = dup */
+ { 0, (sy_call_t *)pipe }, /* 42 = pipe */
+ { SYF_MPSAFE | 0, (sy_call_t *)getegid }, /* 43 = getegid */
+ { SYF_MPSAFE | AS(profil_args), (sy_call_t *)profil }, /* 44 = profil */
+ { AS(ktrace_args), (sy_call_t *)ktrace }, /* 45 = ktrace */
+ { 0, (sy_call_t *)nosys }, /* 46 = osigaction */
+ { SYF_MPSAFE | 0, (sy_call_t *)getgid }, /* 47 = getgid */
+ { 0, (sy_call_t *)nosys }, /* 48 = osigprocmask */
+ { SYF_MPSAFE | AS(getlogin_args), (sy_call_t *)getlogin }, /* 49 = getlogin */
+ { SYF_MPSAFE | AS(setlogin_args), (sy_call_t *)setlogin }, /* 50 = setlogin */
+ { SYF_MPSAFE | AS(acct_args), (sy_call_t *)acct }, /* 51 = acct */
+ { SYF_MPSAFE | 0, (sy_call_t *)sigpending }, /* 52 = sigpending */
+ { AS(ia32_sigaltstack_args), (sy_call_t *)ia32_sigaltstack }, /* 53 = ia32_sigaltstack */
+ { SYF_MPSAFE | AS(ioctl_args), (sy_call_t *)ioctl }, /* 54 = ioctl */
+ { SYF_MPSAFE | AS(reboot_args), (sy_call_t *)reboot }, /* 55 = reboot */
+ { AS(revoke_args), (sy_call_t *)revoke }, /* 56 = revoke */
+ { AS(symlink_args), (sy_call_t *)symlink }, /* 57 = symlink */
+ { AS(readlink_args), (sy_call_t *)readlink }, /* 58 = readlink */
+ { AS(ia32_execve_args), (sy_call_t *)ia32_execve }, /* 59 = ia32_execve */
+ { SYF_MPSAFE | AS(umask_args), (sy_call_t *)umask }, /* 60 = umask */
+ { AS(chroot_args), (sy_call_t *)chroot }, /* 61 = chroot */
+ { 0, (sy_call_t *)nosys }, /* 62 = obsolete ofstat */
+ { 0, (sy_call_t *)nosys }, /* 63 = obsolete ogetkerninfo */
+ { 0, (sy_call_t *)nosys }, /* 64 = obsolete ogetpagesize */
+ { 0, (sy_call_t *)nosys }, /* 65 = obsolete omsync */
+ { 0, (sy_call_t *)nosys }, /* 66 = obsolete ovfork */
+ { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */
+ { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */
+ { SYF_MPSAFE | AS(sbrk_args), (sy_call_t *)sbrk }, /* 69 = sbrk */
+ { SYF_MPSAFE | AS(sstk_args), (sy_call_t *)sstk }, /* 70 = sstk */
+ { 0, (sy_call_t *)nosys }, /* 71 = obsolete ommap */
+ { SYF_MPSAFE | AS(ovadvise_args), (sy_call_t *)ovadvise }, /* 72 = vadvise */
+ { SYF_MPSAFE | AS(munmap_args), (sy_call_t *)munmap }, /* 73 = munmap */
+ { SYF_MPSAFE | AS(mprotect_args), (sy_call_t *)mprotect }, /* 74 = mprotect */
+ { SYF_MPSAFE | AS(madvise_args), (sy_call_t *)madvise }, /* 75 = madvise */
+ { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */
+ { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */
+ { SYF_MPSAFE | AS(mincore_args), (sy_call_t *)mincore }, /* 78 = mincore */
+ { SYF_MPSAFE | AS(getgroups_args), (sy_call_t *)getgroups }, /* 79 = getgroups */
+ { SYF_MPSAFE | AS(setgroups_args), (sy_call_t *)setgroups }, /* 80 = setgroups */
+ { SYF_MPSAFE | 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */
+ { SYF_MPSAFE | AS(setpgid_args), (sy_call_t *)setpgid }, /* 82 = setpgid */
+ { AS(ia32_setitimer_args), (sy_call_t *)ia32_setitimer }, /* 83 = ia32_setitimer */
+ { 0, (sy_call_t *)nosys }, /* 84 = obsolete owait */
+ { 0, (sy_call_t *)nosys }, /* 85 = obsolete oswapon */
+ { 0, (sy_call_t *)nosys }, /* 86 = obsolete ogetitimer */
+ { 0, (sy_call_t *)nosys }, /* 87 = obsolete ogethostname */
+ { 0, (sy_call_t *)nosys }, /* 88 = obsolete osethostname */
+ { SYF_MPSAFE | 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */
+ { SYF_MPSAFE | AS(dup2_args), (sy_call_t *)dup2 }, /* 90 = dup2 */
+ { 0, (sy_call_t *)nosys }, /* 91 = getdopt */
+ { SYF_MPSAFE | AS(fcntl_args), (sy_call_t *)fcntl }, /* 92 = fcntl */
+ { AS(ia32_select_args), (sy_call_t *)ia32_select }, /* 93 = ia32_select */
+ { 0, (sy_call_t *)nosys }, /* 94 = setdopt */
+ { AS(fsync_args), (sy_call_t *)fsync }, /* 95 = fsync */
+ { SYF_MPSAFE | AS(setpriority_args), (sy_call_t *)setpriority }, /* 96 = setpriority */
+ { SYF_MPSAFE | AS(socket_args), (sy_call_t *)socket }, /* 97 = socket */
+ { SYF_MPSAFE | AS(connect_args), (sy_call_t *)connect }, /* 98 = connect */
+ { SYF_MPSAFE | AS(accept_args), (sy_call_t *)accept }, /* 99 = accept */
+ { SYF_MPSAFE | AS(getpriority_args), (sy_call_t *)getpriority }, /* 100 = getpriority */
+ { 0, (sy_call_t *)nosys }, /* 101 = obsolete osend */
+ { 0, (sy_call_t *)nosys }, /* 102 = obsolete orecv */
+ { 0, (sy_call_t *)nosys }, /* 103 = obsolete osigreturn */
+ { SYF_MPSAFE | AS(bind_args), (sy_call_t *)bind }, /* 104 = bind */
+ { SYF_MPSAFE | AS(setsockopt_args), (sy_call_t *)setsockopt }, /* 105 = setsockopt */
+ { SYF_MPSAFE | AS(listen_args), (sy_call_t *)listen }, /* 106 = listen */
+ { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */
+ { 0, (sy_call_t *)nosys }, /* 108 = obsolete osigvec */
+ { 0, (sy_call_t *)nosys }, /* 109 = obsolete osigblock */
+ { 0, (sy_call_t *)nosys }, /* 110 = obsolete osigsetmask */
+ { 0, (sy_call_t *)nosys }, /* 111 = obsolete osigsuspend */
+ { 0, (sy_call_t *)nosys }, /* 112 = obsolete osigstack */
+ { 0, (sy_call_t *)nosys }, /* 113 = obsolete orecvmsg */
+ { 0, (sy_call_t *)nosys }, /* 114 = obsolete osendmsg */
+ { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */
+ { AS(ia32_gettimeofday_args), (sy_call_t *)ia32_gettimeofday }, /* 116 = ia32_gettimeofday */
+ { AS(ia32_getrusage_args), (sy_call_t *)ia32_getrusage }, /* 117 = ia32_getrusage */
+ { SYF_MPSAFE | AS(getsockopt_args), (sy_call_t *)getsockopt }, /* 118 = getsockopt */
+ { 0, (sy_call_t *)nosys }, /* 119 = resuba */
+ { AS(ia32_readv_args), (sy_call_t *)ia32_readv }, /* 120 = ia32_readv */
+ { AS(ia32_writev_args), (sy_call_t *)ia32_writev }, /* 121 = ia32_writev */
+ { AS(ia32_settimeofday_args), (sy_call_t *)ia32_settimeofday }, /* 122 = ia32_settimeofday */
+ { AS(fchown_args), (sy_call_t *)fchown }, /* 123 = fchown */
+ { AS(fchmod_args), (sy_call_t *)fchmod }, /* 124 = fchmod */
+ { SYF_MPSAFE | AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 125 = recvfrom */
+ { SYF_MPSAFE | AS(setreuid_args), (sy_call_t *)setreuid }, /* 126 = setreuid */
+ { SYF_MPSAFE | AS(setregid_args), (sy_call_t *)setregid }, /* 127 = setregid */
+ { AS(rename_args), (sy_call_t *)rename }, /* 128 = rename */
+ { 0, (sy_call_t *)nosys }, /* 129 = obsolete otruncate */
+ { 0, (sy_call_t *)nosys }, /* 130 = obsolete ftruncate */
+ { SYF_MPSAFE | AS(flock_args), (sy_call_t *)flock }, /* 131 = flock */
+ { AS(mkfifo_args), (sy_call_t *)mkfifo }, /* 132 = mkfifo */
+ { SYF_MPSAFE | AS(sendto_args), (sy_call_t *)sendto }, /* 133 = sendto */
+ { SYF_MPSAFE | AS(shutdown_args), (sy_call_t *)shutdown }, /* 134 = shutdown */
+ { SYF_MPSAFE | AS(socketpair_args), (sy_call_t *)socketpair }, /* 135 = socketpair */
+ { AS(mkdir_args), (sy_call_t *)mkdir }, /* 136 = mkdir */
+ { AS(rmdir_args), (sy_call_t *)rmdir }, /* 137 = rmdir */
+ { AS(ia32_utimes_args), (sy_call_t *)ia32_utimes }, /* 138 = ia32_utimes */
+ { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */
+ { AS(ia32_adjtime_args), (sy_call_t *)ia32_adjtime }, /* 140 = ia32_adjtime */
+ { 0, (sy_call_t *)nosys }, /* 141 = obsolete ogetpeername */
+ { 0, (sy_call_t *)nosys }, /* 142 = obsolete ogethostid */
+ { 0, (sy_call_t *)nosys }, /* 143 = obsolete sethostid */
+ { 0, (sy_call_t *)nosys }, /* 144 = obsolete getrlimit */
+ { 0, (sy_call_t *)nosys }, /* 145 = obsolete setrlimit */
+ { 0, (sy_call_t *)nosys }, /* 146 = obsolete killpg */
+ { SYF_MPSAFE | 0, (sy_call_t *)setsid }, /* 147 = setsid */
+ { AS(quotactl_args), (sy_call_t *)quotactl }, /* 148 = quotactl */
+ { 0, (sy_call_t *)nosys }, /* 149 = obsolete oquota */
+ { 0, (sy_call_t *)nosys }, /* 150 = obsolete ogetsockname */
+ { 0, (sy_call_t *)nosys }, /* 151 = sem_lock */
+ { 0, (sy_call_t *)nosys }, /* 152 = sem_wakeup */
+ { 0, (sy_call_t *)nosys }, /* 153 = asyncdaemon */
+ { 0, (sy_call_t *)nosys }, /* 154 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 155 = nfssvc */
+ { AS(getdirentries_args), (sy_call_t *)getdirentries }, /* 156 = getdirentries */
+ { AS(ia32_statfs_args), (sy_call_t *)ia32_statfs }, /* 157 = ia32_statfs */
+ { AS(ia32_fstatfs_args), (sy_call_t *)ia32_fstatfs }, /* 158 = ia32_fstatfs */
+ { 0, (sy_call_t *)nosys }, /* 159 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 160 = nosys */
+ { AS(getfh_args), (sy_call_t *)getfh }, /* 161 = getfh */
+ { SYF_MPSAFE | AS(getdomainname_args), (sy_call_t *)getdomainname }, /* 162 = getdomainname */
+ { SYF_MPSAFE | AS(setdomainname_args), (sy_call_t *)setdomainname }, /* 163 = setdomainname */
+ { SYF_MPSAFE | AS(uname_args), (sy_call_t *)uname }, /* 164 = uname */
+ { AS(sysarch_args), (sy_call_t *)sysarch }, /* 165 = sysarch */
+ { SYF_MPSAFE | AS(rtprio_args), (sy_call_t *)rtprio }, /* 166 = rtprio */
+ { 0, (sy_call_t *)nosys }, /* 167 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 168 = nosys */
+ { AS(ia32_semsys_args), (sy_call_t *)ia32_semsys }, /* 169 = ia32_semsys */
+ { AS(ia32_msgsys_args), (sy_call_t *)ia32_msgsys }, /* 170 = ia32_msgsys */
+ { AS(ia32_shmsys_args), (sy_call_t *)ia32_shmsys }, /* 171 = ia32_shmsys */
+ { 0, (sy_call_t *)nosys }, /* 172 = nosys */
+ { AS(ia32_pread_args), (sy_call_t *)ia32_pread }, /* 173 = ia32_pread */
+ { AS(ia32_pwrite_args), (sy_call_t *)ia32_pwrite }, /* 174 = ia32_pwrite */
+ { 0, (sy_call_t *)nosys }, /* 175 = nosys */
+ { SYF_MPSAFE | AS(ntp_adjtime_args), (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */
+ { 0, (sy_call_t *)nosys }, /* 177 = sfork */
+ { 0, (sy_call_t *)nosys }, /* 178 = getdescriptor */
+ { 0, (sy_call_t *)nosys }, /* 179 = setdescriptor */
+ { 0, (sy_call_t *)nosys }, /* 180 = nosys */
+ { SYF_MPSAFE | AS(setgid_args), (sy_call_t *)setgid }, /* 181 = setgid */
+ { SYF_MPSAFE | AS(setegid_args), (sy_call_t *)setegid }, /* 182 = setegid */
+ { SYF_MPSAFE | AS(seteuid_args), (sy_call_t *)seteuid }, /* 183 = seteuid */
+ { 0, (sy_call_t *)nosys }, /* 184 = lfs_bmapv */
+ { 0, (sy_call_t *)nosys }, /* 185 = lfs_markv */
+ { 0, (sy_call_t *)nosys }, /* 186 = lfs_segclean */
+ { 0, (sy_call_t *)nosys }, /* 187 = lfs_segwait */
+ { AS(ia32_stat_args), (sy_call_t *)ia32_stat }, /* 188 = ia32_stat */
+ { AS(ia32_fstat_args), (sy_call_t *)ia32_fstat }, /* 189 = ia32_fstat */
+ { AS(ia32_lstat_args), (sy_call_t *)ia32_lstat }, /* 190 = ia32_lstat */
+ { AS(pathconf_args), (sy_call_t *)pathconf }, /* 191 = pathconf */
+ { SYF_MPSAFE | AS(fpathconf_args), (sy_call_t *)fpathconf }, /* 192 = fpathconf */
+ { 0, (sy_call_t *)nosys }, /* 193 = nosys */
+ { SYF_MPSAFE | AS(__getrlimit_args), (sy_call_t *)getrlimit }, /* 194 = getrlimit */
+ { SYF_MPSAFE | AS(__setrlimit_args), (sy_call_t *)setrlimit }, /* 195 = setrlimit */
+ { AS(getdirentries_args), (sy_call_t *)getdirentries }, /* 196 = getdirentries */
+ { AS(ia32_mmap_args), (sy_call_t *)ia32_mmap }, /* 197 = ia32_mmap */
+ { 0, (sy_call_t *)nosys }, /* 198 = __syscall */
+ { AS(ia32_lseek_args), (sy_call_t *)ia32_lseek }, /* 199 = ia32_lseek */
+ { AS(ia32_truncate_args), (sy_call_t *)ia32_truncate }, /* 200 = ia32_truncate */
+ { AS(ia32_ftruncate_args), (sy_call_t *)ia32_ftruncate }, /* 201 = ia32_ftruncate */
+ { SYF_MPSAFE | AS(ia32_sysctl_args), (sy_call_t *)ia32_sysctl }, /* 202 = ia32_sysctl */
+ { SYF_MPSAFE | AS(mlock_args), (sy_call_t *)mlock }, /* 203 = mlock */
+ { SYF_MPSAFE | AS(munlock_args), (sy_call_t *)munlock }, /* 204 = munlock */
+ { AS(undelete_args), (sy_call_t *)undelete }, /* 205 = undelete */
+ { AS(futimes_args), (sy_call_t *)futimes }, /* 206 = futimes */
+ { SYF_MPSAFE | AS(getpgid_args), (sy_call_t *)getpgid }, /* 207 = getpgid */
+ { 0, (sy_call_t *)nosys }, /* 208 = newreboot */
+ { SYF_MPSAFE | AS(poll_args), (sy_call_t *)poll }, /* 209 = poll */
+ { 0, (sy_call_t *)nosys }, /* 210 = */
+ { 0, (sy_call_t *)nosys }, /* 211 = */
+ { 0, (sy_call_t *)nosys }, /* 212 = */
+ { 0, (sy_call_t *)nosys }, /* 213 = */
+ { 0, (sy_call_t *)nosys }, /* 214 = */
+ { 0, (sy_call_t *)nosys }, /* 215 = */
+ { 0, (sy_call_t *)nosys }, /* 216 = */
+ { 0, (sy_call_t *)nosys }, /* 217 = */
+ { 0, (sy_call_t *)nosys }, /* 218 = */
+ { 0, (sy_call_t *)nosys }, /* 219 = */
+ { SYF_MPSAFE | AS(__semctl_args), (sy_call_t *)__semctl }, /* 220 = __semctl */
+ { SYF_MPSAFE | AS(semget_args), (sy_call_t *)semget }, /* 221 = semget */
+ { SYF_MPSAFE | AS(semop_args), (sy_call_t *)semop }, /* 222 = semop */
+ { 0, (sy_call_t *)nosys }, /* 223 = semconfig */
+ { SYF_MPSAFE | AS(msgctl_args), (sy_call_t *)msgctl }, /* 224 = msgctl */
+ { SYF_MPSAFE | AS(msgget_args), (sy_call_t *)msgget }, /* 225 = msgget */
+ { SYF_MPSAFE | AS(msgsnd_args), (sy_call_t *)msgsnd }, /* 226 = msgsnd */
+ { SYF_MPSAFE | AS(msgrcv_args), (sy_call_t *)msgrcv }, /* 227 = msgrcv */
+ { SYF_MPSAFE | AS(shmat_args), (sy_call_t *)shmat }, /* 228 = shmat */
+ { SYF_MPSAFE | AS(shmctl_args), (sy_call_t *)shmctl }, /* 229 = shmctl */
+ { SYF_MPSAFE | AS(shmdt_args), (sy_call_t *)shmdt }, /* 230 = shmdt */
+ { SYF_MPSAFE | AS(shmget_args), (sy_call_t *)shmget }, /* 231 = shmget */
+ { SYF_MPSAFE | AS(clock_gettime_args), (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */
+ { SYF_MPSAFE | AS(clock_settime_args), (sy_call_t *)clock_settime }, /* 233 = clock_settime */
+ { SYF_MPSAFE | AS(clock_getres_args), (sy_call_t *)clock_getres }, /* 234 = clock_getres */
+ { 0, (sy_call_t *)nosys }, /* 235 = timer_create */
+ { 0, (sy_call_t *)nosys }, /* 236 = timer_delete */
+ { 0, (sy_call_t *)nosys }, /* 237 = timer_settime */
+ { 0, (sy_call_t *)nosys }, /* 238 = timer_gettime */
+ { 0, (sy_call_t *)nosys }, /* 239 = timer_getoverrun */
+ { SYF_MPSAFE | AS(nanosleep_args), (sy_call_t *)nanosleep }, /* 240 = nanosleep */
+ { 0, (sy_call_t *)nosys }, /* 241 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 242 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 243 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 244 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 245 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 246 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 247 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 248 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 249 = nosys */
+ { SYF_MPSAFE | AS(minherit_args), (sy_call_t *)minherit }, /* 250 = minherit */
+ { SYF_MPSAFE | AS(rfork_args), (sy_call_t *)rfork }, /* 251 = rfork */
+ { SYF_MPSAFE | AS(openbsd_poll_args), (sy_call_t *)openbsd_poll }, /* 252 = openbsd_poll */
+ { 0, (sy_call_t *)issetugid }, /* 253 = issetugid */
+ { AS(lchown_args), (sy_call_t *)lchown }, /* 254 = lchown */
+ { 0, (sy_call_t *)nosys }, /* 255 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 256 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 257 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 258 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 259 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 260 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 261 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 262 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 263 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 264 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 265 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 266 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 267 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 268 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 269 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 270 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 271 = nosys */
+ { AS(getdents_args), (sy_call_t *)getdents }, /* 272 = getdents */
+ { 0, (sy_call_t *)nosys }, /* 273 = nosys */
+ { AS(lchmod_args), (sy_call_t *)lchmod }, /* 274 = lchmod */
+ { AS(lchown_args), (sy_call_t *)lchown }, /* 275 = netbsd_lchown */
+ { AS(lutimes_args), (sy_call_t *)lutimes }, /* 276 = lutimes */
+ { SYF_MPSAFE | AS(msync_args), (sy_call_t *)msync }, /* 277 = netbsd_msync */
+ { AS(nstat_args), (sy_call_t *)nstat }, /* 278 = nstat */
+ { SYF_MPSAFE | AS(nfstat_args), (sy_call_t *)nfstat }, /* 279 = nfstat */
+ { AS(nlstat_args), (sy_call_t *)nlstat }, /* 280 = nlstat */
+ { 0, (sy_call_t *)nosys }, /* 281 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 282 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 283 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 284 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 285 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 286 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 287 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 288 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 289 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 290 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 291 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 292 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 293 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 294 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 295 = nosys */
+ { 0, (sy_call_t *)nosys }, /* 296 = nosys */
+ { AS(fhstatfs_args), (sy_call_t *)fhstatfs }, /* 297 = fhstatfs */
+ { AS(fhopen_args), (sy_call_t *)fhopen }, /* 298 = fhopen */
+ { AS(fhstat_args), (sy_call_t *)fhstat }, /* 299 = fhstat */
+ { SYF_MPSAFE | AS(modnext_args), (sy_call_t *)modnext }, /* 300 = modnext */
+ { SYF_MPSAFE | AS(modstat_args), (sy_call_t *)modstat }, /* 301 = modstat */
+ { SYF_MPSAFE | AS(modfnext_args), (sy_call_t *)modfnext }, /* 302 = modfnext */
+ { SYF_MPSAFE | AS(modfind_args), (sy_call_t *)modfind }, /* 303 = modfind */
+ { SYF_MPSAFE | AS(kldload_args), (sy_call_t *)kldload }, /* 304 = kldload */
+ { SYF_MPSAFE | AS(kldunload_args), (sy_call_t *)kldunload }, /* 305 = kldunload */
+ { SYF_MPSAFE | AS(kldfind_args), (sy_call_t *)kldfind }, /* 306 = kldfind */
+ { SYF_MPSAFE | AS(kldnext_args), (sy_call_t *)kldnext }, /* 307 = kldnext */
+ { SYF_MPSAFE | AS(kldstat_args), (sy_call_t *)kldstat }, /* 308 = kldstat */
+ { SYF_MPSAFE | AS(kldfirstmod_args), (sy_call_t *)kldfirstmod }, /* 309 = kldfirstmod */
+ { SYF_MPSAFE | AS(getsid_args), (sy_call_t *)getsid }, /* 310 = getsid */
+ { SYF_MPSAFE | AS(setresuid_args), (sy_call_t *)setresuid }, /* 311 = setresuid */
+ { SYF_MPSAFE | AS(setresgid_args), (sy_call_t *)setresgid }, /* 312 = setresgid */
+ { 0, (sy_call_t *)nosys }, /* 313 = obsolete signanosleep */
+ { 0, (sy_call_t *)nosys }, /* 314 = aio_return */
+ { 0, (sy_call_t *)nosys }, /* 315 = aio_suspend */
+ { 0, (sy_call_t *)nosys }, /* 316 = aio_cancel */
+ { 0, (sy_call_t *)nosys }, /* 317 = aio_error */
+ { 0, (sy_call_t *)nosys }, /* 318 = aio_read */
+ { 0, (sy_call_t *)nosys }, /* 319 = aio_write */
+ { 0, (sy_call_t *)nosys }, /* 320 = lio_listio */
+ { SYF_MPSAFE | 0, (sy_call_t *)yield }, /* 321 = yield */
+ { 0, (sy_call_t *)nosys }, /* 322 = obsolete thr_sleep */
+ { 0, (sy_call_t *)nosys }, /* 323 = obsolete thr_wakeup */
+ { SYF_MPSAFE | AS(mlockall_args), (sy_call_t *)mlockall }, /* 324 = mlockall */
+ { SYF_MPSAFE | 0, (sy_call_t *)munlockall }, /* 325 = munlockall */
+ { AS(__getcwd_args), (sy_call_t *)__getcwd }, /* 326 = __getcwd */
+ { SYF_MPSAFE | AS(sched_setparam_args), (sy_call_t *)sched_setparam }, /* 327 = sched_setparam */
+ { SYF_MPSAFE | AS(sched_getparam_args), (sy_call_t *)sched_getparam }, /* 328 = sched_getparam */
+ { SYF_MPSAFE | AS(sched_setscheduler_args), (sy_call_t *)sched_setscheduler }, /* 329 = sched_setscheduler */
+ { SYF_MPSAFE | AS(sched_getscheduler_args), (sy_call_t *)sched_getscheduler }, /* 330 = sched_getscheduler */
+ { SYF_MPSAFE | 0, (sy_call_t *)sched_yield }, /* 331 = sched_yield */
+ { SYF_MPSAFE | AS(sched_get_priority_max_args), (sy_call_t *)sched_get_priority_max }, /* 332 = sched_get_priority_max */
+ { SYF_MPSAFE | AS(sched_get_priority_min_args), (sy_call_t *)sched_get_priority_min }, /* 333 = sched_get_priority_min */
+ { SYF_MPSAFE | AS(sched_rr_get_interval_args), (sy_call_t *)sched_rr_get_interval }, /* 334 = sched_rr_get_interval */
+ { AS(utrace_args), (sy_call_t *)utrace }, /* 335 = utrace */
+ { SYF_MPSAFE | AS(ia32_sendfile_args), (sy_call_t *)ia32_sendfile }, /* 336 = ia32_sendfile */
+ { AS(kldsym_args), (sy_call_t *)kldsym }, /* 337 = kldsym */
+ { SYF_MPSAFE | AS(jail_args), (sy_call_t *)jail }, /* 338 = jail */
+ { 0, (sy_call_t *)nosys }, /* 339 = pioctl */
+ { SYF_MPSAFE | AS(sigprocmask_args), (sy_call_t *)sigprocmask }, /* 340 = sigprocmask */
+ { SYF_MPSAFE | AS(sigsuspend_args), (sy_call_t *)sigsuspend }, /* 341 = sigsuspend */
+ { AS(ia32_sigaction_args), (sy_call_t *)ia32_sigaction }, /* 342 = ia32_sigaction */
+ { SYF_MPSAFE | AS(sigpending_args), (sy_call_t *)sigpending }, /* 343 = sigpending */
+ { SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn }, /* 344 = sigreturn */
+ { 0, (sy_call_t *)nosys }, /* 345 = sigtimedwait */
+ { 0, (sy_call_t *)nosys }, /* 346 = sigwaitinfo */
+ { SYF_MPSAFE | AS(__acl_get_file_args), (sy_call_t *)__acl_get_file }, /* 347 = __acl_get_file */
+ { SYF_MPSAFE | AS(__acl_set_file_args), (sy_call_t *)__acl_set_file }, /* 348 = __acl_set_file */
+ { SYF_MPSAFE | AS(__acl_get_fd_args), (sy_call_t *)__acl_get_fd }, /* 349 = __acl_get_fd */
+ { SYF_MPSAFE | AS(__acl_set_fd_args), (sy_call_t *)__acl_set_fd }, /* 350 = __acl_set_fd */
+ { SYF_MPSAFE | AS(__acl_delete_file_args), (sy_call_t *)__acl_delete_file }, /* 351 = __acl_delete_file */
+ { SYF_MPSAFE | AS(__acl_delete_fd_args), (sy_call_t *)__acl_delete_fd }, /* 352 = __acl_delete_fd */
+ { SYF_MPSAFE | AS(__acl_aclcheck_file_args), (sy_call_t *)__acl_aclcheck_file }, /* 353 = __acl_aclcheck_file */
+ { SYF_MPSAFE | AS(__acl_aclcheck_fd_args), (sy_call_t *)__acl_aclcheck_fd }, /* 354 = __acl_aclcheck_fd */
+ { AS(extattrctl_args), (sy_call_t *)extattrctl }, /* 355 = extattrctl */
+ { AS(extattr_set_file_args), (sy_call_t *)extattr_set_file }, /* 356 = extattr_set_file */
+ { AS(extattr_get_file_args), (sy_call_t *)extattr_get_file }, /* 357 = extattr_get_file */
+ { AS(extattr_delete_file_args), (sy_call_t *)extattr_delete_file }, /* 358 = extattr_delete_file */
+ { 0, (sy_call_t *)nosys }, /* 359 = aio_waitcomplete */
+ { SYF_MPSAFE | AS(getresuid_args), (sy_call_t *)getresuid }, /* 360 = getresuid */
+ { SYF_MPSAFE | AS(getresgid_args), (sy_call_t *)getresgid }, /* 361 = getresgid */
+ { SYF_MPSAFE | 0, (sy_call_t *)kqueue }, /* 362 = kqueue */
+ { SYF_MPSAFE | AS(kevent_args), (sy_call_t *)kevent }, /* 363 = kevent */
+ { 0, (sy_call_t *)nosys }, /* 364 = __cap_get_proc */
+ { 0, (sy_call_t *)nosys }, /* 365 = __cap_set_proc */
+ { 0, (sy_call_t *)nosys }, /* 366 = __cap_get_fd */
+ { 0, (sy_call_t *)nosys }, /* 367 = __cap_get_file */
+ { 0, (sy_call_t *)nosys }, /* 368 = __cap_set_fd */
+ { 0, (sy_call_t *)nosys }, /* 369 = __cap_set_file */
+ { 0, (sy_call_t *)nosys }, /* 370 = lkmressys */
+ { AS(extattr_set_fd_args), (sy_call_t *)extattr_set_fd }, /* 371 = extattr_set_fd */
+ { AS(extattr_get_fd_args), (sy_call_t *)extattr_get_fd }, /* 372 = extattr_get_fd */
+ { AS(extattr_delete_fd_args), (sy_call_t *)extattr_delete_fd }, /* 373 = extattr_delete_fd */
+ { SYF_MPSAFE | AS(__setugid_args), (sy_call_t *)__setugid }, /* 374 = __setugid */
+ { 0, (sy_call_t *)nosys }, /* 375 = nfsclnt */
+ { AS(eaccess_args), (sy_call_t *)eaccess }, /* 376 = eaccess */
+ { 0, (sy_call_t *)nosys }, /* 377 = afs_syscall */
+ { AS(nmount_args), (sy_call_t *)nmount }, /* 378 = nmount */
+ { 0, (sy_call_t *)kse_exit }, /* 379 = kse_exit */
+ { 0, (sy_call_t *)kse_wakeup }, /* 380 = kse_wakeup */
+ { AS(kse_new_args), (sy_call_t *)kse_new }, /* 381 = kse_new */
+ { AS(thread_wakeup_args), (sy_call_t *)thread_wakeup }, /* 382 = thread_wakeup */
+ { 0, (sy_call_t *)kse_yield }, /* 383 = kse_yield */
+ { 0, (sy_call_t *)nosys }, /* 384 = __mac_get_proc */
+ { 0, (sy_call_t *)nosys }, /* 385 = __mac_set_proc */
+ { 0, (sy_call_t *)nosys }, /* 386 = __mac_get_fd */
+ { 0, (sy_call_t *)nosys }, /* 387 = __mac_get_file */
+ { 0, (sy_call_t *)nosys }, /* 388 = __mac_set_fd */
+ { 0, (sy_call_t *)nosys }, /* 389 = __mac_set_file */
+ { AS(kenv_args), (sy_call_t *)kenv }, /* 390 = kenv */
+ { AS(lchflags_args), (sy_call_t *)lchflags }, /* 391 = lchflags */
+ { AS(uuidgen_args), (sy_call_t *)uuidgen }, /* 392 = uuidgen */
+};
diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h
new file mode 100644
index 0000000..b9e0a7c
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/compat/freebsd32/syscalls.conf b/sys/compat/freebsd32/syscalls.conf
new file mode 100644
index 0000000..16d94ea
--- /dev/null
+++ b/sys/compat/freebsd32/syscalls.conf
@@ -0,0 +1,12 @@
+# $FreeBSD$
+sysnames="/dev/null"
+sysproto="ia32_proto.h"
+sysproto_h=_IA32_SYSPROTO_H_
+syshdr="ia32_syscall.h"
+syssw="ia32_sysent.c"
+sysmk="/dev/null"
+syshide="/dev/null"
+syscallprefix="IA32_SYS_"
+switchname="ia32_sysent"
+namesname="ia32_syscallnames"
+sysvec="\n"
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
new file mode 100644
index 0000000..6de1c57
--- /dev/null
+++ b/sys/compat/freebsd32/syscalls.master
@@ -0,0 +1,563 @@
+ $FreeBSD$
+; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
+; from: src/sys/kern/syscalls.master 1.107
+;
+; System call name/number master file.
+; Processed to created init_sysent.c, syscalls.c and syscall.h.
+
+; Columns: number [M]type nargs namespc name alt{name,tag,rtyp}/comments
+; number system call number, must be in order
+; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA,
+; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL,
+; [M]NOSTD
+; namespc one of POSIX, BSD, NOHIDE
+; name psuedo-prototype of syscall routine
+; If one of the following alts is different, then all appear:
+; altname name of system call if different
+; alttag name of args struct tag if different from [o]`name'"_args"
+; altrtyp return type if not int (bogus - syscalls always return int)
+; for UNIMPL/OBSOL, name continues with comments
+
+; types:
+; [M] e.g. like MSTD -- means the system call is MP-safe. If no
+; M prefix is used, the syscall wrapper will obtain the Giant
+; lock for the syscall.
+; STD always included
+; COMPAT included on COMPAT #ifdef
+; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h
+; OBSOL obsolete, not included in system, only specifies name
+; UNIMPL not implemented, placeholder only
+; NOSTD implemented but as a lkm that can be statically
+; compiled in sysent entry will be filled with lkmsys
+; so the SYSCALL_MODULE macro works
+
+; #ifdef's, etc. may be included, and are copied to the output files.
+
+#include <sys/param.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/mount.h>
+#include <ia64/ia32/ia32.h>
+#include <ia64/ia32/ia32_proto.h>
+
+; Reserved/unimplemented system calls in the range 0-150 inclusive
+; are reserved for use in future Berkeley releases.
+; Additional system calls implemented in vendor and other
+; redistributions should be placed in the reserved range at the end
+; of the current calls.
+
+0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int
+1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void
+2 MNOPROTO POSIX { int fork(void); }
+3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); }
+4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); }
+5 STD POSIX { int ia32_open(char *path, int flags, int mode); }
+; XXX should be { int open(const char *path, int flags, ...); }
+; but we're not ready for `const' or varargs.
+; XXX man page says `mode_t mode'.
+6 MNOPROTO POSIX { int close(int fd); }
+7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \
+ struct rusage32 *rusage); }
+8 OBSOL BSD old creat
+9 NOPROTO POSIX { int link(char *path, char *link); }
+10 NOPROTO POSIX { int unlink(char *path); }
+11 OBSOL NOHIDE execv
+12 NOPROTO POSIX { int chdir(char *path); }
+13 NOPROTO BSD { int fchdir(int fd); }
+14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); }
+15 NOPROTO POSIX { int chmod(char *path, int mode); }
+16 NOPROTO POSIX { int chown(char *path, int uid, int gid); }
+17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int
+18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \
+ long bufsize, int flags); }
+19 OBSOL POSIX olseek
+20 MNOPROTO POSIX { pid_t getpid(void); }
+21 NOPROTO BSD { int mount(char *type, char *path, int flags, \
+ caddr_t data); }
+; XXX `path' should have type `const char *' but we're not ready for that.
+22 NOPROTO BSD { int unmount(char *path, int flags); }
+23 MNOPROTO POSIX { int setuid(uid_t uid); }
+24 MNOPROTO POSIX { uid_t getuid(void); }
+25 MNOPROTO POSIX { uid_t geteuid(void); }
+26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \
+ int data); }
+27 UNIMPL BSD recvmsg
+28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); }
+29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+ int flags, caddr_t from, int *fromlenaddr); }
+30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); }
+31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); }
+32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); }
+33 STD POSIX { int ia32_access(char *path, int flags); }
+34 STD BSD { int ia32_chflags(char *path, int flags); }
+35 NOPROTO BSD { int fchflags(int fd, int flags); }
+36 NOPROTO BSD { int sync(void); }
+37 MNOPROTO POSIX { int kill(int pid, int signum); }
+38 UNIMPL POSIX ostat
+39 MNOPROTO POSIX { pid_t getppid(void); }
+40 UNIMPL POSIX olstat
+41 NOPROTO POSIX { int dup(u_int fd); }
+42 NOPROTO POSIX { int pipe(void); }
+43 MNOPROTO POSIX { gid_t getegid(void); }
+44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \
+ size_t offset, u_int scale); }
+45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \
+ int pid); }
+46 UNIMPL POSIX osigaction
+47 MNOPROTO POSIX { gid_t getgid(void); }
+48 UNIMPL POSIX osigprocmask
+49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); }
+50 MNOPROTO BSD { int setlogin(char *namebuf); }
+51 MNOPROTO BSD { int acct(char *path); }
+52 MNOPROTO POSIX { int sigpending(void); }
+53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); }
+54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); }
+55 MNOPROTO BSD { int reboot(int opt); }
+56 NOPROTO POSIX { int revoke(char *path); }
+57 NOPROTO POSIX { int symlink(char *path, char *link); }
+58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); }
+59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); }
+60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int
+61 NOPROTO BSD { int chroot(char *path); }
+62 OBSOL POSIX ofstat
+63 OBSOL BSD ogetkerninfo
+64 OBSOL BSD ogetpagesize
+65 OBSOL BSD omsync
+66 OBSOL BSD ovfork
+67 OBSOL NOHIDE vread
+68 OBSOL NOHIDE vwrite
+69 MNOPROTO BSD { int sbrk(int incr); }
+70 MNOPROTO BSD { int sstk(int incr); }
+71 OBSOL BSD ommap
+72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int
+73 MNOPROTO BSD { int munmap(void *addr, size_t len); }
+74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); }
+75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); }
+76 OBSOL NOHIDE vhangup
+77 OBSOL NOHIDE vlimit
+78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \
+ char *vec); }
+79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); }
+80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); }
+81 MNOPROTO POSIX { int getpgrp(void); }
+82 MNOPROTO POSIX { int setpgid(int pid, int pgid); }
+83 STD BSD { int ia32_setitimer(u_int which, \
+ struct itimerval32 *itv, \
+ struct itimerval32 *oitv); }
+84 OBSOL BSD owait
+85 OBSOL BSD oswapon
+86 OBSOL BSD ogetitimer
+87 OBSOL BSD ogethostname
+88 OBSOL BSD osethostname
+89 MNOPROTO BSD { int getdtablesize(void); }
+90 MNOPROTO POSIX { int dup2(u_int from, u_int to); }
+91 UNIMPL BSD getdopt
+92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); }
+; XXX should be { int fcntl(int fd, int cmd, ...); }
+; but we're not ready for varargs.
+; XXX man page says `int arg' too.
+93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \
+ fd_set *ex, struct timeval32 *tv); }
+; XXX need to override for big-endian - little-endian should work fine.
+94 UNIMPL BSD setdopt
+95 NOPROTO POSIX { int fsync(int fd); }
+96 MNOPROTO BSD { int setpriority(int which, int who, int prio); }
+97 MNOPROTO BSD { int socket(int domain, int type, int protocol); }
+98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); }
+99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \
+ accept accept_args int
+100 MNOPROTO BSD { int getpriority(int which, int who); }
+101 OBSOL BSD osend
+102 OBSOL BSD orecv
+103 OBSOL BSD osigreturn
+104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); }
+105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \
+ caddr_t val, int valsize); }
+106 MNOPROTO BSD { int listen(int s, int backlog); }
+107 OBSOL NOHIDE vtimes
+108 OBSOL BSD osigvec
+109 OBSOL BSD osigblock
+110 OBSOL BSD osigsetmask
+111 OBSOL POSIX osigsuspend
+112 OBSOL BSD osigstack
+113 OBSOL BSD orecvmsg
+114 OBSOL BSD osendmsg
+115 OBSOL NOHIDE vtrace
+116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \
+ struct timezone *tzp); }
+117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); }
+118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \
+ caddr_t val, int *avalsize); }
+119 UNIMPL NOHIDE resuba (BSD/OS 2.x)
+120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); }
+121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \
+ u_int iovcnt); }
+122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \
+ struct timezone *tzp); }
+123 NOPROTO BSD { int fchown(int fd, int uid, int gid); }
+124 NOPROTO BSD { int fchmod(int fd, int mode); }
+125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \
+ int flags, caddr_t from, int *fromlenaddr); } \
+ recvfrom recvfrom_args int
+126 MNOPROTO BSD { int setreuid(int ruid, int euid); }
+127 MNOPROTO BSD { int setregid(int rgid, int egid); }
+128 NOPROTO POSIX { int rename(char *from, char *to); }
+129 OBSOL BSD otruncate
+130 OBSOL BSD ftruncate
+131 MNOPROTO BSD { int flock(int fd, int how); }
+132 NOPROTO POSIX { int mkfifo(char *path, int mode); }
+133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \
+ int flags, caddr_t to, int tolen); }
+134 MNOPROTO BSD { int shutdown(int s, int how); }
+135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \
+ int *rsv); }
+136 NOPROTO POSIX { int mkdir(char *path, int mode); }
+137 NOPROTO POSIX { int rmdir(char *path); }
+138 STD BSD { int ia32_utimes(char *path, \
+ struct timeval32 *tptr); }
+139 OBSOL NOHIDE 4.2 sigreturn
+140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \
+ struct timeval32 *olddelta); }
+141 OBSOL BSD ogetpeername
+142 OBSOL BSD ogethostid
+143 OBSOL BSD sethostid
+144 OBSOL BSD getrlimit
+145 OBSOL BSD setrlimit
+146 OBSOL BSD killpg
+147 MNOPROTO POSIX { int setsid(void); }
+148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \
+ caddr_t arg); }
+149 OBSOL BSD oquota
+150 OBSOL BSD ogetsockname
+
+; Syscalls 151-180 inclusive are reserved for vendor-specific
+; system calls. (This includes various calls added for compatibity
+; with other Unix variants.)
+; Some of these calls are now supported by BSD...
+151 UNIMPL NOHIDE sem_lock (BSD/OS 2.x)
+152 UNIMPL NOHIDE sem_wakeup (BSD/OS 2.x)
+153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x)
+154 UNIMPL NOHIDE nosys
+; 155 is initialized by the NFS code, if present.
+155 UNIMPL NOHIDE nfssvc
+156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
+ long *basep); }
+157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); }
+158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); }
+159 UNIMPL NOHIDE nosys
+160 UNIMPL NOHIDE nosys
+161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); }
+162 MNOPROTO BSD { int getdomainname(char *domainname, int len); }
+163 MNOPROTO BSD { int setdomainname(char *domainname, int len); }
+164 MNOPROTO BSD { int uname(struct utsname *name); }
+165 NOPROTO BSD { int sysarch(int op, char *parms); }
+166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \
+ struct rtprio *rtp); }
+167 UNIMPL NOHIDE nosys
+168 UNIMPL NOHIDE nosys
+169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \
+ int a5); }
+170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \
+ int a5, int a6); }
+171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); }
+172 UNIMPL NOHIDE nosys
+173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \
+ int pad, u_int32_t offsetlo, u_int32_t offsethi); }
+; XXX note - bigendian is different
+174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \
+ size_t nbyte, int pad, u_int32_t offsetlo, \
+ u_int32_t offsethi); }
+; XXX note - bigendian is different
+175 UNIMPL NOHIDE nosys
+176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); }
+177 UNIMPL NOHIDE sfork (BSD/OS 2.x)
+178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x)
+179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x)
+180 UNIMPL NOHIDE nosys
+
+; Syscalls 181-199 are used by/reserved for BSD
+181 MNOPROTO POSIX { int setgid(gid_t gid); }
+182 MNOPROTO BSD { int setegid(gid_t egid); }
+183 MNOPROTO BSD { int seteuid(uid_t euid); }
+184 UNIMPL BSD lfs_bmapv
+185 UNIMPL BSD lfs_markv
+186 UNIMPL BSD lfs_segclean
+187 UNIMPL BSD lfs_segwait
+188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); }
+189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); }
+190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); }
+191 NOPROTO POSIX { int pathconf(char *path, int name); }
+192 MNOPROTO POSIX { int fpathconf(int fd, int name); }
+193 UNIMPL NOHIDE nosys
+194 MNOPROTO BSD { int getrlimit(u_int which, \
+ struct rlimit *rlp); } \
+ getrlimit __getrlimit_args int
+195 MNOPROTO BSD { int setrlimit(u_int which, \
+ struct rlimit *rlp); } \
+ setrlimit __setrlimit_args int
+196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \
+ long *basep); }
+197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \
+ int prot, int flags, int fd, int pad, \
+ u_int32_t poslo, u_int32_t poshi); }
+198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int
+; XXX note - bigendian is different
+199 STD POSIX { off_t ia32_lseek(int fd, int pad, \
+ u_int32_t offsetlo, u_int32_t offsethi, \
+ int whence); }
+; XXX note - bigendian is different
+200 STD BSD { int ia32_truncate(char *path, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+; XXX note - bigendian is different
+201 STD BSD { int ia32_ftruncate(int fd, int pad, \
+ u_int32_t lengthlo, u_int32_t lengthhi); }
+202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \
+ void *old, u_int32_t *oldlenp, void *new, \
+ u_int32_t newlen); }
+203 MNOPROTO BSD { int mlock(const void *addr, size_t len); }
+204 MNOPROTO BSD { int munlock(const void *addr, size_t len); }
+205 NOPROTO BSD { int undelete(char *path); }
+206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); }
+207 MNOPROTO BSD { int getpgid(pid_t pid); }
+208 UNIMPL NOHIDE newreboot (NetBSD)
+209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \
+ int timeout); }
+
+;
+; The following are reserved for loadable syscalls
+;
+210 UNIMPL NOHIDE
+211 UNIMPL NOHIDE
+212 UNIMPL NOHIDE
+213 UNIMPL NOHIDE
+214 UNIMPL NOHIDE
+215 UNIMPL NOHIDE
+216 UNIMPL NOHIDE
+217 UNIMPL NOHIDE
+218 UNIMPL NOHIDE
+219 UNIMPL NOHIDE
+
+;
+; The following were introduced with NetBSD/4.4Lite-2
+; They are initialized by thier respective modules/sysinits
+220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \
+ union semun *arg); }
+221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); }
+222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \
+ u_int nsops); }
+223 UNIMPL NOHIDE semconfig
+224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \
+ struct msqid_ds *buf); }
+225 MNOPROTO BSD { int msgget(key_t key, int msgflg); }
+226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \
+ int msgflg); }
+227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \
+ long msgtyp, int msgflg); }
+228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); }
+229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \
+ struct shmid_ds *buf); }
+230 MNOPROTO BSD { int shmdt(void *shmaddr); }
+231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); }
+;
+232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \
+ struct timespec *tp); }
+233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \
+ const struct timespec *tp); }
+234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \
+ struct timespec *tp); }
+235 UNIMPL NOHIDE timer_create
+236 UNIMPL NOHIDE timer_delete
+237 UNIMPL NOHIDE timer_settime
+238 UNIMPL NOHIDE timer_gettime
+239 UNIMPL NOHIDE timer_getoverrun
+240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \
+ struct timespec *rmtp); }
+241 UNIMPL NOHIDE nosys
+242 UNIMPL NOHIDE nosys
+243 UNIMPL NOHIDE nosys
+244 UNIMPL NOHIDE nosys
+245 UNIMPL NOHIDE nosys
+246 UNIMPL NOHIDE nosys
+247 UNIMPL NOHIDE nosys
+248 UNIMPL NOHIDE nosys
+249 UNIMPL NOHIDE nosys
+; syscall numbers initially used in OpenBSD
+250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); }
+251 MNOPROTO BSD { int rfork(int flags); }
+252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \
+ int timeout); }
+253 NOPROTO BSD { int issetugid(void); }
+254 NOPROTO BSD { int lchown(char *path, int uid, int gid); }
+255 UNIMPL NOHIDE nosys
+256 UNIMPL NOHIDE nosys
+257 UNIMPL NOHIDE nosys
+258 UNIMPL NOHIDE nosys
+259 UNIMPL NOHIDE nosys
+260 UNIMPL NOHIDE nosys
+261 UNIMPL NOHIDE nosys
+262 UNIMPL NOHIDE nosys
+263 UNIMPL NOHIDE nosys
+264 UNIMPL NOHIDE nosys
+265 UNIMPL NOHIDE nosys
+266 UNIMPL NOHIDE nosys
+267 UNIMPL NOHIDE nosys
+268 UNIMPL NOHIDE nosys
+269 UNIMPL NOHIDE nosys
+270 UNIMPL NOHIDE nosys
+271 UNIMPL NOHIDE nosys
+272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); }
+273 UNIMPL NOHIDE nosys
+274 NOPROTO BSD { int lchmod(char *path, mode_t mode); }
+275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int
+276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); }
+277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int
+278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); }
+279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); }
+280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); }
+281 UNIMPL NOHIDE nosys
+282 UNIMPL NOHIDE nosys
+283 UNIMPL NOHIDE nosys
+284 UNIMPL NOHIDE nosys
+285 UNIMPL NOHIDE nosys
+286 UNIMPL NOHIDE nosys
+287 UNIMPL NOHIDE nosys
+288 UNIMPL NOHIDE nosys
+289 UNIMPL NOHIDE nosys
+290 UNIMPL NOHIDE nosys
+291 UNIMPL NOHIDE nosys
+292 UNIMPL NOHIDE nosys
+293 UNIMPL NOHIDE nosys
+294 UNIMPL NOHIDE nosys
+295 UNIMPL NOHIDE nosys
+296 UNIMPL NOHIDE nosys
+; XXX 297 is 300 in NetBSD
+297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); }
+298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); }
+299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); }
+; syscall numbers for FreeBSD
+300 MNOPROTO BSD { int modnext(int modid); }
+301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); }
+302 MNOPROTO BSD { int modfnext(int modid); }
+303 MNOPROTO BSD { int modfind(const char *name); }
+304 MNOPROTO BSD { int kldload(const char *file); }
+305 MNOPROTO BSD { int kldunload(int fileid); }
+306 MNOPROTO BSD { int kldfind(const char *file); }
+307 MNOPROTO BSD { int kldnext(int fileid); }
+308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); }
+309 MNOPROTO BSD { int kldfirstmod(int fileid); }
+310 MNOPROTO BSD { int getsid(pid_t pid); }
+311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); }
+312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); }
+313 OBSOL NOHIDE signanosleep
+314 UNIMPL NOHIDE aio_return
+315 UNIMPL NOHIDE aio_suspend
+316 UNIMPL NOHIDE aio_cancel
+317 UNIMPL NOHIDE aio_error
+318 UNIMPL NOHIDE aio_read
+319 UNIMPL NOHIDE aio_write
+320 UNIMPL NOHIDE lio_listio
+321 MNOPROTO BSD { int yield(void); }
+322 OBSOL NOHIDE thr_sleep
+323 OBSOL NOHIDE thr_wakeup
+324 MNOPROTO BSD { int mlockall(int how); }
+325 MNOPROTO BSD { int munlockall(void); }
+326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); }
+
+327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); }
+328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); }
+
+329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); }
+330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); }
+
+331 MNOPROTO POSIX { int sched_yield (void); }
+332 MNOPROTO POSIX { int sched_get_priority_max (int policy); }
+333 MNOPROTO POSIX { int sched_get_priority_min (int policy); }
+334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); }
+335 NOPROTO BSD { int utrace(const void *addr, size_t len); }
+; XXX note - bigendian is different
+336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \
+ u_int32_t offsethi, size_t nbytes, \
+ struct sf_hdtr *hdtr, off_t *sbytes, int flags); }
+337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); }
+338 MNOPROTO BSD { int jail(struct jail *jail); }
+339 UNIMPL BSD pioctl
+340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \
+ sigset_t *oset); }
+341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); }
+342 STD POSIX { int ia32_sigaction(int sig, \
+ struct sigaction32 *act, \
+ struct sigaction32 *oact); }
+343 MNOPROTO POSIX { int sigpending(sigset_t *set); }
+344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); }
+345 UNIMPL NOHIDE sigtimedwait
+346 UNIMPL NOHIDE sigwaitinfo
+347 MNOPROTO BSD { int __acl_get_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+348 MNOPROTO BSD { int __acl_set_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \
+ struct acl *aclp); }
+350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \
+ struct acl *aclp); }
+351 MNOPROTO BSD { int __acl_delete_file(const char *path, \
+ acl_type_t type); }
+352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); }
+353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \
+ acl_type_t type, struct acl *aclp); }
+354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \
+ struct acl *aclp); }
+355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \
+ const char *filename, int attrnamespace, \
+ const char *attrname); }
+356 NOPROTO BSD { int extattr_set_file(const char *path, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \
+ int attrnamespace, const char *attrname, \
+ void *data, size_t nbytes); }
+358 NOPROTO BSD { int extattr_delete_file(const char *path, \
+ int attrnamespace, const char *attrname); }
+359 UNIMPL NOHIDE aio_waitcomplete
+360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); }
+361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); }
+362 MNOPROTO BSD { int kqueue(void); }
+363 MNOPROTO BSD { int kevent(int fd, \
+ const struct kevent *changelist, int nchanges, \
+ struct kevent *eventlist, int nevents, \
+ const struct timespec *timeout); }
+364 UNIMPL NOHIDE __cap_get_proc
+365 UNIMPL NOHIDE __cap_set_proc
+366 UNIMPL NOHIDE __cap_get_fd
+367 UNIMPL NOHIDE __cap_get_file
+368 UNIMPL NOHIDE __cap_set_fd
+369 UNIMPL NOHIDE __cap_set_file
+370 UNIMPL NOHIDE lkmressys
+371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \
+ const char *attrname, void *data, \
+ size_t nbytes); }
+372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
+ const char *attrname, void *data, size_t nbytes); }
+373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \
+ const char *attrname); }
+374 MNOPROTO BSD { int __setugid(int flag); }
+375 UNIMPL BSD nfsclnt
+376 NOPROTO BSD { int eaccess(char *path, int flags); }
+377 UNIMPL BSD afs_syscall
+378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \
+ int flags); }
+379 NOPROTO BSD { int kse_exit(void); }
+380 NOPROTO BSD { int kse_wakeup(void); }
+381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \
+ int new_grp_flag); }
+382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); }
+383 NOPROTO BSD { int kse_yield(void); }
+384 UNIMPL BSD __mac_get_proc
+385 UNIMPL BSD __mac_set_proc
+386 UNIMPL BSD __mac_get_fd
+387 UNIMPL BSD __mac_get_file
+388 UNIMPL BSD __mac_set_fd
+389 UNIMPL BSD __mac_set_file
+390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \
+ int len); }
+391 NOPROTO BSD { int lchflags(const char *path, int flags); }
+392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); }
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
new file mode 100644
index 0000000..06e6505
--- /dev/null
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define __ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/fcntl.h>
+#include <sys/imgact.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/mman.h>
+#include <sys/namei.h>
+#include <sys/pioctl.h>
+#include <sys/proc.h>
+#include <sys/procfs.h>
+#include <sys/resourcevar.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/syscall.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+#include <sys/imgact_elf.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <ia64/ia32/ia32_util.h>
+#include <i386/include/psl.h>
+#include <i386/include/segments.h>
+#include <i386/include/specialreg.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+
+static register_t *ia32_copyout_strings(struct image_params *imgp);
+static void ia32_setregs(struct thread *td, u_long entry, u_long stack,
+ u_long ps_strings);
+
+extern struct sysent ia32_sysent[];
+
+static char ia32_sigcode[] = {
+ 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */
+ 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */
+ 0x50, /* pushl %eax */
+ 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */
+ 0x75, 0x03, /* jne 9f */
+ 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */
+ 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */
+ 0x50, /* pushl %eax */
+ 0xcd, 0x80, /* int $0x80 */
+ 0xeb, 0xfe, /* 0: jmp 0b */
+ 0, 0, 0, 0
+};
+static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3;
+
+struct sysentvec ia32_freebsd_sysvec = {
+ SYS_MAXSYSCALL,
+ ia32_sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ elf32_freebsd_fixup,
+ sendsig,
+ ia32_sigcode,
+ &ia32_szsigcode,
+ 0,
+ "FreeBSD ELF",
+ elf32_coredump,
+ NULL,
+ MINSIGSTKSZ,
+ 4096,
+ IA32_USRSTACK,
+ IA32_USRSTACK,
+ ia32_copyout_strings,
+ ia32_setregs
+};
+
+static Elf32_Brandinfo ia32_brand_info = {
+ ELFOSABI_FREEBSD,
+ EM_386,
+ "FreeBSD",
+ "/compat/ia32",
+ "/usr/libexec/ld-elf.so.1",
+ &ia32_freebsd_sysvec
+ };
+
+SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
+ (sysinit_cfunc_t) elf32_insert_brand_entry,
+ &ia32_brand_info);
+
+static register_t *
+ia32_copyout_strings(struct image_params *imgp)
+{
+ int argc, envc;
+ u_int32_t *vectp;
+ char *stringp, *destp;
+ u_int32_t *stack_base;
+ struct ia32_ps_strings *arginfo;
+ int szsigcode;
+
+ /*
+ * Calculate string base and vector table pointers.
+ * Also deal with signal trampoline code for this exec type.
+ */
+ arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
+ szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
+ destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+
+ /*
+ * install sigcode
+ */
+ if (szsigcode)
+ copyout(imgp->proc->p_sysent->sv_sigcode,
+ ((caddr_t)arginfo - szsigcode), szsigcode);
+
+ /*
+ * If we have a valid auxargs ptr, prepare some room
+ * on the stack.
+ */
+ if (imgp->auxargs) {
+ /*
+ * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+ * lower compatibility.
+ */
+ imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+ : (AT_COUNT * 2);
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets,and imgp->auxarg_size is room
+ * for argument of Runtime loader.
+ */
+ vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
+ imgp->auxarg_size) * sizeof(u_int32_t));
+
+ } else
+ /*
+ * The '+ 2' is for the null pointers at the end of each of
+ * the arg and env vector sets
+ */
+ vectp = (u_int32_t *)
+ (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
+
+ /*
+ * vectp also becomes our initial stack base
+ */
+ stack_base = vectp;
+
+ stringp = imgp->stringbase;
+ argc = imgp->argc;
+ envc = imgp->envc;
+
+ /*
+ * Copy out strings - arguments and environment.
+ */
+ copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+
+ /*
+ * Fill in "ps_strings" struct for ps, w, etc.
+ */
+ suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nargvstr, argc);
+
+ /*
+ * Fill in argument portion of vector table.
+ */
+ for (; argc > 0; --argc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* a null vector table pointer separates the argp's from the envp's */
+ suword32(vectp++, 0);
+
+ suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+ suword32(&arginfo->ps_nenvstr, envc);
+
+ /*
+ * Fill in environment portion of vector table.
+ */
+ for (; envc > 0; --envc) {
+ suword32(vectp++, (u_int32_t)(intptr_t)destp);
+ while (*stringp++ != 0)
+ destp++;
+ destp++;
+ }
+
+ /* end of vector table is a null pointer */
+ suword32(vectp, 0);
+
+ return ((register_t *)stack_base);
+}
+
+static void
+ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+ struct trapframe *frame = td->td_frame;
+ vm_offset_t gdt, ldt;
+ u_int64_t codesel, datasel, ldtsel;
+ u_int64_t codeseg, dataseg, gdtseg, ldtseg;
+ struct segment_descriptor desc;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+
+ /*
+ * Make sure that we restore the entire trapframe after an
+ * execve.
+ */
+ frame->tf_flags &= ~FRAME_SYSCALL;
+
+ bzero(frame->tf_r, sizeof(frame->tf_r));
+ bzero(frame->tf_f, sizeof(frame->tf_f));
+
+ frame->tf_cr_iip = entry;
+ frame->tf_cr_ipsr = (IA64_PSR_IC
+ | IA64_PSR_I
+ | IA64_PSR_IT
+ | IA64_PSR_DT
+ | IA64_PSR_RT
+ | IA64_PSR_DFH
+ | IA64_PSR_IS
+ | IA64_PSR_BN
+ | IA64_PSR_CPL_USER);
+ frame->tf_r[FRAME_R12] = stack;
+
+ codesel = LSEL(LUCODE_SEL, SEL_UPL);
+ datasel = LSEL(LUDATA_SEL, SEL_UPL);
+ ldtsel = GSEL(GLDT_SEL, SEL_UPL);
+
+#if 1
+ frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32)
+ | (datasel << 16) | datasel;
+ frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel;
+#else
+ frame->tf_r[FRAME_R16] = datasel;
+ frame->tf_r[FRAME_R17] = codesel;
+ frame->tf_r[FRAME_R18] = datasel;
+ frame->tf_r[FRAME_R19] = datasel;
+ frame->tf_r[FRAME_R20] = datasel;
+ frame->tf_r[FRAME_R21] = datasel;
+ frame->tf_r[FRAME_R22] = ldtsel;
+#endif
+
+ /*
+ * Build the GDT and LDT.
+ */
+ gdt = IA32_USRSTACK;
+ vm_map_find(&vmspace->vm_map, 0, 0,
+ &gdt, PAGE_SIZE, 0,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ ldt = gdt + 4096;
+
+ desc.sd_lolimit = 8*NLDT-1;
+ desc.sd_lobase = ldt & 0xffffff;
+ desc.sd_type = SDT_SYSLDT;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = 0;
+ desc.sd_def32 = 0;
+ desc.sd_gran = 0;
+ desc.sd_hibase = ldt >> 24;
+ copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc));
+
+ desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff;
+ desc.sd_lobase = 0;
+ desc.sd_type = SDT_MEMERA;
+ desc.sd_dpl = SEL_UPL;
+ desc.sd_p = 1;
+ desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16;
+ desc.sd_def32 = 1;
+ desc.sd_gran = 1;
+ desc.sd_hibase = 0;
+ copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc));
+ desc.sd_type = SDT_MEMRWA;
+ copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc));
+
+ codeseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMERA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ dataseg = 0 /* base */
+ + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */
+ + ((long)SDT_MEMRWA << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (1L << 62) /* 32 bits */
+ + (1L << 63); /* page granularity */
+ ia64_set_csd(codeseg);
+ ia64_set_ssd(dataseg);
+ frame->tf_r[FRAME_R24] = dataseg; /* ESD */
+ frame->tf_r[FRAME_R27] = dataseg; /* DSD */
+ frame->tf_r[FRAME_R28] = dataseg; /* FSD */
+ frame->tf_r[FRAME_R29] = dataseg; /* GSD */
+
+ gdtseg = gdt /* base */
+ + ((8L*NGDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSNULL << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ ldtseg = ldt /* base */
+ + ((8L*NLDT - 1) << 32) /* limit */
+ + ((long)SDT_SYSLDT << 52)
+ + ((long)SEL_UPL << 57)
+ + (1L << 59) /* present */
+ + (0L << 62) /* 16 bits */
+ + (0L << 63); /* byte granularity */
+ frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */
+ frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */
+
+ ia64_set_eflag(PSL_USER);
+
+ /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
+ frame->tf_r[FRAME_R11] = IA32_PS_STRINGS;
+
+ /*
+ * XXX - Linux emulator
+ * Make sure sure edx is 0x0 on entry. Linux binaries depend
+ * on it.
+ */
+ td->td_retval[1] = 0;
+}
diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h
new file mode 100644
index 0000000..b9e0a7c
--- /dev/null
+++ b/sys/compat/ia32/ia32_util.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+struct ia32_ps_strings {
+ u_int32_t ps_argvstr; /* first of 0 or more argument strings */
+ int ps_nargvstr; /* the number of argument strings */
+ u_int32_t ps_envstr; /* first of 0 or more environment strings */
+ int ps_nenvstr; /* the number of environment strings */
+};
+
+#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE)
+#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings))
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+#undef szsigcode
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p;
+
+ p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+
+extern const char ia32_emul_path[];
+int ia32_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1)
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
new file mode 100644
index 0000000..5129746
--- /dev/null
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -0,0 +1,861 @@
+/*
+ * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 1999 Pierre Beyssac
+ * Copyright (c) 1993 Jan-Simon Pendry
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jan-Simon Pendry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/blist.h>
+#include <sys/conf.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/tty.h>
+#include <sys/user.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+
+#include <net/if.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#include <machine/clock.h>
+
+#ifdef __alpha__
+#include <machine/alpha_cpu.h>
+#include <machine/cpuconf.h>
+#include <machine/rpb.h>
+extern int ncpus;
+#endif /* __alpha__ */
+
+#ifdef __i386__
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#endif /* __i386__ */
+
+#include <machine/../linux/linux.h>
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_util.h>
+#include <fs/pseudofs/pseudofs.h>
+#include <fs/procfs/procfs.h>
+
+/*
+ * Various conversion macros
+ */
+#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */
+#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
+#define B2K(x) ((x) >> 10) /* bytes to kbytes */
+#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
+#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
+#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
+
+/*
+ * Filler function for proc/meminfo
+ */
+static int
+linprocfs_domeminfo(PFS_FILL_ARGS)
+{
+ unsigned long memtotal; /* total memory in bytes */
+ unsigned long memused; /* used memory in bytes */
+ unsigned long memfree; /* free memory in bytes */
+ unsigned long memshared; /* shared memory ??? */
+ unsigned long buffers, cached; /* buffer / cache memory ??? */
+ u_quad_t swaptotal; /* total swap space in bytes */
+ u_quad_t swapused; /* used swap space in bytes */
+ u_quad_t swapfree; /* free swap space in bytes */
+ vm_object_t object;
+
+ memtotal = physmem * PAGE_SIZE;
+ /*
+ * The correct thing here would be:
+ *
+ memfree = cnt.v_free_count * PAGE_SIZE;
+ memused = memtotal - memfree;
+ *
+ * but it might mislead linux binaries into thinking there
+ * is very little memory left, so we cheat and tell them that
+ * all memory that isn't wired down is free.
+ */
+ memused = cnt.v_wire_count * PAGE_SIZE;
+ memfree = memtotal - memused;
+ if (swapblist == NULL) {
+ swaptotal = 0;
+ swapfree = 0;
+ } else {
+ swaptotal = (u_quad_t)swapblist->bl_blocks * 1024; /* XXX why 1024? */
+ swapfree = (u_quad_t)swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
+ }
+ swapused = swaptotal - swapfree;
+ memshared = 0;
+ TAILQ_FOREACH(object, &vm_object_list, object_list)
+ if (object->shadow_count > 1)
+ memshared += object->resident_page_count;
+ memshared *= PAGE_SIZE;
+ /*
+ * We'd love to be able to write:
+ *
+ buffers = bufspace;
+ *
+ * but bufspace is internal to vfs_bio.c and we don't feel
+ * like unstaticizing it just for linprocfs's sake.
+ */
+ buffers = 0;
+ cached = cnt.v_cache_count * PAGE_SIZE;
+
+ sbuf_printf(sb,
+ " total: used: free: shared: buffers: cached:\n"
+ "Mem: %lu %lu %lu %lu %lu %lu\n"
+ "Swap: %llu %llu %llu\n"
+ "MemTotal: %9lu kB\n"
+ "MemFree: %9lu kB\n"
+ "MemShared:%9lu kB\n"
+ "Buffers: %9lu kB\n"
+ "Cached: %9lu kB\n"
+ "SwapTotal:%9llu kB\n"
+ "SwapFree: %9llu kB\n",
+ memtotal, memused, memfree, memshared, buffers, cached,
+ swaptotal, swapused, swapfree,
+ B2K(memtotal), B2K(memfree),
+ B2K(memshared), B2K(buffers), B2K(cached),
+ B2K(swaptotal), B2K(swapfree));
+
+ return (0);
+}
+
+#ifdef __alpha__
+/*
+ * Filler function for proc/cpuinfo (Alpha version)
+ */
+static int
+linprocfs_docpuinfo(PFS_FILL_ARGS)
+{
+ u_int64_t type, major;
+ struct pcs *pcsp;
+ const char *model, *sysname;
+
+ static const char *cpuname[] = {
+ "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
+ "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL"
+ };
+
+ pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
+ type = pcsp->pcs_proc_type;
+ major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT;
+ if (major < sizeof(cpuname)/sizeof(char *)) {
+ model = cpuname[major - 1];
+ } else {
+ model = "unknown";
+ }
+
+ sysname = alpha_dsr_sysname();
+
+ sbuf_printf(sb,
+ "cpu\t\t\t: Alpha\n"
+ "cpu model\t\t: %s\n"
+ "cpu variation\t\t: %ld\n"
+ "cpu revision\t\t: %ld\n"
+ "cpu serial number\t: %s\n"
+ "system type\t\t: %s\n"
+ "system variation\t: %s\n"
+ "system revision\t\t: %ld\n"
+ "system serial number\t: %s\n"
+ "cycle frequency [Hz]\t: %lu\n"
+ "timer frequency [Hz]\t: %lu\n"
+ "page size [bytes]\t: %ld\n"
+ "phys. address bits\t: %ld\n"
+ "max. addr. space #\t: %ld\n"
+ "BogoMIPS\t\t: %lu.%02lu\n"
+ "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "platform string\t\t: %s\n"
+ "cpus detected\t\t: %d\n"
+ ,
+ model,
+ pcsp->pcs_proc_var,
+ *(int *)hwrpb->rpb_revision,
+ " ",
+ " ",
+ "0",
+ 0,
+ " ",
+ hwrpb->rpb_cc_freq,
+ hz,
+ hwrpb->rpb_page_size,
+ hwrpb->rpb_phys_addr_size,
+ hwrpb->rpb_max_asn,
+ 0, 0,
+ 0, 0, 0,
+ 0, 0, 0,
+ sysname,
+ ncpus);
+ return (0);
+}
+#endif /* __alpha__ */
+
+#ifdef __i386__
+/*
+ * Filler function for proc/cpuinfo (i386 version)
+ */
+static int
+linprocfs_docpuinfo(PFS_FILL_ARGS)
+{
+ int class, i, fqmhz, fqkhz;
+
+ /*
+ * We default the flags to include all non-conflicting flags,
+ * and the Intel versions of conflicting flags.
+ */
+ static char *flags[] = {
+ "fpu", "vme", "de", "pse", "tsc",
+ "msr", "pae", "mce", "cx8", "apic",
+ "sep", "sep", "mtrr", "pge", "mca",
+ "cmov", "pat", "pse36", "pn", "b19",
+ "b20", "b21", "mmxext", "mmx", "fxsr",
+ "xmm", "b26", "b27", "b28", "b29",
+ "3dnowext", "3dnow"
+ };
+
+ switch (cpu_class) {
+ case CPUCLASS_286:
+ class = 2;
+ break;
+ case CPUCLASS_386:
+ class = 3;
+ break;
+ case CPUCLASS_486:
+ class = 4;
+ break;
+ case CPUCLASS_586:
+ class = 5;
+ break;
+ case CPUCLASS_686:
+ class = 6;
+ break;
+ default:
+ class = 0;
+ break;
+ }
+
+ sbuf_printf(sb,
+ "processor\t: %d\n"
+ "vendor_id\t: %.20s\n"
+ "cpu family\t: %d\n"
+ "model\t\t: %d\n"
+ "stepping\t: %d\n",
+ 0, cpu_vendor, class, cpu, cpu_id & 0xf);
+
+ sbuf_cat(sb,
+ "flags\t\t:");
+
+ if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
+ flags[16] = "fcmov";
+ } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
+ flags[24] = "cxmmx";
+ }
+
+ for (i = 0; i < 32; i++)
+ if (cpu_feature & (1 << i))
+ sbuf_printf(sb, " %s", flags[i]);
+ sbuf_cat(sb, "\n");
+ if (class >= 5) {
+ fqmhz = (tsc_freq + 4999) / 1000000;
+ fqkhz = ((tsc_freq + 4999) / 10000) % 100;
+ sbuf_printf(sb,
+ "cpu MHz\t\t: %d.%02d\n"
+ "bogomips\t: %d.%02d\n",
+ fqmhz, fqkhz, fqmhz, fqkhz);
+ }
+
+ return (0);
+}
+#endif /* __i386__ */
+
+/*
+ * Filler function for proc/mtab
+ *
+ * This file doesn't exist in Linux' procfs, but is included here so
+ * users can symlink /compat/linux/etc/mtab to /proc/mtab
+ */
+static int
+linprocfs_domtab(PFS_FILL_ARGS)
+{
+ struct nameidata nd;
+ struct mount *mp;
+ const char *lep;
+ char *dlep, *flep, *mntto, *mntfrom, *fstype;
+ size_t lep_len;
+ int error;
+
+ /* resolve symlinks etc. in the emulation tree prefix */
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
+ flep = NULL;
+ if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) == -1)
+ lep = linux_emul_path;
+ else
+ lep = dlep;
+ lep_len = strlen(lep);
+
+ mtx_lock(&mountlist_mtx);
+ error = 0;
+ TAILQ_FOREACH(mp, &mountlist, mnt_list) {
+ error = VFS_STATFS(mp, &mp->mnt_stat, td);
+ if (error)
+ break;
+
+ /* determine device name */
+ mntfrom = mp->mnt_stat.f_mntfromname;
+
+ /* determine mount point */
+ mntto = mp->mnt_stat.f_mntonname;
+ if (strncmp(mntto, lep, lep_len) == 0 &&
+ mntto[lep_len] == '/')
+ mntto += lep_len;
+
+ /* determine fs type */
+ fstype = mp->mnt_stat.f_fstypename;
+ if (strcmp(fstype, pn->pn_info->pi_name) == 0)
+ mntfrom = fstype = "proc";
+ else if (strcmp(fstype, "procfs") == 0)
+ continue;
+
+ sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
+ mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
+#define ADD_OPTION(opt, name) \
+ if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
+ ADD_OPTION(MNT_SYNCHRONOUS, "sync");
+ ADD_OPTION(MNT_NOEXEC, "noexec");
+ ADD_OPTION(MNT_NOSUID, "nosuid");
+ ADD_OPTION(MNT_NODEV, "nodev");
+ ADD_OPTION(MNT_UNION, "union");
+ ADD_OPTION(MNT_ASYNC, "async");
+ ADD_OPTION(MNT_SUIDDIR, "suiddir");
+ ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
+ ADD_OPTION(MNT_NOATIME, "noatime");
+#undef ADD_OPTION
+ /* a real Linux mtab will also show NFS options */
+ sbuf_printf(sb, " 0 0\n");
+ }
+ mtx_unlock(&mountlist_mtx);
+ if (flep != NULL)
+ free(flep, M_TEMP);
+ return (error);
+}
+
+/*
+ * Filler function for proc/stat
+ */
+static int
+linprocfs_dostat(PFS_FILL_ARGS)
+{
+ sbuf_printf(sb,
+ "cpu %ld %ld %ld %ld\n"
+ "disk 0 0 0 0\n"
+ "page %u %u\n"
+ "swap %u %u\n"
+ "intr %u\n"
+ "ctxt %u\n"
+ "btime %lld\n",
+ T2J(cp_time[CP_USER]),
+ T2J(cp_time[CP_NICE]),
+ T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
+ T2J(cp_time[CP_IDLE]),
+ cnt.v_vnodepgsin,
+ cnt.v_vnodepgsout,
+ cnt.v_swappgsin,
+ cnt.v_swappgsout,
+ cnt.v_intr,
+ cnt.v_swtch,
+ (quad_t)boottime.tv_sec);
+ return (0);
+}
+
+/*
+ * Filler function for proc/uptime
+ */
+static int
+linprocfs_douptime(PFS_FILL_ARGS)
+{
+ struct timeval tv;
+
+ getmicrouptime(&tv);
+ sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n",
+ (quad_t)tv.tv_sec, tv.tv_usec / 10000,
+ T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
+ return (0);
+}
+
+/*
+ * Filler function for proc/version
+ */
+static int
+linprocfs_doversion(PFS_FILL_ARGS)
+{
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
+
+ linux_get_osname(td->td_proc, osname);
+ linux_get_osrelease(td->td_proc, osrelease);
+
+ sbuf_printf(sb,
+ "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
+ " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease);
+ return (0);
+}
+
+/*
+ * Filler function for proc/loadavg
+ */
+static int
+linprocfs_doloadavg(PFS_FILL_ARGS)
+{
+ sbuf_printf(sb,
+ "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
+ (int)(averunnable.ldavg[0] / averunnable.fscale),
+ (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
+ (int)(averunnable.ldavg[1] / averunnable.fscale),
+ (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
+ (int)(averunnable.ldavg[2] / averunnable.fscale),
+ (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
+ 1, /* number of running tasks */
+ nprocs, /* number of tasks */
+ lastpid /* the last pid */
+ );
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/stat
+ */
+static int
+linprocfs_doprocstat(PFS_FILL_ARGS)
+{
+ struct kinfo_proc kp;
+
+ PROC_LOCK(p);
+ fill_kinfo_proc(p, &kp);
+ sbuf_printf(sb, "%d", p->p_pid);
+#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
+ PS_ADD("comm", "(%s)", p->p_comm);
+ PS_ADD("statr", "%c", '0'); /* XXX */
+ PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
+ PS_ADD("pgrp", "%d", p->p_pgid);
+ PS_ADD("session", "%d", p->p_session->s_sid);
+ PROC_UNLOCK(p);
+ PS_ADD("tty", "%d", 0); /* XXX */
+ PS_ADD("tpgid", "%d", 0); /* XXX */
+ PS_ADD("flags", "%u", 0); /* XXX */
+ PS_ADD("minflt", "%u", 0); /* XXX */
+ PS_ADD("cminflt", "%u", 0); /* XXX */
+ PS_ADD("majflt", "%u", 0); /* XXX */
+ PS_ADD("cminflt", "%u", 0); /* XXX */
+ PS_ADD("utime", "%d", 0); /* XXX */
+ PS_ADD("stime", "%d", 0); /* XXX */
+ PS_ADD("cutime", "%d", 0); /* XXX */
+ PS_ADD("cstime", "%d", 0); /* XXX */
+ PS_ADD("counter", "%d", 0); /* XXX */
+ PS_ADD("priority", "%d", 0); /* XXX */
+ PS_ADD("timeout", "%u", 0); /* XXX */
+ PS_ADD("itrealvalue", "%u", 0); /* XXX */
+ PS_ADD("starttime", "%d", 0); /* XXX */
+ PS_ADD("vsize", "%u", kp.ki_size);
+ PS_ADD("rss", "%u", P2K(kp.ki_rssize));
+ PS_ADD("rlim", "%u", 0); /* XXX */
+ PS_ADD("startcode", "%u", (unsigned)0);
+ PS_ADD("endcode", "%u", 0); /* XXX */
+ PS_ADD("startstack", "%u", 0); /* XXX */
+ PS_ADD("esp", "%u", 0); /* XXX */
+ PS_ADD("eip", "%u", 0); /* XXX */
+ PS_ADD("signal", "%d", 0); /* XXX */
+ PS_ADD("blocked", "%d", 0); /* XXX */
+ PS_ADD("sigignore", "%d", 0); /* XXX */
+ PS_ADD("sigcatch", "%d", 0); /* XXX */
+ PS_ADD("wchan", "%u", 0); /* XXX */
+ PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */
+ PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */
+ PS_ADD("exitsignal", "%d", 0); /* XXX */
+ PS_ADD("processor", "%d", 0); /* XXX */
+#undef PS_ADD
+ sbuf_putc(sb, '\n');
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/status
+ */
+static int
+linprocfs_doprocstatus(PFS_FILL_ARGS)
+{
+ struct kinfo_proc kp;
+ char *state;
+ segsz_t lsize;
+ struct thread *td2;
+ int i;
+
+ mtx_lock_spin(&sched_lock);
+ td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
+
+ if (P_SHOULDSTOP(p)) {
+ state = "T (stopped)";
+ } else {
+ switch(p->p_state) {
+ case PRS_NEW:
+ state = "I (idle)";
+ break;
+ case PRS_NORMAL:
+ if (p->p_flag & P_WEXIT) {
+ state = "X (exiting)";
+ break;
+ }
+ switch(td2->td_state) {
+ case TDS_SLP:
+ case TDS_MTX:
+ state = "S (sleeping)";
+ break;
+ case TDS_RUNQ:
+ case TDS_RUNNING:
+ state = "R (running)";
+ break;
+ case TDS_NEW:
+ case TDS_UNQUEUED:
+ case TDS_IWAIT:
+ case TDS_SURPLUS:
+ default:
+ state = "? (unknown)";
+ break;
+ }
+ break;
+ case PRS_WAIT:
+ state = "W (waiting)";
+ break;
+ case PRS_ZOMBIE:
+ state = "Z (zombie)";
+ break;
+ default:
+ state = "? (unknown)";
+ break;
+ }
+ }
+ mtx_unlock_spin(&sched_lock);
+
+ PROC_LOCK(p);
+ fill_kinfo_proc(p, &kp);
+ sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
+ sbuf_printf(sb, "State:\t%s\n", state);
+
+ /*
+ * Credentials
+ */
+ sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
+ sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
+ p->p_pptr->p_pid : 0);
+ sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
+ p->p_ucred->cr_uid,
+ p->p_ucred->cr_svuid,
+ /* FreeBSD doesn't have fsuid */
+ p->p_ucred->cr_uid);
+ sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
+ p->p_ucred->cr_gid,
+ p->p_ucred->cr_svgid,
+ /* FreeBSD doesn't have fsgid */
+ p->p_ucred->cr_gid);
+ sbuf_cat(sb, "Groups:\t");
+ for (i = 0; i < p->p_ucred->cr_ngroups; i++)
+ sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
+ PROC_UNLOCK(p);
+ sbuf_putc(sb, '\n');
+
+ /*
+ * Memory
+ *
+ * While our approximation of VmLib may not be accurate (I
+ * don't know of a simple way to verify it, and I'm not sure
+ * it has much meaning anyway), I believe it's good enough.
+ *
+ * The same code that could (I think) accurately compute VmLib
+ * could also compute VmLck, but I don't really care enough to
+ * implement it. Submissions are welcome.
+ */
+ sbuf_printf(sb, "VmSize:\t%8u kB\n", B2K(kp.ki_size));
+ sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
+ sbuf_printf(sb, "VmRss:\t%8u kB\n", P2K(kp.ki_rssize));
+ sbuf_printf(sb, "VmData:\t%8u kB\n", P2K(kp.ki_dsize));
+ sbuf_printf(sb, "VmStk:\t%8u kB\n", P2K(kp.ki_ssize));
+ sbuf_printf(sb, "VmExe:\t%8u kB\n", P2K(kp.ki_tsize));
+ lsize = B2P(kp.ki_size) - kp.ki_dsize -
+ kp.ki_ssize - kp.ki_tsize - 1;
+ sbuf_printf(sb, "VmLib:\t%8u kB\n", P2K(lsize));
+
+ /*
+ * Signal masks
+ *
+ * We support up to 128 signals, while Linux supports 32,
+ * but we only define 32 (the same 32 as Linux, to boot), so
+ * just show the lower 32 bits of each mask. XXX hack.
+ *
+ * NB: on certain platforms (Sparc at least) Linux actually
+ * supports 64 signals, but this code is a long way from
+ * running on anything but i386, so ignore that for now.
+ */
+ PROC_LOCK(p);
+ sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
+ /*
+ * I can't seem to find out where the signal mask is in
+ * relation to struct proc, so SigBlk is left unimplemented.
+ */
+ sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */
+ sbuf_printf(sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]);
+ sbuf_printf(sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]);
+ PROC_UNLOCK(p);
+
+ /*
+ * Linux also prints the capability masks, but we don't have
+ * capabilities yet, and when we do get them they're likely to
+ * be meaningless to Linux programs, so we lie. XXX
+ */
+ sbuf_printf(sb, "CapInh:\t%016x\n", 0);
+ sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
+ sbuf_printf(sb, "CapEff:\t%016x\n", 0);
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/pid/cmdline
+ */
+static int
+linprocfs_doproccmdline(PFS_FILL_ARGS)
+{
+ struct ps_strings pstr;
+ int error, i;
+
+ /*
+ * If we are using the ps/cmdline caching, use that. Otherwise
+ * revert back to the old way which only implements full cmdline
+ * for the currept process and just p->p_comm for all other
+ * processes.
+ * Note that if the argv is no longer available, we deliberately
+ * don't fall back on p->p_comm or return an error: the authentic
+ * Linux behaviour is to return zero-length in this case.
+ */
+
+ PROC_LOCK(p);
+ if (p->p_args && (ps_argsopen || !p_cansee(td, p))) {
+ sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
+ PROC_UNLOCK(p);
+ } else if (p != td->td_proc) {
+ PROC_UNLOCK(p);
+ sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
+ } else {
+ PROC_UNLOCK(p);
+ error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
+ if (error)
+ return (error);
+ for (i = 0; i < pstr.ps_nargvstr; i++) {
+ sbuf_copyin(sb, pstr.ps_argvstr[i], 0);
+ sbuf_printf(sb, "%c", '\0');
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Filler function for proc/net/dev
+ */
+static int
+linprocfs_donetdev(PFS_FILL_ARGS)
+{
+ char ifname[16]; /* XXX LINUX_IFNAMSIZ */
+ struct ifnet *ifp;
+
+ sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
+ "Inter-", " Receive", " Transmit", " face",
+ "bytes packets errs drop fifo frame compressed",
+ "bytes packets errs drop fifo frame compressed");
+
+ TAILQ_FOREACH(ifp, &ifnet, if_link) {
+ linux_ifname(ifp, ifname, sizeof ifname);
+ sbuf_printf(sb, "%6.6s:", ifname);
+ sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+ sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
+ }
+
+ return (0);
+}
+
+#if 0
+extern struct cdevsw *cdevsw[];
+
+/*
+ * Filler function for proc/devices
+ */
+static int
+linprocfs_dodevices(PFS_FILL_ARGS)
+{
+ int i;
+
+ sbuf_printf(sb, "Character devices:\n");
+
+ for (i = 0; i < NUMCDEVSW; i++)
+ if (cdevsw[i] != NULL)
+ sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name);
+
+ sbuf_printf(sb, "\nBlock devices:\n");
+
+ return (0);
+}
+#endif
+
+/*
+ * Filler function for proc/cmdline
+ */
+static int
+linprocfs_docmdline(PFS_FILL_ARGS)
+{
+ sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
+ sbuf_printf(sb, " ro root=302\n");
+ return (0);
+}
+
+#if 0
+/*
+ * Filler function for proc/modules
+ */
+static int
+linprocfs_domodules(PFS_FILL_ARGS)
+{
+ struct linker_file *lf;
+
+ TAILQ_FOREACH(lf, &linker_files, link) {
+ sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
+ (unsigned long)lf->size, lf->refs);
+ }
+ return (0);
+}
+#endif
+
+/*
+ * Constructor
+ */
+static int
+linprocfs_init(PFS_INIT_ARGS)
+{
+ struct pfs_node *root;
+ struct pfs_node *dir;
+
+ root = pi->pi_root;
+
+#define PFS_CREATE_FILE(name) \
+ pfs_create_file(root, #name, &linprocfs_do##name, NULL, NULL, PFS_RD)
+ PFS_CREATE_FILE(cmdline);
+ PFS_CREATE_FILE(cpuinfo);
+#if 0
+ PFS_CREATE_FILE(devices);
+#endif
+ PFS_CREATE_FILE(loadavg);
+ PFS_CREATE_FILE(meminfo);
+#if 0
+ PFS_CREATE_FILE(modules);
+#endif
+ PFS_CREATE_FILE(mtab);
+ PFS_CREATE_FILE(stat);
+ PFS_CREATE_FILE(uptime);
+ PFS_CREATE_FILE(version);
+#undef PFS_CREATE_FILE
+ pfs_create_link(root, "self", &procfs_docurproc,
+ NULL, NULL, 0);
+
+ dir = pfs_create_dir(root, "net", NULL, NULL, 0);
+ pfs_create_file(dir, "dev", &linprocfs_donetdev,
+ NULL, NULL, PFS_RD);
+
+ dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP);
+ pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
+ NULL, NULL, PFS_RD);
+ pfs_create_link(dir, "exe", &procfs_doprocfile,
+ NULL, &procfs_notsystem, 0);
+ pfs_create_file(dir, "mem", &procfs_doprocmem,
+ &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW);
+ pfs_create_file(dir, "stat", &linprocfs_doprocstat,
+ NULL, NULL, PFS_RD);
+ pfs_create_file(dir, "status", &linprocfs_doprocstatus,
+ NULL, NULL, PFS_RD);
+
+ return (0);
+}
+
+/*
+ * Destructor
+ */
+static int
+linprocfs_uninit(PFS_INIT_ARGS)
+{
+
+ /* nothing to do, pseudofs will GC */
+ return (0);
+}
+
+PSEUDOFS(linprocfs, 1);
+MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
+MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
new file mode 100644
index 0000000..3c459dd
--- /dev/null
+++ b/sys/compat/linux/linux_file.c
@@ -0,0 +1,1197 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/mac.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysproto.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+
+#include <ufs/ufs/extattr.h>
+#include <ufs/ufs/quota.h>
+#include <ufs/ufs/ufsmount.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+#ifndef __alpha__
+int
+linux_creat(struct thread *td, struct linux_creat_args *args)
+{
+ struct open_args /* {
+ char *path;
+ int flags;
+ int mode;
+ } */ bsd_open_args;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(creat))
+ printf(ARGS(creat, "%s, %d"), args->path, args->mode);
+#endif
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+ bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
+ return open(td, &bsd_open_args);
+}
+#endif /*!__alpha__*/
+
+int
+linux_open(struct thread *td, struct linux_open_args *args)
+{
+ struct open_args /* {
+ char *path;
+ int flags;
+ int mode;
+ } */ bsd_open_args;
+ struct proc *p = td->td_proc;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+
+ if (args->flags & LINUX_O_CREAT)
+ CHECKALTCREAT(td, &sg, args->path);
+ else
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(open))
+ printf(ARGS(open, "%s, 0x%x, 0x%x"),
+ args->path, args->flags, args->mode);
+#endif
+ bsd_open_args.flags = 0;
+ if (args->flags & LINUX_O_RDONLY)
+ bsd_open_args.flags |= O_RDONLY;
+ if (args->flags & LINUX_O_WRONLY)
+ bsd_open_args.flags |= O_WRONLY;
+ if (args->flags & LINUX_O_RDWR)
+ bsd_open_args.flags |= O_RDWR;
+ if (args->flags & LINUX_O_NDELAY)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_O_APPEND)
+ bsd_open_args.flags |= O_APPEND;
+ if (args->flags & LINUX_O_SYNC)
+ bsd_open_args.flags |= O_FSYNC;
+ if (args->flags & LINUX_O_NONBLOCK)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_FASYNC)
+ bsd_open_args.flags |= O_ASYNC;
+ if (args->flags & LINUX_O_CREAT)
+ bsd_open_args.flags |= O_CREAT;
+ if (args->flags & LINUX_O_TRUNC)
+ bsd_open_args.flags |= O_TRUNC;
+ if (args->flags & LINUX_O_EXCL)
+ bsd_open_args.flags |= O_EXCL;
+ if (args->flags & LINUX_O_NOCTTY)
+ bsd_open_args.flags |= O_NOCTTY;
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+
+ error = open(td, &bsd_open_args);
+ PROC_LOCK(p);
+ if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct file *fp;
+
+ error = fget(td, td->td_retval[0], &fp);
+ PROC_UNLOCK(p);
+ if (!error) {
+ if (fp->f_type == DTYPE_VNODE)
+ fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
+ fdrop(fp, td);
+ }
+ } else {
+ PROC_UNLOCK(p);
+#ifdef DEBUG
+ if (ldebug(open))
+ printf(LMSG("open returns error %d"), error);
+#endif
+ }
+ return error;
+}
+
+int
+linux_lseek(struct thread *td, struct linux_lseek_args *args)
+{
+
+ struct lseek_args /* {
+ int fd;
+ int pad;
+ off_t offset;
+ int whence;
+ } */ tmp_args;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(lseek))
+ printf(ARGS(lseek, "%d, %ld, %d"),
+ args->fdes, (long)args->off, args->whence);
+#endif
+ tmp_args.fd = args->fdes;
+ tmp_args.offset = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = lseek(td, &tmp_args);
+ return error;
+}
+
+#ifndef __alpha__
+int
+linux_llseek(struct thread *td, struct linux_llseek_args *args)
+{
+ struct lseek_args bsd_args;
+ int error;
+ off_t off;
+
+#ifdef DEBUG
+ if (ldebug(llseek))
+ printf(ARGS(llseek, "%d, %d:%d, %d"),
+ args->fd, args->ohigh, args->olow, args->whence);
+#endif
+ off = (args->olow) | (((off_t) args->ohigh) << 32);
+
+ bsd_args.fd = args->fd;
+ bsd_args.offset = off;
+ bsd_args.whence = args->whence;
+
+ if ((error = lseek(td, &bsd_args)))
+ return error;
+
+ if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t))))
+ return error;
+
+ td->td_retval[0] = 0;
+ return 0;
+}
+#endif /*!__alpha__*/
+
+#ifndef __alpha__
+int
+linux_readdir(struct thread *td, struct linux_readdir_args *args)
+{
+ struct linux_getdents_args lda;
+
+ lda.fd = args->fd;
+ lda.dent = args->dent;
+ lda.count = 1;
+ return linux_getdents(td, &lda);
+}
+#endif /*!__alpha__*/
+
+/*
+ * Note that linux_getdents(2) and linux_getdents64(2) have the same
+ * arguments. They only differ in the definition of struct dirent they
+ * operate on. We use this to common the code, with the exception of
+ * accessing struct dirent. Note that linux_readdir(2) is implemented
+ * by means of linux_getdents(2). In this case we never operate on
+ * struct dirent64 and thus don't need to handle it...
+ */
+
+struct l_dirent {
+ l_long d_ino;
+ l_off_t d_off;
+ l_ushort d_reclen;
+ char d_name[LINUX_NAME_MAX + 1];
+};
+
+struct l_dirent64 {
+ uint64_t d_ino;
+ int64_t d_off;
+ l_ushort d_reclen;
+ u_char d_type;
+ char d_name[LINUX_NAME_MAX + 1];
+};
+
+#define LINUX_RECLEN(de,namlen) \
+ ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
+
+#define LINUX_DIRBLKSIZ 512
+
+static int
+getdents_common(struct thread *td, struct linux_getdents64_args *args,
+ int is64bit)
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct l_dirent linux_dirent;
+ struct l_dirent64 linux_dirent64;
+ int buflen, error, eofflag, nbytes, justone;
+ u_long *cookies = NULL, *cookiep;
+ int ncookies;
+
+ if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ vp = (struct vnode *) fp->f_data;
+ if (vp->v_type != VDIR) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) {
+ fdrop(fp, td);
+ return (error);
+ }
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ /* readdir(2) case. Always struct dirent. */
+ if (is64bit) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ nbytes = sizeof(linux_dirent);
+ justone = 1;
+ } else
+ justone = 0;
+
+ off = fp->f_offset;
+
+ buflen = max(LINUX_DIRBLKSIZ, nbytes);
+ buflen = min(buflen, MAXBSIZE);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+ if (cookies) {
+ free(cookies, M_TEMP);
+ cookies = NULL;
+ }
+
+#ifdef MAC
+ /*
+ * Do directory search MAC check using non-cached credentials.
+ */
+ if ((error = mac_check_vnode_readdir(td->td_proc->p_ucred, vp))
+ goto out;
+#endif /* MAC */
+ if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
+ &cookies)))
+ goto out;
+
+ inp = buf;
+ outp = (caddr_t)args->dirent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) <= 0)
+ goto eof;
+
+ cookiep = cookies;
+
+ if (cookies) {
+ /*
+ * When using cookies, the vfs has the option of reading from
+ * a different offset than that supplied (UFS truncates the
+ * offset to a block boundary to make sure that it never reads
+ * partway through a directory entry, even if the directory
+ * has been compacted).
+ */
+ while (len > 0 && ncookies > 0 && *cookiep <= off) {
+ bdp = (struct dirent *) inp;
+ len -= bdp->d_reclen;
+ inp += bdp->d_reclen;
+ cookiep++;
+ ncookies--;
+ }
+ }
+
+ while (len > 0) {
+ if (cookiep && ncookies == 0)
+ break;
+ bdp = (struct dirent *) inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3) {
+ error = EFAULT;
+ goto out;
+ }
+
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+
+ len -= reclen;
+ continue;
+ }
+
+ linuxreclen = (is64bit)
+ ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
+ : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
+
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+
+ if (justone) {
+ /* readdir(2) case. */
+ linux_dirent.d_ino = (l_long)bdp->d_fileno;
+ linux_dirent.d_off = (l_off_t)linuxreclen;
+ linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
+ strcpy(linux_dirent.d_name, bdp->d_name);
+ error = copyout(&linux_dirent, outp, linuxreclen);
+ } else {
+ if (is64bit) {
+ linux_dirent64.d_ino = bdp->d_fileno;
+ linux_dirent64.d_off = (cookiep)
+ ? (l_off_t)*cookiep
+ : (l_off_t)(off + reclen);
+ linux_dirent64.d_reclen =
+ (l_ushort)linuxreclen;
+ linux_dirent64.d_type = bdp->d_type;
+ strcpy(linux_dirent64.d_name, bdp->d_name);
+ error = copyout(&linux_dirent64, outp,
+ linuxreclen);
+ } else {
+ linux_dirent.d_ino = bdp->d_fileno;
+ linux_dirent.d_off = (cookiep)
+ ? (l_off_t)*cookiep
+ : (l_off_t)(off + reclen);
+ linux_dirent.d_reclen = (l_ushort)linuxreclen;
+ strcpy(linux_dirent.d_name, bdp->d_name);
+ error = copyout(&linux_dirent, outp,
+ linuxreclen);
+ }
+ }
+ if (error)
+ goto out;
+
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t)args->dirent)
+ goto again;
+
+ fp->f_offset = off;
+ if (justone)
+ nbytes = resid + linuxreclen;
+
+eof:
+ td->td_retval[0] = nbytes - resid;
+
+out:
+ if (cookies)
+ free(cookies, M_TEMP);
+
+ VOP_UNLOCK(vp, 0, td);
+ fdrop(fp, td);
+ free(buf, M_TEMP);
+ return (error);
+}
+
+int
+linux_getdents(struct thread *td, struct linux_getdents_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getdents))
+ printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count);
+#endif
+
+ return (getdents_common(td, (struct linux_getdents64_args*)args, 0));
+}
+
+int
+linux_getdents64(struct thread *td, struct linux_getdents64_args *args)
+{
+
+#ifdef DEBUG
+ if (ldebug(getdents64))
+ printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count);
+#endif
+
+ return (getdents_common(td, args, 1));
+}
+
+/*
+ * These exist mainly for hooks for doing /compat/linux translation.
+ */
+
+int
+linux_access(struct thread *td, struct linux_access_args *args)
+{
+ struct access_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(access))
+ printf(ARGS(access, "%s, %d"), args->path, args->flags);
+#endif
+ bsd.path = args->path;
+ bsd.flags = args->flags;
+
+ return access(td, &bsd);
+}
+
+int
+linux_unlink(struct thread *td, struct linux_unlink_args *args)
+{
+ struct unlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(unlink))
+ printf(ARGS(unlink, "%s"), args->path);
+#endif
+ bsd.path = args->path;
+
+ return unlink(td, &bsd);
+}
+
+int
+linux_chdir(struct thread *td, struct linux_chdir_args *args)
+{
+ struct chdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(chdir))
+ printf(ARGS(chdir, "%s"), args->path);
+#endif
+ bsd.path = args->path;
+
+ return chdir(td, &bsd);
+}
+
+int
+linux_chmod(struct thread *td, struct linux_chmod_args *args)
+{
+ struct chmod_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(chmod))
+ printf(ARGS(chmod, "%s, %d"), args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return chmod(td, &bsd);
+}
+
+int
+linux_mkdir(struct thread *td, struct linux_mkdir_args *args)
+{
+ struct mkdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(mkdir))
+ printf(ARGS(mkdir, "%s, %d"), args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return mkdir(td, &bsd);
+}
+
+int
+linux_rmdir(struct thread *td, struct linux_rmdir_args *args)
+{
+ struct rmdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(rmdir))
+ printf(ARGS(rmdir, "%s"), args->path);
+#endif
+ bsd.path = args->path;
+
+ return rmdir(td, &bsd);
+}
+
+int
+linux_rename(struct thread *td, struct linux_rename_args *args)
+{
+ struct rename_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->from);
+ CHECKALTCREAT(td, &sg, args->to);
+
+#ifdef DEBUG
+ if (ldebug(rename))
+ printf(ARGS(rename, "%s, %s"), args->from, args->to);
+#endif
+ bsd.from = args->from;
+ bsd.to = args->to;
+
+ return rename(td, &bsd);
+}
+
+int
+linux_symlink(struct thread *td, struct linux_symlink_args *args)
+{
+ struct symlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+ CHECKALTCREAT(td, &sg, args->to);
+
+#ifdef DEBUG
+ if (ldebug(symlink))
+ printf(ARGS(symlink, "%s, %s"), args->path, args->to);
+#endif
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return symlink(td, &bsd);
+}
+
+int
+linux_readlink(struct thread *td, struct linux_readlink_args *args)
+{
+ struct readlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->name);
+
+#ifdef DEBUG
+ if (ldebug(readlink))
+ printf(ARGS(readlink, "%s, %p, %d"),
+ args->name, (void *)args->buf, args->count);
+#endif
+ bsd.path = args->name;
+ bsd.buf = args->buf;
+ bsd.count = args->count;
+
+ return readlink(td, &bsd);
+}
+
+int
+linux_truncate(struct thread *td, struct linux_truncate_args *args)
+{
+ struct truncate_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(truncate))
+ printf(ARGS(truncate, "%s, %ld"), args->path,
+ (long)args->length);
+#endif
+ bsd.path = args->path;
+ bsd.length = args->length;
+
+ return truncate(td, &bsd);
+}
+
+int
+linux_link(struct thread *td, struct linux_link_args *args)
+{
+ struct link_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+ CHECKALTCREAT(td, &sg, args->to);
+
+#ifdef DEBUG
+ if (ldebug(link))
+ printf(ARGS(link, "%s, %s"), args->path, args->to);
+#endif
+
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return link(td, &bsd);
+}
+
+#ifndef __alpha__
+int
+linux_fdatasync(td, uap)
+ struct thread *td;
+ struct linux_fdatasync_args *uap;
+{
+ struct fsync_args bsd;
+
+ bsd.fd = uap->fd;
+ return fsync(td, &bsd);
+}
+#endif /*!__alpha__*/
+
+int
+linux_pread(td, uap)
+ struct thread *td;
+ struct linux_pread_args *uap;
+{
+ struct pread_args bsd;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+ return pread(td, &bsd);
+}
+
+int
+linux_pwrite(td, uap)
+ struct thread *td;
+ struct linux_pwrite_args *uap;
+{
+ struct pwrite_args bsd;
+
+ bsd.fd = uap->fd;
+ bsd.buf = uap->buf;
+ bsd.nbyte = uap->nbyte;
+ bsd.offset = uap->offset;
+ return pwrite(td, &bsd);
+}
+
+int
+linux_mount(struct thread *td, struct linux_mount_args *args)
+{
+ struct ufs_args ufs;
+ char fstypename[MFSNAMELEN];
+ char mntonname[MNAMELEN], mntfromname[MNAMELEN];
+ int error;
+ int fsflags;
+ const char *fstype;
+ void *fsdata;
+
+ error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
+ NULL);
+ if (error)
+ return (error);
+ error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL);
+ if (error)
+ return (error);
+ error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL);
+ if (error)
+ return (error);
+
+#ifdef DEBUG
+ if (ldebug(mount))
+ printf(ARGS(mount, "%s, %s, %s"),
+ fstypename, mntfromname, mntonname);
+#endif
+
+ if (strcmp(fstypename, "ext2") == 0) {
+ fstype = "ext2fs";
+ fsdata = &ufs;
+ ufs.fspec = mntfromname;
+#define DEFAULT_ROOTID -2
+ ufs.export.ex_root = DEFAULT_ROOTID;
+ ufs.export.ex_flags =
+ args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0;
+ } else if (strcmp(fstypename, "proc") == 0) {
+ fstype = "linprocfs";
+ fsdata = NULL;
+ } else {
+ return (ENODEV);
+ }
+
+ fsflags = 0;
+
+ if ((args->rwflag & 0xffff0000) == 0xc0ed0000) {
+ /*
+ * Linux SYNC flag is not included; the closest equivalent
+ * FreeBSD has is !ASYNC, which is our default.
+ */
+ if (args->rwflag & LINUX_MS_RDONLY)
+ fsflags |= MNT_RDONLY;
+ if (args->rwflag & LINUX_MS_NOSUID)
+ fsflags |= MNT_NOSUID;
+ if (args->rwflag & LINUX_MS_NODEV)
+ fsflags |= MNT_NODEV;
+ if (args->rwflag & LINUX_MS_NOEXEC)
+ fsflags |= MNT_NOEXEC;
+ if (args->rwflag & LINUX_MS_REMOUNT)
+ fsflags |= MNT_UPDATE;
+ }
+
+ return (vfs_mount(td, fstype, mntonname, fsflags, fsdata));
+}
+
+int
+linux_oldumount(struct thread *td, struct linux_oldumount_args *args)
+{
+ struct linux_umount_args args2;
+
+ args2.path = args->path;
+ args2.flags = 0;
+ return (linux_umount(td, &args2));
+}
+
+int
+linux_umount(struct thread *td, struct linux_umount_args *args)
+{
+ struct unmount_args bsd;
+
+ bsd.path = args->path;
+ bsd.flags = args->flags; /* XXX correct? */
+ return (unmount(td, &bsd));
+}
+
+/*
+ * fcntl family of syscalls
+ */
+
+struct l_flock {
+ l_short l_type;
+ l_short l_whence;
+ l_off_t l_start;
+ l_off_t l_len;
+ l_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ default:
+ bsd_flock->l_type = -1;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (l_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (l_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
+}
+
+#if defined(__i386__)
+struct l_flock64 {
+ l_short l_type;
+ l_short l_whence;
+ l_loff_t l_start;
+ l_loff_t l_len;
+ l_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ default:
+ bsd_flock->l_type = -1;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (l_loff_t)bsd_flock->l_start;
+ linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
+ linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
+}
+#endif /* __i386__ */
+
+#if defined(__alpha__)
+#define linux_fcntl64_args linux_fcntl_args
+#endif
+
+static int
+fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
+{
+ struct fcntl_args fcntl_args;
+ struct file *fp;
+ int error, result;
+
+ fcntl_args.fd = args->fd;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ fcntl_args.cmd = F_DUPFD;
+ fcntl_args.arg = args->arg;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_GETFD:
+ fcntl_args.cmd = F_GETFD;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_SETFD:
+ fcntl_args.cmd = F_SETFD;
+ fcntl_args.arg = args->arg;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_GETFL:
+ fcntl_args.cmd = F_GETFL;
+ error = fcntl(td, &fcntl_args);
+ result = td->td_retval[0];
+ td->td_retval[0] = 0;
+ if (result & O_RDONLY)
+ td->td_retval[0] |= LINUX_O_RDONLY;
+ if (result & O_WRONLY)
+ td->td_retval[0] |= LINUX_O_WRONLY;
+ if (result & O_RDWR)
+ td->td_retval[0] |= LINUX_O_RDWR;
+ if (result & O_NDELAY)
+ td->td_retval[0] |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND)
+ td->td_retval[0] |= LINUX_O_APPEND;
+ if (result & O_FSYNC)
+ td->td_retval[0] |= LINUX_O_SYNC;
+ if (result & O_ASYNC)
+ td->td_retval[0] |= LINUX_FASYNC;
+ return (error);
+
+ case LINUX_F_SETFL:
+ fcntl_args.arg = 0;
+ if (args->arg & LINUX_O_NDELAY)
+ fcntl_args.arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND)
+ fcntl_args.arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC)
+ fcntl_args.arg |= O_FSYNC;
+ if (args->arg & LINUX_FASYNC)
+ fcntl_args.arg |= O_ASYNC;
+ fcntl_args.cmd = F_SETFL;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_GETOWN:
+ fcntl_args.cmd = F_GETOWN;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_SETOWN:
+ /*
+ * XXX some Linux applications depend on F_SETOWN having no
+ * significant effect for pipes (SIGIO is not delivered for
+ * pipes under Linux-2.2.35 at least).
+ */
+ error = fget(td, args->fd, &fp);
+ if (error)
+ return (error);
+ if (fp->f_type == DTYPE_PIPE) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ fdrop(fp, td);
+
+ fcntl_args.cmd = F_SETOWN;
+ fcntl_args.arg = args->arg;
+ return (fcntl(td, &fcntl_args));
+ }
+
+ return (EINVAL);
+}
+
+int
+linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
+{
+ struct linux_fcntl64_args args64;
+ struct fcntl_args fcntl_args;
+ struct l_flock linux_flock;
+ struct flock *bsd_flock;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
+
+#ifdef DEBUG
+ if (ldebug(fcntl))
+ printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
+#endif
+
+ switch (args->cmd) {
+ case LINUX_F_GETLK:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (long)bsd_flock;
+ error = fcntl(td, &fcntl_args);
+ if (error)
+ return (error);
+ bsd_to_linux_flock(bsd_flock, &linux_flock);
+ return (copyout(&linux_flock, (caddr_t)args->arg,
+ sizeof(linux_flock)));
+
+ case LINUX_F_SETLK:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (long)bsd_flock;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_SETLKW:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (long)bsd_flock;
+ return (fcntl(td, &fcntl_args));
+ }
+
+ args64.fd = args->fd;
+ args64.cmd = args->cmd;
+ args64.arg = args->arg;
+ return (fcntl_common(td, &args64));
+}
+
+#if defined(__i386__)
+int
+linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
+{
+ struct fcntl_args fcntl_args;
+ struct l_flock64 linux_flock;
+ struct flock *bsd_flock;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock));
+
+#ifdef DEBUG
+ if (ldebug(fcntl64))
+ printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd);
+#endif
+
+ switch (args->cmd) {
+ case LINUX_F_GETLK:
+ case LINUX_F_GETLK64:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (long)bsd_flock;
+ error = fcntl(td, &fcntl_args);
+ if (error)
+ return (error);
+ bsd_to_linux_flock64(bsd_flock, &linux_flock);
+ return (copyout(&linux_flock, (caddr_t)args->arg,
+ sizeof(linux_flock)));
+
+ case LINUX_F_SETLK:
+ case LINUX_F_SETLK64:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (long)bsd_flock;
+ return (fcntl(td, &fcntl_args));
+
+ case LINUX_F_SETLKW:
+ case LINUX_F_SETLKW64:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock64(&linux_flock, bsd_flock);
+ fcntl_args.fd = args->fd;
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (long)bsd_flock;
+ return (fcntl(td, &fcntl_args));
+ }
+
+ return (fcntl_common(td, args));
+}
+#endif /* __i386__ */
+
+int
+linux_chown(struct thread *td, struct linux_chown_args *args)
+{
+ struct chown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(chown))
+ printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid,
+ args->gid);
+#endif
+
+ bsd.path = args->path;
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+ return (chown(td, &bsd));
+}
+
+int
+linux_lchown(struct thread *td, struct linux_lchown_args *args)
+{
+ struct lchown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(lchown))
+ printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid,
+ args->gid);
+#endif
+
+ bsd.path = args->path;
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+ return (lchown(td, &bsd));
+}
diff --git a/sys/compat/linux/linux_getcwd.c b/sys/compat/linux/linux_getcwd.c
new file mode 100644
index 0000000..2773562
--- /dev/null
+++ b/sys/compat/linux/linux_getcwd.c
@@ -0,0 +1,473 @@
+/* $FreeBSD$ */
+/* $OpenBSD: linux_getcwd.c,v 1.2 2001/05/16 12:50:21 ho Exp $ */
+/* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bill Sommerfeld.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "opt_compat.h"
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/namei.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/mac.h>
+#include <sys/malloc.h>
+#include <sys/dirent.h>
+#include <ufs/ufs/dir.h> /* XXX only for DIRBLKSIZ */
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+static int
+linux_getcwd_scandir(struct vnode **, struct vnode **,
+ char **, char *, struct thread *);
+static int
+linux_getcwd_common(struct vnode *, struct vnode *,
+ char **, char *, int, int, struct thread *);
+
+#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
+
+/*
+ * Vnode variable naming conventions in this file:
+ *
+ * rvp: the current root we're aiming towards.
+ * lvp, *lvpp: the "lower" vnode
+ * uvp, *uvpp: the "upper" vnode.
+ *
+ * Since all the vnodes we're dealing with are directories, and the
+ * lookups are going *up* in the filesystem rather than *down*, the
+ * usual "pvp" (parent) or "dvp" (directory) naming conventions are
+ * too confusing.
+ */
+
+/*
+ * XXX Will infinite loop in certain cases if a directory read reliably
+ * returns EINVAL on last block.
+ * XXX is EINVAL the right thing to return if a directory is malformed?
+ */
+
+/*
+ * XXX Untested vs. mount -o union; probably does the wrong thing.
+ */
+
+/*
+ * Find parent vnode of *lvpp, return in *uvpp
+ *
+ * If we care about the name, scan it looking for name of directory
+ * entry pointing at lvp.
+ *
+ * Place the name in the buffer which starts at bufp, immediately
+ * before *bpp, and move bpp backwards to point at the start of it.
+ *
+ * On entry, *lvpp is a locked vnode reference; on exit, it is vput and NULL'ed
+ * On exit, *uvpp is either NULL or is a locked vnode reference.
+ */
+static int
+linux_getcwd_scandir(lvpp, uvpp, bpp, bufp, td)
+ struct vnode **lvpp;
+ struct vnode **uvpp;
+ char **bpp;
+ char *bufp;
+ struct thread *td;
+{
+ int error = 0;
+ int eofflag;
+ off_t off;
+ int tries;
+ struct uio uio;
+ struct iovec iov;
+ char *dirbuf = NULL;
+ int dirbuflen;
+ ino_t fileno;
+ struct vattr va;
+ struct vnode *uvp = NULL;
+ struct vnode *lvp = *lvpp;
+ struct componentname cn;
+ int len, reclen;
+ tries = 0;
+
+ /*
+ * If we want the filename, get some info we need while the
+ * current directory is still locked.
+ */
+ if (bufp != NULL) {
+ error = VOP_GETATTR(lvp, &va, td->td_ucred, td);
+ if (error) {
+ vput(lvp);
+ *lvpp = NULL;
+ *uvpp = NULL;
+ return error;
+ }
+ }
+
+ /*
+ * Ok, we have to do it the hard way..
+ * Next, get parent vnode using lookup of ..
+ */
+ cn.cn_nameiop = LOOKUP;
+ cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY;
+ cn.cn_thread = td;
+ cn.cn_cred = td->td_ucred;
+ cn.cn_pnbuf = NULL;
+ cn.cn_nameptr = "..";
+ cn.cn_namelen = 2;
+ cn.cn_consume = 0;
+
+ /*
+ * At this point, lvp is locked and will be unlocked by the lookup.
+ * On successful return, *uvpp will be locked
+ */
+ error = VOP_LOOKUP(lvp, uvpp, &cn);
+ if (error) {
+ vput(lvp);
+ *lvpp = NULL;
+ *uvpp = NULL;
+ return error;
+ }
+ uvp = *uvpp;
+
+ /* If we don't care about the pathname, we're done */
+ if (bufp == NULL) {
+ vrele(lvp);
+ *lvpp = NULL;
+ return 0;
+ }
+
+ fileno = va.va_fileid;
+
+ dirbuflen = DIRBLKSIZ;
+ if (dirbuflen < va.va_blocksize)
+ dirbuflen = va.va_blocksize;
+ dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
+
+#if 0
+unionread:
+#endif
+ off = 0;
+ do {
+ /* call VOP_READDIR of parent */
+ iov.iov_base = dirbuf;
+ iov.iov_len = dirbuflen;
+
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = off;
+ uio.uio_resid = dirbuflen;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+
+ eofflag = 0;
+
+#ifdef MAC
+ error = mac_check_vnode_readdir(td->td_ucred, uvp);
+ if (error == 0)
+#endif /* MAC */
+ error = VOP_READDIR(uvp, &uio, td->td_ucred, &eofflag,
+ 0, 0);
+
+ off = uio.uio_offset;
+
+ /*
+ * Try again if NFS tosses its cookies.
+ * XXX this can still loop forever if the directory is busted
+ * such that the second or subsequent page of it always
+ * returns EINVAL
+ */
+ if ((error == EINVAL) && (tries < 3)) {
+ off = 0;
+ tries++;
+ continue; /* once more, with feeling */
+ }
+
+ if (!error) {
+ char *cpos;
+ struct dirent *dp;
+
+ cpos = dirbuf;
+ tries = 0;
+
+ /* scan directory page looking for matching vnode */
+ for (len = (dirbuflen - uio.uio_resid); len > 0; len -= reclen) {
+ dp = (struct dirent *) cpos;
+ reclen = dp->d_reclen;
+
+ /* check for malformed directory.. */
+ if (reclen < DIRENT_MINSIZE) {
+ error = EINVAL;
+ goto out;
+ }
+ /*
+ * XXX should perhaps do VOP_LOOKUP to
+ * check that we got back to the right place,
+ * but getting the locking games for that
+ * right would be heinous.
+ */
+ if ((dp->d_type != DT_WHT) &&
+ (dp->d_fileno == fileno)) {
+ char *bp = *bpp;
+ bp -= dp->d_namlen;
+
+ if (bp <= bufp) {
+ error = ERANGE;
+ goto out;
+ }
+ bcopy(dp->d_name, bp, dp->d_namlen);
+ error = 0;
+ *bpp = bp;
+ goto out;
+ }
+ cpos += reclen;
+ }
+ }
+ } while (!eofflag);
+ error = ENOENT;
+
+out:
+ vrele(lvp);
+ *lvpp = NULL;
+ free(dirbuf, M_TEMP);
+ return error;
+}
+
+
+/*
+ * common routine shared by sys___getcwd() and linux_vn_isunder()
+ */
+
+#define GETCWD_CHECK_ACCESS 0x0001
+
+static int
+linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td)
+ struct vnode *lvp;
+ struct vnode *rvp;
+ char **bpp;
+ char *bufp;
+ int limit;
+ int flags;
+ struct thread *td;
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ struct vnode *uvp = NULL;
+ char *bp = NULL;
+ int error;
+ int perms = VEXEC;
+
+ if (rvp == NULL) {
+ rvp = fdp->fd_rdir;
+ if (rvp == NULL)
+ rvp = rootvnode;
+ }
+
+ VREF(rvp);
+ VREF(lvp);
+
+ /*
+ * Error handling invariant:
+ * Before a `goto out':
+ * lvp is either NULL, or locked and held.
+ * uvp is either NULL, or locked and held.
+ */
+
+ error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+ if (error) {
+ vrele(lvp);
+ lvp = NULL;
+ goto out;
+ }
+ if (bufp)
+ bp = *bpp;
+ /*
+ * this loop will terminate when one of the following happens:
+ * - we hit the root
+ * - getdirentries or lookup fails
+ * - we run out of space in the buffer.
+ */
+ if (lvp == rvp) {
+ if (bp)
+ *(--bp) = '/';
+ goto out;
+ }
+ do {
+ if (lvp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ }
+
+ /*
+ * access check here is optional, depending on
+ * whether or not caller cares.
+ */
+ if (flags & GETCWD_CHECK_ACCESS) {
+ error = VOP_ACCESS(lvp, perms, td->td_ucred, td);
+ if (error)
+ goto out;
+ perms = VEXEC|VREAD;
+ }
+
+ /*
+ * step up if we're a covered vnode..
+ */
+ while (lvp->v_vflag & VV_ROOT) {
+ struct vnode *tvp;
+
+ if (lvp == rvp)
+ goto out;
+
+ tvp = lvp;
+ lvp = lvp->v_mount->mnt_vnodecovered;
+ vput(tvp);
+ /*
+ * hodie natus est radici frater
+ */
+ if (lvp == NULL) {
+ error = ENOENT;
+ goto out;
+ }
+ VREF(lvp);
+ error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+ if (error != 0) {
+ vrele(lvp);
+ lvp = NULL;
+ goto out;
+ }
+ }
+ error = linux_getcwd_scandir(&lvp, &uvp, &bp, bufp, td);
+ if (error)
+ goto out;
+#if DIAGNOSTIC
+ if (lvp != NULL)
+ panic("getcwd: oops, forgot to null lvp");
+ if (bufp && (bp <= bufp)) {
+ panic("getcwd: oops, went back too far");
+ }
+#endif
+ if (bp)
+ *(--bp) = '/';
+ lvp = uvp;
+ uvp = NULL;
+ limit--;
+ } while ((lvp != rvp) && (limit > 0));
+
+out:
+ if (bpp)
+ *bpp = bp;
+ if (uvp)
+ vput(uvp);
+ if (lvp)
+ vput(lvp);
+ vrele(rvp);
+ return error;
+}
+
+
+/*
+ * Find pathname of process's current directory.
+ *
+ * Use vfs vnode-to-name reverse cache; if that fails, fall back
+ * to reading directory contents.
+ */
+
+int
+linux_getcwd(struct thread *td, struct linux_getcwd_args *args)
+{
+ struct __getcwd_args bsd;
+ caddr_t sg, bp, bend, path;
+ int error, len, lenused;
+
+#ifdef DEBUG
+ printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)td->td_proc->p_pid,
+ args->buf, (long)args->bufsize);
+#endif
+
+ sg = stackgap_init();
+ bsd.buf = stackgap_alloc(&sg, SPARE_USRSPACE);
+ bsd.buflen = SPARE_USRSPACE;
+ error = __getcwd(td, &bsd);
+ if (!error) {
+ lenused = strlen(bsd.buf) + 1;
+ if (lenused <= args->bufsize) {
+ td->td_retval[0] = lenused;
+ error = copyout(bsd.buf, args->buf, lenused);
+ }
+ else
+ error = ERANGE;
+ } else {
+ len = args->bufsize;
+
+ if (len > MAXPATHLEN*4)
+ len = MAXPATHLEN*4;
+ else if (len < 2)
+ return ERANGE;
+
+ path = (char *)malloc(len, M_TEMP, M_WAITOK);
+
+ bp = &path[len];
+ bend = bp;
+ *(--bp) = '\0';
+
+ /*
+ * 5th argument here is "max number of vnodes to traverse".
+ * Since each entry takes up at least 2 bytes in the output buffer,
+ * limit it to N/2 vnodes for an N byte buffer.
+ */
+
+ error = linux_getcwd_common (td->td_proc->p_fd->fd_cdir, NULL,
+ &bp, path, len/2, GETCWD_CHECK_ACCESS, td);
+
+ if (error)
+ goto out;
+ lenused = bend - bp;
+ td->td_retval[0] = lenused;
+ /* put the result into user buffer */
+ error = copyout(bp, args->buf, lenused);
+
+out:
+ free(path, M_TEMP);
+ }
+ return (error);
+}
+
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
new file mode 100644
index 0000000..77e2942
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.c
@@ -0,0 +1,2379 @@
+/*
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/cdio.h>
+#include <sys/dvdio.h>
+#include <sys/consio.h>
+#include <sys/ctype.h>
+#include <sys/disklabel.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/filio.h>
+#include <sys/kbio.h>
+#include <sys/linker_set.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/soundcard.h>
+#include <sys/tty.h>
+#include <sys/uio.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_util.h>
+
+static linux_ioctl_function_t linux_ioctl_cdrom;
+static linux_ioctl_function_t linux_ioctl_console;
+static linux_ioctl_function_t linux_ioctl_disk;
+static linux_ioctl_function_t linux_ioctl_socket;
+static linux_ioctl_function_t linux_ioctl_sound;
+static linux_ioctl_function_t linux_ioctl_termio;
+static linux_ioctl_function_t linux_ioctl_private;
+static linux_ioctl_function_t linux_ioctl_special;
+
+static struct linux_ioctl_handler cdrom_handler =
+{ linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX };
+static struct linux_ioctl_handler console_handler =
+{ linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX };
+static struct linux_ioctl_handler disk_handler =
+{ linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX };
+static struct linux_ioctl_handler socket_handler =
+{ linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX };
+static struct linux_ioctl_handler sound_handler =
+{ linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX };
+static struct linux_ioctl_handler termio_handler =
+{ linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX };
+static struct linux_ioctl_handler private_handler =
+{ linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
+
+DATA_SET(linux_ioctl_handler_set, cdrom_handler);
+DATA_SET(linux_ioctl_handler_set, console_handler);
+DATA_SET(linux_ioctl_handler_set, disk_handler);
+DATA_SET(linux_ioctl_handler_set, socket_handler);
+DATA_SET(linux_ioctl_handler_set, sound_handler);
+DATA_SET(linux_ioctl_handler_set, termio_handler);
+DATA_SET(linux_ioctl_handler_set, private_handler);
+
+struct handler_element
+{
+ TAILQ_ENTRY(handler_element) list;
+ int (*func)(struct thread *, struct linux_ioctl_args *);
+ int low, high, span;
+};
+
+static TAILQ_HEAD(, handler_element) handlers =
+ TAILQ_HEAD_INITIALIZER(handlers);
+
+static int
+linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+ struct disklabel dl;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+ case LINUX_BLKGETSIZE:
+ error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, td);
+ fdrop(fp, td);
+ if (error)
+ return (error);
+ return (copyout(&(dl.d_secperunit), (caddr_t)args->arg,
+ sizeof(dl.d_secperunit)));
+ }
+ fdrop(fp, td);
+ return (ENOIOCTL);
+}
+
+/*
+ * termio related ioctls
+ */
+
+struct linux_termio {
+ unsigned short c_iflag;
+ unsigned short c_oflag;
+ unsigned short c_cflag;
+ unsigned short c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCC];
+};
+
+struct linux_termios {
+ unsigned int c_iflag;
+ unsigned int c_oflag;
+ unsigned int c_cflag;
+ unsigned int c_lflag;
+#ifdef __alpha__
+ unsigned char c_cc[LINUX_NCCS];
+ unsigned char c_line;
+ unsigned int c_ispeed;
+ unsigned int c_ospeed;
+#else
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCCS];
+#endif
+};
+
+struct linux_winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+
+static struct speedtab sptab[] = {
+ { B0, LINUX_B0 }, { B50, LINUX_B50 },
+ { B75, LINUX_B75 }, { B110, LINUX_B110 },
+ { B134, LINUX_B134 }, { B150, LINUX_B150 },
+ { B200, LINUX_B200 }, { B300, LINUX_B300 },
+ { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
+ { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
+ { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
+ { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
+ { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
+ {-1, -1 }
+};
+
+struct linux_serial_struct {
+ int type;
+ int line;
+ int port;
+ int irq;
+ int flags;
+ int xmit_fifo_size;
+ int custom_divisor;
+ int baud_base;
+ unsigned short close_delay;
+ char reserved_char[2];
+ int hub6;
+ unsigned short closing_wait;
+ unsigned short closing_wait2;
+ int reserved[4];
+};
+
+static int
+linux_to_bsd_speed(int code, struct speedtab *table)
+{
+ for ( ; table->sp_code != -1; table++)
+ if (table->sp_code == code)
+ return (table->sp_speed);
+ return -1;
+}
+
+static int
+bsd_to_linux_speed(int speed, struct speedtab *table)
+{
+ for ( ; table->sp_speed != -1; table++)
+ if (table->sp_speed == speed)
+ return (table->sp_code);
+ return -1;
+}
+
+static void
+bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
+{
+ int i;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: BSD termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
+ bios->c_ispeed, bios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+
+ lios->c_iflag = 0;
+ if (bios->c_iflag & IGNBRK)
+ lios->c_iflag |= LINUX_IGNBRK;
+ if (bios->c_iflag & BRKINT)
+ lios->c_iflag |= LINUX_BRKINT;
+ if (bios->c_iflag & IGNPAR)
+ lios->c_iflag |= LINUX_IGNPAR;
+ if (bios->c_iflag & PARMRK)
+ lios->c_iflag |= LINUX_PARMRK;
+ if (bios->c_iflag & INPCK)
+ lios->c_iflag |= LINUX_INPCK;
+ if (bios->c_iflag & ISTRIP)
+ lios->c_iflag |= LINUX_ISTRIP;
+ if (bios->c_iflag & INLCR)
+ lios->c_iflag |= LINUX_INLCR;
+ if (bios->c_iflag & IGNCR)
+ lios->c_iflag |= LINUX_IGNCR;
+ if (bios->c_iflag & ICRNL)
+ lios->c_iflag |= LINUX_ICRNL;
+ if (bios->c_iflag & IXON)
+ lios->c_iflag |= LINUX_IXON;
+ if (bios->c_iflag & IXANY)
+ lios->c_iflag |= LINUX_IXANY;
+ if (bios->c_iflag & IXOFF)
+ lios->c_iflag |= LINUX_IXOFF;
+ if (bios->c_iflag & IMAXBEL)
+ lios->c_iflag |= LINUX_IMAXBEL;
+
+ lios->c_oflag = 0;
+ if (bios->c_oflag & OPOST)
+ lios->c_oflag |= LINUX_OPOST;
+ if (bios->c_oflag & ONLCR)
+ lios->c_oflag |= LINUX_ONLCR;
+ if (bios->c_oflag & OXTABS)
+ lios->c_oflag |= LINUX_XTABS;
+
+ lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
+ lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
+ if (bios->c_cflag & CSTOPB)
+ lios->c_cflag |= LINUX_CSTOPB;
+ if (bios->c_cflag & CREAD)
+ lios->c_cflag |= LINUX_CREAD;
+ if (bios->c_cflag & PARENB)
+ lios->c_cflag |= LINUX_PARENB;
+ if (bios->c_cflag & PARODD)
+ lios->c_cflag |= LINUX_PARODD;
+ if (bios->c_cflag & HUPCL)
+ lios->c_cflag |= LINUX_HUPCL;
+ if (bios->c_cflag & CLOCAL)
+ lios->c_cflag |= LINUX_CLOCAL;
+ if (bios->c_cflag & CRTSCTS)
+ lios->c_cflag |= LINUX_CRTSCTS;
+
+ lios->c_lflag = 0;
+ if (bios->c_lflag & ISIG)
+ lios->c_lflag |= LINUX_ISIG;
+ if (bios->c_lflag & ICANON)
+ lios->c_lflag |= LINUX_ICANON;
+ if (bios->c_lflag & ECHO)
+ lios->c_lflag |= LINUX_ECHO;
+ if (bios->c_lflag & ECHOE)
+ lios->c_lflag |= LINUX_ECHOE;
+ if (bios->c_lflag & ECHOK)
+ lios->c_lflag |= LINUX_ECHOK;
+ if (bios->c_lflag & ECHONL)
+ lios->c_lflag |= LINUX_ECHONL;
+ if (bios->c_lflag & NOFLSH)
+ lios->c_lflag |= LINUX_NOFLSH;
+ if (bios->c_lflag & TOSTOP)
+ lios->c_lflag |= LINUX_TOSTOP;
+ if (bios->c_lflag & ECHOCTL)
+ lios->c_lflag |= LINUX_ECHOCTL;
+ if (bios->c_lflag & ECHOPRT)
+ lios->c_lflag |= LINUX_ECHOPRT;
+ if (bios->c_lflag & ECHOKE)
+ lios->c_lflag |= LINUX_ECHOKE;
+ if (bios->c_lflag & FLUSHO)
+ lios->c_lflag |= LINUX_FLUSHO;
+ if (bios->c_lflag & PENDIN)
+ lios->c_lflag |= LINUX_PENDIN;
+ if (bios->c_lflag & IEXTEN)
+ lios->c_lflag |= LINUX_IEXTEN;
+
+ for (i=0; i<LINUX_NCCS; i++)
+ lios->c_cc[i] = LINUX_POSIX_VDISABLE;
+ lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
+ lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
+ lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
+ lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
+ lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
+ lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
+ lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
+ lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
+ lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
+ lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
+ lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
+ lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
+ lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
+ lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
+ lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
+ lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
+
+ for (i=0; i<LINUX_NCCS; i++) {
+ if (lios->c_cc[i] == _POSIX_VDISABLE)
+ lios->c_cc[i] = LINUX_POSIX_VDISABLE;
+ }
+ lios->c_line = 0;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: LINUX termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ lios->c_iflag, lios->c_oflag, lios->c_cflag,
+ lios->c_lflag, (int)lios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", lios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+}
+
+static void
+linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
+{
+ int i;
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: LINUX termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ lios->c_iflag, lios->c_oflag, lios->c_cflag,
+ lios->c_lflag, (int)lios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", lios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+
+ bios->c_iflag = 0;
+ if (lios->c_iflag & LINUX_IGNBRK)
+ bios->c_iflag |= IGNBRK;
+ if (lios->c_iflag & LINUX_BRKINT)
+ bios->c_iflag |= BRKINT;
+ if (lios->c_iflag & LINUX_IGNPAR)
+ bios->c_iflag |= IGNPAR;
+ if (lios->c_iflag & LINUX_PARMRK)
+ bios->c_iflag |= PARMRK;
+ if (lios->c_iflag & LINUX_INPCK)
+ bios->c_iflag |= INPCK;
+ if (lios->c_iflag & LINUX_ISTRIP)
+ bios->c_iflag |= ISTRIP;
+ if (lios->c_iflag & LINUX_INLCR)
+ bios->c_iflag |= INLCR;
+ if (lios->c_iflag & LINUX_IGNCR)
+ bios->c_iflag |= IGNCR;
+ if (lios->c_iflag & LINUX_ICRNL)
+ bios->c_iflag |= ICRNL;
+ if (lios->c_iflag & LINUX_IXON)
+ bios->c_iflag |= IXON;
+ if (lios->c_iflag & LINUX_IXANY)
+ bios->c_iflag |= IXANY;
+ if (lios->c_iflag & LINUX_IXOFF)
+ bios->c_iflag |= IXOFF;
+ if (lios->c_iflag & LINUX_IMAXBEL)
+ bios->c_iflag |= IMAXBEL;
+
+ bios->c_oflag = 0;
+ if (lios->c_oflag & LINUX_OPOST)
+ bios->c_oflag |= OPOST;
+ if (lios->c_oflag & LINUX_ONLCR)
+ bios->c_oflag |= ONLCR;
+ if (lios->c_oflag & LINUX_XTABS)
+ bios->c_oflag |= OXTABS;
+
+ bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
+ if (lios->c_cflag & LINUX_CSTOPB)
+ bios->c_cflag |= CSTOPB;
+ if (lios->c_cflag & LINUX_CREAD)
+ bios->c_cflag |= CREAD;
+ if (lios->c_cflag & LINUX_PARENB)
+ bios->c_cflag |= PARENB;
+ if (lios->c_cflag & LINUX_PARODD)
+ bios->c_cflag |= PARODD;
+ if (lios->c_cflag & LINUX_HUPCL)
+ bios->c_cflag |= HUPCL;
+ if (lios->c_cflag & LINUX_CLOCAL)
+ bios->c_cflag |= CLOCAL;
+ if (lios->c_cflag & LINUX_CRTSCTS)
+ bios->c_cflag |= CRTSCTS;
+
+ bios->c_lflag = 0;
+ if (lios->c_lflag & LINUX_ISIG)
+ bios->c_lflag |= ISIG;
+ if (lios->c_lflag & LINUX_ICANON)
+ bios->c_lflag |= ICANON;
+ if (lios->c_lflag & LINUX_ECHO)
+ bios->c_lflag |= ECHO;
+ if (lios->c_lflag & LINUX_ECHOE)
+ bios->c_lflag |= ECHOE;
+ if (lios->c_lflag & LINUX_ECHOK)
+ bios->c_lflag |= ECHOK;
+ if (lios->c_lflag & LINUX_ECHONL)
+ bios->c_lflag |= ECHONL;
+ if (lios->c_lflag & LINUX_NOFLSH)
+ bios->c_lflag |= NOFLSH;
+ if (lios->c_lflag & LINUX_TOSTOP)
+ bios->c_lflag |= TOSTOP;
+ if (lios->c_lflag & LINUX_ECHOCTL)
+ bios->c_lflag |= ECHOCTL;
+ if (lios->c_lflag & LINUX_ECHOPRT)
+ bios->c_lflag |= ECHOPRT;
+ if (lios->c_lflag & LINUX_ECHOKE)
+ bios->c_lflag |= ECHOKE;
+ if (lios->c_lflag & LINUX_FLUSHO)
+ bios->c_lflag |= FLUSHO;
+ if (lios->c_lflag & LINUX_PENDIN)
+ bios->c_lflag |= PENDIN;
+ if (lios->c_lflag & LINUX_IEXTEN)
+ bios->c_lflag |= IEXTEN;
+
+ for (i=0; i<NCCS; i++)
+ bios->c_cc[i] = _POSIX_VDISABLE;
+ bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
+ bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
+ bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
+ bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
+ bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
+ bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
+ bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
+ bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
+ bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
+ bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
+ bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
+ bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
+ bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
+ bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
+ bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
+ bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
+
+ for (i=0; i<NCCS; i++) {
+ if (bios->c_cc[i] == LINUX_POSIX_VDISABLE)
+ bios->c_cc[i] = _POSIX_VDISABLE;
+ }
+
+ bios->c_ispeed = bios->c_ospeed =
+ linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
+
+#ifdef DEBUG
+ if (ldebug(ioctl)) {
+ printf("LINUX: BSD termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
+ bios->c_ispeed, bios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bios->c_cc[i]);
+ printf("\n");
+ }
+#endif
+}
+
+static void
+bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
+{
+ struct linux_termios lios;
+
+ bsd_to_linux_termios(bios, &lios);
+ lio->c_iflag = lios.c_iflag;
+ lio->c_oflag = lios.c_oflag;
+ lio->c_cflag = lios.c_cflag;
+ lio->c_lflag = lios.c_lflag;
+ lio->c_line = lios.c_line;
+#ifdef __alpha__
+ lio->c_cc[LINUX__VINTR] = lios.c_cc[LINUX_VINTR];
+ lio->c_cc[LINUX__VQUIT] = lios.c_cc[LINUX_VQUIT];
+ lio->c_cc[LINUX__VERASE] = lios.c_cc[LINUX_VERASE];
+ lio->c_cc[LINUX__VKILL] = lios.c_cc[LINUX_VKILL];
+ lio->c_cc[LINUX__VEOF] =
+ lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN];
+ lio->c_cc[LINUX__VEOL] =
+ lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME];
+ lio->c_cc[LINUX__VEOL2] = lios.c_cc[LINUX_VEOL2];
+ lio->c_cc[LINUX__VSWTC] = lios.c_cc[LINUX_VSWTC];
+#else
+ memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
+#endif
+}
+
+static void
+linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
+{
+ struct linux_termios lios;
+ int i;
+
+ lios.c_iflag = lio->c_iflag;
+ lios.c_oflag = lio->c_oflag;
+ lios.c_cflag = lio->c_cflag;
+ lios.c_lflag = lio->c_lflag;
+#ifdef __alpha__
+ for (i=0; i<LINUX_NCCS; i++)
+ lios.c_cc[i] = LINUX_POSIX_VDISABLE;
+ lios.c_cc[LINUX_VINTR] = lio->c_cc[LINUX__VINTR];
+ lios.c_cc[LINUX_VQUIT] = lio->c_cc[LINUX__VQUIT];
+ lios.c_cc[LINUX_VERASE] = lio->c_cc[LINUX__VERASE];
+ lios.c_cc[LINUX_VKILL] = lio->c_cc[LINUX__VKILL];
+ lios.c_cc[LINUX_VEOL2] = lio->c_cc[LINUX__VEOL2];
+ lios.c_cc[LINUX_VSWTC] = lio->c_cc[LINUX__VSWTC];
+ lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN] =
+ lio->c_cc[LINUX__VEOF];
+ lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME] =
+ lio->c_cc[LINUX__VEOL];
+#else
+ for (i=LINUX_NCC; i<LINUX_NCCS; i++)
+ lios.c_cc[i] = LINUX_POSIX_VDISABLE;
+ memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
+#endif
+ linux_to_bsd_termios(&lios, bios);
+}
+
+static int
+linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct termios bios;
+ struct linux_termios lios;
+ struct linux_termio lio;
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_TCGETS:
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td);
+ if (error)
+ break;
+ bsd_to_linux_termios(&bios, &lios);
+ error = copyout(&lios, (caddr_t)args->arg, sizeof(lios));
+ break;
+
+ case LINUX_TCSETS:
+ error = copyin((caddr_t)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td));
+ break;
+
+ case LINUX_TCSETSW:
+ error = copyin((caddr_t)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td));
+ break;
+
+ case LINUX_TCSETSF:
+ error = copyin((caddr_t)args->arg, &lios, sizeof(lios));
+ if (error)
+ break;
+ linux_to_bsd_termios(&lios, &bios);
+ error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td));
+ break;
+
+ case LINUX_TCGETA:
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td);
+ if (error)
+ break;
+ bsd_to_linux_termio(&bios, &lio);
+ error = (copyout(&lio, (caddr_t)args->arg, sizeof(lio)));
+ break;
+
+ case LINUX_TCSETA:
+ error = copyin((caddr_t)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td));
+ break;
+
+ case LINUX_TCSETAW:
+ error = copyin((caddr_t)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td));
+ break;
+
+ case LINUX_TCSETAF:
+ error = copyin((caddr_t)args->arg, &lio, sizeof(lio));
+ if (error)
+ break;
+ linux_to_bsd_termio(&lio, &bios);
+ error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td));
+ break;
+
+ /* LINUX_TCSBRK */
+
+ case LINUX_TCXONC: {
+ switch (args->arg) {
+ case LINUX_TCOOFF:
+ args->cmd = TIOCSTOP;
+ break;
+ case LINUX_TCOON:
+ args->cmd = TIOCSTART;
+ break;
+ case LINUX_TCIOFF:
+ case LINUX_TCION: {
+ int c;
+ struct write_args wr;
+ error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td);
+ if (error)
+ break;
+ fdrop(fp, td);
+ c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
+ c = bios.c_cc[c];
+ if (c != _POSIX_VDISABLE) {
+ wr.fd = args->fd;
+ wr.buf = &c;
+ wr.nbyte = sizeof(c);
+ return (write(td, &wr));
+ } else
+ return (0);
+ }
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ args->arg = 0;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+ }
+
+ case LINUX_TCFLSH: {
+ args->cmd = TIOCFLUSH;
+ switch (args->arg) {
+ case LINUX_TCIFLUSH:
+ args->arg = FREAD;
+ break;
+ case LINUX_TCOFLUSH:
+ args->arg = FWRITE;
+ break;
+ case LINUX_TCIOFLUSH:
+ args->arg = FREAD | FWRITE;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+ }
+
+ case LINUX_TIOCEXCL:
+ args->cmd = TIOCEXCL;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCNXCL:
+ args->cmd = TIOCNXCL;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCSCTTY */
+
+ case LINUX_TIOCGPGRP:
+ args->cmd = TIOCGPGRP;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSPGRP:
+ args->cmd = TIOCSPGRP;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCOUTQ */
+ /* LINUX_TIOCSTI */
+
+ case LINUX_TIOCGWINSZ:
+ args->cmd = TIOCGWINSZ;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSWINSZ:
+ args->cmd = TIOCSWINSZ;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMGET:
+ args->cmd = TIOCMGET;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMBIS:
+ args->cmd = TIOCMBIS;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMBIC:
+ args->cmd = TIOCMBIC;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCMSET:
+ args->cmd = TIOCMSET;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* TIOCGSOFTCAR */
+ /* TIOCSSOFTCAR */
+
+ case LINUX_FIONREAD: /* LINUX_TIOCINQ */
+ args->cmd = FIONREAD;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCLINUX */
+
+ case LINUX_TIOCCONS:
+ args->cmd = TIOCCONS;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCGSERIAL: {
+ struct linux_serial_struct lss;
+ lss.type = LINUX_PORT_16550A;
+ lss.flags = 0;
+ lss.close_delay = 0;
+ error = copyout(&lss, (caddr_t)args->arg, sizeof(lss));
+ break;
+ }
+
+ case LINUX_TIOCSSERIAL: {
+ struct linux_serial_struct lss;
+ error = copyin((caddr_t)args->arg, &lss, sizeof(lss));
+ if (error)
+ break;
+ /* XXX - It really helps to have an implementation that
+ * does nothing. NOT!
+ */
+ error = 0;
+ break;
+ }
+
+ /* LINUX_TIOCPKT */
+
+ case LINUX_FIONBIO:
+ args->cmd = FIONBIO;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCNOTTY:
+ args->cmd = TIOCNOTTY;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_TIOCSETD: {
+ int line;
+ switch (args->arg) {
+ case LINUX_N_TTY:
+ line = TTYDISC;
+ break;
+ case LINUX_N_SLIP:
+ line = SLIPDISC;
+ break;
+ case LINUX_N_PPP:
+ line = PPPDISC;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td));
+ break;
+ }
+
+ case LINUX_TIOCGETD: {
+ int linux_line;
+ int bsd_line = TTYDISC;
+ error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, td);
+ if (error)
+ return (error);
+ switch (bsd_line) {
+ case TTYDISC:
+ linux_line = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ linux_line = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ linux_line = LINUX_N_PPP;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (copyout(&linux_line, (caddr_t)args->arg, sizeof(int)));
+ break;
+ }
+
+ /* LINUX_TCSBRKP */
+ /* LINUX_TIOCTTYGSTRUCT */
+
+ case LINUX_FIONCLEX:
+ args->cmd = FIONCLEX;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_FIOCLEX:
+ args->cmd = FIOCLEX;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_FIOASYNC:
+ args->cmd = FIOASYNC;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_TIOCSERCONFIG */
+ /* LINUX_TIOCSERGWILD */
+ /* LINUX_TIOCSERSWILD */
+ /* LINUX_TIOCGLCKTRMIOS */
+ /* LINUX_TIOCSLCKTRMIOS */
+
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * CDROM related ioctls
+ */
+
+struct linux_cdrom_msf
+{
+ u_char cdmsf_min0;
+ u_char cdmsf_sec0;
+ u_char cdmsf_frame0;
+ u_char cdmsf_min1;
+ u_char cdmsf_sec1;
+ u_char cdmsf_frame1;
+};
+
+struct linux_cdrom_tochdr
+{
+ u_char cdth_trk0;
+ u_char cdth_trk1;
+};
+
+union linux_cdrom_addr
+{
+ struct {
+ u_char minute;
+ u_char second;
+ u_char frame;
+ } msf;
+ int lba;
+};
+
+struct linux_cdrom_tocentry
+{
+ u_char cdte_track;
+ u_char cdte_adr:4;
+ u_char cdte_ctrl:4;
+ u_char cdte_format;
+ union linux_cdrom_addr cdte_addr;
+ u_char cdte_datamode;
+};
+
+struct linux_cdrom_subchnl
+{
+ u_char cdsc_format;
+ u_char cdsc_audiostatus;
+ u_char cdsc_adr:4;
+ u_char cdsc_ctrl:4;
+ u_char cdsc_trk;
+ u_char cdsc_ind;
+ union linux_cdrom_addr cdsc_absaddr;
+ union linux_cdrom_addr cdsc_reladdr;
+};
+
+struct l_dvd_layer {
+ u_char book_version:4;
+ u_char book_type:4;
+ u_char min_rate:4;
+ u_char disc_size:4;
+ u_char layer_type:4;
+ u_char track_path:1;
+ u_char nlayers:2;
+ u_char track_density:4;
+ u_char linear_density:4;
+ u_char bca:1;
+ u_int32_t start_sector;
+ u_int32_t end_sector;
+ u_int32_t end_sector_l0;
+};
+
+struct l_dvd_physical {
+ u_char type;
+ u_char layer_num;
+ struct l_dvd_layer layer[4];
+};
+
+struct l_dvd_copyright {
+ u_char type;
+ u_char layer_num;
+ u_char cpst;
+ u_char rmi;
+};
+
+struct l_dvd_disckey {
+ u_char type;
+ l_uint agid:2;
+ u_char value[2048];
+};
+
+struct l_dvd_bca {
+ u_char type;
+ l_int len;
+ u_char value[188];
+};
+
+struct l_dvd_manufact {
+ u_char type;
+ u_char layer_num;
+ l_int len;
+ u_char value[2048];
+};
+
+typedef union {
+ u_char type;
+ struct l_dvd_physical physical;
+ struct l_dvd_copyright copyright;
+ struct l_dvd_disckey disckey;
+ struct l_dvd_bca bca;
+ struct l_dvd_manufact manufact;
+} l_dvd_struct;
+
+typedef u_char l_dvd_key[5];
+typedef u_char l_dvd_challenge[10];
+
+struct l_dvd_lu_send_agid {
+ u_char type;
+ l_uint agid:2;
+};
+
+struct l_dvd_host_send_challenge {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_challenge chal;
+};
+
+struct l_dvd_send_key {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_key key;
+};
+
+struct l_dvd_lu_send_challenge {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_challenge chal;
+};
+
+struct l_dvd_lu_send_title_key {
+ u_char type;
+ l_uint agid:2;
+ l_dvd_key title_key;
+ l_int lba;
+ l_uint cpm:1;
+ l_uint cp_sec:1;
+ l_uint cgms:2;
+};
+
+struct l_dvd_lu_send_asf {
+ u_char type;
+ l_uint agid:2;
+ l_uint asf:1;
+};
+
+struct l_dvd_host_send_rpcstate {
+ u_char type;
+ u_char pdrc;
+};
+
+struct l_dvd_lu_send_rpcstate {
+ u_char type:2;
+ u_char vra:3;
+ u_char ucca:3;
+ u_char region_mask;
+ u_char rpc_scheme;
+};
+
+typedef union {
+ u_char type;
+ struct l_dvd_lu_send_agid lsa;
+ struct l_dvd_host_send_challenge hsc;
+ struct l_dvd_send_key lsk;
+ struct l_dvd_lu_send_challenge lsc;
+ struct l_dvd_send_key hsk;
+ struct l_dvd_lu_send_title_key lstk;
+ struct l_dvd_lu_send_asf lsasf;
+ struct l_dvd_host_send_rpcstate hrpcs;
+ struct l_dvd_lu_send_rpcstate lrpcs;
+} l_dvd_authinfo;
+
+static void
+bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
+{
+ if (af == CD_LBA_FORMAT)
+ lp->lba = bp->lba;
+ else {
+ lp->msf.minute = bp->msf.minute;
+ lp->msf.second = bp->msf.second;
+ lp->msf.frame = bp->msf.frame;
+ }
+}
+
+static void
+set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
+{
+ if (format == LINUX_CDROM_MSF) {
+ addr->msf.frame = lba % 75;
+ lba /= 75;
+ lba += 2;
+ addr->msf.second = lba % 60;
+ addr->msf.minute = lba / 60;
+ } else
+ addr->lba = lba;
+}
+
+static int
+linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
+{
+ bp->format = lp->type;
+ switch (bp->format) {
+ case DVD_STRUCT_PHYSICAL:
+ if (bp->layer_num >= 4)
+ return (EINVAL);
+ bp->layer_num = lp->physical.layer_num;
+ break;
+ case DVD_STRUCT_COPYRIGHT:
+ bp->layer_num = lp->copyright.layer_num;
+ break;
+ case DVD_STRUCT_DISCKEY:
+ bp->agid = lp->disckey.agid;
+ break;
+ case DVD_STRUCT_BCA:
+ case DVD_STRUCT_MANUFACT:
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
+{
+ switch (bp->format) {
+ case DVD_STRUCT_PHYSICAL: {
+ struct dvd_layer *blp = (struct dvd_layer *)bp->data;
+ struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
+ memset(llp, 0, sizeof(*llp));
+ llp->book_version = blp->book_version;
+ llp->book_type = blp->book_type;
+ llp->min_rate = blp->max_rate;
+ llp->disc_size = blp->disc_size;
+ llp->layer_type = blp->layer_type;
+ llp->track_path = blp->track_path;
+ llp->nlayers = blp->nlayers;
+ llp->track_density = blp->track_density;
+ llp->linear_density = blp->linear_density;
+ llp->bca = blp->bca;
+ llp->start_sector = blp->start_sector;
+ llp->end_sector = blp->end_sector;
+ llp->end_sector_l0 = blp->end_sector_l0;
+ break;
+ }
+ case DVD_STRUCT_COPYRIGHT:
+ lp->copyright.cpst = bp->cpst;
+ lp->copyright.rmi = bp->rmi;
+ break;
+ case DVD_STRUCT_DISCKEY:
+ memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
+ break;
+ case DVD_STRUCT_BCA:
+ lp->bca.len = bp->length;
+ memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
+ break;
+ case DVD_STRUCT_MANUFACT:
+ lp->manufact.len = bp->length;
+ memcpy(lp->manufact.value, bp->data,
+ sizeof(lp->manufact.value));
+ /* lp->manufact.layer_num is unused in linux (redhat 7.0) */
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
+ struct dvd_authinfo *bp)
+{
+ switch (lp->type) {
+ case LINUX_DVD_LU_SEND_AGID:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_AGID;
+ bp->agid = lp->lsa.agid;
+ break;
+ case LINUX_DVD_HOST_SEND_CHALLENGE:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_CHALLENGE;
+ bp->agid = lp->hsc.agid;
+ memcpy(bp->keychal, lp->hsc.chal, 10);
+ break;
+ case LINUX_DVD_LU_SEND_KEY1:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_KEY1;
+ bp->agid = lp->lsk.agid;
+ break;
+ case LINUX_DVD_LU_SEND_CHALLENGE:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_CHALLENGE;
+ bp->agid = lp->lsc.agid;
+ break;
+ case LINUX_DVD_HOST_SEND_KEY2:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_KEY2;
+ bp->agid = lp->hsk.agid;
+ memcpy(bp->keychal, lp->hsk.key, 5);
+ break;
+ case LINUX_DVD_LU_SEND_TITLE_KEY:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_TITLE_KEY;
+ bp->agid = lp->lstk.agid;
+ bp->lba = lp->lstk.lba;
+ break;
+ case LINUX_DVD_LU_SEND_ASF:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_ASF;
+ bp->agid = lp->lsasf.agid;
+ break;
+ case LINUX_DVD_INVALIDATE_AGID:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_INVALIDATE_AGID;
+ bp->agid = lp->lsa.agid;
+ break;
+ case LINUX_DVD_LU_SEND_RPC_STATE:
+ *bcode = DVDIOCREPORTKEY;
+ bp->format = DVD_REPORT_RPC;
+ break;
+ case LINUX_DVD_HOST_SEND_RPC_STATE:
+ *bcode = DVDIOCSENDKEY;
+ bp->format = DVD_SEND_RPC;
+ bp->region = lp->hrpcs.pdrc;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
+{
+ switch (lp->type) {
+ case LINUX_DVD_LU_SEND_AGID:
+ lp->lsa.agid = bp->agid;
+ break;
+ case LINUX_DVD_HOST_SEND_CHALLENGE:
+ lp->type = LINUX_DVD_LU_SEND_KEY1;
+ break;
+ case LINUX_DVD_LU_SEND_KEY1:
+ memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
+ break;
+ case LINUX_DVD_LU_SEND_CHALLENGE:
+ memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
+ break;
+ case LINUX_DVD_HOST_SEND_KEY2:
+ lp->type = LINUX_DVD_AUTH_ESTABLISHED;
+ break;
+ case LINUX_DVD_LU_SEND_TITLE_KEY:
+ memcpy(lp->lstk.title_key, bp->keychal,
+ sizeof(lp->lstk.title_key));
+ lp->lstk.cpm = bp->cpm;
+ lp->lstk.cp_sec = bp->cp_sec;
+ lp->lstk.cgms = bp->cgms;
+ break;
+ case LINUX_DVD_LU_SEND_ASF:
+ lp->lsasf.asf = bp->asf;
+ break;
+ case LINUX_DVD_INVALIDATE_AGID:
+ break;
+ case LINUX_DVD_LU_SEND_RPC_STATE:
+ lp->lrpcs.type = bp->reg_type;
+ lp->lrpcs.vra = bp->vend_rsts;
+ lp->lrpcs.ucca = bp->user_rsts;
+ lp->lrpcs.region_mask = bp->region;
+ lp->lrpcs.rpc_scheme = bp->rpc_scheme;
+ break;
+ case LINUX_DVD_HOST_SEND_RPC_STATE:
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static int
+linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_CDROMPAUSE:
+ args->cmd = CDIOCPAUSE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMRESUME:
+ args->cmd = CDIOCRESUME;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMPLAYMSF:
+ args->cmd = CDIOCPLAYMSF;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMPLAYTRKIND:
+ args->cmd = CDIOCPLAYTRACKS;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMREADTOCHDR: {
+ struct ioc_toc_header th;
+ struct linux_cdrom_tochdr lth;
+ error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, td);
+ if (!error) {
+ lth.cdth_trk0 = th.starting_track;
+ lth.cdth_trk1 = th.ending_track;
+ copyout(&lth, (caddr_t)args->arg, sizeof(lth));
+ }
+ break;
+ }
+
+ case LINUX_CDROMREADTOCENTRY: {
+ struct linux_cdrom_tocentry lte, *ltep =
+ (struct linux_cdrom_tocentry *)args->arg;
+ struct ioc_read_toc_single_entry irtse;
+ irtse.address_format = ltep->cdte_format;
+ irtse.track = ltep->cdte_track;
+ error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, td);
+ if (!error) {
+ lte = *ltep;
+ lte.cdte_ctrl = irtse.entry.control;
+ lte.cdte_adr = irtse.entry.addr_type;
+ bsd_to_linux_msf_lba(irtse.address_format,
+ &irtse.entry.addr, &lte.cdte_addr);
+ copyout(&lte, (caddr_t)args->arg, sizeof(lte));
+ }
+ break;
+ }
+
+ case LINUX_CDROMSTOP:
+ args->cmd = CDIOCSTOP;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMSTART:
+ args->cmd = CDIOCSTART;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_CDROMEJECT:
+ args->cmd = CDIOCEJECT;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_CDROMVOLCTRL */
+
+ case LINUX_CDROMSUBCHNL: {
+ struct linux_cdrom_subchnl sc;
+ struct ioc_read_subchannel bsdsc;
+ struct cd_sub_channel_info *bsdinfo;
+ caddr_t sg = stackgap_init();
+ bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg,
+ sizeof(struct cd_sub_channel_info));
+ bsdsc.address_format = CD_LBA_FORMAT;
+ bsdsc.data_format = CD_CURRENT_POSITION;
+ bsdsc.track = 0;
+ bsdsc.data_len = sizeof(struct cd_sub_channel_info);
+ bsdsc.data = bsdinfo;
+ error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, td);
+ if (error)
+ break;
+ error = copyin((caddr_t)args->arg, &sc,
+ sizeof(struct linux_cdrom_subchnl));
+ if (error)
+ break;
+ sc.cdsc_audiostatus = bsdinfo->header.audio_status;
+ sc.cdsc_adr = bsdinfo->what.position.addr_type;
+ sc.cdsc_ctrl = bsdinfo->what.position.control;
+ sc.cdsc_trk = bsdinfo->what.position.track_number;
+ sc.cdsc_ind = bsdinfo->what.position.index_number;
+ set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
+ bsdinfo->what.position.absaddr.lba);
+ set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
+ bsdinfo->what.position.reladdr.lba);
+ error = copyout(&sc, (caddr_t)args->arg,
+ sizeof(struct linux_cdrom_subchnl));
+ break;
+ }
+
+ /* LINUX_CDROMREADMODE2 */
+ /* LINUX_CDROMREADMODE1 */
+ /* LINUX_CDROMREADAUDIO */
+ /* LINUX_CDROMEJECT_SW */
+ /* LINUX_CDROMMULTISESSION */
+ /* LINUX_CDROM_GET_UPC */
+
+ case LINUX_CDROMRESET:
+ args->cmd = CDIOCRESET;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ /* LINUX_CDROMVOLREAD */
+ /* LINUX_CDROMREADRAW */
+ /* LINUX_CDROMREADCOOKED */
+ /* LINUX_CDROMSEEK */
+ /* LINUX_CDROMPLAYBLK */
+ /* LINUX_CDROMREADALL */
+ /* LINUX_CDROMCLOSETRAY */
+ /* LINUX_CDROMLOADFROMSLOT */
+ /* LINUX_CDROMGETSPINDOWN */
+ /* LINUX_CDROMSETSPINDOWN */
+ /* LINUX_CDROM_SET_OPTIONS */
+ /* LINUX_CDROM_CLEAR_OPTIONS */
+ /* LINUX_CDROM_SELECT_SPEED */
+ /* LINUX_CDROM_SELECT_DISC */
+ /* LINUX_CDROM_MEDIA_CHANGED */
+ /* LINUX_CDROM_DRIVE_STATUS */
+ /* LINUX_CDROM_DISC_STATUS */
+ /* LINUX_CDROM_CHANGER_NSLOTS */
+ /* LINUX_CDROM_LOCKDOOR */
+ /* LINUX_CDROM_DEBUG */
+ /* LINUX_CDROM_GET_CAPABILITY */
+ /* LINUX_CDROMAUDIOBUFSIZ */
+
+ case LINUX_DVD_READ_STRUCT: {
+ l_dvd_struct lds;
+ struct dvd_struct bds;
+
+ error = copyin((caddr_t)args->arg, &lds, sizeof(l_dvd_struct));
+ if (error)
+ break;
+ error = linux_to_bsd_dvd_struct(&lds, &bds);
+ if (error)
+ break;
+ error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)&bds, td);
+ if (error)
+ break;
+ error = bsd_to_linux_dvd_struct(&bds, &lds);
+ if (error)
+ break;
+ error = copyout(&lds, (caddr_t)args->arg,
+ sizeof(l_dvd_struct));
+ break;
+ }
+
+ /* LINUX_DVD_WRITE_STRUCT */
+
+ case LINUX_DVD_AUTH: {
+ l_dvd_authinfo lda;
+ struct dvd_authinfo bda;
+ int bcode;
+
+ error = copyin((caddr_t)args->arg, &lda,
+ sizeof(l_dvd_authinfo));
+ if (error)
+ break;
+ error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
+ if (error)
+ break;
+ error = fo_ioctl(fp, bcode, (caddr_t)&bda, td);
+ if (error) {
+ if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
+ lda.type = LINUX_DVD_AUTH_FAILURE;
+ copyout(&lda, (caddr_t)args->arg,
+ sizeof(l_dvd_authinfo));
+ }
+ break;
+ }
+ error = bsd_to_linux_dvd_authinfo(&bda, &lda);
+ if (error)
+ break;
+ error = copyout(&lda, (caddr_t)args->arg,
+ sizeof(l_dvd_authinfo));
+ break;
+ }
+
+ /* LINUX_CDROM_SEND_PACKET */
+ /* LINUX_CDROM_NEXT_WRITABLE */
+ /* LINUX_CDROM_LAST_WRITTEN */
+
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Sound related ioctls
+ */
+
+static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
+
+#define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
+
+static int
+linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
+{
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_SOUND_MIXER_WRITE_VOLUME:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_BASS:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_TREBLE:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_SYNTH:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_PCM:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_SPEAKER:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_MIC:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_CD:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_IMIX:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_ALTPCM:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_RECLEV:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_IGAIN:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_OGAIN:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE1:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE2:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_LINE3:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_OSS_GETVERSION: {
+ int version = linux_get_oss_version(td->td_proc);
+ return (copyout(&version, (caddr_t)args->arg, sizeof(int)));
+ }
+
+ case LINUX_SOUND_MIXER_READ_DEVMASK:
+ args->cmd = SOUND_MIXER_READ_DEVMASK;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_MIXER_WRITE_RECSRC:
+ args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_RESET:
+ args->cmd = SNDCTL_DSP_RESET;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SYNC:
+ args->cmd = SNDCTL_DSP_SYNC;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SPEED:
+ args->cmd = SNDCTL_DSP_SPEED;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_STEREO:
+ args->cmd = SNDCTL_DSP_STEREO;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
+ args->cmd = SNDCTL_DSP_GETBLKSIZE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETFMT:
+ args->cmd = SNDCTL_DSP_SETFMT;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_PCM_WRITE_CHANNELS:
+ args->cmd = SOUND_PCM_WRITE_CHANNELS;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SOUND_PCM_WRITE_FILTER:
+ args->cmd = SOUND_PCM_WRITE_FILTER;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_POST:
+ args->cmd = SNDCTL_DSP_POST;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SUBDIVIDE:
+ args->cmd = SNDCTL_DSP_SUBDIVIDE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETFRAGMENT:
+ args->cmd = SNDCTL_DSP_SETFRAGMENT;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETFMTS:
+ args->cmd = SNDCTL_DSP_GETFMTS;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETOSPACE:
+ args->cmd = SNDCTL_DSP_GETOSPACE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETISPACE:
+ args->cmd = SNDCTL_DSP_GETISPACE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_NONBLOCK:
+ args->cmd = SNDCTL_DSP_NONBLOCK;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETCAPS:
+ args->cmd = SNDCTL_DSP_GETCAPS;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
+ args->cmd = SNDCTL_DSP_SETTRIGGER;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETIPTR:
+ args->cmd = SNDCTL_DSP_GETIPTR;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETOPTR:
+ args->cmd = SNDCTL_DSP_GETOPTR;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_DSP_GETODELAY:
+ args->cmd = SNDCTL_DSP_GETODELAY;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_RESET:
+ args->cmd = SNDCTL_SEQ_RESET;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_SYNC:
+ args->cmd = SNDCTL_SEQ_SYNC;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SYNTH_INFO:
+ args->cmd = SNDCTL_SYNTH_INFO;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_CTRLRATE:
+ args->cmd = SNDCTL_SEQ_CTRLRATE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
+ args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_GETINCOUNT:
+ args->cmd = SNDCTL_SEQ_GETINCOUNT;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_PERCMODE:
+ args->cmd = SNDCTL_SEQ_PERCMODE;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_FM_LOAD_INSTR:
+ args->cmd = SNDCTL_FM_LOAD_INSTR;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_TESTMIDI:
+ args->cmd = SNDCTL_SEQ_TESTMIDI;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_RESETSAMPLES:
+ args->cmd = SNDCTL_SEQ_RESETSAMPLES;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_NRSYNTHS:
+ args->cmd = SNDCTL_SEQ_NRSYNTHS;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_NRMIDIS:
+ args->cmd = SNDCTL_SEQ_NRMIDIS;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_MIDI_INFO:
+ args->cmd = SNDCTL_MIDI_INFO;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SEQ_TRESHOLD:
+ args->cmd = SNDCTL_SEQ_TRESHOLD;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ case LINUX_SNDCTL_SYNTH_MEMAVL:
+ args->cmd = SNDCTL_SYNTH_MEMAVL;
+ return (ioctl(td, (struct ioctl_args *)args));
+
+ }
+
+ return (ENOIOCTL);
+}
+
+/*
+ * Console related ioctls
+ */
+
+#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
+
+static int
+linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_KIOCSOUND:
+ args->cmd = KIOCSOUND;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDMKTONE:
+ args->cmd = KDMKTONE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGETLED:
+ args->cmd = KDGETLED;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSETLED:
+ args->cmd = KDSETLED;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSETMODE:
+ args->cmd = KDSETMODE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGETMODE:
+ args->cmd = KDGETMODE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDGKBMODE:
+ args->cmd = KDGKBMODE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_KDSKBMODE: {
+ int kbdmode;
+ switch (args->arg) {
+ case LINUX_KBD_RAW:
+ kbdmode = K_RAW;
+ break;
+ case LINUX_KBD_XLATE:
+ kbdmode = K_XLATE;
+ break;
+ case LINUX_KBD_MEDIUMRAW:
+ kbdmode = K_RAW;
+ break;
+ default:
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+ error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, td));
+ break;
+ }
+
+ case LINUX_VT_OPENQRY:
+ args->cmd = VT_OPENQRY;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_GETMODE:
+ args->cmd = VT_GETMODE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_SETMODE: {
+ struct vt_mode *mode;
+ args->cmd = VT_SETMODE;
+ mode = (struct vt_mode *)args->arg;
+ if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig))
+ mode->frsig = mode->acqsig;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+ }
+
+ case LINUX_VT_GETSTATE:
+ args->cmd = VT_GETACTIVE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_RELDISP:
+ args->cmd = VT_RELDISP;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_ACTIVATE:
+ args->cmd = VT_ACTIVATE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ case LINUX_VT_WAITACTIVE:
+ args->cmd = VT_WAITACTIVE;
+ error = (ioctl(td, (struct ioctl_args *)args));
+ break;
+
+ default:
+ error = ENOIOCTL;
+ break;
+ }
+
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Criteria for interface name translation
+ */
+#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
+
+/*
+ * Interface function used by linprocfs (at the time of writing). It's not
+ * used by the Linuxulator itself.
+ */
+int
+linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
+{
+ struct ifnet *ifscan;
+ int ethno;
+
+ /* Short-circuit non ethernet interfaces */
+ if (!IFP_IS_ETH(ifp))
+ return (snprintf(buffer, buflen, "%s%d", ifp->if_name,
+ ifp->if_unit));
+
+ /* Determine the (relative) unit number for ethernet interfaces */
+ ethno = 0;
+ TAILQ_FOREACH(ifscan, &ifnet, if_link) {
+ if (ifscan == ifp)
+ return (snprintf(buffer, buflen, "eth%d", ethno));
+ if (IFP_IS_ETH(ifscan))
+ ethno++;
+ }
+
+ return (0);
+}
+
+/*
+ * Translate a Linux interface name to a FreeBSD interface name,
+ * and return the associated ifnet structure
+ * bsdname and lxname need to be least IFNAMSIZ bytes long, but
+ * can point to the same buffer.
+ */
+
+static struct ifnet *
+ifname_linux_to_bsd(const char *lxname, char *bsdname)
+{
+ struct ifnet *ifp;
+ int len, unit;
+ char *ep;
+ int is_eth, index;
+
+ for (len = 0; len < LINUX_IFNAMSIZ; ++len)
+ if (!isalpha(lxname[len]))
+ break;
+ if (len == 0 || len == LINUX_IFNAMSIZ)
+ return (NULL);
+ unit = (int)strtoul(lxname + len, &ep, 10);
+ if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ)
+ return (NULL);
+ index = 0;
+ is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
+ TAILQ_FOREACH(ifp, &ifnet, if_link) {
+ /*
+ * Allow Linux programs to use FreeBSD names. Don't presume
+ * we never have an interface named "eth", so don't make
+ * the test optional based on is_eth.
+ */
+ if (ifp->if_unit == unit && ifp->if_name[len] == '\0' &&
+ strncmp(ifp->if_name, lxname, len) == 0)
+ break;
+ if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
+ break;
+ }
+ if (ifp != NULL)
+ snprintf(bsdname, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit);
+ return (ifp);
+}
+
+/*
+ * Implement the SIOCGIFCONF ioctl
+ */
+
+static int
+linux_ifconf(struct thread *td, struct ifconf *uifc)
+{
+ struct ifconf ifc;
+ struct l_ifreq ifr;
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ struct iovec iov;
+ struct uio uio;
+ int error, ethno;
+
+ error = copyin(uifc, &ifc, sizeof ifc);
+ if (error != 0)
+ return (error);
+
+ /* much easier to use uiomove than keep track ourselves */
+ iov.iov_base = ifc.ifc_buf;
+ iov.iov_len = ifc.ifc_len;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = 0;
+ uio.uio_resid = ifc.ifc_len;
+ uio.uio_segflg = UIO_USERSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+
+ /* Keep track of eth interfaces */
+ ethno = 0;
+
+ /* Return all AF_INET addresses of all interfaces */
+ TAILQ_FOREACH(ifp, &ifnet, if_link) {
+ if (uio.uio_resid <= 0)
+ break;
+
+ bzero(&ifr, sizeof ifr);
+ if (IFP_IS_ETH(ifp))
+ snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
+ ethno++);
+ else
+ snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "%s%d",
+ ifp->if_name, ifp->if_unit);
+
+ /* Walk the address list */
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ struct sockaddr *sa = ifa->ifa_addr;
+
+ if (uio.uio_resid <= 0)
+ break;
+
+ if (sa->sa_family == AF_INET) {
+ ifr.ifr_addr.sa_family = LINUX_AF_INET;
+ memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
+ sizeof(ifr.ifr_addr.sa_data));
+
+ error = uiomove((caddr_t)&ifr, sizeof ifr,
+ &uio);
+ if (error != 0)
+ return (error);
+ }
+ }
+ }
+
+ ifc.ifc_len -= uio.uio_resid;
+ error = copyout(&ifc, uifc, sizeof ifc);
+
+ return (error);
+}
+
+static int
+linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr)
+{
+ l_short flags;
+
+ flags = ifp->if_flags;
+ /* these flags have no Linux equivalent */
+ flags &= ~(IFF_SMART|IFF_OACTIVE|IFF_SIMPLEX|
+ IFF_LINK0|IFF_LINK1|IFF_LINK2);
+ /* Linux' multicast flag is in a different bit */
+ if (flags & IFF_MULTICAST) {
+ flags &= ~IFF_MULTICAST;
+ flags |= 0x1000;
+ }
+
+ return (copyout(&flags, &ifr->ifr_flags, sizeof flags));
+}
+
+#define ARPHRD_ETHER 1
+#define ARPHRD_LOOPBACK 772
+
+static int
+linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr)
+{
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
+ struct l_sockaddr lsa;
+
+ if (ifp->if_type == IFT_LOOP) {
+ bzero(&lsa, sizeof lsa);
+ lsa.sa_family = ARPHRD_LOOPBACK;
+ return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa));
+ }
+
+ if (ifp->if_type != IFT_ETHER)
+ return (ENOENT);
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ sdl = (struct sockaddr_dl*)ifa->ifa_addr;
+ if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
+ (sdl->sdl_type == IFT_ETHER)) {
+ bzero(&lsa, sizeof lsa);
+ lsa.sa_family = ARPHRD_ETHER;
+ bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN);
+ return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa));
+ }
+ }
+
+ return (ENOENT);
+}
+
+/*
+ * Socket related ioctls
+ */
+
+static int
+linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
+{
+ char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
+ struct ifnet *ifp;
+ struct file *fp;
+ int error, type;
+
+ KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ,
+ ("%s(): LINUX_IFNAMSIZ != IFNAMSIZ", __func__));
+
+ ifp = NULL;
+ error = 0;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ type = fp->f_type;
+ fdrop(fp, td);
+ if (type != DTYPE_SOCKET) {
+ /* not a socket - probably a tap / vmnet device */
+ switch (args->cmd) {
+ case LINUX_SIOCGIFADDR:
+ case LINUX_SIOCSIFADDR:
+ case LINUX_SIOCGIFFLAGS:
+ return (linux_ioctl_special(td, args));
+ default:
+ return (ENOIOCTL);
+ }
+ }
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_FIOGETOWN:
+ case LINUX_FIOSETOWN:
+ case LINUX_SIOCADDMULTI:
+ case LINUX_SIOCATMARK:
+ case LINUX_SIOCDELMULTI:
+ case LINUX_SIOCGIFCONF:
+ case LINUX_SIOCGPGRP:
+ case LINUX_SIOCSPGRP:
+ /* these ioctls don't take an interface name */
+#ifdef DEBUG
+ printf("%s(): ioctl %d\n", __func__,
+ args->cmd & 0xffff);
+#endif
+ break;
+
+ case LINUX_SIOCGIFFLAGS:
+ case LINUX_SIOCGIFADDR:
+ case LINUX_SIOCSIFADDR:
+ case LINUX_SIOCGIFDSTADDR:
+ case LINUX_SIOCGIFBRDADDR:
+ case LINUX_SIOCGIFNETMASK:
+ case LINUX_SIOCSIFNETMASK:
+ case LINUX_SIOCGIFMTU:
+ case LINUX_SIOCSIFMTU:
+ case LINUX_SIOCSIFNAME:
+ case LINUX_SIOCGIFHWADDR:
+ case LINUX_SIOCSIFHWADDR:
+ case LINUX_SIOCDEVPRIVATE:
+ case LINUX_SIOCDEVPRIVATE+1:
+ /* copy in the interface name and translate it. */
+ error = copyin((char *)args->arg, lifname, LINUX_IFNAMSIZ);
+ if (error != 0)
+ return (error);
+#ifdef DEBUG
+ printf("%s(): ioctl %d on %.*s\n", __func__,
+ args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname);
+#endif
+ ifp = ifname_linux_to_bsd(lifname, ifname);
+ if (ifp == NULL)
+ return (EINVAL);
+ /*
+ * We need to copy it back out in case we pass the
+ * request on to our native ioctl(), which will expect
+ * the ifreq to be in user space and have the correct
+ * interface name.
+ */
+ error = copyout(ifname, (char *)args->arg, IFNAMSIZ);
+ if (error != 0)
+ return (error);
+#ifdef DEBUG
+ printf("%s(): %s translated to %s\n", __func__,
+ lifname, ifname);
+#endif
+ break;
+
+ default:
+ return (ENOIOCTL);
+ }
+
+ switch (args->cmd & 0xffff) {
+
+ case LINUX_FIOSETOWN:
+ args->cmd = FIOSETOWN;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSPGRP:
+ args->cmd = SIOCSPGRP;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_FIOGETOWN:
+ args->cmd = FIOGETOWN;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGPGRP:
+ args->cmd = SIOCGPGRP;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCATMARK:
+ args->cmd = SIOCATMARK;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ /* LINUX_SIOCGSTAMP */
+
+ case LINUX_SIOCGIFCONF:
+ error = linux_ifconf(td, (struct ifconf *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFFLAGS:
+ args->cmd = SIOCGIFFLAGS;
+ error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCGIFADDR:
+ args->cmd = OSIOCGIFADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFADDR:
+ /* XXX probably doesn't work, included for completeness */
+ args->cmd = SIOCSIFADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFDSTADDR:
+ args->cmd = OSIOCGIFDSTADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFBRDADDR:
+ args->cmd = OSIOCGIFBRDADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCGIFNETMASK:
+ args->cmd = OSIOCGIFNETMASK;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFNETMASK:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCGIFMTU:
+ args->cmd = SIOCGIFMTU;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFMTU:
+ args->cmd = SIOCSIFMTU;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCSIFNAME:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCGIFHWADDR:
+ error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg);
+ break;
+
+ case LINUX_SIOCSIFHWADDR:
+ error = ENOIOCTL;
+ break;
+
+ case LINUX_SIOCADDMULTI:
+ args->cmd = SIOCADDMULTI;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCDELMULTI:
+ args->cmd = SIOCDELMULTI;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ /*
+ * XXX This is slightly bogus, but these ioctls are currently
+ * XXX only used by the aironet (if_an) network driver.
+ */
+ case LINUX_SIOCDEVPRIVATE:
+ args->cmd = SIOCGPRIVATE_0;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+
+ case LINUX_SIOCDEVPRIVATE+1:
+ args->cmd = SIOCGPRIVATE_1;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+ }
+
+ if (ifp != NULL)
+ /* restore the original interface name */
+ copyout(lifname, (char *)args->arg, LINUX_IFNAMSIZ);
+
+#ifdef DEBUG
+ printf("%s(): returning %d\n", __func__, error);
+#endif
+ return (error);
+}
+
+/*
+ * Device private ioctl handler
+ */
+static int
+linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ int error, type;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ type = fp->f_type;
+ fdrop(fp, td);
+ if (type == DTYPE_SOCKET)
+ return (linux_ioctl_socket(td, args));
+ return (ENOIOCTL);
+}
+
+/*
+ * Special ioctl handler
+ */
+static int
+linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
+{
+ int error;
+
+ switch (args->cmd) {
+ case LINUX_SIOCGIFADDR:
+ args->cmd = SIOCGIFADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+ case LINUX_SIOCSIFADDR:
+ args->cmd = SIOCSIFADDR;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+ case LINUX_SIOCGIFFLAGS:
+ args->cmd = SIOCGIFFLAGS;
+ error = ioctl(td, (struct ioctl_args *)args);
+ break;
+ default:
+ error = ENOIOCTL;
+ }
+
+ return (error);
+}
+
+/*
+ * main ioctl syscall function
+ */
+
+int
+linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ struct handler_element *he;
+ int error, cmd;
+
+#ifdef DEBUG
+ if (ldebug(ioctl))
+ printf(ARGS(ioctl, "%d, %04lx, *"), args->fd,
+ (unsigned long)args->cmd);
+#endif
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ /* Iterate over the ioctl handlers */
+ cmd = args->cmd & 0xffff;
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (cmd >= he->low && cmd <= he->high) {
+ error = (*he->func)(td, args);
+ if (error != ENOIOCTL) {
+ fdrop(fp, td);
+ return (error);
+ }
+ }
+ }
+ fdrop(fp, td);
+
+ printf("linux: 'ioctl' fd=%d, cmd=0x%x ('%c',%d) not implemented\n",
+ args->fd, (int)(args->cmd & 0xffff),
+ (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
+
+ return (EINVAL);
+}
+
+int
+linux_ioctl_register_handler(struct linux_ioctl_handler *h)
+{
+ struct handler_element *he, *cur;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ /*
+ * Reuse the element if the handler is already on the list, otherwise
+ * create a new element.
+ */
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (he->func == h->func)
+ break;
+ }
+ if (he == NULL) {
+ MALLOC(he, struct handler_element *, sizeof(*he),
+ M_LINUX, M_WAITOK);
+ he->func = h->func;
+ } else
+ TAILQ_REMOVE(&handlers, he, list);
+
+ /* Initialize range information. */
+ he->low = h->low;
+ he->high = h->high;
+ he->span = h->high - h->low + 1;
+
+ /* Add the element to the list, sorted on span. */
+ TAILQ_FOREACH(cur, &handlers, list) {
+ if (cur->span > he->span) {
+ TAILQ_INSERT_BEFORE(cur, he, list);
+ return (0);
+ }
+ }
+ TAILQ_INSERT_TAIL(&handlers, he, list);
+
+ return (0);
+}
+
+int
+linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
+{
+ struct handler_element *he;
+
+ if (h == NULL || h->func == NULL)
+ return (EINVAL);
+
+ TAILQ_FOREACH(he, &handlers, list) {
+ if (he->func == h->func) {
+ TAILQ_REMOVE(&handlers, he, list);
+ FREE(he, M_LINUX);
+ return (0);
+ }
+ }
+
+ return (EINVAL);
+}
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
new file mode 100644
index 0000000..0d77e0d
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.h
@@ -0,0 +1,668 @@
+/*
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_IOCTL_H_
+#define _LINUX_IOCTL_H_
+
+/*
+ * disk
+ */
+#define LINUX_BLKROSET 0x125d
+#define LINUX_BLKROGET 0x125e
+#define LINUX_BLKRRPART 0x125f
+#define LINUX_BLKGETSIZE 0x1260
+#define LINUX_BLKFLSBUF 0x1261
+#define LINUX_BLKRASET 0x1262
+#define LINUX_BLKRAGET 0x1263
+#define LINUX_BLKFRASET 0x1264
+#define LINUX_BLKFRAGET 0x1265
+#define LINUX_BLKSECTSET 0x1266
+#define LINUX_BLKSECTGET 0x1267
+#define LINUX_BLKSSZGET 0x1268
+
+#define LINUX_IOCTL_DISK_MIN LINUX_BLKROSET
+#define LINUX_IOCTL_DISK_MAX LINUX_BLKSSZGET
+
+/*
+ * cdrom
+ */
+#define LINUX_CDROMPAUSE 0x5301
+#define LINUX_CDROMRESUME 0x5302
+#define LINUX_CDROMPLAYMSF 0x5303
+#define LINUX_CDROMPLAYTRKIND 0x5304
+#define LINUX_CDROMREADTOCHDR 0x5305
+#define LINUX_CDROMREADTOCENTRY 0x5306
+#define LINUX_CDROMSTOP 0x5307
+#define LINUX_CDROMSTART 0x5308
+#define LINUX_CDROMEJECT 0x5309
+#define LINUX_CDROMVOLCTRL 0x530a
+#define LINUX_CDROMSUBCHNL 0x530b
+#define LINUX_CDROMREADMODE2 0x530c
+#define LINUX_CDROMREADMODE1 0x530d
+#define LINUX_CDROMREADAUDIO 0x530e
+#define LINUX_CDROMEJECT_SW 0x530f
+#define LINUX_CDROMMULTISESSION 0x5310
+#define LINUX_CDROM_GET_UPC 0x5311
+#define LINUX_CDROMRESET 0x5312
+#define LINUX_CDROMVOLREAD 0x5313
+#define LINUX_CDROMREADRAW 0x5314
+#define LINUX_CDROMREADCOOKED 0x5315
+#define LINUX_CDROMSEEK 0x5316
+#define LINUX_CDROMPLAYBLK 0x5317
+#define LINUX_CDROMREADALL 0x5318
+#define LINUX_CDROMCLOSETRAY 0x5319
+#define LINUX_CDROMLOADFROMSLOT 0x531a
+#define LINUX_CDROMGETSPINDOWN 0x531d
+#define LINUX_CDROMSETSPINDOWN 0x531e
+#define LINUX_CDROM_SET_OPTIONS 0x5320
+#define LINUX_CDROM_CLEAR_OPTIONS 0x5321
+#define LINUX_CDROM_SELECT_SPEED 0x5322
+#define LINUX_CDROM_SELECT_DISC 0x5323
+#define LINUX_CDROM_MEDIA_CHANGED 0x5325
+#define LINUX_CDROM_DRIVE_STATUS 0x5326
+#define LINUX_CDROM_DISC_STATUS 0x5327
+#define LINUX_CDROM_CHANGER_NSLOTS 0x5328
+#define LINUX_CDROM_LOCKDOOR 0x5329
+#define LINUX_CDROM_DEBUG 0x5330
+#define LINUX_CDROM_GET_CAPABILITY 0x5331
+#define LINUX_CDROMAUDIOBUFSIZ 0x5382
+#define LINUX_DVD_READ_STRUCT 0x5390
+#define LINUX_DVD_WRITE_STRUCT 0x5391
+#define LINUX_DVD_AUTH 0x5392
+#define LINUX_CDROM_SEND_PACKET 0x5393
+#define LINUX_CDROM_NEXT_WRITABLE 0x5394
+#define LINUX_CDROM_LAST_WRITTEN 0x5395
+
+#define LINUX_IOCTL_CDROM_MIN LINUX_CDROMPAUSE
+#define LINUX_IOCTL_CDROM_MAX LINUX_CDROM_LAST_WRITTEN
+
+#define LINUX_CDROM_LBA 0x01
+#define LINUX_CDROM_MSF 0x02
+
+#define LINUX_DVD_LU_SEND_AGID 0
+#define LINUX_DVD_HOST_SEND_CHALLENGE 1
+#define LINUX_DVD_LU_SEND_KEY1 2
+#define LINUX_DVD_LU_SEND_CHALLENGE 3
+#define LINUX_DVD_HOST_SEND_KEY2 4
+#define LINUX_DVD_AUTH_ESTABLISHED 5
+#define LINUX_DVD_AUTH_FAILURE 6
+#define LINUX_DVD_LU_SEND_TITLE_KEY 7
+#define LINUX_DVD_LU_SEND_ASF 8
+#define LINUX_DVD_INVALIDATE_AGID 9
+#define LINUX_DVD_LU_SEND_RPC_STATE 10
+#define LINUX_DVD_HOST_SEND_RPC_STATE 11
+
+/*
+ * console
+ */
+#define LINUX_KIOCSOUND 0x4B2F
+#define LINUX_KDMKTONE 0x4B30
+#define LINUX_KDGETLED 0x4B31
+#define LINUX_KDSETLED 0x4B32
+#define LINUX_KDSETMODE 0x4B3A
+#define LINUX_KDGETMODE 0x4B3B
+#define LINUX_KDGKBMODE 0x4B44
+#define LINUX_KDSKBMODE 0x4B45
+#define LINUX_VT_OPENQRY 0x5600
+#define LINUX_VT_GETMODE 0x5601
+#define LINUX_VT_SETMODE 0x5602
+#define LINUX_VT_GETSTATE 0x5603
+#define LINUX_VT_RELDISP 0x5605
+#define LINUX_VT_ACTIVATE 0x5606
+#define LINUX_VT_WAITACTIVE 0x5607
+
+#define LINUX_IOCTL_CONSOLE_MIN LINUX_KIOCSOUND
+#define LINUX_IOCTL_CONSOLE_MAX LINUX_VT_WAITACTIVE
+
+#define LINUX_LED_SCR 0x01
+#define LINUX_LED_NUM 0x02
+#define LINUX_LED_CAP 0x04
+
+#define LINUX_KD_TEXT 0x0
+#define LINUX_KD_GRAPHICS 0x1
+#define LINUX_KD_TEXT0 0x2
+#define LINUX_KD_TEXT1 0x3
+
+#define LINUX_KBD_RAW 0
+#define LINUX_KBD_XLATE 1
+#define LINUX_KBD_MEDIUMRAW 2
+
+/*
+ * socket
+ */
+#define LINUX_FIOSETOWN 0x8901
+#define LINUX_SIOCSPGRP 0x8902
+#define LINUX_FIOGETOWN 0x8903
+#define LINUX_SIOCGPGRP 0x8904
+#define LINUX_SIOCATMARK 0x8905
+#define LINUX_SIOCGSTAMP 0x8906
+#define LINUX_SIOCGIFCONF 0x8912
+#define LINUX_SIOCGIFFLAGS 0x8913
+#define LINUX_SIOCGIFADDR 0x8915
+#define LINUX_SIOCSIFADDR 0x8916
+#define LINUX_SIOCGIFDSTADDR 0x8917
+#define LINUX_SIOCGIFBRDADDR 0x8919
+#define LINUX_SIOCGIFNETMASK 0x891b
+#define LINUX_SIOCSIFNETMASK 0x891c
+#define LINUX_SIOCGIFMTU 0x8921
+#define LINUX_SIOCSIFMTU 0x8922
+#define LINUX_SIOCSIFNAME 0x8923
+#define LINUX_SIOCSIFHWADDR 0x8924
+#define LINUX_SIOCGIFHWADDR 0x8927
+#define LINUX_SIOCADDMULTI 0x8931
+#define LINUX_SIOCDELMULTI 0x8932
+
+#define LINUX_IOCTL_SOCKET_MIN LINUX_FIOSETOWN
+#define LINUX_IOCTL_SOCKET_MAX LINUX_SIOCDELMULTI
+
+/*
+ * Device private ioctl calls
+ */
+#define LINUX_SIOCDEVPRIVATE 0x89F0 /* to 89FF */
+#define LINUX_IOCTL_PRIVATE_MIN LINUX_SIOCDEVPRIVATE
+#define LINUX_IOCTL_PRIVATE_MAX LINUX_SIOCDEVPRIVATE+0xf
+
+/*
+ * sound
+ */
+#define LINUX_SOUND_MIXER_WRITE_VOLUME 0x4d00
+#define LINUX_SOUND_MIXER_WRITE_BASS 0x4d01
+#define LINUX_SOUND_MIXER_WRITE_TREBLE 0x4d02
+#define LINUX_SOUND_MIXER_WRITE_SYNTH 0x4d03
+#define LINUX_SOUND_MIXER_WRITE_PCM 0x4d04
+#define LINUX_SOUND_MIXER_WRITE_SPEAKER 0x4d05
+#define LINUX_SOUND_MIXER_WRITE_LINE 0x4d06
+#define LINUX_SOUND_MIXER_WRITE_MIC 0x4d07
+#define LINUX_SOUND_MIXER_WRITE_CD 0x4d08
+#define LINUX_SOUND_MIXER_WRITE_IMIX 0x4d09
+#define LINUX_SOUND_MIXER_WRITE_ALTPCM 0x4d0A
+#define LINUX_SOUND_MIXER_WRITE_RECLEV 0x4d0B
+#define LINUX_SOUND_MIXER_WRITE_IGAIN 0x4d0C
+#define LINUX_SOUND_MIXER_WRITE_OGAIN 0x4d0D
+#define LINUX_SOUND_MIXER_WRITE_LINE1 0x4d0E
+#define LINUX_SOUND_MIXER_WRITE_LINE2 0x4d0F
+#define LINUX_SOUND_MIXER_WRITE_LINE3 0x4d10
+#define LINUX_OSS_GETVERSION 0x4d76
+#define LINUX_SOUND_MIXER_READ_DEVMASK 0x4dfe
+#define LINUX_SOUND_MIXER_WRITE_RECSRC 0x4dff
+#define LINUX_SNDCTL_DSP_RESET 0x5000
+#define LINUX_SNDCTL_DSP_SYNC 0x5001
+#define LINUX_SNDCTL_DSP_SPEED 0x5002
+#define LINUX_SNDCTL_DSP_STEREO 0x5003
+#define LINUX_SNDCTL_DSP_GETBLKSIZE 0x5004
+#define LINUX_SNDCTL_DSP_SETBLKSIZE LINUX_SNDCTL_DSP_GETBLKSIZE
+#define LINUX_SNDCTL_DSP_SETFMT 0x5005
+#define LINUX_SOUND_PCM_WRITE_CHANNELS 0x5006
+#define LINUX_SOUND_PCM_WRITE_FILTER 0x5007
+#define LINUX_SNDCTL_DSP_POST 0x5008
+#define LINUX_SNDCTL_DSP_SUBDIVIDE 0x5009
+#define LINUX_SNDCTL_DSP_SETFRAGMENT 0x500A
+#define LINUX_SNDCTL_DSP_GETFMTS 0x500B
+#define LINUX_SNDCTL_DSP_GETOSPACE 0x500C
+#define LINUX_SNDCTL_DSP_GETISPACE 0x500D
+#define LINUX_SNDCTL_DSP_NONBLOCK 0x500E
+#define LINUX_SNDCTL_DSP_GETCAPS 0x500F
+#define LINUX_SNDCTL_DSP_GETTRIGGER 0x5010
+#define LINUX_SNDCTL_DSP_SETTRIGGER LINUX_SNDCTL_DSP_GETTRIGGER
+#define LINUX_SNDCTL_DSP_GETIPTR 0x5011
+#define LINUX_SNDCTL_DSP_GETOPTR 0x5012
+#define LINUX_SNDCTL_DSP_GETODELAY 0x5017
+#define LINUX_SNDCTL_SEQ_RESET 0x5100
+#define LINUX_SNDCTL_SEQ_SYNC 0x5101
+#define LINUX_SNDCTL_SYNTH_INFO 0x5102
+#define LINUX_SNDCTL_SEQ_CTRLRATE 0x5103
+#define LINUX_SNDCTL_SEQ_GETOUTCOUNT 0x5104
+#define LINUX_SNDCTL_SEQ_GETINCOUNT 0x5105
+#define LINUX_SNDCTL_SEQ_PERCMODE 0x5106
+#define LINUX_SNDCTL_FM_LOAD_INSTR 0x5107
+#define LINUX_SNDCTL_SEQ_TESTMIDI 0x5108
+#define LINUX_SNDCTL_SEQ_RESETSAMPLES 0x5109
+#define LINUX_SNDCTL_SEQ_NRSYNTHS 0x510A
+#define LINUX_SNDCTL_SEQ_NRMIDIS 0x510B
+#define LINUX_SNDCTL_MIDI_INFO 0x510C
+#define LINUX_SNDCTL_SEQ_TRESHOLD 0x510D
+#define LINUX_SNDCTL_SYNTH_MEMAVL 0x510E
+
+#define LINUX_IOCTL_SOUND_MIN LINUX_SOUND_MIXER_WRITE_VOLUME
+#define LINUX_IOCTL_SOUND_MAX LINUX_SNDCTL_SYNTH_MEMAVL
+
+/*
+ * termio
+ */
+#ifdef __alpha__
+#define LINUX_TCGETS 0x7413
+#define LINUX_TCSETS 0x7414
+#define LINUX_TCSETSW 0x7415
+#define LINUX_TCSETSF 0x7416
+#define LINUX_TCGETA 0x7417
+#define LINUX_TCSETA 0x7418
+#define LINUX_TCSETAW 0x7419
+#define LINUX_TCSETAF 0x741c
+#define LINUX_TCSBRK 0x741d
+#define LINUX_TCXONC 0x741e
+#define LINUX_TCFLSH 0x741f
+#else
+#define LINUX_TCGETS 0x5401
+#define LINUX_TCSETS 0x5402
+#define LINUX_TCSETSW 0x5403
+#define LINUX_TCSETSF 0x5404
+#define LINUX_TCGETA 0x5405
+#define LINUX_TCSETA 0x5406
+#define LINUX_TCSETAW 0x5407
+#define LINUX_TCSETAF 0x5408
+#define LINUX_TCSBRK 0x5409
+#define LINUX_TCXONC 0x540A
+#define LINUX_TCFLSH 0x540B
+#endif
+
+#define LINUX_TIOCEXCL 0x540C
+#define LINUX_TIOCNXCL 0x540D
+#define LINUX_TIOCSCTTY 0x540E
+
+#ifdef __alpha__
+#define LINUX_TIOCSPGRP 0x7476
+#define LINUX_TIOCGPGRP 0x7477
+#else
+#define LINUX_TIOCGPGRP 0x540F
+#define LINUX_TIOCSPGRP 0x5410
+#endif
+
+#define LINUX_TIOCOUTQ 0x5411
+#define LINUX_TIOCSTI 0x5412
+
+#ifdef __alpha__
+#define LINUX_TIOCSWINSZ 0x7467
+#define LINUX_TIOCGWINSZ 0x7468
+#else
+#define LINUX_TIOCGWINSZ 0x5413
+#define LINUX_TIOCSWINSZ 0x5414
+#endif
+
+#define LINUX_TIOCMGET 0x5415
+#define LINUX_TIOCMBIS 0x5416
+#define LINUX_TIOCMBIC 0x5417
+#define LINUX_TIOCMSET 0x5418
+#define LINUX_TIOCGSOFTCAR 0x5419
+#define LINUX_TIOCSSOFTCAR 0x541A
+
+#ifdef __alpha__
+#define LINUX_FIONREAD 0x667f
+#else
+#define LINUX_FIONREAD 0x541B
+#endif
+
+#define LINUX_TIOCINQ FIONREAD
+#define LINUX_TIOCLINUX 0x541C
+#define LINUX_TIOCCONS 0x541D
+#define LINUX_TIOCGSERIAL 0x541E
+#define LINUX_TIOCSSERIAL 0x541F
+#define LINUX_TIOCPKT 0x5420
+
+#ifdef __alpha__
+#define LINUX_FIONBIO 0x667e
+#else
+#define LINUX_FIONBIO 0x5421
+#endif
+
+#define LINUX_TIOCNOTTY 0x5422
+#define LINUX_TIOCSETD 0x5423
+#define LINUX_TIOCGETD 0x5424
+#define LINUX_TCSBRKP 0x5425
+#define LINUX_TIOCTTYGSTRUCT 0x5426
+
+#ifdef __alpha__
+#define LINUX_FIOCLEX 0x6601
+#define LINUX_FIONCLEX 0x6602
+#define LINUX_FIOASYNC 0x667d
+#else
+#define LINUX_FIONCLEX 0x5450
+#define LINUX_FIOCLEX 0x5451
+#define LINUX_FIOASYNC 0x5452
+#endif
+
+#define LINUX_TIOCSERCONFIG 0x5453
+#define LINUX_TIOCSERGWILD 0x5454
+#define LINUX_TIOCSERSWILD 0x5455
+#define LINUX_TIOCGLCKTRMIOS 0x5456
+#define LINUX_TIOCSLCKTRMIOS 0x5457
+
+#ifdef __alpha__
+#define LINUX_IOCTL_TERMIO_MIN LINUX_TIOCEXCL
+#define LINUX_IOCTL_TERMIO_MAX LINUX_TIOCGPGRP
+#else
+#define LINUX_IOCTL_TERMIO_MIN LINUX_TCGETS
+#define LINUX_IOCTL_TERMIO_MAX LINUX_TIOCSLCKTRMIOS
+#endif
+
+/* arguments for tcflow() and LINUX_TCXONC */
+#define LINUX_TCOOFF 0
+#define LINUX_TCOON 1
+#define LINUX_TCIOFF 2
+#define LINUX_TCION 3
+
+/* arguments for tcflush() and LINUX_TCFLSH */
+#define LINUX_TCIFLUSH 0
+#define LINUX_TCOFLUSH 1
+#define LINUX_TCIOFLUSH 2
+
+/* line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+/* Linux termio c_cc values */
+#ifdef __alpha__
+#define LINUX__VINTR 0
+#define LINUX__VQUIT 1
+#define LINUX__VERASE 2
+#define LINUX__VKILL 3
+#define LINUX__VEOF 4
+#define LINUX__VMIN 4
+#define LINUX__VEOL 5
+#define LINUX__VTIME 5
+#define LINUX__VEOL2 6
+#define LINUX__VSWTC 7
+#else
+#define LINUX_VINTR 0
+#define LINUX_VQUIT 1
+#define LINUX_VERASE 2
+#define LINUX_VKILL 3
+#define LINUX_VEOF 4
+#define LINUX_VTIME 5
+#define LINUX_VMIN 6
+#define LINUX_VSWTC 7
+#endif
+#define LINUX_NCC 8
+
+/* Linux termios c_cc values */
+#ifdef __alpha__
+#define LINUX_VEOF 0
+#define LINUX_VEOL 1
+#define LINUX_VEOL2 2
+#define LINUX_VERASE 3
+#define LINUX_VWERASE 4
+#define LINUX_VKILL 5
+#define LINUX_VREPRINT 6
+#define LINUX_VSWTC 7
+#define LINUX_VINTR 8
+#define LINUX_VQUIT 9
+#define LINUX_VSUSP 10
+#define LINUX_VSTART 12
+#define LINUX_VSTOP 13
+#define LINUX_VLNEXT 14
+#define LINUX_VDISCARD 15
+#define LINUX_VMIN 16
+#define LINUX_VTIME 17
+#else
+/* In addition to the termio values */
+#define LINUX_VSTART 8
+#define LINUX_VSTOP 9
+#define LINUX_VSUSP 10
+#define LINUX_VEOL 11
+#define LINUX_VREPRINT 12
+#define LINUX_VDISCARD 13
+#define LINUX_VWERASE 14
+#define LINUX_VLNEXT 15
+#define LINUX_VEOL2 16
+#endif
+#define LINUX_NCCS 19
+
+#define LINUX_POSIX_VDISABLE '\0'
+
+/* Linux c_iflag masks */
+#define LINUX_IGNBRK 0x0000001
+#define LINUX_BRKINT 0x0000002
+#define LINUX_IGNPAR 0x0000004
+#define LINUX_PARMRK 0x0000008
+#define LINUX_INPCK 0x0000010
+#define LINUX_ISTRIP 0x0000020
+#define LINUX_INLCR 0x0000040
+#define LINUX_IGNCR 0x0000080
+#define LINUX_ICRNL 0x0000100
+
+#ifdef __alpha__
+#define LINUX_IXON 0x0000200
+#define LINUX_IXOFF 0x0000400
+#define LINUX_IXANY 0x0000800
+#define LINUX_IUCLC 0x0001000
+#else
+#define LINUX_IUCLC 0x0000200
+#define LINUX_IXON 0x0000400
+#define LINUX_IXANY 0x0000800
+#define LINUX_IXOFF 0x0001000
+#endif
+
+#define LINUX_IMAXBEL 0x0002000
+
+/* Linux c_oflag masks */
+#define LINUX_OPOST 0x0000001
+
+#ifdef __alpha__
+#define LINUX_ONLCR 0x0000002
+#define LINUX_OLCUC 0x0000004
+#else
+#define LINUX_OLCUC 0x0000002
+#define LINUX_ONLCR 0x0000004
+#endif
+
+#define LINUX_OCRNL 0x0000008
+#define LINUX_ONOCR 0x0000010
+#define LINUX_ONLRET 0x0000020
+#define LINUX_OFILL 0x0000040
+#define LINUX_OFDEL 0x0000080
+
+#ifdef __alpha__
+#define LINUX_NLDLY 0x0000300
+#define LINUX_NL0 0x0000000
+#define LINUX_NL1 0x0000100
+#define LINUX_NL2 0x0000200
+#define LINUX_NL3 0x0000300
+#define LINUX_TABDLY 0x000C000
+#define LINUX_TAB0 0x0000000
+#define LINUX_TAB1 0x0004000
+#define LINUX_TAB2 0x0008000
+#define LINUX_TAB3 0x000C000
+#define LINUX_CRDLY 0x0030000
+#define LINUX_CR0 0x0000000
+#define LINUX_CR1 0x0010000
+#define LINUX_CR2 0x0020000
+#define LINUX_CR3 0x0030000
+#define LINUX_FFDLY 0x0040000
+#define LINUX_FF0 0x0000000
+#define LINUX_FF1 0x0040000
+#define LINUX_BSDLY 0x0080000
+#define LINUX_BS0 0x0000000
+#define LINUX_BS1 0x0080000
+#define LINUX_VTDLY 0x0100000
+#define LINUX_VT0 0x0000000
+#define LINUX_VT1 0x0100000
+#define LINUX_XTABS 0x0200000
+#else
+#define LINUX_NLDLY 0x0000100
+#define LINUX_NL0 0x0000000
+#define LINUX_NL1 0x0000100
+#define LINUX_CRDLY 0x0000600
+#define LINUX_CR0 0x0000000
+#define LINUX_CR1 0x0000200
+#define LINUX_CR2 0x0000400
+#define LINUX_CR3 0x0000600
+#define LINUX_TABDLY 0x0001800
+#define LINUX_TAB0 0x0000000
+#define LINUX_TAB1 0x0000800
+#define LINUX_TAB2 0x0001000
+#define LINUX_TAB3 0x0001800
+#define LINUX_XTABS 0x0001800
+#define LINUX_BSDLY 0x0002000
+#define LINUX_BS0 0x0000000
+#define LINUX_BS1 0x0002000
+#define LINUX_VTDLY 0x0004000
+#define LINUX_VT0 0x0000000
+#define LINUX_VT1 0x0004000
+#define LINUX_FFDLY 0x0008000
+#define LINUX_FF0 0x0000000
+#define LINUX_FF1 0x0008000
+#endif
+
+#ifdef __alpha__
+#define LINUX_CBAUD 0x0000001f
+#else
+#define LINUX_CBAUD 0x0000100f
+#endif
+
+#define LINUX_B0 0x00000000
+#define LINUX_B50 0x00000001
+#define LINUX_B75 0x00000002
+#define LINUX_B110 0x00000003
+#define LINUX_B134 0x00000004
+#define LINUX_B150 0x00000005
+#define LINUX_B200 0x00000006
+#define LINUX_B300 0x00000007
+#define LINUX_B600 0x00000008
+#define LINUX_B1200 0x00000009
+#define LINUX_B1800 0x0000000a
+#define LINUX_B2400 0x0000000b
+#define LINUX_B4800 0x0000000c
+#define LINUX_B9600 0x0000000d
+#define LINUX_B19200 0x0000000e
+#define LINUX_B38400 0x0000000f
+#define LINUX_EXTA LINUX_B19200
+#define LINUX_EXTB LINUX_B38400
+
+#ifdef __alpha__
+#define LINUX_CBAUDEX 0x00000000
+#define LINUX_B57600 0x00000010
+#define LINUX_B115200 0x00000011
+#else
+#define LINUX_CBAUDEX 0x00001000
+#define LINUX_B57600 0x00001001
+#define LINUX_B115200 0x00001002
+#endif
+
+#ifdef __alpha__
+#define LINUX_CSIZE 0x00000300
+#define LINUX_CS5 0x00000000
+#define LINUX_CS6 0x00000100
+#define LINUX_CS7 0x00000200
+#define LINUX_CS8 0x00000300
+#define LINUX_CSTOPB 0x00000400
+#define LINUX_CREAD 0x00000800
+#define LINUX_PARENB 0x00001000
+#define LINUX_PARODD 0x00002000
+#define LINUX_HUPCL 0x00004000
+#define LINUX_CLOCAL 0x00008000
+#else
+#define LINUX_CSIZE 0x00000030
+#define LINUX_CS5 0x00000000
+#define LINUX_CS6 0x00000010
+#define LINUX_CS7 0x00000020
+#define LINUX_CS8 0x00000030
+#define LINUX_CSTOPB 0x00000040
+#define LINUX_CREAD 0x00000080
+#define LINUX_PARENB 0x00000100
+#define LINUX_PARODD 0x00000200
+#define LINUX_HUPCL 0x00000400
+#define LINUX_CLOCAL 0x00000800
+#endif
+
+#define LINUX_CRTSCTS 0x80000000
+
+/* Linux c_lflag masks */
+#ifdef __alpha__
+#define LINUX_ECHOKE 0x00000001
+#define LINUX_ECHOE 0x00000002
+#define LINUX_ECHOK 0x00000004
+#define LINUX_ECHO 0x00000008
+#define LINUX_ECHONL 0x00000010
+#define LINUX_ECHOPRT 0x00000020
+#define LINUX_ECHOCTL 0x00000040
+#define LINUX_ISIG 0x00000080
+#define LINUX_ICANON 0x00000100
+#define LINUX_IEXTEN 0x00000400
+#define LINUX_XCASE 0x00004000
+#define LINUX_TOSTOP 0x00400000
+#define LINUX_FLUSHO 0x00800000
+#define LINUX_PENDIN 0x20000000
+#define LINUX_NOFLSH 0x80000000
+#else
+#define LINUX_ISIG 0x00000001
+#define LINUX_ICANON 0x00000002
+#define LINUX_XCASE 0x00000004
+#define LINUX_ECHO 0x00000008
+#define LINUX_ECHOE 0x00000010
+#define LINUX_ECHOK 0x00000020
+#define LINUX_ECHONL 0x00000040
+#define LINUX_NOFLSH 0x00000080
+#define LINUX_TOSTOP 0x00000100
+#define LINUX_ECHOCTL 0x00000200
+#define LINUX_ECHOPRT 0x00000400
+#define LINUX_ECHOKE 0x00000800
+#define LINUX_FLUSHO 0x00001000
+#define LINUX_PENDIN 0x00002000
+#define LINUX_IEXTEN 0x00008000
+#endif
+
+/* serial_struct values for TIOC[GS]SERIAL ioctls */
+#define LINUX_ASYNC_CLOSING_WAIT_INF 0
+#define LINUX_ASYNC_CLOSING_WAIT_NONE 65535
+
+#define LINUX_PORT_UNKNOWN 0
+#define LINUX_PORT_8250 1
+#define LINUX_PORT_16450 2
+#define LINUX_PORT_16550 3
+#define LINUX_PORT_16550A 4
+#define LINUX_PORT_CIRRUS 5
+#define LINUX_PORT_16650 6
+
+#define LINUX_PORT_MAX 6
+
+#define LINUX_ASYNC_HUP_NOTIFY 0x0001
+#define LINUX_ASYNC_FOURPORT 0x0002
+#define LINUX_ASYNC_SAK 0x0004
+#define LINUX_ASYNC_SPLIT_TERMIOS 0x0008
+#define LINUX_ASYNC_SPD_MASK 0x0030
+#define LINUX_ASYNC_SPD_HI 0x0010
+#define LINUX_ASYNC_SPD_VHI 0x0020
+#define LINUX_ASYNC_SPD_CUST 0x0030
+#define LINUX_ASYNC_SKIP_TEST 0x0040
+#define LINUX_ASYNC_AUTO_IRQ 0x0080
+#define LINUX_ASYNC_SESSION_LOCKOUT 0x0100
+#define LINUX_ASYNC_PGRP_LOCKOUT 0x0200
+#define LINUX_ASYNC_CALLOUT_NOHUP 0x0400
+#define LINUX_ASYNC_FLAGS 0x0FFF
+
+/*
+ * This doesn't really belong here, but I can't think of a better
+ * place to put it.
+ */
+struct ifnet;
+int linux_ifname(struct ifnet *, char *, size_t);
+
+#endif /* !_LINUX_IOCTL_H_ */
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
new file mode 100644
index 0000000..cf3bf61
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.c
@@ -0,0 +1,528 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_util.h>
+
+struct l_seminfo {
+ l_int semmap;
+ l_int semmni;
+ l_int semmns;
+ l_int semmnu;
+ l_int semmsl;
+ l_int semopm;
+ l_int semume;
+ l_int semusz;
+ l_int semvmx;
+ l_int semaem;
+};
+
+struct l_shminfo {
+ l_int shmmax;
+ l_int shmmin;
+ l_int shmmni;
+ l_int shmseg;
+ l_int shmall;
+};
+
+struct l_shm_info {
+ l_int used_ids;
+ l_ulong shm_tot; /* total allocated shm */
+ l_ulong shm_rss; /* total resident shm */
+ l_ulong shm_swp; /* total swapped shm */
+ l_ulong swap_attempts;
+ l_ulong swap_successes;
+};
+
+static void
+bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp)
+{
+ lpp->shmmax = bpp->shmmax;
+ lpp->shmmin = bpp->shmmin;
+ lpp->shmmni = bpp->shmmni;
+ lpp->shmseg = bpp->shmseg;
+ lpp->shmall = bpp->shmall;
+}
+
+static void
+bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp)
+{
+ lpp->used_ids = bpp->used_ids ;
+ lpp->shm_tot = bpp->shm_tot ;
+ lpp->shm_rss = bpp->shm_rss ;
+ lpp->shm_swp = bpp->shm_swp ;
+ lpp->swap_attempts = bpp->swap_attempts ;
+ lpp->swap_successes = bpp->swap_successes ;
+}
+
+struct l_ipc_perm {
+ l_key_t key;
+ l_uid16_t uid;
+ l_gid16_t gid;
+ l_uid16_t cuid;
+ l_gid16_t cgid;
+ l_ushort mode;
+ l_ushort seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
+{
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct l_semid_ds {
+ struct l_ipc_perm sem_perm;
+ l_time_t sem_otime;
+ l_time_t sem_ctime;
+ void *sem_base;
+ void *sem_pending;
+ void *sem_pending_last;
+ void *undo;
+ l_ushort sem_nsems;
+};
+
+struct l_shmid_ds {
+ struct l_ipc_perm shm_perm;
+ l_int shm_segsz;
+ l_time_t shm_atime;
+ l_time_t shm_dtime;
+ l_time_t shm_ctime;
+ l_ushort shm_cpid;
+ l_ushort shm_lpid;
+ l_short shm_nattch;
+ l_ushort private1;
+ void *private2;
+ void *private3;
+};
+
+static void
+linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
+ bsp->sem_otime = lsp->sem_otime;
+ bsp->sem_ctime = lsp->sem_ctime;
+ bsp->sem_nsems = lsp->sem_nsems;
+ bsp->sem_base = lsp->sem_base;
+}
+
+static void
+bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
+ lsp->sem_otime = bsp->sem_otime;
+ lsp->sem_ctime = bsp->sem_ctime;
+ lsp->sem_nsems = bsp->sem_nsems;
+ lsp->sem_base = bsp->sem_base;
+}
+
+static void
+linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
+}
+
+int
+linux_semop(struct thread *td, struct linux_semop_args *args)
+{
+ struct semop_args /* {
+ int semid;
+ struct sembuf *sops;
+ int nsops;
+ } */ bsd_args;
+
+ bsd_args.semid = args->semid;
+ bsd_args.sops = (struct sembuf *)args->tsops;
+ bsd_args.nsops = args->nsops;
+ return semop(td, &bsd_args);
+}
+
+int
+linux_semget(struct thread *td, struct linux_semget_args *args)
+{
+ struct semget_args /* {
+ key_t key;
+ int nsems;
+ int semflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->key;
+ bsd_args.nsems = args->nsems;
+ bsd_args.semflg = args->semflg;
+ return semget(td, &bsd_args);
+}
+
+int
+linux_semctl(struct thread *td, struct linux_semctl_args *args)
+{
+ struct l_semid_ds linux_semid;
+ struct __semctl_args /* {
+ int semid;
+ int semnum;
+ int cmd;
+ union semun *arg;
+ } */ bsd_args;
+ struct l_seminfo linux_seminfo;
+ int error;
+ union semun *unptr;
+ caddr_t sg;
+
+ sg = stackgap_init();
+
+ /* Make sure the arg parameter can be copied in. */
+ unptr = stackgap_alloc(&sg, sizeof(union semun));
+ bcopy(&args->arg, unptr, sizeof(union semun));
+
+ bsd_args.semid = args->semid;
+ bsd_args.semnum = args->semnum;
+ bsd_args.arg = unptr;
+
+ switch (args->cmd) {
+ case LINUX_IPC_RMID:
+ bsd_args.cmd = IPC_RMID;
+ break;
+ case LINUX_GETNCNT:
+ bsd_args.cmd = GETNCNT;
+ break;
+ case LINUX_GETPID:
+ bsd_args.cmd = GETPID;
+ break;
+ case LINUX_GETVAL:
+ bsd_args.cmd = GETVAL;
+ break;
+ case LINUX_GETZCNT:
+ bsd_args.cmd = GETZCNT;
+ break;
+ case LINUX_SETVAL:
+ bsd_args.cmd = SETVAL;
+ break;
+ case LINUX_IPC_SET:
+ bsd_args.cmd = IPC_SET;
+ error = copyin((caddr_t)args->arg.buf, &linux_semid,
+ sizeof(linux_semid));
+ if (error)
+ return (error);
+ unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
+ linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
+ return __semctl(td, &bsd_args);
+ case LINUX_IPC_STAT:
+ case LINUX_SEM_STAT:
+ if( args->cmd == LINUX_IPC_STAT )
+ bsd_args.cmd = IPC_STAT;
+ else
+ bsd_args.cmd = SEM_STAT;
+ unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
+ error = __semctl(td, &bsd_args);
+ if (error)
+ return error;
+ td->td_retval[0] = IXSEQ_TO_IPCID(bsd_args.semid,
+ unptr->buf->sem_perm);
+ bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
+ return copyout(&linux_semid, (caddr_t)args->arg.buf,
+ sizeof(linux_semid));
+ case LINUX_IPC_INFO:
+ case LINUX_SEM_INFO:
+ error = copyin((caddr_t)args->arg.buf, &linux_seminfo,
+ sizeof(linux_seminfo) );
+ if (error)
+ return error;
+ bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) );
+/* XXX BSD equivalent?
+#define used_semids 10
+#define used_sems 10
+ linux_seminfo.semusz = used_semids;
+ linux_seminfo.semaem = used_sems;
+*/
+ error = copyout((caddr_t)&linux_seminfo, (caddr_t)args->arg.buf,
+ sizeof(linux_seminfo) );
+ if (error)
+ return error;
+ td->td_retval[0] = seminfo.semmni;
+ return 0; /* No need for __semctl call */
+ case LINUX_GETALL:
+ /* FALLTHROUGH */
+ case LINUX_SETALL:
+ /* FALLTHROUGH */
+ default:
+ uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd);
+ return EINVAL;
+ }
+ return __semctl(td, &bsd_args);
+}
+
+int
+linux_msgsnd(struct thread *td, struct linux_msgsnd_args *args)
+{
+ struct msgsnd_args /* {
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.msqid = args->msqid;
+ bsd_args.msgp = args->msgp;
+ bsd_args.msgsz = args->msgsz;
+ bsd_args.msgflg = args->msgflg;
+ return msgsnd(td, &bsd_args);
+}
+
+int
+linux_msgrcv(struct thread *td, struct linux_msgrcv_args *args)
+{
+ struct msgrcv_args /* {
+ int msqid;
+ void *msgp;
+ size_t msgsz;
+ long msgtyp;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.msqid = args->msqid;
+ bsd_args.msgp = args->msgp;
+ bsd_args.msgsz = args->msgsz;
+ bsd_args.msgtyp = args->msgtyp;
+ bsd_args.msgflg = args->msgflg;
+ return msgrcv(td, &bsd_args);
+}
+
+int
+linux_msgget(struct thread *td, struct linux_msgget_args *args)
+{
+ struct msgget_args /* {
+ key_t key;
+ int msgflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->key;
+ bsd_args.msgflg = args->msgflg;
+ return msgget(td, &bsd_args);
+}
+
+int
+linux_msgctl(struct thread *td, struct linux_msgctl_args *args)
+{
+ struct msgctl_args /* {
+ int msqid;
+ int cmd;
+ struct msqid_ds *buf;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.msqid = args->msqid;
+ bsd_args.cmd = args->cmd;
+ bsd_args.buf = (struct msqid_ds *)args->buf;
+ error = msgctl(td, &bsd_args);
+ return ((args->cmd == LINUX_IPC_RMID && error == EINVAL) ? 0 : error);
+}
+
+int
+linux_shmat(struct thread *td, struct linux_shmat_args *args)
+{
+ struct shmat_args /* {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } */ bsd_args;
+ int error;
+
+ bsd_args.shmid = args->shmid;
+ bsd_args.shmaddr = args->shmaddr;
+ bsd_args.shmflg = args->shmflg;
+ if ((error = shmat(td, &bsd_args)))
+ return error;
+#ifdef __i386__
+ if ((error = copyout(td->td_retval, (caddr_t)args->raddr, sizeof(l_ulong))))
+ return error;
+ td->td_retval[0] = 0;
+#endif
+ return 0;
+}
+
+int
+linux_shmdt(struct thread *td, struct linux_shmdt_args *args)
+{
+ struct shmdt_args /* {
+ void *shmaddr;
+ } */ bsd_args;
+
+ bsd_args.shmaddr = args->shmaddr;
+ return shmdt(td, &bsd_args);
+}
+
+int
+linux_shmget(struct thread *td, struct linux_shmget_args *args)
+{
+ struct shmget_args /* {
+ key_t key;
+ int size;
+ int shmflg;
+ } */ bsd_args;
+
+ bsd_args.key = args->key;
+ bsd_args.size = args->size;
+ bsd_args.shmflg = args->shmflg;
+ return shmget(td, &bsd_args);
+}
+
+int
+linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
+{
+ struct l_shmid_ds linux_shmid;
+ struct l_shminfo linux_shminfo;
+ struct l_shm_info linux_shm_info;
+ struct shmctl_args /* {
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+ } */ bsd_args;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ switch (args->cmd) {
+
+ case LINUX_IPC_INFO:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = IPC_INFO;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shminfo));
+ if ((error = shmctl(td, &bsd_args)))
+ return error;
+ bsd_to_linux_shminfo( (struct shminfo *)bsd_args.buf, &linux_shminfo );
+ return copyout(&linux_shminfo, (caddr_t)args->buf, sizeof(shminfo));
+
+ case LINUX_SHM_INFO:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = SHM_INFO;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shm_info));
+ if ((error = shmctl(td, &bsd_args)))
+ return error;
+ bsd_to_linux_shm_info( (struct shm_info *)bsd_args.buf, &linux_shm_info );
+ return copyout(&linux_shm_info, (caddr_t)args->buf, sizeof(struct shm_info));
+
+ case LINUX_IPC_STAT:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = IPC_STAT;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = shmctl(td, &bsd_args)))
+ return error;
+ bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
+ return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
+
+ case LINUX_SHM_STAT:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = SHM_STAT;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ if ((error = shmctl(td, &bsd_args))) {
+ return error;
+ }
+ bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
+ return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
+
+ case LINUX_IPC_SET:
+ if ((error = copyin((caddr_t)args->buf, &linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = IPC_SET;
+ return shmctl(td, &bsd_args);
+
+ case LINUX_IPC_RMID:
+ bsd_args.shmid = args->shmid;
+ bsd_args.cmd = IPC_RMID;
+ if (args->buf == NULL)
+ bsd_args.buf = NULL;
+ else {
+ if ((error = copyin((caddr_t)args->buf, &linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
+ linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
+ }
+ return shmctl(td, &bsd_args);
+
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ default:
+ uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd);
+ return EINVAL;
+ }
+}
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
new file mode 100644
index 0000000..183afe1
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.h
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_IPC_H_
+#define _LINUX_IPC_H_
+
+#ifdef __i386__
+
+struct linux_msgctl_args
+{
+ l_int msqid;
+ l_int cmd;
+ struct l_msqid_ds *buf;
+};
+
+struct linux_msgget_args
+{
+ l_key_t key;
+ l_int msgflg;
+};
+
+struct linux_msgrcv_args
+{
+ l_int msqid;
+ struct l_msgbuf *msgp;
+ l_size_t msgsz;
+ l_long msgtyp;
+ l_int msgflg;
+};
+
+struct linux_msgsnd_args
+{
+ l_int msqid;
+ struct l_msgbuf *msgp;
+ l_size_t msgsz;
+ l_int msgflg;
+};
+
+struct linux_semctl_args
+{
+ l_int semid;
+ l_int semnum;
+ l_int cmd;
+ union l_semun arg;
+};
+
+struct linux_semget_args
+{
+ l_key_t key;
+ l_int nsems;
+ l_int semflg;
+};
+
+struct linux_semop_args
+{
+ l_int semid;
+ struct l_sembuf *tsops;
+ l_uint nsops;
+};
+
+struct linux_shmat_args
+{
+ l_int shmid;
+ char *shmaddr;
+ l_int shmflg;
+ l_ulong *raddr;
+};
+
+struct linux_shmctl_args
+{
+ l_int shmid;
+ l_int cmd;
+ struct l_shmid_ds *buf;
+};
+
+struct linux_shmdt_args
+{
+ char *shmaddr;
+};
+
+struct linux_shmget_args
+{
+ l_key_t key;
+ l_size_t size;
+ l_int shmflg;
+};
+
+int linux_msgctl(struct thread *, struct linux_msgctl_args *);
+int linux_msgget(struct thread *, struct linux_msgget_args *);
+int linux_msgrcv(struct thread *, struct linux_msgrcv_args *);
+int linux_msgsnd(struct thread *, struct linux_msgsnd_args *);
+
+int linux_semctl(struct thread *, struct linux_semctl_args *);
+int linux_semget(struct thread *, struct linux_semget_args *);
+int linux_semop(struct thread *, struct linux_semop_args *);
+
+int linux_shmat(struct thread *, struct linux_shmat_args *);
+int linux_shmctl(struct thread *, struct linux_shmctl_args *);
+int linux_shmdt(struct thread *, struct linux_shmdt_args *);
+int linux_shmget(struct thread *, struct linux_shmget_args *);
+
+#endif /* __i386__ */
+
+#endif /* _LINUX_IPC_H_ */
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
new file mode 100644
index 0000000..d9cdd07
--- /dev/null
+++ b/sys/compat/linux/linux_mib.c
@@ -0,0 +1,354 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/jail.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/../linux/linux.h>
+#include <compat/linux/linux_mib.h>
+
+struct linux_prison {
+ char pr_osname[LINUX_MAX_UTSNAME];
+ char pr_osrelease[LINUX_MAX_UTSNAME];
+ int pr_oss_version;
+};
+
+SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
+ "Linux mode");
+
+static char linux_osname[LINUX_MAX_UTSNAME] = "Linux";
+
+static int
+linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
+{
+ char osname[LINUX_MAX_UTSNAME];
+ int error;
+
+ linux_get_osname(req->td->td_proc, osname);
+ error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ error = linux_set_osname(req->td->td_proc, osname);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, osname,
+ CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
+ 0, 0, linux_sysctl_osname, "A",
+ "Linux kernel OS name");
+
+static char linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2";
+
+static int
+linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
+{
+ char osrelease[LINUX_MAX_UTSNAME];
+ int error;
+
+ linux_get_osrelease(req->td->td_proc, osrelease);
+ error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ error = linux_set_osrelease(req->td->td_proc, osrelease);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
+ CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
+ 0, 0, linux_sysctl_osrelease, "A",
+ "Linux kernel OS release");
+
+static int linux_oss_version = 0x030600;
+
+static int
+linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
+{
+ int oss_version;
+ int error;
+
+ oss_version = linux_get_oss_version(req->td->td_proc);
+ error = sysctl_handle_int(oidp, &oss_version, 0, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ error = linux_set_oss_version(req->td->td_proc, oss_version);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON,
+ 0, 0, linux_sysctl_oss_version, "I",
+ "Linux OSS version");
+
+/*
+ * Returns holding the prison mutex if return non-NULL.
+ */
+static struct linux_prison *
+linux_get_prison(struct proc *p)
+{
+ register struct prison *pr;
+ register struct linux_prison *lpr;
+
+ if (!jailed(p->p_ucred))
+ return (NULL);
+
+ pr = p->p_ucred->cr_prison;
+
+ /*
+ * Rather than hold the prison mutex during allocation, check to
+ * see if we need to allocate while holding the mutex, release it,
+ * allocate, then once we've allocated the memory, check again to
+ * see if it's still needed, and set if appropriate. If it's not,
+ * we release the mutex again to FREE(), and grab it again so as
+ * to release holding the lock.
+ */
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux == NULL) {
+ mtx_unlock(&pr->pr_mtx);
+ MALLOC(lpr, struct linux_prison *, sizeof *lpr,
+ M_PRISON, M_WAITOK|M_ZERO);
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux == NULL) {
+ pr->pr_linux = lpr;
+ } else {
+ mtx_unlock(&pr->pr_mtx);
+ FREE(lpr, M_PRISON);
+ mtx_lock(&pr->pr_mtx);
+ }
+ }
+
+ return (pr->pr_linux);
+}
+
+void
+linux_get_osname(p, dst)
+ struct proc *p;
+ char *dst;
+{
+ register struct prison *pr;
+ register struct linux_prison *lpr;
+
+ if (p->p_ucred->cr_prison == NULL) {
+ bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
+ return;
+ }
+
+ pr = p->p_ucred->cr_prison;
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *)pr->pr_linux;
+ if (lpr->pr_osname[0]) {
+ bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
+}
+
+int
+linux_set_osname(p, osname)
+ struct proc *p;
+ char *osname;
+{
+ register struct linux_prison *lpr;
+
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
+ strcpy(lpr->pr_osname, osname);
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
+ strcpy(linux_osname, osname);
+ }
+
+ return (0);
+}
+
+void
+linux_get_osrelease(p, dst)
+ struct proc *p;
+ char *dst;
+{
+ register struct prison *pr;
+ struct linux_prison *lpr;
+
+ if (p->p_ucred->cr_prison == NULL) {
+ bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
+ return;
+ }
+
+ pr = p->p_ucred->cr_prison;
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *) pr->pr_linux;
+ if (lpr->pr_osrelease[0]) {
+ bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
+ mtx_unlock(&pr->pr_mtx);
+ return;
+ }
+ }
+ mtx_unlock(&pr->pr_mtx);
+ bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
+}
+
+int
+linux_set_osrelease(p, osrelease)
+ struct proc *p;
+ char *osrelease;
+{
+ register struct linux_prison *lpr;
+
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
+ strcpy(lpr->pr_osrelease, osrelease);
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
+ strcpy(linux_osrelease, osrelease);
+ }
+
+ return (0);
+}
+
+int
+linux_get_oss_version(p)
+ struct proc *p;
+{
+ register struct prison *pr;
+ register struct linux_prison *lpr;
+ int version;
+
+ if (p->p_ucred->cr_prison == NULL)
+ return (linux_oss_version);
+
+ pr = p->p_ucred->cr_prison;
+
+ mtx_lock(&pr->pr_mtx);
+ if (pr->pr_linux != NULL) {
+ lpr = (struct linux_prison *) pr->pr_linux;
+ if (lpr->pr_oss_version) {
+ version = lpr->pr_oss_version;
+ } else {
+ version = linux_oss_version;
+ }
+ } else {
+ version = linux_oss_version;
+ }
+ mtx_unlock(&pr->pr_mtx);
+
+ return (version);
+}
+
+int
+linux_set_oss_version(p, oss_version)
+ struct proc *p;
+ int oss_version;
+{
+ register struct linux_prison *lpr;
+
+ lpr = linux_get_prison(p);
+ if (lpr != NULL) {
+ lpr->pr_oss_version = oss_version;
+ mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
+ } else {
+ linux_oss_version = oss_version;
+ }
+
+ return (0);
+}
+
+#ifdef DEBUG
+
+u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
+
+static int
+linux_debug(int syscall, int toggle, int global)
+{
+
+ if (global) {
+ char c = toggle ? 0 : 0xff;
+
+ memset(linux_debug_map, c, sizeof(linux_debug_map));
+ return (0);
+ }
+ if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
+ return (EINVAL);
+ if (toggle)
+ clrbit(linux_debug_map, syscall);
+ else
+ setbit(linux_debug_map, syscall);
+ return (0);
+}
+
+/*
+ * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
+ *
+ * E.g.: sysctl linux.debug=21.0
+ *
+ * As a special case, syscall "all" will apply to all syscalls globally.
+ */
+#define LINUX_MAX_DEBUGSTR 16
+static int
+linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
+{
+ char value[LINUX_MAX_DEBUGSTR], *p;
+ int error, sysc, toggle;
+ int global = 0;
+
+ value[0] = '\0';
+ error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
+ if (error || req->newptr == NULL)
+ return (error);
+ for (p = value; *p != '\0' && *p != '.'; p++);
+ if (*p == '\0')
+ return (EINVAL);
+ *p++ = '\0';
+ sysc = strtol(value, NULL, 0);
+ toggle = strtol(p, NULL, 0);
+ if (strcmp(value, "all") == 0)
+ global = 1;
+ error = linux_debug(sysc, toggle, global);
+ return (error);
+}
+
+SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
+ CTLTYPE_STRING | CTLFLAG_RW,
+ 0, 0, linux_sysctl_debug, "A",
+ "Linux debugging control");
+
+#endif /* DEBUG */
diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h
new file mode 100644
index 0000000..9e122ec
--- /dev/null
+++ b/sys/compat/linux/linux_mib.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_MIB_H_
+#define _LINUX_MIB_H_
+
+void linux_get_osname(struct proc *p, char *dst);
+int linux_set_osname(struct proc *p, char *osname);
+
+void linux_get_osrelease(struct proc *p, char *dst);
+int linux_set_osrelease(struct proc *p, char *osrelease);
+
+int linux_get_oss_version(struct proc *p);
+int linux_set_oss_version(struct proc *p, int oss_version);
+
+#endif /* _LINUX_MIB_H_ */
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
new file mode 100644
index 0000000..d6259bc
--- /dev/null
+++ b/sys/compat/linux/linux_misc.c
@@ -0,0 +1,1349 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/imgact_aout.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mac.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/blist.h>
+#include <sys/reboot.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/unistd.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#include <machine/limits.h>
+
+#include <posix4/sched.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_util.h>
+
+#ifdef __alpha__
+#define BSD_TO_LINUX_SIGNAL(sig) (sig)
+#else
+#define BSD_TO_LINUX_SIGNAL(sig) \
+ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
+#endif
+
+#ifndef __alpha__
+static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = {
+ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK,
+ RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE,
+ RLIMIT_MEMLOCK, -1
+};
+#endif /*!__alpha__*/
+
+struct l_sysinfo {
+ l_long uptime; /* Seconds since boot */
+ l_ulong loads[3]; /* 1, 5, and 15 minute load averages */
+ l_ulong totalram; /* Total usable main memory size */
+ l_ulong freeram; /* Available memory size */
+ l_ulong sharedram; /* Amount of shared memory */
+ l_ulong bufferram; /* Memory used by buffers */
+ l_ulong totalswap; /* Total swap space size */
+ l_ulong freeswap; /* swap space still available */
+ l_ushort procs; /* Number of current processes */
+ char _f[22]; /* Pads structure to 64 bytes */
+};
+#ifndef __alpha__
+int
+linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
+{
+ struct l_sysinfo sysinfo;
+ vm_object_t object;
+ int i;
+ struct timespec ts;
+
+ /* Uptime is copied out of print_uptime() in kern_shutdown.c */
+ getnanouptime(&ts);
+ i = 0;
+ if (ts.tv_sec >= 86400) {
+ ts.tv_sec %= 86400;
+ i = 1;
+ }
+ if (i || ts.tv_sec >= 3600) {
+ ts.tv_sec %= 3600;
+ i = 1;
+ }
+ if (i || ts.tv_sec >= 60) {
+ ts.tv_sec %= 60;
+ i = 1;
+ }
+ sysinfo.uptime=ts.tv_sec;
+
+ /* Use the information from the mib to get our load averages */
+ for (i = 0; i < 3; i++)
+ sysinfo.loads[i] = averunnable.ldavg[i];
+
+ sysinfo.totalram = physmem * PAGE_SIZE;
+ sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE;
+
+ sysinfo.sharedram = 0;
+ for (object = TAILQ_FIRST(&vm_object_list); object != NULL;
+ object = TAILQ_NEXT(object, object_list))
+ if (object->shadow_count > 1)
+ sysinfo.sharedram += object->resident_page_count;
+
+ sysinfo.sharedram *= PAGE_SIZE;
+ sysinfo.bufferram = 0;
+
+ if (swapblist == NULL) {
+ sysinfo.totalswap= 0;
+ sysinfo.freeswap = 0;
+ } else {
+ sysinfo.totalswap = swapblist->bl_blocks * 1024;
+ sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
+ }
+
+ sysinfo.procs = 20; /* Hack */
+
+ return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo));
+}
+#endif /*!__alpha__*/
+
+#ifndef __alpha__
+int
+linux_alarm(struct thread *td, struct linux_alarm_args *args)
+{
+ struct itimerval it, old_it;
+ struct timeval tv;
+ int s;
+
+#ifdef DEBUG
+ if (ldebug(alarm))
+ printf(ARGS(alarm, "%u"), args->secs);
+#endif
+
+ if (args->secs > 100000000)
+ return EINVAL;
+
+ it.it_value.tv_sec = (long)args->secs;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ s = splsoftclock();
+ old_it = td->td_proc->p_realtimer;
+ getmicrouptime(&tv);
+ if (timevalisset(&old_it.it_value))
+ callout_stop(&td->td_proc->p_itcallout);
+ if (it.it_value.tv_sec != 0) {
+ callout_reset(&td->td_proc->p_itcallout, tvtohz(&it.it_value),
+ realitexpire, td->td_proc);
+ timevaladd(&it.it_value, &tv);
+ }
+ td->td_proc->p_realtimer = it;
+ splx(s);
+ if (timevalcmp(&old_it.it_value, &tv, >)) {
+ timevalsub(&old_it.it_value, &tv);
+ if (old_it.it_value.tv_usec != 0)
+ old_it.it_value.tv_sec++;
+ td->td_retval[0] = old_it.it_value.tv_sec;
+ }
+ return 0;
+}
+#endif /*!__alpha__*/
+
+int
+linux_brk(struct thread *td, struct linux_brk_args *args)
+{
+ struct vmspace *vm = td->td_proc->p_vmspace;
+ vm_offset_t new, old;
+ struct obreak_args /* {
+ char * nsize;
+ } */ tmp;
+
+#ifdef DEBUG
+ if (ldebug(brk))
+ printf(ARGS(brk, "%p"), (void *)args->dsend);
+#endif
+ old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
+ new = (vm_offset_t)args->dsend;
+ tmp.nsize = (char *) new;
+ if (((caddr_t)new > vm->vm_daddr) && !obreak(td, &tmp))
+ td->td_retval[0] = (long)new;
+ else
+ td->td_retval[0] = (long)old;
+
+ return 0;
+}
+
+int
+linux_uselib(struct thread *td, struct linux_uselib_args *args)
+{
+ struct nameidata ni;
+ struct vnode *vp;
+ struct exec *a_out;
+ struct vattr attr;
+ vm_offset_t vmaddr;
+ unsigned long file_offset;
+ vm_offset_t buffer;
+ unsigned long bss_size;
+ int error;
+ caddr_t sg;
+ int locked;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->library);
+
+#ifdef DEBUG
+ if (ldebug(uselib))
+ printf(ARGS(uselib, "%s"), args->library);
+#endif
+
+ a_out = NULL;
+ locked = 0;
+ vp = NULL;
+
+ /*
+ * XXX: This code should make use of vn_open(), rather than doing
+ * all this stuff itself.
+ */
+ NDINIT(&ni, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, args->library, td);
+ error = namei(&ni);
+ if (error)
+ goto cleanup;
+
+ vp = ni.ni_vp;
+ /*
+ * XXX - This looks like a bogus check. A LOCKLEAF namei should not
+ * succeed without returning a vnode.
+ */
+ if (vp == NULL) {
+ error = ENOEXEC; /* ?? */
+ goto cleanup;
+ }
+ NDFREE(&ni, NDF_ONLY_PNBUF);
+
+ /*
+ * From here on down, we have a locked vnode that must be unlocked.
+ */
+ locked++;
+
+ /* Writable? */
+ if (vp->v_writecount) {
+ error = ETXTBSY;
+ goto cleanup;
+ }
+
+ /* Executable? */
+ error = VOP_GETATTR(vp, &attr, td->td_ucred, td);
+ if (error)
+ goto cleanup;
+
+ if ((vp->v_mount->mnt_flag & MNT_NOEXEC) ||
+ ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* Sensible size? */
+ if (attr.va_size == 0) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* Can we access it? */
+ error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
+ if (error)
+ goto cleanup;
+
+ /*
+ * XXX: This should use vn_open() so that it is properly authorized,
+ * and to reduce code redundancy all over the place here.
+ */
+#ifdef MAC
+ error = mac_check_vnode_open(td->td_ucred, vp, FREAD);
+ if (error)
+ goto cleanup;
+#endif
+ error = VOP_OPEN(vp, FREAD, td->td_ucred, td);
+ if (error)
+ goto cleanup;
+
+ /*
+ * Lock no longer needed
+ */
+ VOP_UNLOCK(vp, 0, td);
+ locked = 0;
+
+ /* Pull in executable header into kernel_map */
+ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE,
+ VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
+ if (error)
+ goto cleanup;
+
+ /* Is it a Linux binary ? */
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /*
+ * While we are here, we should REALLY do some more checks
+ */
+
+ /* Set file/virtual offset based on a.out variant. */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413: /* ZMAGIC */
+ file_offset = 1024;
+ break;
+ case 0314: /* QMAGIC */
+ file_offset = 0;
+ break;
+ default:
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ bss_size = round_page(a_out->a_bss);
+
+ /* Check various fields in header for validity/bounds. */
+ if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) {
+ error = ENOEXEC;
+ goto cleanup;
+ }
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > attr.va_size) {
+ error = EFAULT;
+ goto cleanup;
+ }
+
+ /* To protect td->td_proc->p_rlimit in the if condition. */
+ mtx_assert(&Giant, MA_OWNED);
+
+ /*
+ * text/data/bss must not exceed limits
+ * XXX - this is not complete. it should check current usage PLUS
+ * the resources needed by this library.
+ */
+ if (a_out->a_text > maxtsiz ||
+ a_out->a_data + bss_size >
+ td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur) {
+ error = ENOMEM;
+ goto cleanup;
+ }
+
+ mp_fixme("Unlocked vflags access.");
+ /* prevent more writers */
+ vp->v_vflag |= VV_TEXT;
+
+ /*
+ * Check if file_offset page aligned. Currently we cannot handle
+ * misalinged file offsets, and so we read in the entire image
+ * (what a waste).
+ */
+ if (file_offset & PAGE_MASK) {
+#ifdef DEBUG
+ printf("uselib: Non page aligned binary %lu\n", file_offset);
+#endif
+ /* Map text+data read/write/execute */
+
+ /* a_entry is the load address and is page aligned */
+ vmaddr = trunc_page(a_out->a_entry);
+
+ /* get anon user mapping, read+write+execute */
+ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
+ &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL,
+ VM_PROT_ALL, 0);
+ if (error)
+ goto cleanup;
+
+ /* map file into kernel_map */
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp,
+ trunc_page(file_offset));
+ if (error)
+ goto cleanup;
+
+ /* copy from kernel VM space to user space */
+ error = copyout((caddr_t)(uintptr_t)(buffer + file_offset),
+ (caddr_t)vmaddr, a_out->a_text + a_out->a_data);
+
+ /* release temporary kernel space */
+ vm_map_remove(kernel_map, buffer, buffer +
+ round_page(a_out->a_text + a_out->a_data + file_offset));
+
+ if (error)
+ goto cleanup;
+ } else {
+#ifdef DEBUG
+ printf("uselib: Page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * for QMAGIC, a_entry is 20 bytes beyond the load address
+ * to skip the executable header
+ */
+ vmaddr = trunc_page(a_out->a_entry);
+
+ /*
+ * Map it all into the process's space as a single
+ * copy-on-write "data" segment.
+ */
+ error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL,
+ MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset);
+ if (error)
+ goto cleanup;
+ }
+#ifdef DEBUG
+ printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0],
+ ((long*)vmaddr)[1]);
+#endif
+ if (bss_size != 0) {
+ /* Calculate BSS start address */
+ vmaddr = trunc_page(a_out->a_entry) + a_out->a_text +
+ a_out->a_data;
+
+ /* allocate some 'anon' space */
+ error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0,
+ &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ goto cleanup;
+ }
+
+cleanup:
+ /* Unlock vnode if needed */
+ if (locked)
+ VOP_UNLOCK(vp, 0, td);
+
+ /* Release the kernel mapping. */
+ if (a_out)
+ vm_map_remove(kernel_map, (vm_offset_t)a_out,
+ (vm_offset_t)a_out + PAGE_SIZE);
+
+ return error;
+}
+
+int
+linux_select(struct thread *td, struct linux_select_args *args)
+{
+ struct select_args bsa;
+ struct timeval tv0, tv1, utv, *tvp;
+ caddr_t sg;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds,
+ (void *)args->readfds, (void *)args->writefds,
+ (void *)args->exceptfds, (void *)args->timeout);
+#endif
+
+ error = 0;
+ bsa.nd = args->nfds;
+ bsa.in = args->readfds;
+ bsa.ou = args->writefds;
+ bsa.ex = args->exceptfds;
+ bsa.tv = (struct timeval *)args->timeout;
+
+ /*
+ * Store current time for computation of the amount of
+ * time left.
+ */
+ if (args->timeout) {
+ if ((error = copyin((caddr_t)args->timeout, &utv,
+ sizeof(utv))))
+ goto select_out;
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("incoming timeout (%ld/%ld)"),
+ utv.tv_sec, utv.tv_usec);
+#endif
+
+ if (itimerfix(&utv)) {
+ /*
+ * The timeval was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ sg = stackgap_init();
+ tvp = stackgap_alloc(&sg, sizeof(utv));
+ utv.tv_sec += utv.tv_usec / 1000000;
+ utv.tv_usec %= 1000000;
+ if (utv.tv_usec < 0) {
+ utv.tv_sec -= 1;
+ utv.tv_usec += 1000000;
+ }
+ if (utv.tv_sec < 0)
+ timevalclear(&utv);
+ if ((error = copyout(&utv, tvp, sizeof(utv))))
+ goto select_out;
+ bsa.tv = tvp;
+ }
+ microtime(&tv0);
+ }
+
+ error = select(td, &bsa);
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("real select returns %d"), error);
+#endif
+ if (error) {
+ /*
+ * See fs/select.c in the Linux kernel. Without this,
+ * Maelstrom doesn't work.
+ */
+ if (error == ERESTART)
+ error = EINTR;
+ goto select_out;
+ }
+
+ if (args->timeout) {
+ if (td->td_retval[0]) {
+ /*
+ * Compute how much time was left of the timeout,
+ * by subtracting the current time and the time
+ * before we started the call, and subtracting
+ * that result from the user-supplied value.
+ */
+ microtime(&tv1);
+ timevalsub(&tv1, &tv0);
+ timevalsub(&utv, &tv1);
+ if (utv.tv_sec < 0)
+ timevalclear(&utv);
+ } else
+ timevalclear(&utv);
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("outgoing timeout (%ld/%ld)"),
+ utv.tv_sec, utv.tv_usec);
+#endif
+ if ((error = copyout(&utv, (caddr_t)args->timeout,
+ sizeof(utv))))
+ goto select_out;
+ }
+
+select_out:
+#ifdef DEBUG
+ if (ldebug(select))
+ printf(LMSG("select_out -> %d"), error);
+#endif
+ return error;
+}
+
+int
+linux_mremap(struct thread *td, struct linux_mremap_args *args)
+{
+ struct munmap_args /* {
+ void *addr;
+ size_t len;
+ } */ bsd_args;
+ int error = 0;
+
+#ifdef DEBUG
+ if (ldebug(mremap))
+ printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"),
+ (void *)args->addr,
+ (unsigned long)args->old_len,
+ (unsigned long)args->new_len,
+ (unsigned long)args->flags);
+#endif
+ args->new_len = round_page(args->new_len);
+ args->old_len = round_page(args->old_len);
+
+ if (args->new_len > args->old_len) {
+ td->td_retval[0] = 0;
+ return ENOMEM;
+ }
+
+ if (args->new_len < args->old_len) {
+ bsd_args.addr = (caddr_t)(args->addr + args->new_len);
+ bsd_args.len = args->old_len - args->new_len;
+ error = munmap(td, &bsd_args);
+ }
+
+ td->td_retval[0] = error ? 0 : (u_long)args->addr;
+ return error;
+}
+
+int
+linux_msync(struct thread *td, struct linux_msync_args *args)
+{
+ struct msync_args bsd_args;
+
+ bsd_args.addr = (caddr_t)args->addr;
+ bsd_args.len = args->len;
+ bsd_args.flags = 0; /* XXX ignore */
+
+ return msync(td, &bsd_args);
+}
+
+#ifndef __alpha__
+int
+linux_time(struct thread *td, struct linux_time_args *args)
+{
+ struct timeval tv;
+ l_time_t tm;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(time))
+ printf(ARGS(time, "*"));
+#endif
+
+ microtime(&tv);
+ tm = tv.tv_sec;
+ if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm))))
+ return error;
+ td->td_retval[0] = tm;
+ return 0;
+}
+#endif /*!__alpha__*/
+
+struct l_times_argv {
+ l_long tms_utime;
+ l_long tms_stime;
+ l_long tms_cutime;
+ l_long tms_cstime;
+};
+
+#ifdef __alpha__
+#define CLK_TCK 1024 /* Linux uses 1024 on alpha */
+#else
+#define CLK_TCK 100 /* Linux uses 100 */
+#endif
+
+#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
+
+int
+linux_times(struct thread *td, struct linux_times_args *args)
+{
+ struct timeval tv;
+ struct l_times_argv tms;
+ struct rusage ru;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(times))
+ printf(ARGS(times, "*"));
+#endif
+
+ mtx_lock_spin(&sched_lock);
+ calcru(td->td_proc, &ru.ru_utime, &ru.ru_stime, NULL);
+ mtx_unlock_spin(&sched_lock);
+
+ tms.tms_utime = CONVTCK(ru.ru_utime);
+ tms.tms_stime = CONVTCK(ru.ru_stime);
+
+ tms.tms_cutime = CONVTCK(td->td_proc->p_stats->p_cru.ru_utime);
+ tms.tms_cstime = CONVTCK(td->td_proc->p_stats->p_cru.ru_stime);
+
+ if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms))))
+ return error;
+
+ microuptime(&tv);
+ td->td_retval[0] = (int)CONVTCK(tv);
+ return 0;
+}
+
+int
+linux_newuname(struct thread *td, struct linux_newuname_args *args)
+{
+ struct l_new_utsname utsname;
+ char osname[LINUX_MAX_UTSNAME];
+ char osrelease[LINUX_MAX_UTSNAME];
+
+#ifdef DEBUG
+ if (ldebug(newuname))
+ printf(ARGS(newuname, "*"));
+#endif
+
+ linux_get_osname(td->td_proc, osname);
+ linux_get_osrelease(td->td_proc, osrelease);
+
+ bzero(&utsname, sizeof(utsname));
+ strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1);
+ getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME-1);
+ strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1);
+ strncpy(utsname.version, version, LINUX_MAX_UTSNAME-1);
+ strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1);
+ strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1);
+
+ return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname)));
+}
+
+#if defined(__i386__)
+struct l_utimbuf {
+ l_time_t l_actime;
+ l_time_t l_modtime;
+};
+
+int
+linux_utime(struct thread *td, struct linux_utime_args *args)
+{
+ struct utimes_args /* {
+ char *path;
+ struct timeval *tptr;
+ } */ bsdutimes;
+ struct timeval tv[2], *tvp;
+ struct l_utimbuf lut;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->fname);
+
+#ifdef DEBUG
+ if (ldebug(utime))
+ printf(ARGS(utime, "%s, *"), args->fname);
+#endif
+
+ if (args->times) {
+ if ((error = copyin((caddr_t)args->times, &lut, sizeof lut)))
+ return error;
+ tv[0].tv_sec = lut.l_actime;
+ tv[0].tv_usec = 0;
+ tv[1].tv_sec = lut.l_modtime;
+ tv[1].tv_usec = 0;
+ /* so that utimes can copyin */
+ tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv));
+ if (tvp == NULL)
+ return (ENAMETOOLONG);
+ if ((error = copyout(tv, tvp, sizeof(tv))))
+ return error;
+ bsdutimes.tptr = tvp;
+ } else
+ bsdutimes.tptr = NULL;
+
+ bsdutimes.path = args->fname;
+ return utimes(td, &bsdutimes);
+}
+#endif /* __i386__ */
+
+#define __WCLONE 0x80000000
+
+#ifndef __alpha__
+int
+linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
+{
+ struct wait_args /* {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ } */ tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ if (ldebug(waitpid))
+ printf(ARGS(waitpid, "%d, %p, %d"),
+ args->pid, (void *)args->status, args->options);
+#endif
+
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+ /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
+ if (args->options & __WCLONE)
+ tmp.options |= WLINUXCLONE;
+ tmp.rusage = NULL;
+
+ if ((error = wait4(td, &tmp)) != 0)
+ return error;
+
+ if (args->status) {
+ if ((error = copyin((caddr_t)args->status, &tmpstat,
+ sizeof(int))) != 0)
+ return error;
+ tmpstat &= 0xffff;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
+ return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
+ }
+
+ return 0;
+}
+#endif /*!__alpha__*/
+
+int
+linux_wait4(struct thread *td, struct linux_wait4_args *args)
+{
+ struct wait_args /* {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ } */ tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ if (ldebug(wait4))
+ printf(ARGS(wait4, "%d, %p, %d, %p"),
+ args->pid, (void *)args->status, args->options,
+ (void *)args->rusage);
+#endif
+
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = (args->options & (WNOHANG | WUNTRACED));
+ /* WLINUXCLONE should be equal to __WCLONE, but we make sure */
+ if (args->options & __WCLONE)
+ tmp.options |= WLINUXCLONE;
+ tmp.rusage = (struct rusage *)args->rusage;
+
+ if ((error = wait4(td, &tmp)) != 0)
+ return error;
+
+ SIGDELSET(td->td_proc->p_siglist, SIGCHLD);
+
+ if (args->status) {
+ if ((error = copyin((caddr_t)args->status, &tmpstat,
+ sizeof(int))) != 0)
+ return error;
+ tmpstat &= 0xffff;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat));
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8);
+ return copyout(&tmpstat, (caddr_t)args->status, sizeof(int));
+ }
+
+ return 0;
+}
+
+int
+linux_mknod(struct thread *td, struct linux_mknod_args *args)
+{
+ caddr_t sg;
+ struct mknod_args bsd_mknod;
+ struct mkfifo_args bsd_mkfifo;
+
+ sg = stackgap_init();
+
+ CHECKALTCREAT(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(mknod))
+ printf(ARGS(mknod, "%s, %d, %d"),
+ args->path, args->mode, args->dev);
+#endif
+
+ if (args->mode & S_IFIFO) {
+ bsd_mkfifo.path = args->path;
+ bsd_mkfifo.mode = args->mode;
+ return mkfifo(td, &bsd_mkfifo);
+ } else {
+ bsd_mknod.path = args->path;
+ bsd_mknod.mode = args->mode;
+ bsd_mknod.dev = args->dev;
+ return mknod(td, &bsd_mknod);
+ }
+}
+
+/*
+ * UGH! This is just about the dumbest idea I've ever heard!!
+ */
+int
+linux_personality(struct thread *td, struct linux_personality_args *args)
+{
+#ifdef DEBUG
+ if (ldebug(personality))
+ printf(ARGS(personality, "%d"), args->per);
+#endif
+#ifndef __alpha__
+ if (args->per != 0)
+ return EINVAL;
+#endif
+
+ /* Yes Jim, it's still a Linux... */
+ td->td_retval[0] = 0;
+ return 0;
+}
+
+/*
+ * Wrappers for get/setitimer for debugging..
+ */
+int
+linux_setitimer(struct thread *td, struct linux_setitimer_args *args)
+{
+ struct setitimer_args bsa;
+ struct itimerval foo;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(setitimer))
+ printf(ARGS(setitimer, "%p, %p"),
+ (void *)args->itv, (void *)args->oitv);
+#endif
+ bsa.which = args->which;
+ bsa.itv = (struct itimerval *)args->itv;
+ bsa.oitv = (struct itimerval *)args->oitv;
+ if (args->itv) {
+ if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo))))
+ return error;
+#ifdef DEBUG
+ if (ldebug(setitimer)) {
+ printf("setitimer: value: sec: %ld, usec: %ld\n",
+ foo.it_value.tv_sec, foo.it_value.tv_usec);
+ printf("setitimer: interval: sec: %ld, usec: %ld\n",
+ foo.it_interval.tv_sec, foo.it_interval.tv_usec);
+ }
+#endif
+ }
+ return setitimer(td, &bsa);
+}
+
+int
+linux_getitimer(struct thread *td, struct linux_getitimer_args *args)
+{
+ struct getitimer_args bsa;
+#ifdef DEBUG
+ if (ldebug(getitimer))
+ printf(ARGS(getitimer, "%p"), (void *)args->itv);
+#endif
+ bsa.which = args->which;
+ bsa.itv = (struct itimerval *)args->itv;
+ return getitimer(td, &bsa);
+}
+
+#ifndef __alpha__
+int
+linux_nice(struct thread *td, struct linux_nice_args *args)
+{
+ struct setpriority_args bsd_args;
+
+ bsd_args.which = PRIO_PROCESS;
+ bsd_args.who = 0; /* current process */
+ bsd_args.prio = args->inc;
+ return setpriority(td, &bsd_args);
+}
+#endif /*!__alpha__*/
+
+int
+linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
+{
+ struct ucred *newcred, *oldcred;
+ l_gid_t linux_gidset[NGROUPS];
+ gid_t *bsd_gidset;
+ int ngrp, error;
+ struct proc *p;
+
+ ngrp = args->gidsetsize;
+ if (ngrp >= NGROUPS)
+ return (EINVAL);
+ error = copyin((caddr_t)args->grouplist, linux_gidset,
+ ngrp * sizeof(l_gid_t));
+ if (error)
+ return (error);
+ newcred = crget();
+ p = td->td_proc;
+ PROC_LOCK(p);
+ oldcred = p->p_ucred;
+
+ /*
+ * cr_groups[0] holds egid. Setting the whole set from
+ * the supplied set will cause egid to be changed too.
+ * Keep cr_groups[0] unchanged to prevent that.
+ */
+
+ if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
+ PROC_UNLOCK(p);
+ crfree(newcred);
+ return (error);
+ }
+
+ crcopy(newcred, oldcred);
+ if (ngrp > 0) {
+ newcred->cr_ngroups = ngrp + 1;
+
+ bsd_gidset = newcred->cr_groups;
+ ngrp--;
+ while (ngrp >= 0) {
+ bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
+ ngrp--;
+ }
+ }
+ else
+ newcred->cr_ngroups = 1;
+
+ setsugid(p);
+ p->p_ucred = newcred;
+ PROC_UNLOCK(p);
+ crfree(oldcred);
+ return (0);
+}
+
+int
+linux_getgroups(struct thread *td, struct linux_getgroups_args *args)
+{
+ struct ucred *cred;
+ l_gid_t linux_gidset[NGROUPS];
+ gid_t *bsd_gidset;
+ int bsd_gidsetsz, ngrp, error;
+
+ cred = td->td_ucred;
+ bsd_gidset = cred->cr_groups;
+ bsd_gidsetsz = cred->cr_ngroups - 1;
+
+ /*
+ * cr_groups[0] holds egid. Returning the whole set
+ * here will cause a duplicate. Exclude cr_groups[0]
+ * to prevent that.
+ */
+
+ if ((ngrp = args->gidsetsize) == 0) {
+ td->td_retval[0] = bsd_gidsetsz;
+ return (0);
+ }
+
+ if (ngrp < bsd_gidsetsz)
+ return (EINVAL);
+
+ ngrp = 0;
+ while (ngrp < bsd_gidsetsz) {
+ linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ ngrp++;
+ }
+
+ if ((error = copyout(linux_gidset, (caddr_t)args->grouplist,
+ ngrp * sizeof(l_gid_t))))
+ return (error);
+
+ td->td_retval[0] = ngrp;
+ return (0);
+}
+
+#ifndef __alpha__
+int
+linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args)
+{
+ struct __setrlimit_args bsd;
+ struct l_rlimit rlim;
+ int error;
+ caddr_t sg = stackgap_init();
+
+#ifdef DEBUG
+ if (ldebug(setrlimit))
+ printf(ARGS(setrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ bsd.which = linux_to_bsd_resource[args->resource];
+ if (bsd.which == -1)
+ return (EINVAL);
+
+ error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim));
+ if (error)
+ return (error);
+
+ bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
+ bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur;
+ bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max;
+ return (setrlimit(td, &bsd));
+}
+
+int
+linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args)
+{
+ struct __getrlimit_args bsd;
+ struct l_rlimit rlim;
+ int error;
+ caddr_t sg = stackgap_init();
+
+#ifdef DEBUG
+ if (ldebug(old_getrlimit))
+ printf(ARGS(old_getrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ bsd.which = linux_to_bsd_resource[args->resource];
+ if (bsd.which == -1)
+ return (EINVAL);
+
+ bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
+ error = getrlimit(td, &bsd);
+ if (error)
+ return (error);
+
+ rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur;
+ if (rlim.rlim_cur == ULONG_MAX)
+ rlim.rlim_cur = LONG_MAX;
+ rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max;
+ if (rlim.rlim_max == ULONG_MAX)
+ rlim.rlim_max = LONG_MAX;
+ return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
+}
+
+int
+linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args)
+{
+ struct __getrlimit_args bsd;
+ struct l_rlimit rlim;
+ int error;
+ caddr_t sg = stackgap_init();
+
+#ifdef DEBUG
+ if (ldebug(getrlimit))
+ printf(ARGS(getrlimit, "%d, %p"),
+ args->resource, (void *)args->rlim);
+#endif
+
+ if (args->resource >= LINUX_RLIM_NLIMITS)
+ return (EINVAL);
+
+ bsd.which = linux_to_bsd_resource[args->resource];
+ if (bsd.which == -1)
+ return (EINVAL);
+
+ bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit));
+ error = getrlimit(td, &bsd);
+ if (error)
+ return (error);
+
+ rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur;
+ rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max;
+ return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim)));
+}
+#endif /*!__alpha__*/
+
+int
+linux_sched_setscheduler(struct thread *td,
+ struct linux_sched_setscheduler_args *args)
+{
+ struct sched_setscheduler_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_setscheduler))
+ printf(ARGS(sched_setscheduler, "%d, %d, %p"),
+ args->pid, args->policy, (const void *)args->param);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ bsd.pid = args->pid;
+ bsd.param = (struct sched_param *)args->param;
+ return sched_setscheduler(td, &bsd);
+}
+
+int
+linux_sched_getscheduler(struct thread *td,
+ struct linux_sched_getscheduler_args *args)
+{
+ struct sched_getscheduler_args bsd;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sched_getscheduler))
+ printf(ARGS(sched_getscheduler, "%d"), args->pid);
+#endif
+
+ bsd.pid = args->pid;
+ error = sched_getscheduler(td, &bsd);
+
+ switch (td->td_retval[0]) {
+ case SCHED_OTHER:
+ td->td_retval[0] = LINUX_SCHED_OTHER;
+ break;
+ case SCHED_FIFO:
+ td->td_retval[0] = LINUX_SCHED_FIFO;
+ break;
+ case SCHED_RR:
+ td->td_retval[0] = LINUX_SCHED_RR;
+ break;
+ }
+
+ return error;
+}
+
+int
+linux_sched_get_priority_max(struct thread *td,
+ struct linux_sched_get_priority_max_args *args)
+{
+ struct sched_get_priority_max_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_get_priority_max))
+ printf(ARGS(sched_get_priority_max, "%d"), args->policy);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return EINVAL;
+ }
+ return sched_get_priority_max(td, &bsd);
+}
+
+int
+linux_sched_get_priority_min(struct thread *td,
+ struct linux_sched_get_priority_min_args *args)
+{
+ struct sched_get_priority_min_args bsd;
+
+#ifdef DEBUG
+ if (ldebug(sched_get_priority_min))
+ printf(ARGS(sched_get_priority_min, "%d"), args->policy);
+#endif
+
+ switch (args->policy) {
+ case LINUX_SCHED_OTHER:
+ bsd.policy = SCHED_OTHER;
+ break;
+ case LINUX_SCHED_FIFO:
+ bsd.policy = SCHED_FIFO;
+ break;
+ case LINUX_SCHED_RR:
+ bsd.policy = SCHED_RR;
+ break;
+ default:
+ return EINVAL;
+ }
+ return sched_get_priority_min(td, &bsd);
+}
+
+#define REBOOT_CAD_ON 0x89abcdef
+#define REBOOT_CAD_OFF 0
+#define REBOOT_HALT 0xcdef0123
+
+int
+linux_reboot(struct thread *td, struct linux_reboot_args *args)
+{
+ struct reboot_args bsd_args;
+
+#ifdef DEBUG
+ if (ldebug(reboot))
+ printf(ARGS(reboot, "0x%x"), args->cmd);
+#endif
+ if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF)
+ return (0);
+ bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0;
+ return (reboot(td, &bsd_args));
+}
+
+#ifndef __alpha__
+
+/*
+ * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify
+ * td->td_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This
+ * globbers registers that are assumed to be preserved. The following
+ * lightweight syscalls fixes this. See also linux_getgid16() and
+ * linux_getuid16() in linux_uid16.c.
+ *
+ * linux_getpid() - MP SAFE
+ * linux_getgid() - MP SAFE
+ * linux_getuid() - MP SAFE
+ */
+
+int
+linux_getpid(struct thread *td, struct linux_getpid_args *args)
+{
+
+ td->td_retval[0] = td->td_proc->p_pid;
+ return (0);
+}
+
+int
+linux_getgid(struct thread *td, struct linux_getgid_args *args)
+{
+
+ td->td_retval[0] = td->td_ucred->cr_rgid;
+ return (0);
+}
+
+int
+linux_getuid(struct thread *td, struct linux_getuid_args *args)
+{
+
+ td->td_retval[0] = td->td_ucred->cr_ruid;
+ return (0);
+}
+
+#endif /*!__alpha__*/
+
+int
+linux_getsid(struct thread *td, struct linux_getsid_args *args)
+{
+ struct getsid_args bsd;
+ bsd.pid = args->pid;
+ return getsid(td, &bsd);
+}
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
new file mode 100644
index 0000000..61fc98c
--- /dev/null
+++ b/sys/compat/linux/linux_signal.c
@@ -0,0 +1,438 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/sysproto.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+
+void
+linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
+{
+ int b, l;
+
+ SIGEMPTYSET(*bss);
+ bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
+ bss->__bits[1] = lss->__bits[1];
+ for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
+ if (LINUX_SIGISMEMBER(*lss, l)) {
+#ifdef __alpha__
+ b = _SIG_IDX(l);
+#else
+ b = linux_to_bsd_signal[_SIG_IDX(l)];
+#endif
+ if (b)
+ SIGADDSET(*bss, b);
+ }
+ }
+}
+
+void
+bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss)
+{
+ int b, l;
+
+ LINUX_SIGEMPTYSET(*lss);
+ lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
+ lss->__bits[1] = bss->__bits[1];
+ for (b = 1; b <= LINUX_SIGTBLSZ; b++) {
+ if (SIGISMEMBER(*bss, b)) {
+#if __alpha__
+ l = _SIG_IDX(b);
+#else
+ l = bsd_to_linux_signal[_SIG_IDX(b)];
+#endif
+ if (l)
+ LINUX_SIGADDSET(*lss, l);
+ }
+ }
+}
+
+static void
+linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa)
+{
+
+ linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask);
+ bsa->sa_handler = lsa->lsa_handler;
+ bsa->sa_flags = 0;
+ if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT)
+ bsa->sa_flags |= SA_NOCLDWAIT;
+ if (lsa->lsa_flags & LINUX_SA_SIGINFO)
+ bsa->sa_flags |= SA_SIGINFO;
+ if (lsa->lsa_flags & LINUX_SA_ONSTACK)
+ bsa->sa_flags |= SA_ONSTACK;
+ if (lsa->lsa_flags & LINUX_SA_RESTART)
+ bsa->sa_flags |= SA_RESTART;
+ if (lsa->lsa_flags & LINUX_SA_ONESHOT)
+ bsa->sa_flags |= SA_RESETHAND;
+ if (lsa->lsa_flags & LINUX_SA_NOMASK)
+ bsa->sa_flags |= SA_NODEFER;
+}
+
+static void
+bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa)
+{
+
+ bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask);
+ lsa->lsa_handler = bsa->sa_handler;
+ lsa->lsa_restorer = NULL; /* unsupported */
+ lsa->lsa_flags = 0;
+ if (bsa->sa_flags & SA_NOCLDSTOP)
+ lsa->lsa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsa->sa_flags & SA_NOCLDWAIT)
+ lsa->lsa_flags |= LINUX_SA_NOCLDWAIT;
+ if (bsa->sa_flags & SA_SIGINFO)
+ lsa->lsa_flags |= LINUX_SA_SIGINFO;
+ if (bsa->sa_flags & SA_ONSTACK)
+ lsa->lsa_flags |= LINUX_SA_ONSTACK;
+ if (bsa->sa_flags & SA_RESTART)
+ lsa->lsa_flags |= LINUX_SA_RESTART;
+ if (bsa->sa_flags & SA_RESETHAND)
+ lsa->lsa_flags |= LINUX_SA_ONESHOT;
+ if (bsa->sa_flags & SA_NODEFER)
+ lsa->lsa_flags |= LINUX_SA_NOMASK;
+}
+
+int
+linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa,
+ l_sigaction_t *linux_osa)
+{
+ struct sigaction *nsa, *osa;
+ struct sigaction_args sa_args;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ if (linux_sig <= 0 || linux_sig > LINUX_NSIG)
+ return (EINVAL);
+
+ if (linux_osa != NULL)
+ osa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ else
+ osa = NULL;
+
+ if (linux_nsa != NULL) {
+ nsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ linux_to_bsd_sigaction(linux_nsa, nsa);
+ }
+ else
+ nsa = NULL;
+
+#ifndef __alpha__
+ if (linux_sig <= LINUX_SIGTBLSZ)
+ sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)];
+ else
+#endif
+ sa_args.sig = linux_sig;
+
+ sa_args.act = nsa;
+ sa_args.oact = osa;
+ error = sigaction(td, &sa_args);
+ if (error)
+ return (error);
+
+ if (linux_osa != NULL)
+ bsd_to_linux_sigaction(osa, linux_osa);
+
+ return (0);
+}
+
+
+#ifndef __alpha__
+int
+linux_signal(struct thread *td, struct linux_signal_args *args)
+{
+ l_sigaction_t nsa, osa;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(signal))
+ printf(ARGS(signal, "%d, %p"),
+ args->sig, (void *)args->handler);
+#endif
+
+ nsa.lsa_handler = args->handler;
+ nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK;
+ LINUX_SIGEMPTYSET(nsa.lsa_mask);
+
+ error = linux_do_sigaction(td, args->sig, &nsa, &osa);
+ td->td_retval[0] = (int)osa.lsa_handler;
+
+ return (error);
+}
+#endif /*!__alpha__*/
+
+int
+linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args)
+{
+ l_sigaction_t nsa, osa;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigaction))
+ printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"),
+ (long)args->sig, (void *)args->act,
+ (void *)args->oact, (long)args->sigsetsize);
+#endif
+
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return (EINVAL);
+
+ if (args->act != NULL) {
+ error = copyin(args->act, &nsa, sizeof(l_sigaction_t));
+ if (error)
+ return (error);
+ }
+
+ error = linux_do_sigaction(td, args->sig,
+ args->act ? &nsa : NULL,
+ args->oact ? &osa : NULL);
+
+ if (args->oact != NULL && !error) {
+ error = copyout(&osa, args->oact, sizeof(l_sigaction_t));
+ }
+
+ return (error);
+}
+
+static int
+linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new,
+ l_sigset_t *old)
+{
+ int error;
+ sigset_t mask;
+ struct proc *p = td->td_proc;
+
+ error = 0;
+ td->td_retval[0] = 0;
+
+ PROC_LOCK(p);
+ if (old != NULL)
+ bsd_to_linux_sigset(&p->p_sigmask, old);
+
+ if (new != NULL) {
+ linux_to_bsd_sigset(new, &mask);
+
+ switch (how) {
+ case LINUX_SIG_BLOCK:
+ SIGSETOR(p->p_sigmask, mask);
+ SIG_CANTMASK(p->p_sigmask);
+ break;
+ case LINUX_SIG_UNBLOCK:
+ SIGSETNAND(p->p_sigmask, mask);
+ signotify(p);
+ break;
+ case LINUX_SIG_SETMASK:
+ p->p_sigmask = mask;
+ SIG_CANTMASK(p->p_sigmask);
+ signotify(p);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ }
+ PROC_UNLOCK(p);
+
+ return (error);
+}
+
+#ifndef __alpha__
+int
+linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args)
+{
+ l_osigset_t mask;
+ l_sigset_t set, oset;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(sigprocmask))
+ printf(ARGS(sigprocmask, "%d, *, *"), args->how);
+#endif
+
+ if (args->mask != NULL) {
+ error = copyin(args->mask, &mask, sizeof(l_osigset_t));
+ if (error)
+ return (error);
+ LINUX_SIGEMPTYSET(set);
+ set.__bits[0] = mask;
+ }
+
+ error = linux_do_sigprocmask(td, args->how,
+ args->mask ? &set : NULL,
+ args->omask ? &oset : NULL);
+
+ if (args->omask != NULL && !error) {
+ mask = oset.__bits[0];
+ error = copyout(&mask, args->omask, sizeof(l_osigset_t));
+ }
+
+ return (error);
+}
+#endif /*!__alpha__*/
+
+int
+linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args)
+{
+ l_sigset_t set, oset;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(rt_sigprocmask))
+ printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"),
+ args->how, (void *)args->mask,
+ (void *)args->omask, (long)args->sigsetsize);
+#endif
+
+ if (args->sigsetsize != sizeof(l_sigset_t))
+ return EINVAL;
+
+ if (args->mask != NULL) {
+ error = copyin(args->mask, &set, sizeof(l_sigset_t));
+ if (error)
+ return (error);
+ }
+
+ error = linux_do_sigprocmask(td, args->how,
+ args->mask ? &set : NULL,
+ args->omask ? &oset : NULL);
+
+ if (args->omask != NULL && !error) {
+ error = copyout(&oset, args->omask, sizeof(l_sigset_t));
+ }
+
+ return (error);
+}
+
+#ifndef __alpha__
+int
+linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args)
+{
+ struct proc *p = td->td_proc;
+ l_sigset_t mask;
+
+#ifdef DEBUG
+ if (ldebug(sgetmask))
+ printf(ARGS(sgetmask, ""));
+#endif
+
+ PROC_LOCK(p);
+ bsd_to_linux_sigset(&p->p_sigmask, &mask);
+ PROC_UNLOCK(p);
+ td->td_retval[0] = mask.__bits[0];
+ return (0);
+}
+
+int
+linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args)
+{
+ struct proc *p = td->td_proc;
+ l_sigset_t lset;
+ sigset_t bset;
+
+#ifdef DEBUG
+ if (ldebug(ssetmask))
+ printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask);
+#endif
+
+ PROC_LOCK(p);
+ bsd_to_linux_sigset(&p->p_sigmask, &lset);
+ td->td_retval[0] = lset.__bits[0];
+ LINUX_SIGEMPTYSET(lset);
+ lset.__bits[0] = args->mask;
+ linux_to_bsd_sigset(&lset, &bset);
+ p->p_sigmask = bset;
+ SIG_CANTMASK(p->p_sigmask);
+ signotify(p);
+ PROC_UNLOCK(p);
+ return (0);
+}
+
+int
+linux_sigpending(struct thread *td, struct linux_sigpending_args *args)
+{
+ struct proc *p = td->td_proc;
+ sigset_t bset;
+ l_sigset_t lset;
+ l_osigset_t mask;
+
+#ifdef DEBUG
+ if (ldebug(sigpending))
+ printf(ARGS(sigpending, "*"));
+#endif
+
+ PROC_LOCK(p);
+ bset = p->p_siglist;
+ SIGSETAND(bset, p->p_sigmask);
+ bsd_to_linux_sigset(&bset, &lset);
+ PROC_UNLOCK(p);
+ mask = lset.__bits[0];
+ return (copyout(&mask, args->mask, sizeof(mask)));
+}
+#endif /*!__alpha__*/
+
+int
+linux_kill(struct thread *td, struct linux_kill_args *args)
+{
+ struct kill_args /* {
+ int pid;
+ int signum;
+ } */ tmp;
+
+#ifdef DEBUG
+ if (ldebug(kill))
+ printf(ARGS(kill, "%d, %d"), args->pid, args->signum);
+#endif
+
+ /*
+ * Allow signal 0 as a means to check for privileges
+ */
+ if (args->signum < 0 || args->signum > LINUX_NSIG)
+ return EINVAL;
+
+#ifndef __alpha__
+ if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ)
+ tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)];
+ else
+#endif
+ tmp.signum = args->signum;
+
+ tmp.pid = args->pid;
+ return (kill(td, &tmp));
+}
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
new file mode 100644
index 0000000..edb7c66
--- /dev/null
+++ b/sys/compat/linux/linux_signal.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2000 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_SIGNAL_H_
+#define _LINUX_SIGNAL_H_
+
+void linux_to_bsd_sigset(l_sigset_t *, sigset_t *);
+void bsd_to_linux_sigset(sigset_t *, l_sigset_t *);
+int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *);
+
+#endif /* _LINUX_SIGNAL_H_ */
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
new file mode 100644
index 0000000..a3af70f
--- /dev/null
+++ b/sys/compat/linux/linux_socket.c
@@ -0,0 +1,971 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* XXX we use functions that might not exist. */
+#include "opt_compat.h"
+
+#ifndef COMPAT_43
+#error "Unable to compile Linux-emulator due to missing COMPAT_43 option!"
+#endif
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_socket.h>
+#include <compat/linux/linux_util.h>
+
+/*
+ * FreeBSD's socket calls require the sockaddr struct length to agree
+ * with the address family. Linux does not, so we must force it.
+ */
+static int
+linux_to_bsd_namelen(caddr_t name, int namelen)
+{
+ uint16_t family; /* XXX must match Linux sockaddr */
+
+ if (copyin(name, &family, sizeof(family)))
+ return namelen;
+
+ switch (family) {
+ case AF_INET:
+ return sizeof(struct sockaddr_in);
+ case AF_INET6:
+ return sizeof(struct sockaddr_in6);
+ }
+ return namelen;
+}
+
+#ifndef __alpha__
+static int
+linux_to_bsd_domain(int domain)
+{
+
+ switch (domain) {
+ case LINUX_AF_UNSPEC:
+ return (AF_UNSPEC);
+ case LINUX_AF_UNIX:
+ return (AF_LOCAL);
+ case LINUX_AF_INET:
+ return (AF_INET);
+ case LINUX_AF_AX25:
+ return (AF_CCITT);
+ case LINUX_AF_IPX:
+ return (AF_IPX);
+ case LINUX_AF_APPLETALK:
+ return (AF_APPLETALK);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+
+ switch (level) {
+ case LINUX_SOL_SOCKET:
+ return (SOL_SOCKET);
+ }
+ return (level);
+}
+
+static int
+linux_to_bsd_ip_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_IP_TOS:
+ return (IP_TOS);
+ case LINUX_IP_TTL:
+ return (IP_TTL);
+ case LINUX_IP_OPTIONS:
+ return (IP_OPTIONS);
+ case LINUX_IP_MULTICAST_IF:
+ return (IP_MULTICAST_IF);
+ case LINUX_IP_MULTICAST_TTL:
+ return (IP_MULTICAST_TTL);
+ case LINUX_IP_MULTICAST_LOOP:
+ return (IP_MULTICAST_LOOP);
+ case LINUX_IP_ADD_MEMBERSHIP:
+ return (IP_ADD_MEMBERSHIP);
+ case LINUX_IP_DROP_MEMBERSHIP:
+ return (IP_DROP_MEMBERSHIP);
+ case LINUX_IP_HDRINCL:
+ return (IP_HDRINCL);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_so_sockopt(int opt)
+{
+
+ switch (opt) {
+ case LINUX_SO_DEBUG:
+ return (SO_DEBUG);
+ case LINUX_SO_REUSEADDR:
+ return (SO_REUSEADDR);
+ case LINUX_SO_TYPE:
+ return (SO_TYPE);
+ case LINUX_SO_ERROR:
+ return (SO_ERROR);
+ case LINUX_SO_DONTROUTE:
+ return (SO_DONTROUTE);
+ case LINUX_SO_BROADCAST:
+ return (SO_BROADCAST);
+ case LINUX_SO_SNDBUF:
+ return (SO_SNDBUF);
+ case LINUX_SO_RCVBUF:
+ return (SO_RCVBUF);
+ case LINUX_SO_KEEPALIVE:
+ return (SO_KEEPALIVE);
+ case LINUX_SO_OOBINLINE:
+ return (SO_OOBINLINE);
+ case LINUX_SO_LINGER:
+ return (SO_LINGER);
+ }
+ return (-1);
+}
+
+static int
+linux_to_bsd_msg_flags(int flags)
+{
+ int ret_flags = 0;
+
+ if (flags & LINUX_MSG_OOB)
+ ret_flags |= MSG_OOB;
+ if (flags & LINUX_MSG_PEEK)
+ ret_flags |= MSG_PEEK;
+ if (flags & LINUX_MSG_DONTROUTE)
+ ret_flags |= MSG_DONTROUTE;
+ if (flags & LINUX_MSG_CTRUNC)
+ ret_flags |= MSG_CTRUNC;
+ if (flags & LINUX_MSG_TRUNC)
+ ret_flags |= MSG_TRUNC;
+ if (flags & LINUX_MSG_DONTWAIT)
+ ret_flags |= MSG_DONTWAIT;
+ if (flags & LINUX_MSG_EOR)
+ ret_flags |= MSG_EOR;
+ if (flags & LINUX_MSG_WAITALL)
+ ret_flags |= MSG_WAITALL;
+#if 0 /* not handled */
+ if (flags & LINUX_MSG_PROXY)
+ ;
+ if (flags & LINUX_MSG_FIN)
+ ;
+ if (flags & LINUX_MSG_SYN)
+ ;
+ if (flags & LINUX_MSG_CONFIRM)
+ ;
+ if (flags & LINUX_MSG_RST)
+ ;
+ if (flags & LINUX_MSG_ERRQUEUE)
+ ;
+ if (flags & LINUX_MSG_NOSIGNAL)
+ ;
+#endif
+ return ret_flags;
+}
+
+/* Return 0 if IP_HDRINCL is set for the given socket. */
+static int
+linux_check_hdrincl(struct thread *td, int s)
+{
+ struct getsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } */ bsd_args;
+ int error;
+ caddr_t sg, val, valsize;
+ int size_val = sizeof val;
+ int optval;
+
+ sg = stackgap_init();
+ val = stackgap_alloc(&sg, sizeof(int));
+ valsize = stackgap_alloc(&sg, sizeof(int));
+
+ if ((error = copyout(&size_val, valsize, sizeof(size_val))))
+ return (error);
+
+ bsd_args.s = s;
+ bsd_args.level = IPPROTO_IP;
+ bsd_args.name = IP_HDRINCL;
+ bsd_args.val = val;
+ bsd_args.avalsize = (int *)valsize;
+ if ((error = getsockopt(td, &bsd_args)))
+ return (error);
+
+ if ((error = copyin(val, &optval, sizeof(optval))))
+ return (error);
+
+ return (optval == 0);
+}
+
+/*
+ * Updated sendto() when IP_HDRINCL is set:
+ * tweak endian-dependent fields in the IP packet.
+ */
+static int
+linux_sendto_hdrincl(struct thread *td, struct sendto_args *bsd_args)
+{
+/*
+ * linux_ip_copysize defines how many bytes we should copy
+ * from the beginning of the IP packet before we customize it for BSD.
+ * It should include all the fields we modify (ip_len and ip_off)
+ * and be as small as possible to minimize copying overhead.
+ */
+#define linux_ip_copysize 8
+
+ caddr_t sg;
+ struct ip *packet;
+ struct msghdr *msg;
+ struct iovec *iov;
+
+ int error;
+ struct sendmsg_args /* {
+ int s;
+ caddr_t msg;
+ int flags;
+ } */ sendmsg_args;
+
+ /* Check the packet isn't too small before we mess with it */
+ if (bsd_args->len < linux_ip_copysize)
+ return (EINVAL);
+
+ /*
+ * Tweaking the user buffer in place would be bad manners.
+ * We create a corrected IP header with just the needed length,
+ * then use an iovec to glue it to the rest of the user packet
+ * when calling sendmsg().
+ */
+ sg = stackgap_init();
+ packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize);
+ msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg));
+ iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2);
+
+ /* Make a copy of the beginning of the packet to be sent */
+ if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize)))
+ return (error);
+
+ /* Convert fields from Linux to BSD raw IP socket format */
+ packet->ip_len = bsd_args->len;
+ packet->ip_off = ntohs(packet->ip_off);
+
+ /* Prepare the msghdr and iovec structures describing the new packet */
+ msg->msg_name = bsd_args->to;
+ msg->msg_namelen = bsd_args->tolen;
+ msg->msg_iov = iov;
+ msg->msg_iovlen = 2;
+ msg->msg_control = NULL;
+ msg->msg_controllen = 0;
+ msg->msg_flags = 0;
+ iov[0].iov_base = (char *)packet;
+ iov[0].iov_len = linux_ip_copysize;
+ iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize;
+ iov[1].iov_len = bsd_args->len - linux_ip_copysize;
+
+ sendmsg_args.s = bsd_args->s;
+ sendmsg_args.msg = (caddr_t)msg;
+ sendmsg_args.flags = bsd_args->flags;
+ return (sendmsg(td, &sendmsg_args));
+}
+
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+static int
+linux_socket(struct thread *td, struct linux_socket_args *args)
+{
+ struct linux_socket_args linux_args;
+ struct socket_args /* {
+ int domain;
+ int type;
+ int protocol;
+ } */ bsd_args;
+ int error;
+ int retval_socket;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.type = linux_args.type;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return (EINVAL);
+
+ retval_socket = socket(td, &bsd_args);
+ if (bsd_args.type == SOCK_RAW
+ && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0)
+ && bsd_args.domain == AF_INET
+ && retval_socket >= 0) {
+ /* It's a raw IP socket: set the IP_HDRINCL option. */
+ struct setsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } */ bsd_setsockopt_args;
+ caddr_t sg;
+ int *hdrincl;
+
+ sg = stackgap_init();
+ hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl));
+ *hdrincl = 1;
+ bsd_setsockopt_args.s = td->td_retval[0];
+ bsd_setsockopt_args.level = IPPROTO_IP;
+ bsd_setsockopt_args.name = IP_HDRINCL;
+ bsd_setsockopt_args.val = (caddr_t)hdrincl;
+ bsd_setsockopt_args.valsize = sizeof(*hdrincl);
+ /* We ignore any error returned by setsockopt() */
+ setsockopt(td, &bsd_setsockopt_args);
+ /* Copy back the return value from socket() */
+ td->td_retval[0] = bsd_setsockopt_args.s;
+ }
+
+ return (retval_socket);
+}
+
+struct linux_bind_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+static int
+linux_bind(struct thread *td, struct linux_bind_args *args)
+{
+ struct linux_bind_args linux_args;
+ struct bind_args /* {
+ int s;
+ caddr_t name;
+ int namelen;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen);
+ return (bind(td, &bsd_args));
+}
+
+struct linux_connect_args {
+ int s;
+ struct sockaddr * name;
+ int namelen;
+};
+int linux_connect(struct thread *, struct linux_connect_args *);
+#endif /* !__alpha__*/
+
+int
+linux_connect(struct thread *td, struct linux_connect_args *args)
+{
+ struct linux_connect_args linux_args;
+ struct connect_args /* {
+ int s;
+ caddr_t name;
+ int namelen;
+ } */ bsd_args;
+ struct socket *so;
+ u_int fflag;
+ int error;
+
+#ifdef __alpha__
+ bcopy(args, &linux_args, sizeof(linux_args));
+#else
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+#endif /* __alpha__ */
+
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen);
+ error = connect(td, &bsd_args);
+ if (error != EISCONN)
+ return (error);
+
+ /*
+ * Linux doesn't return EISCONN the first time it occurs,
+ * when on a non-blocking socket. Instead it returns the
+ * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD.
+ */
+ if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0)
+ return(error);
+ error = EISCONN;
+ if (fflag & FNONBLOCK) {
+ if (so->so_emuldata == 0)
+ error = so->so_error;
+ so->so_emuldata = (void *)1;
+ }
+ fputsock(so);
+ return (error);
+}
+
+#ifndef __alpha__
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+static int
+linux_listen(struct thread *td, struct linux_listen_args *args)
+{
+ struct linux_listen_args linux_args;
+ struct listen_args /* {
+ int s;
+ int backlog;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.backlog = linux_args.backlog;
+ return (listen(td, &bsd_args));
+}
+
+struct linux_accept_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_accept(struct thread *td, struct linux_accept_args *args)
+{
+ struct linux_accept_args linux_args;
+ struct accept_args /* {
+ int s;
+ caddr_t name;
+ int *anamelen;
+ } */ bsd_args;
+ struct fcntl_args /* {
+ int fd;
+ int cmd;
+ long arg;
+ } */ f_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.addr;
+ bsd_args.anamelen = linux_args.namelen;
+ error = oaccept(td, &bsd_args);
+ if (error)
+ return (error);
+
+ /*
+ * linux appears not to copy flags from the parent socket to the
+ * accepted one, so we must clear the flags in the new descriptor.
+ * Ignore any errors, because we already have an open fd.
+ */
+ f_args.fd = td->td_retval[0];
+ f_args.cmd = F_SETFL;
+ f_args.arg = 0;
+ (void)fcntl(td, &f_args);
+ td->td_retval[0] = f_args.fd;
+ return (0);
+}
+
+struct linux_getsockname_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
+{
+ struct linux_getsockname_args linux_args;
+ struct getsockname_args /* {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return (ogetsockname(td, &bsd_args));
+}
+
+struct linux_getpeername_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
+{
+ struct linux_getpeername_args linux_args;
+ struct ogetpeername_args /* {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return (ogetpeername(td, &bsd_args));
+}
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+};
+
+static int
+linux_socketpair(struct thread *td, struct linux_socketpair_args *args)
+{
+ struct linux_socketpair_args linux_args;
+ struct socketpair_args /* {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return (EINVAL);
+
+ bsd_args.type = linux_args.type;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.rsv = linux_args.rsv;
+ return (socketpair(td, &bsd_args));
+}
+
+struct linux_send_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_send(struct thread *td, struct linux_send_args *args)
+{
+ struct linux_send_args linux_args;
+ struct osend_args /* {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return (osend(td, &bsd_args));
+}
+
+struct linux_recv_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_recv(struct thread *td, struct linux_recv_args *args)
+{
+ struct linux_recv_args linux_args;
+ struct orecv_args /* {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return (orecv(td, &bsd_args));
+}
+
+struct linux_sendto_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+};
+
+static int
+linux_sendto(struct thread *td, struct linux_sendto_args *args)
+{
+ struct linux_sendto_args linux_args;
+ struct sendto_args /* {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.to = linux_args.to;
+ bsd_args.tolen = linux_args.tolen;
+
+ if (linux_check_hdrincl(td, linux_args.s) == 0)
+ /* IP_HDRINCL set, tweak the packet before sending */
+ return (linux_sendto_hdrincl(td, &bsd_args));
+
+ return (sendto(td, &bsd_args));
+}
+
+struct linux_recvfrom_args {
+ int s;
+ void *buf;
+ int len;
+ int flags;
+ caddr_t from;
+ int *fromlen;
+};
+
+static int
+linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
+{
+ struct linux_recvfrom_args linux_args;
+ struct recvfrom_args /* {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t from;
+ int *fromlenaddr;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.buf;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
+ bsd_args.from = linux_args.from;
+ bsd_args.fromlenaddr = linux_args.fromlen;
+ return (orecvfrom(td, &bsd_args));
+}
+
+struct linux_recvmsg_args {
+ int s;
+ struct msghdr *msg;
+ int flags;
+};
+
+static int
+linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args)
+{
+ struct linux_recvmsg_args linux_args;
+ struct recvmsg_args /* {
+ int s;
+ struct msghdr *msg;
+ int flags;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.msg = linux_args.msg;
+ bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags);
+ return (recvmsg(td, &bsd_args));
+}
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+static int
+linux_shutdown(struct thread *td, struct linux_shutdown_args *args)
+{
+ struct linux_shutdown_args linux_args;
+ struct shutdown_args /* {
+ int s;
+ int how;
+ } */ bsd_args;
+ int error;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.how = linux_args.how;
+ return (shutdown(td, &bsd_args));
+}
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int optlen;
+};
+
+static int
+linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
+{
+ struct linux_setsockopt_args linux_args;
+ struct setsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } */ bsd_args;
+ int error, name;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_TCP:
+ /* Linux TCP option values match BSD's */
+ name = linux_args.optname;
+ break;
+ default:
+ name = -1;
+ break;
+ }
+ if (name == -1)
+ return (EINVAL);
+
+ bsd_args.name = name;
+ bsd_args.val = linux_args.optval;
+ bsd_args.valsize = linux_args.optlen;
+ return (setsockopt(td, &bsd_args));
+}
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int *optlen;
+};
+
+static int
+linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
+{
+ struct linux_getsockopt_args linux_args;
+ struct getsockopt_args /* {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } */ bsd_args;
+ int error, name;
+
+ if ((error = copyin(args, &linux_args, sizeof(linux_args))))
+ return (error);
+
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_TCP:
+ /* Linux TCP option values match BSD's */
+ name = linux_args.optname;
+ break;
+ default:
+ name = -1;
+ break;
+ }
+ if (name == -1)
+ return (EINVAL);
+
+ bsd_args.name = name;
+ bsd_args.val = linux_args.optval;
+ bsd_args.avalsize = linux_args.optlen;
+ return (getsockopt(td, &bsd_args));
+}
+
+int
+linux_socketcall(struct thread *td, struct linux_socketcall_args *args)
+{
+ void *arg = (void *)args->args;
+
+ switch (args->what) {
+ case LINUX_SOCKET:
+ return (linux_socket(td, arg));
+ case LINUX_BIND:
+ return (linux_bind(td, arg));
+ case LINUX_CONNECT:
+ return (linux_connect(td, arg));
+ case LINUX_LISTEN:
+ return (linux_listen(td, arg));
+ case LINUX_ACCEPT:
+ return (linux_accept(td, arg));
+ case LINUX_GETSOCKNAME:
+ return (linux_getsockname(td, arg));
+ case LINUX_GETPEERNAME:
+ return (linux_getpeername(td, arg));
+ case LINUX_SOCKETPAIR:
+ return (linux_socketpair(td, arg));
+ case LINUX_SEND:
+ return (linux_send(td, arg));
+ case LINUX_RECV:
+ return (linux_recv(td, arg));
+ case LINUX_SENDTO:
+ return (linux_sendto(td, arg));
+ case LINUX_RECVFROM:
+ return (linux_recvfrom(td, arg));
+ case LINUX_SHUTDOWN:
+ return (linux_shutdown(td, arg));
+ case LINUX_SETSOCKOPT:
+ return (linux_setsockopt(td, arg));
+ case LINUX_GETSOCKOPT:
+ return (linux_getsockopt(td, arg));
+ case LINUX_SENDMSG:
+ do {
+ int error;
+ int level;
+ caddr_t control;
+ struct {
+ int s;
+ const struct msghdr *msg;
+ int flags;
+ } *uap = arg;
+
+ error = copyin(&uap->msg->msg_control, &control,
+ sizeof(caddr_t));
+ if (error)
+ return (error);
+
+ if (control == NULL)
+ goto done;
+
+ error = copyin(&((struct cmsghdr*)control)->cmsg_level,
+ &level, sizeof(int));
+ if (error)
+ return (error);
+
+ if (level == 1) {
+ /*
+ * Linux thinks that SOL_SOCKET is 1; we know
+ * that it's really 0xffff, of course.
+ */
+ level = SOL_SOCKET;
+ error = copyout(&level,
+ &((struct cmsghdr *)control)->cmsg_level,
+ sizeof(int));
+ if (error)
+ return (error);
+ }
+ done:
+ return (sendmsg(td, arg));
+ } while (0);
+ case LINUX_RECVMSG:
+ return (linux_recvmsg(td, arg));
+ }
+
+ uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
+ return (ENOSYS);
+}
+#endif /*!__alpha__*/
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
new file mode 100644
index 0000000..b6b9841
--- /dev/null
+++ b/sys/compat/linux/linux_socket.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2000 Assar Westerlund
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LINUX_SOCKET_H_
+#define _LINUX_SOCKET_H_
+
+/* msg flags in recvfrom/recvmsg */
+
+#define LINUX_MSG_OOB 0x01
+#define LINUX_MSG_PEEK 0x02
+#define LINUX_MSG_DONTROUTE 0x04
+#define LINUX_MSG_CTRUNC 0x08
+#define LINUX_MSG_PROXY 0x10
+#define LINUX_MSG_TRUNC 0x20
+#define LINUX_MSG_DONTWAIT 0x40
+#define LINUX_MSG_EOR 0x80
+#define LINUX_MSG_WAITALL 0x100
+#define LINUX_MSG_FIN 0x200
+#define LINUX_MSG_SYN 0x400
+#define LINUX_MSG_CONFIRM 0x800
+#define LINUX_MSG_RST 0x1000
+#define LINUX_MSG_ERRQUEUE 0x2000
+#define LINUX_MSG_NOSIGNAL 0x4000
+
+#endif /* _LINUX_SOCKET_H_ */
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
new file mode 100644
index 0000000..5ceb22a
--- /dev/null
+++ b/sys/compat/linux/linux_stats.c
@@ -0,0 +1,499 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/mac.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vnode.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct l_newstat tbuf;
+ struct cdevsw *cdevsw;
+ dev_t dev;
+
+ tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
+ tbuf.st_ino = buf->st_ino;
+ tbuf.st_mode = buf->st_mode;
+ tbuf.st_nlink = buf->st_nlink;
+ tbuf.st_uid = buf->st_uid;
+ tbuf.st_gid = buf->st_gid;
+ tbuf.st_rdev = buf->st_rdev;
+ tbuf.st_size = buf->st_size;
+ tbuf.st_atime = buf->st_atime;
+ tbuf.st_mtime = buf->st_mtime;
+ tbuf.st_ctime = buf->st_ctime;
+ tbuf.st_blksize = buf->st_blksize;
+ tbuf.st_blocks = buf->st_blocks;
+
+ /* Lie about disk drives which are character devices
+ * in FreeBSD but block devices under Linux.
+ */
+ if (S_ISCHR(tbuf.st_mode) &&
+ (dev = udev2dev(buf->st_rdev, 0)) != NODEV) {
+ cdevsw = devsw(dev);
+ if (cdevsw != NULL && (cdevsw->d_flags & D_DISK)) {
+ tbuf.st_mode &= ~S_IFMT;
+ tbuf.st_mode |= S_IFBLK;
+
+ /* XXX this may not be quite right */
+ /* Map major number to 0 */
+ tbuf.st_dev = uminor(buf->st_dev) & 0xf;
+ tbuf.st_rdev = buf->st_rdev & 0xff;
+ }
+ }
+
+ return (copyout(&tbuf, ubuf, sizeof(tbuf)));
+}
+
+int
+linux_newstat(struct thread *td, struct linux_newstat_args *args)
+{
+ struct stat buf;
+ struct nameidata nd;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(newstat))
+ printf(ARGS(newstat, "%s, *"), args->path);
+#endif
+
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = vn_stat(nd.ni_vp, &buf, td);
+ vput(nd.ni_vp);
+ if (error)
+ return (error);
+
+ return (newstat_copyout(&buf, args->buf));
+}
+
+int
+linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
+{
+ int error;
+ struct stat sb;
+ struct nameidata nd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(newlstat))
+ printf(ARGS(newlstat, "%s, *"), args->path);
+#endif
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ args->path, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = vn_stat(nd.ni_vp, &sb, td);
+ vput(nd.ni_vp);
+ if (error)
+ return (error);
+
+ return (newstat_copyout(&sb, args->buf));
+}
+
+int
+linux_newfstat(struct thread *td, struct linux_newfstat_args *args)
+{
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(newfstat))
+ printf(ARGS(newfstat, "%d, *"), args->fd);
+#endif
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+
+ error = fo_stat(fp, &buf, td);
+ fdrop(fp, td);
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+
+ return (error);
+}
+
+/* XXX - All fields of type l_int are defined as l_long on i386 */
+struct l_statfs {
+ l_int f_type;
+ l_int f_bsize;
+ l_int f_blocks;
+ l_int f_bfree;
+ l_int f_bavail;
+ l_int f_files;
+ l_int f_ffree;
+ l_fsid_t f_fsid;
+ l_int f_namelen;
+ l_int f_spare[6];
+};
+
+#define LINUX_CODA_SUPER_MAGIC 0x73757245L
+#define LINUX_EXT2_SUPER_MAGIC 0xEF53L
+#define LINUX_HPFS_SUPER_MAGIC 0xf995e849L
+#define LINUX_ISOFS_SUPER_MAGIC 0x9660L
+#define LINUX_MSDOS_SUPER_MAGIC 0x4d44L
+#define LINUX_NCP_SUPER_MAGIC 0x564cL
+#define LINUX_NFS_SUPER_MAGIC 0x6969L
+#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
+#define LINUX_PROC_SUPER_MAGIC 0x9fa0L
+#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
+
+static long
+bsd_to_linux_ftype(const char *fstypename)
+{
+ int i;
+ static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = {
+ {"ufs", LINUX_UFS_SUPER_MAGIC},
+ {"cd9660", LINUX_ISOFS_SUPER_MAGIC},
+ {"nfs", LINUX_NFS_SUPER_MAGIC},
+ {"ext2fs", LINUX_EXT2_SUPER_MAGIC},
+ {"procfs", LINUX_PROC_SUPER_MAGIC},
+ {"msdosfs", LINUX_MSDOS_SUPER_MAGIC},
+ {"ntfs", LINUX_NTFS_SUPER_MAGIC},
+ {"nwfs", LINUX_NCP_SUPER_MAGIC},
+ {"hpfs", LINUX_HPFS_SUPER_MAGIC},
+ {"coda", LINUX_CODA_SUPER_MAGIC},
+ {NULL, 0L}};
+
+ for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
+ if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0)
+ return (b2l_tbl[i].linux_type);
+
+ return (0L);
+}
+
+int
+linux_statfs(struct thread *td, struct linux_statfs_args *args)
+{
+ struct mount *mp;
+ struct nameidata *ndp;
+ struct statfs *bsd_statfs;
+ struct nameidata nd;
+ struct l_statfs linux_statfs;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(statfs))
+ printf(ARGS(statfs, "%s, *"), args->path);
+#endif
+ ndp = &nd;
+ NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curthread);
+ error = namei(ndp);
+ if (error)
+ return error;
+ NDFREE(ndp, NDF_ONLY_PNBUF);
+ mp = ndp->ni_vp->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ vrele(ndp->ni_vp);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_proc->p_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ error = VFS_STATFS(mp, bsd_statfs, td);
+ if (error)
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
+ linux_statfs.f_bsize = bsd_statfs->f_bsize;
+ linux_statfs.f_blocks = bsd_statfs->f_blocks;
+ linux_statfs.f_bfree = bsd_statfs->f_bfree;
+ linux_statfs.f_bavail = bsd_statfs->f_bavail;
+ linux_statfs.f_ffree = bsd_statfs->f_ffree;
+ linux_statfs.f_files = bsd_statfs->f_files;
+ linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.f_namelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(linux_statfs));
+}
+
+int
+linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *bsd_statfs;
+ struct l_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstatfs))
+ printf(ARGS(fstatfs, "%d, *"), args->fd);
+#endif
+ error = getvnode(td->td_proc->p_fd, args->fd, &fp);
+ if (error)
+ return error;
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_proc->p_ucred, mp);
+ if (error) {
+ fdrop(fp, td);
+ return (error);
+ }
+#endif
+ bsd_statfs = &mp->mnt_stat;
+ error = VFS_STATFS(mp, bsd_statfs, td);
+ if (error) {
+ fdrop(fp, td);
+ return error;
+ }
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
+ linux_statfs.f_bsize = bsd_statfs->f_bsize;
+ linux_statfs.f_blocks = bsd_statfs->f_blocks;
+ linux_statfs.f_bfree = bsd_statfs->f_bfree;
+ linux_statfs.f_bavail = bsd_statfs->f_bavail;
+ linux_statfs.f_ffree = bsd_statfs->f_ffree;
+ linux_statfs.f_files = bsd_statfs->f_files;
+ linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.f_namelen = MAXNAMLEN;
+ error = copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(linux_statfs));
+ fdrop(fp, td);
+ return error;
+}
+
+struct l_ustat
+{
+ l_daddr_t f_tfree;
+ l_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+int
+linux_ustat(struct thread *td, struct linux_ustat_args *args)
+{
+ struct l_ustat lu;
+ dev_t dev;
+ struct vnode *vp;
+ struct statfs *stat;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(ustat))
+ printf(ARGS(ustat, "%d, *"), args->dev);
+#endif
+
+ /*
+ * lu.f_fname and lu.f_fpack are not used. They are always zeroed.
+ * lu.f_tinode and lu.f_tfree are set from the device's super block.
+ */
+ bzero(&lu, sizeof(lu));
+
+ /*
+ * XXX - Don't return an error if we can't find a vnode for the
+ * device. Our dev_t is 32-bits whereas Linux only has a 16-bits
+ * dev_t. The dev_t that is used now may as well be a truncated
+ * dev_t returned from previous syscalls. Just return a bzeroed
+ * ustat in that case.
+ */
+ dev = makedev(args->dev >> 8, args->dev & 0xFF);
+ if (vfinddev(dev, VCHR, &vp)) {
+ if (vp->v_mount == NULL)
+ return (EINVAL);
+#ifdef MAC
+ error = mac_check_mount_stat(td->td_proc->p_ucred, mp);
+ if (error)
+ return (error);
+#endif
+ stat = &(vp->v_mount->mnt_stat);
+ error = VFS_STATFS(vp->v_mount, stat, td);
+ if (error)
+ return (error);
+
+ lu.f_tfree = stat->f_bfree;
+ lu.f_tinode = stat->f_ffree;
+ }
+
+ return (copyout(&lu, args->ubuf, sizeof(lu)));
+}
+
+#if defined(__i386__)
+
+static int
+stat64_copyout(struct stat *buf, void *ubuf)
+{
+ struct l_stat64 lbuf;
+
+ bzero(&lbuf, sizeof(lbuf));
+ lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8);
+ lbuf.st_ino = buf->st_ino;
+ lbuf.st_mode = buf->st_mode;
+ lbuf.st_nlink = buf->st_nlink;
+ lbuf.st_uid = buf->st_uid;
+ lbuf.st_gid = buf->st_gid;
+ lbuf.st_rdev = buf->st_rdev;
+ lbuf.st_size = buf->st_size;
+ lbuf.st_atime = buf->st_atime;
+ lbuf.st_mtime = buf->st_mtime;
+ lbuf.st_ctime = buf->st_ctime;
+ lbuf.st_blksize = buf->st_blksize;
+ lbuf.st_blocks = buf->st_blocks;
+
+ /*
+ * The __st_ino field makes all the difference. In the Linux kernel
+ * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO,
+ * but without the assignment to __st_ino the runtime linker refuses
+ * to mmap(2) any shared libraries. I guess it's broken alright :-)
+ */
+ lbuf.__st_ino = buf->st_ino;
+
+ return (copyout(&lbuf, ubuf, sizeof(lbuf)));
+}
+
+int
+linux_stat64(struct thread *td, struct linux_stat64_args *args)
+{
+ struct stat buf;
+ struct nameidata nd;
+ int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->filename);
+
+#ifdef DEBUG
+ if (ldebug(stat64))
+ printf(ARGS(stat64, "%s, *"), args->filename);
+#endif
+
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ args->filename, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = vn_stat(nd.ni_vp, &buf, td);
+ vput(nd.ni_vp);
+ if (error)
+ return (error);
+
+ return (stat64_copyout(&buf, args->statbuf));
+}
+
+int
+linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
+{
+ int error;
+ struct stat sb;
+ struct nameidata nd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->filename);
+
+#ifdef DEBUG
+ if (ldebug(lstat64))
+ printf(ARGS(lstat64, "%s, *"), args->filename);
+#endif
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
+ args->filename, td);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ error = vn_stat(nd.ni_vp, &sb, td);
+ vput(nd.ni_vp);
+ if (error)
+ return (error);
+
+ return (stat64_copyout(&sb, args->statbuf));
+}
+
+int
+linux_fstat64(struct thread *td, struct linux_fstat64_args *args)
+{
+ struct filedesc *fdp;
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstat64))
+ printf(ARGS(fstat64, "%d, *"), args->fd);
+#endif
+
+ fdp = td->td_proc->p_fd;
+ if ((unsigned)args->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return (EBADF);
+
+ error = fo_stat(fp, &buf, td);
+ if (!error)
+ error = stat64_copyout(&buf, args->statbuf);
+
+ return (error);
+}
+
+#endif /* __i386__ */
diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c
new file mode 100644
index 0000000..98dab20
--- /dev/null
+++ b/sys/compat/linux/linux_sysctl.c
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2001 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/sysproto.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+#define LINUX_CTL_KERN 1
+#define LINUX_CTL_VM 2
+#define LINUX_CTL_NET 3
+#define LINUX_CTL_PROC 4
+#define LINUX_CTL_FS 5
+#define LINUX_CTL_DEBUG 6
+#define LINUX_CTL_DEV 7
+#define LINUX_CTL_BUS 8
+
+/* CTL_KERN names */
+#define LINUX_KERN_OSTYPE 1
+#define LINUX_KERN_OSRELEASE 2
+#define LINUX_KERN_OSREV 3
+#define LINUX_KERN_VERSION 4
+
+static int
+handle_string(struct l___sysctl_args *la, char *value)
+{
+ int error;
+
+ if (la->oldval != NULL) {
+ l_int len = strlen(value);
+ error = copyout(value, la->oldval, len + 1);
+ if (!error && la->oldlenp != NULL)
+ error = copyout(&len, la->oldlenp, sizeof(len));
+ if (error)
+ return (error);
+ }
+
+ if (la->newval != NULL)
+ return (ENOTDIR);
+
+ return (0);
+}
+
+int
+linux_sysctl(struct thread *td, struct linux_sysctl_args *args)
+{
+ struct l___sysctl_args la;
+ l_int *mib;
+ int error, i;
+ caddr_t sg;
+
+ error = copyin((caddr_t)args->args, &la, sizeof(la));
+ if (error)
+ return (error);
+
+ if (la.nlen == 0 || la.nlen > LINUX_CTL_MAXNAME)
+ return (ENOTDIR);
+
+ sg = stackgap_init();
+ mib = stackgap_alloc(&sg, la.nlen * sizeof(l_int));
+ error = copyin(la.name, mib, la.nlen * sizeof(l_int));
+ if (error)
+ return (error);
+
+ switch (mib[0]) {
+ case LINUX_CTL_KERN:
+ if (la.nlen < 2)
+ break;
+
+ switch (mib[1]) {
+ case LINUX_KERN_VERSION:
+ return (handle_string(&la, version));
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ printf("linux: sysctl: unhandled name=");
+ for (i = 0; i < la.nlen; i++)
+ printf("%c%d", (i) ? ',' : '{', mib[i]);
+ printf("}\n");
+
+ return (ENOTDIR);
+}
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
new file mode 100644
index 0000000..ee39025
--- /dev/null
+++ b/sys/compat/linux/linux_uid16.c
@@ -0,0 +1,297 @@
+/*-
+ * Copyright (c) 2001 The FreeBSD Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysproto.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_util.h>
+
+DUMMY(setfsuid16);
+DUMMY(setfsgid16);
+DUMMY(getresuid16);
+DUMMY(getresgid16);
+
+#define CAST_NOCHG(x) (x == 0xFFFF) ? -1 : x;
+
+int
+linux_chown16(struct thread *td, struct linux_chown16_args *args)
+{
+ struct chown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(chown16))
+ printf(ARGS(chown16, "%s, %d, %d"), args->path, args->uid,
+ args->gid);
+#endif
+
+ bsd.path = args->path;
+ bsd.uid = CAST_NOCHG(args->uid);
+ bsd.gid = CAST_NOCHG(args->gid);
+ return (chown(td, &bsd));
+}
+
+int
+linux_lchown16(struct thread *td, struct linux_lchown16_args *args)
+{
+ struct lchown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(lchown16))
+ printf(ARGS(lchown16, "%s, %d, %d"), args->path, args->uid,
+ args->gid);
+#endif
+
+ bsd.path = args->path;
+ bsd.uid = CAST_NOCHG(args->uid);
+ bsd.gid = CAST_NOCHG(args->gid);
+ return (lchown(td, &bsd));
+}
+
+int
+linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args)
+{
+ struct ucred *newcred, *oldcred;
+ l_gid16_t linux_gidset[NGROUPS];
+ gid_t *bsd_gidset;
+ int ngrp, error;
+ struct proc *p;
+
+#ifdef DEBUG
+ if (ldebug(setgroups16))
+ printf(ARGS(setgroups16, "%d, *"), args->gidsetsize);
+#endif
+
+ ngrp = args->gidsetsize;
+ if (ngrp >= NGROUPS)
+ return (EINVAL);
+ error = copyin((caddr_t)args->gidset, linux_gidset,
+ ngrp * sizeof(l_gid16_t));
+ if (error)
+ return (error);
+ newcred = crget();
+ p = td->td_proc;
+ PROC_LOCK(p);
+ oldcred = p->p_ucred;
+
+ /*
+ * cr_groups[0] holds egid. Setting the whole set from
+ * the supplied set will cause egid to be changed too.
+ * Keep cr_groups[0] unchanged to prevent that.
+ */
+
+ if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) {
+ PROC_UNLOCK(p);
+ crfree(newcred);
+ return (error);
+ }
+
+ crcopy(newcred, oldcred);
+ if (ngrp > 0) {
+ newcred->cr_ngroups = ngrp + 1;
+
+ bsd_gidset = newcred->cr_groups;
+ ngrp--;
+ while (ngrp >= 0) {
+ bsd_gidset[ngrp + 1] = linux_gidset[ngrp];
+ ngrp--;
+ }
+ }
+ else
+ newcred->cr_ngroups = 1;
+
+ setsugid(td->td_proc);
+ p->p_ucred = newcred;
+ PROC_UNLOCK(p);
+ crfree(oldcred);
+ return (0);
+}
+
+int
+linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args)
+{
+ struct ucred *cred;
+ l_gid16_t linux_gidset[NGROUPS];
+ gid_t *bsd_gidset;
+ int bsd_gidsetsz, ngrp, error;
+
+#ifdef DEBUG
+ if (ldebug(getgroups16))
+ printf(ARGS(getgroups16, "%d, *"), args->gidsetsize);
+#endif
+
+ cred = td->td_ucred;
+ bsd_gidset = cred->cr_groups;
+ bsd_gidsetsz = cred->cr_ngroups - 1;
+
+ /*
+ * cr_groups[0] holds egid. Returning the whole set
+ * here will cause a duplicate. Exclude cr_groups[0]
+ * to prevent that.
+ */
+
+ if ((ngrp = args->gidsetsize) == 0) {
+ td->td_retval[0] = bsd_gidsetsz;
+ return (0);
+ }
+
+ if (ngrp < bsd_gidsetsz)
+ return (EINVAL);
+
+ ngrp = 0;
+ while (ngrp < bsd_gidsetsz) {
+ linux_gidset[ngrp] = bsd_gidset[ngrp + 1];
+ ngrp++;
+ }
+
+ error = copyout(linux_gidset, (caddr_t)args->gidset,
+ ngrp * sizeof(l_gid16_t));
+ if (error)
+ return (error);
+
+ td->td_retval[0] = ngrp;
+ return (0);
+}
+
+/*
+ * The FreeBSD native getgid(2) and getuid(2) also modify td->td_retval[1]
+ * when COMPAT_43 or COMPAT_SUNOS is defined. This globbers registers that
+ * are assumed to be preserved. The following lightweight syscalls fixes
+ * this. See also linux_getpid(2), linux_getgid(2) and linux_getuid(2) in
+ * linux_misc.c
+ *
+ * linux_getgid16() - MP SAFE
+ * linux_getuid16() - MP SAFE
+ */
+
+int
+linux_getgid16(struct thread *td, struct linux_getgid16_args *args)
+{
+
+ td->td_retval[0] = td->td_ucred->cr_rgid;
+ return (0);
+}
+
+int
+linux_getuid16(struct thread *td, struct linux_getuid16_args *args)
+{
+
+ td->td_retval[0] = td->td_ucred->cr_ruid;
+ return (0);
+}
+
+int
+linux_getegid16(struct thread *td, struct linux_getegid16_args *args)
+{
+ struct getegid_args bsd;
+
+ return (getegid(td, &bsd));
+}
+
+int
+linux_geteuid16(struct thread *td, struct linux_geteuid16_args *args)
+{
+ struct geteuid_args bsd;
+
+ return (geteuid(td, &bsd));
+}
+
+int
+linux_setgid16(struct thread *td, struct linux_setgid16_args *args)
+{
+ struct setgid_args bsd;
+
+ bsd.gid = args->gid;
+ return (setgid(td, &bsd));
+}
+
+int
+linux_setuid16(struct thread *td, struct linux_setuid16_args *args)
+{
+ struct setuid_args bsd;
+
+ bsd.uid = args->uid;
+ return (setuid(td, &bsd));
+}
+
+int
+linux_setregid16(struct thread *td, struct linux_setregid16_args *args)
+{
+ struct setregid_args bsd;
+
+ bsd.rgid = CAST_NOCHG(args->rgid);
+ bsd.egid = CAST_NOCHG(args->egid);
+ return (setregid(td, &bsd));
+}
+
+int
+linux_setreuid16(struct thread *td, struct linux_setreuid16_args *args)
+{
+ struct setreuid_args bsd;
+
+ bsd.ruid = CAST_NOCHG(args->ruid);
+ bsd.euid = CAST_NOCHG(args->euid);
+ return (setreuid(td, &bsd));
+}
+
+int
+linux_setresgid16(struct thread *td, struct linux_setresgid16_args *args)
+{
+ struct setresgid_args bsd;
+
+ bsd.rgid = CAST_NOCHG(args->rgid);
+ bsd.egid = CAST_NOCHG(args->egid);
+ bsd.sgid = CAST_NOCHG(args->sgid);
+ return (setresgid(td, &bsd));
+}
+
+int
+linux_setresuid16(struct thread *td, struct linux_setresuid16_args *args)
+{
+ struct setresuid_args bsd;
+
+ bsd.ruid = CAST_NOCHG(args->ruid);
+ bsd.euid = CAST_NOCHG(args->euid);
+ bsd.suid = CAST_NOCHG(args->suid);
+ return (setresuid(td, &bsd));
+}
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
new file mode 100644
index 0000000..4949a45
--- /dev/null
+++ b/sys/compat/linux/linux_util.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include <compat/linux/linux_util.h>
+
+const char linux_emul_path[] = "/compat/linux";
+
+/*
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+linux_emul_find(td, sgp, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+ int error;
+ const char *prefix;
+ char *ptr, *buf, *cp;
+ size_t sz, len;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ prefix = linux_emul_path;
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--);
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ }
+ else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the linux_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) {
+ goto bad;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td))
+ != 0) {
+ goto bad;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto bad;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ if (*pbuf != NULL)
+ error = copyout(buf, *pbuf, sz);
+ else
+ error = ENAMETOOLONG;
+ free(buf, M_TEMP);
+ }
+
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ if (!cflag) {
+ NDFREE(&ndroot, NDF_ONLY_PNBUF);
+ vrele(ndroot.ni_vp);
+ }
+ return error;
+
+bad:
+ NDFREE(&ndroot, NDF_ONLY_PNBUF);
+ vrele(ndroot.ni_vp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vrele(nd.ni_vp);
+ free(buf, M_TEMP);
+ return error;
+}
diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h
new file mode 100644
index 0000000..ee421a2
--- /dev/null
+++ b/sys/compat/linux/linux_util.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
+ * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
+ * $FreeBSD$
+ */
+
+/*
+ * This file is pretty much the same as Christos' svr4_util.h
+ * (for now).
+ */
+
+#ifndef _LINUX_UTIL_H_
+#define _LINUX_UTIL_H_
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode))
+
+static __inline caddr_t
+stackgap_init()
+{
+ return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE);
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p = (void *) *sgp;
+
+ sz = ALIGN(sz);
+ if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode))
+ return NULL;
+ *sgp += sz;
+ return p;
+}
+
+extern const char linux_emul_path[];
+
+int linux_emul_find(struct thread *, caddr_t *, char *, char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = linux_emul_find(p, sgp, path, &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT(p, sgp, path, 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT(p, sgp, path, 1)
+
+#define DUMMY(s) \
+int \
+linux_ ## s(struct thread *p, struct linux_ ## s ## _args *args) \
+{ \
+ return (unsupported_msg(p, #s)); \
+} \
+struct __hack
+
+static __inline int
+unsupported_msg(struct thread *td, const char *fname)
+{
+
+ printf("linux: syscall %s is obsoleted or not implemented (pid=%ld)\n",
+ fname, (long)td->td_proc->p_pid);
+ return (ENOSYS);
+}
+
+#endif /* !_LINUX_UTIL_H_ */
diff --git a/sys/compat/netbsd/dvcfg.h b/sys/compat/netbsd/dvcfg.h
new file mode 100644
index 0000000..5485f89
--- /dev/null
+++ b/sys/compat/netbsd/dvcfg.h
@@ -0,0 +1,65 @@
+/* $FreeBSD$ */
+/* $NetBSD$ */
+/*
+ * [NetBSD for NEC PC98 series]
+ * Copyright (c) 1996 NetBSD/pc98 porting staff.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1996 Naofumi HONDA. All rights reserved.
+ */
+
+#ifndef _I386_DVCFG_H_
+#define _I386_DVCFG_H_
+
+typedef void *dvcfg_hw_t;
+
+struct dvcfg_hwsel {
+ int cfg_max;
+
+ dvcfg_hw_t *cfg_sel;
+};
+
+#define DVCFG_MAJOR(dvcfg) (((u_int)(dvcfg)) >> 16)
+#define DVCFG_MINOR(dvcfg) (((u_int)(dvcfg)) & 0xffff)
+
+#define DVCFG_MKCFG(major, minor) ((((u_int)(major)) << 16) | ((minor) & 0xffff))
+
+#define DVCFG_HWSEL_SZ(array) (sizeof(array) / sizeof(dvcfg_hw_t))
+
+static __inline dvcfg_hw_t dvcfg_hw(struct dvcfg_hwsel *, u_int);
+
+static __inline dvcfg_hw_t
+dvcfg_hw(selp, num)
+ struct dvcfg_hwsel *selp;
+ u_int num;
+{
+
+ return ((num >= selp->cfg_max) ? 0 : selp->cfg_sel[num]);
+}
+
+#define DVCFG_HW(SELP, NUM) dvcfg_hw((SELP), (NUM))
+#endif /* _I386_DVCFG_H_ */
diff --git a/sys/compat/netbsd/physio_proc.h b/sys/compat/netbsd/physio_proc.h
new file mode 100644
index 0000000..74848a4
--- /dev/null
+++ b/sys/compat/netbsd/physio_proc.h
@@ -0,0 +1,56 @@
+/* $FreeBSD$ */
+/* $NecBSD: physio_proc.h,v 3.4 1999/07/23 20:47:03 honda Exp $ */
+/* $NetBSD$ */
+
+/*
+ * [NetBSD for NEC PC-98 series]
+ * Copyright (c) 1998
+ * NetBSD/pc98 porting staff. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _I386_PHYSIO_PROC_H_
+#define _I386_PHYSIO_PROC_H_
+#include <sys/buf.h>
+#include <sys/queue.h>
+
+struct physio_proc {
+};
+
+static __inline struct physio_proc *physio_proc_enter(struct buf *);
+static __inline void physio_proc_leave(struct physio_proc *);
+
+static __inline struct physio_proc *
+physio_proc_enter(bp)
+ struct buf *bp;
+{
+ return NULL;
+}
+
+static __inline void
+physio_proc_leave(pp)
+ struct physio_proc *pp;
+{
+}
+#endif /* _I386_PHYSIO_PROC_H_ */
diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c
new file mode 100644
index 0000000..175b021
--- /dev/null
+++ b/sys/compat/pecoff/imgact_pecoff.c
@@ -0,0 +1,650 @@
+/* $NetBSD$ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2000 Masaru OKI
+ * Copyright (c) 1994, 1995, 1998 Scott Bartram
+ * Copyright (c) 1994 Adam Glass
+ * Copyright (c) 1993, 1994 Christopher G. Demetriou
+ *
+ * originally from NetBSD kern/exec_ecoff.c
+ *
+ * Copyright (c) 2000 Takanori Watanabe
+ * Copyright (c) 2000 KUROSAWA Takahiro
+ * Copyright (c) 1995-1996 Sen Schmidt
+ * Copyright (c) 1996 Peter Wemm
+ * All rights reserved.
+ *
+ * originally from FreeBSD kern/imgact_elf.c
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Masaru OKI.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/imgact.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/signalvar.h>
+#include <sys/sysent.h>
+#include <sys/vnode.h>
+
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/cpu.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <machine/md_var.h>
+#include <machine/pecoff_machdep.h>
+#include <compat/pecoff/imgact_pecoff.h>
+
+#include "opt_pecoff.h"
+
+#define PECOFF_PE_SIGNATURE "PE\0\0"
+static int pecoff_fixup(register_t **, struct image_params *);
+static int
+pecoff_coredump(register struct thread *, register struct vnode *,
+ off_t);
+#ifndef PECOFF_DEBUG
+#define DPRINTF(a)
+#else
+#define DPRINTF(a) printf a
+#endif
+static struct sysentvec pecoff_sysvec = {
+ SYS_MAXSYSCALL,
+ sysent,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ pecoff_fixup,
+ sendsig,
+ sigcode,
+ &szsigcode,
+ 0,
+ "FreeBSD PECoff",
+ pecoff_coredump,
+ NULL,
+ MINSIGSTKSZ
+
+};
+
+static const char signature[] = PECOFF_PE_SIGNATURE;
+
+static int
+exec_pecoff_coff_prep_omagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+static int
+exec_pecoff_coff_prep_nmagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+static int
+exec_pecoff_coff_prep_zmagic(struct image_params *,
+ struct coff_filehdr *,
+ struct coff_aouthdr *, int peoffs);
+
+static int
+exec_pecoff_coff_makecmds(struct image_params *,
+ struct coff_filehdr *, int);
+
+static int pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *);
+static int pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int);
+static int
+pecoff_load_section(struct thread * td,
+ struct vmspace * vmspace, struct vnode * vp,
+ vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
+ vm_prot_t prot);
+
+static int
+pecoff_fixup(register_t ** stack_base, struct image_params * imgp)
+{
+ int len = sizeof(struct pecoff_args);
+ struct pecoff_imghdr *ap;
+ register_t *pos;
+
+ pos = *stack_base + (imgp->argc + imgp->envc + 2);
+ ap = (struct pecoff_imghdr *) imgp->auxargs;
+ if (copyout(ap, pos, len)) {
+ return NULL;
+ }
+ free(ap, M_TEMP);
+ imgp->auxargs = NULL;
+ (*stack_base)--;
+ suword(*stack_base, (long) imgp->argc);
+ return 0;
+}
+
+
+static int
+pecoff_coredump(register struct thread * td, register struct vnode * vp,
+ off_t limit)
+{
+ register struct ucred *cred = td->td_ucred;
+ struct proc *p = td->td_proc;
+ register struct vmspace *vm = p->p_vmspace;
+ int error;
+#ifdef PECOFF_DEBUG
+ struct vm_map *map;
+ struct vm_map_entry *ent;
+ struct reg regs;
+
+#endif
+ if (ctob((UAREA_PAGES+KSTACK_PAGES) + vm->vm_dsize + vm->vm_ssize) >= limit)
+ return (EFAULT);
+ PROC_LOCK(p);
+ fill_kinfo_proc(p, &p->p_uarea->u_kproc);
+ PROC_UNLOCK(p);
+
+#if PECOFF_DEBUG
+ fill_regs(td, &regs);
+ printf("EIP%x\n", regs.r_eip);
+ printf("EAX%x EBX%x ECX%x EDI%x\n",
+ regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi);
+ map = &vm->vm_map;
+ ent = &map->header;
+ printf("%p %p %p\n", ent, ent->prev, ent->next);
+#endif
+ error = cpu_coredump(td, vp, cred);
+ if (error == 0)
+ error = vn_rdwr_inchunks(UIO_WRITE, vp, vm->vm_daddr,
+ (int)ctob(vm->vm_dsize),
+ (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)),
+ UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td);
+ if (error == 0)
+ error = vn_rdwr_inchunks(UIO_WRITE, vp,
+ (caddr_t)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
+ round_page(ctob(vm->vm_ssize)),
+ (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)) +
+ ctob(vm->vm_dsize),
+ UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td);
+ return (error);
+
+}
+
+static int
+pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot)
+{
+ size_t map_len;
+ vm_offset_t map_addr;
+ int error, rv;
+ size_t copy_len;
+ size_t copy_map_len;
+ size_t copy_start;
+ vm_object_t object;
+ vm_offset_t copy_map_offset;
+ vm_offset_t file_addr;
+ vm_offset_t data_buf = 0;
+
+ object = vp->v_object;
+ error = 0;
+
+ map_addr = trunc_page((vm_offset_t) vmaddr);
+ file_addr = trunc_page(offset);
+ DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz));
+ if (file_addr != offset) {
+ /*
+ * The section is not on page boundary. We can't use
+ * vm_map_insert(). Use copyin instead.
+ */
+ map_len = round_page(memsz);
+ copy_len = filsz;
+ copy_map_offset = file_addr;
+ copy_map_len = round_page(offset + filsz) - file_addr;
+ copy_start = offset - file_addr;
+
+ DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n",
+ offset, (long)vmaddr, filsz, memsz));
+ DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x"
+ " copy_map_len=%x copy_start=%x\n",
+ map_len, copy_len, copy_map_offset,
+ copy_map_len, copy_start));
+ } else {
+
+ map_len = trunc_page(filsz);
+
+ if (map_len != 0) {
+ vm_object_reference(object);
+ vm_map_lock(&vmspace->vm_map);
+ rv = vm_map_insert(&vmspace->vm_map,
+ object,
+ file_addr, /* file offset */
+ map_addr, /* virtual start */
+ map_addr + map_len, /* virtual end */
+ prot,
+ VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_PREFAULT);
+
+ vm_map_unlock(&vmspace->vm_map);
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return EINVAL;
+ }
+ /* we can stop now if we've covered it all */
+ if (memsz == filsz)
+ return 0;
+
+ }
+ copy_map_offset = trunc_page(offset + filsz);
+ copy_map_len = PAGE_SIZE;
+ copy_start = 0;
+ copy_len = (offset + filsz) - trunc_page(offset + filsz);
+ map_addr = trunc_page((vm_offset_t) vmaddr + filsz);
+ map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr;
+
+ }
+
+ if (map_len != 0) {
+ vm_map_lock(&vmspace->vm_map);
+ rv = vm_map_insert(&vmspace->vm_map, NULL, 0,
+ map_addr, map_addr + map_len,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ vm_map_unlock(&vmspace->vm_map);
+ DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len));
+ if (rv != KERN_SUCCESS) {
+ return EINVAL;
+ }
+ }
+ DPRINTF(("COPYARG %x %x\n", map_addr, copy_len));
+ if (copy_len != 0) {
+ vm_object_reference(object);
+ rv = vm_map_find(exec_map,
+ object,
+ copy_map_offset,
+ &data_buf,
+ copy_map_len,
+ TRUE,
+ VM_PROT_READ,
+ VM_PROT_ALL,
+ MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL);
+ if (rv != KERN_SUCCESS) {
+ vm_object_deallocate(object);
+ return EINVAL;
+ }
+ /* send the page fragment to user space */
+
+ error = copyout((caddr_t) data_buf + copy_start,
+ (caddr_t) map_addr, copy_len);
+ vm_map_remove(exec_map, data_buf, data_buf + copy_map_len);
+ DPRINTF(("%d\n", error));
+ if (error)
+ return (error);
+ }
+ /*
+ * set it to the specified protection
+ */
+ vm_map_protect(&vmspace->vm_map, map_addr,
+ map_addr + map_len, prot,
+ FALSE);
+ return error;
+
+}
+static int
+pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport)
+{
+
+ struct nameidata nd;
+ struct pecoff_dos_filehdr dh;
+ struct coff_filehdr *fp = 0;
+ struct coff_aouthdr *ap;
+ struct pecoff_opthdr *wp;
+ struct coff_scnhdr *sh = 0;
+ struct vmspace *vmspace = td->td_proc->p_vmspace;
+ struct vattr attr;
+ struct image_params image_params, *imgp;
+ int peofs;
+ int error, i, scnsiz;
+
+ imgp = &image_params;
+ /*
+ * Initialize part of the common data
+ */
+ imgp->proc = td->td_proc;
+ imgp->uap = NULL;
+ imgp->attr = &attr;
+ imgp->firstpage = NULL;
+
+ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td);
+
+ if ((error = namei(&nd)) != 0) {
+ nd.ni_vp = NULL;
+ goto fail;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ imgp->vp = nd.ni_vp;
+
+ /*
+ * Check permissions, modes, uid, etc on the file, and "open" it.
+ */
+ error = exec_check_permissions(imgp);
+ if (error) {
+ VOP_UNLOCK(nd.ni_vp, 0, td);
+ goto fail;
+ }
+ VOP_UNLOCK(nd.ni_vp, 0, td);
+ if (error)
+ goto fail;
+ if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0)
+ goto fail;
+ if ((error = pecoff_signature(td, imgp->vp, &dh) != 0))
+ goto fail;
+ fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
+ peofs = dh.d_peofs + sizeof(signature) - 1;
+ if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0))
+ goto fail;
+ if (COFF_BADMAG(fp)) {
+ error = ENOEXEC;
+ goto fail;
+ }
+ ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
+ wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
+ /* read section header */
+ scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
+ sh = malloc(scnsiz, M_TEMP, M_WAITOK);
+ if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE,
+ (caddr_t) sh, scnsiz)) != 0)
+ goto fail;
+
+ /*
+ * Read Section infomation and map sections.
+ */
+
+ for (i = 0; i < fp->f_nscns; i++) {
+ int prot = 0;
+
+ if (sh[i].s_flags & COFF_STYP_DISCARD)
+ continue;
+ /* XXX ? */
+ if ((sh[i].s_flags & COFF_STYP_TEXT) &&
+ (sh[i].s_flags & COFF_STYP_EXEC) == 0)
+ continue;
+ if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0)
+ continue;
+
+ prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
+
+ sh[i].s_vaddr += wp->w_base; /* RVA --> VA */
+ if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr
+ ,(caddr_t) sh[i].s_vaddr,
+ sh[i].s_paddr, sh[i].s_size
+ ,prot)) != 0)
+ goto fail;
+
+ }
+ *entry = wp->w_base + ap->a_entry;
+ *addr = wp->w_base;
+ *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base;
+fail:
+ if (fp)
+ free(fp, M_TEMP);
+ if (sh)
+ free(sh, M_TEMP);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+
+ return error;
+}
+static int
+exec_pecoff_coff_prep_omagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ return ENOEXEC;
+}
+static int
+exec_pecoff_coff_prep_nmagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ return ENOEXEC;
+}
+static int
+exec_pecoff_coff_prep_zmagic(struct image_params * imgp,
+ struct coff_filehdr * fp,
+ struct coff_aouthdr * ap, int peofs)
+{
+ int scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns;
+ int error = ENOEXEC, i;
+ int prot;
+ u_long text_size = 0, data_size = 0, dsize;
+ u_long text_addr = 0, data_addr = VM_MAXUSER_ADDRESS;
+ u_long ldexport, ldbase;
+ struct pecoff_opthdr *wp;
+ struct coff_scnhdr *sh;
+ struct vmspace *vmspace;
+ struct pecoff_args *argp = NULL;
+
+ sh = malloc(scnsiz, M_TEMP, M_WAITOK);
+
+ wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr));
+ error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp,
+ peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz);
+ if ((error = exec_extract_strings(imgp)) != 0)
+ goto fail;
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
+ vmspace = imgp->proc->p_vmspace;
+ for (i = 0; i < fp->f_nscns; i++) {
+ prot = VM_PROT_WRITE; /* XXX for relocation? */
+ prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0;
+ prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0;
+ sh[i].s_vaddr += wp->w_base;
+ if (sh[i].s_flags & COFF_STYP_DISCARD)
+ continue;
+ if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) {
+
+ error = pecoff_load_section(
+ FIRST_THREAD_IN_PROC(imgp->proc),
+ vmspace, imgp->vp, sh[i].s_scnptr,
+ (caddr_t) sh[i].s_vaddr, sh[i].s_paddr,
+ sh[i].s_size ,prot);
+ DPRINTF(("ERROR%d\n", error));
+ if (error)
+ goto fail;
+ text_addr = trunc_page(sh[i].s_vaddr);
+ text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr);
+
+ }
+ if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) {
+ if (pecoff_load_section(
+ FIRST_THREAD_IN_PROC(imgp->proc), vmspace,
+ imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr,
+ sh[i].s_paddr, sh[i].s_size, prot) != 0)
+ goto fail;
+ data_addr = min(trunc_page(sh[i].s_vaddr), data_addr);
+ dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr)
+ - data_addr;
+ data_size = max(dsize, data_size);
+
+ }
+ }
+ vmspace->vm_tsize = text_size >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr;
+ vmspace->vm_dsize = data_size >> PAGE_SHIFT;
+ vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr;
+ argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK);
+ if (argp == NULL) {
+ error = ENOMEM;
+ goto fail;
+ }
+ argp->a_base = wp->w_base;
+ argp->a_entry = wp->w_base + ap->a_entry;
+ argp->a_end = data_addr + data_size;
+ argp->a_subsystem = wp->w_subvers;
+ error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc),
+ "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport);
+ if (error)
+ goto fail;
+
+ argp->a_ldbase = ldbase;
+ argp->a_ldexport = ldexport;
+ memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16);
+ for (i = 0; i < 16; i++) {
+ argp->a_imghdr[i].i_vaddr += wp->w_base;
+ }
+ imgp->proc->p_sysent = &pecoff_sysvec;
+ if (error)
+ goto fail;
+ imgp->auxargs = argp;
+ imgp->auxarg_size = sizeof(struct pecoff_args);
+ imgp->interpreted = 0;
+
+ mp_fixme("Unlocked vflag access.");
+ imgp->vp->v_vflag |= VV_TEXT;
+ if (sh != NULL)
+ free(sh, M_TEMP);
+ return 0;
+fail:
+ error = (error) ? error : ENOEXEC;
+ if (sh != NULL)
+ free(sh, M_TEMP);
+ if (argp != NULL)
+ free(argp, M_TEMP);
+
+ return error;
+}
+
+int
+exec_pecoff_coff_makecmds(struct image_params * imgp,
+ struct coff_filehdr * fp, int peofs)
+{
+ struct coff_aouthdr *ap;
+ int error;
+
+ if (COFF_BADMAG(fp)) {
+ return ENOEXEC;
+ }
+ ap = (void *) ((char *) fp + sizeof(struct coff_filehdr));
+ switch (ap->a_magic) {
+ case COFF_OMAGIC:
+ error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs);
+ break;
+ case COFF_NMAGIC:
+ error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs);
+ break;
+ case COFF_ZMAGIC:
+ error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs);
+ break;
+ default:
+ return ENOEXEC;
+ }
+
+ return error;
+}
+
+static int
+pecoff_signature(td, vp, dp)
+ struct thread *td;
+ struct vnode *vp;
+ const struct pecoff_dos_filehdr *dp;
+{
+ int error;
+ char buf[512];
+ char *pesig;
+ if (DOS_BADMAG(dp)) {
+ return ENOEXEC;
+ }
+ error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf));
+ if (error) {
+ return error;
+ }
+ pesig = buf;
+ if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) {
+ return 0;
+ }
+ return EFTYPE;
+}
+int
+pecoff_read_from(td, vp, pos, buf, siz)
+ struct thread *td;
+ struct vnode *vp;
+ int pos;
+ caddr_t buf;
+ int siz;
+{
+ int error;
+ size_t resid;
+
+ error = vn_rdwr(UIO_READ, vp, buf, siz, pos,
+ UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
+ &resid, td);
+ if (error)
+ return error;
+
+ if (resid != 0) {
+ return ENOEXEC;
+ }
+ return 0;
+}
+
+static int
+imgact_pecoff(struct image_params * imgp)
+{
+ const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *)
+ imgp->image_header;
+ struct coff_filehdr *fp;
+ int error, peofs;
+ error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc),
+ imgp->vp, dp);
+ if (error) {
+ return -1;
+ }
+ peofs = dp->d_peofs + sizeof(signature) - 1;
+ fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK);
+ error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc),
+ imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE);
+ if (error) {
+ free(fp, M_TEMP);
+ return error;
+ }
+ error = exec_pecoff_coff_makecmds(imgp, fp, peofs);
+ free(fp, M_TEMP);
+ return error;
+}
+
+static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"};
+EXEC_SET(pecoff, pecoff_execsw);
diff --git a/sys/compat/pecoff/imgact_pecoff.h b/sys/compat/pecoff/imgact_pecoff.h
new file mode 100644
index 0000000..0da3a56
--- /dev/null
+++ b/sys/compat/pecoff/imgact_pecoff.h
@@ -0,0 +1,142 @@
+/* $NetBSD$ */
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 2000 Masaru OKI
+ */
+
+#ifndef _PECOFF_EXEC_H_
+#define _PECOFF_EXEC_H_
+
+struct pecoff_dos_filehdr {
+ u_int16_t d_magic;/* +0x00 'MZ' */
+ u_int8_t d_stub[0x3a];
+ u_int32_t d_peofs;/* +0x3c */
+};
+
+#define PECOFF_DOS_MAGIC 0x5a4d
+#define PECOFF_DOS_HDR_SIZE (sizeof(struct pecoff_dos_filehdr))
+
+#define DOS_BADMAG(dp) ((dp)->d_magic != PECOFF_DOS_MAGIC)
+
+/*
+ * COFF file header
+ */
+
+struct coff_filehdr {
+ u_short f_magic;/* magic number */
+ u_short f_nscns;/* # of sections */
+ long f_timdat; /* timestamp */
+ long f_symptr; /* file offset of symbol table */
+ long f_nsyms;/* # of symbol table entries */
+ u_short f_opthdr; /* size of optional header */
+ u_short f_flags;/* flags */
+};
+
+/*
+ * COFF system header
+ */
+
+struct coff_aouthdr {
+ short a_magic;
+ short a_vstamp;
+ long a_tsize;
+ long a_dsize;
+ long a_bsize;
+ long a_entry;
+ long a_tstart;
+ long a_dstart;
+};
+
+/* magic */
+#define COFF_OMAGIC 0407 /* text not write-protected; data seg is
+ * contiguous with text */
+#define COFF_NMAGIC 0410 /* text is write-protected; data starts at
+ * next seg following text */
+#define COFF_ZMAGIC 0413 /* text and data segs are aligned for direct
+ * paging */
+#define COFF_SMAGIC 0443 /* shared lib */
+
+struct pecoff_imghdr {
+ long i_vaddr;
+ long i_size;
+};
+
+struct pecoff_opthdr {
+ long w_base;
+ long w_salign;
+ long w_falign;
+ long w_osvers;
+ long w_imgvers;
+ long w_subvers;
+ long w_rsvd;
+ long w_imgsize;
+ long w_hdrsize;
+ long w_chksum;
+ u_short w_subsys;
+ u_short w_dllflags;
+ long w_ssize;
+ long w_cssize;
+ long w_hsize;
+ long w_chsize;
+ long w_lflag;
+ long w_nimghdr;
+ struct pecoff_imghdr w_imghdr[16];
+};
+
+/*
+ * COFF section header
+ */
+
+struct coff_scnhdr {
+ char s_name[8];
+ long s_paddr;
+ long s_vaddr;
+ long s_size;
+ long s_scnptr;
+ long s_relptr;
+ long s_lnnoptr;
+ u_short s_nreloc;
+ u_short s_nlnno;
+ long s_flags;
+};
+
+/* s_flags */
+#define COFF_STYP_REG 0x00
+#define COFF_STYP_DSECT 0x01
+#define COFF_STYP_NOLOAD 0x02
+#define COFF_STYP_GROUP 0x04
+#define COFF_STYP_PAD 0x08
+#define COFF_STYP_COPY 0x10
+#define COFF_STYP_TEXT 0x20
+#define COFF_STYP_DATA 0x40
+#define COFF_STYP_BSS 0x80
+#define COFF_STYP_INFO 0x200
+#define COFF_STYP_OVER 0x400
+#define COFF_STYP_SHLIB 0x800
+/* s_flags for PE */
+#define COFF_STYP_DISCARD 0x2000000
+#define COFF_STYP_EXEC 0x20000000
+#define COFF_STYP_READ 0x40000000
+#define COFF_STYP_WRITE 0x80000000
+
+struct pecoff_args {
+ u_long a_base;
+ u_long a_entry;
+ u_long a_end;
+ u_long a_subsystem;
+ struct pecoff_imghdr a_imghdr[16];
+ u_long a_ldbase;
+ u_long a_ldexport;
+};
+
+#define COFF_LDPGSZ 4096
+#define COFF_ALIGN(a) ((a) & ~(COFF_LDPGSZ - 1))
+#define COFF_ROUND(a) COFF_ALIGN((a) + COFF_LDPGSZ - 1)
+
+#define COFF_HDR_SIZE \
+ (sizeof(struct coff_filehdr) + sizeof(struct coff_aouthdr))
+
+#define PECOFF_HDR_SIZE (COFF_HDR_SIZE + sizeof(struct pecoff_opthdr))
+
+
+#endif
diff --git a/sys/compat/svr4/Makefile b/sys/compat/svr4/Makefile
new file mode 100644
index 0000000..7da356e
--- /dev/null
+++ b/sys/compat/svr4/Makefile
@@ -0,0 +1,19 @@
+# Makefile for syscall tables
+#
+# $FreeBSD$
+
+MAINTAINER= newton@freebsd.org
+
+all:
+ @echo "make sysent only"
+
+sysent: svr4_sysent.c svr4_syscall.h svr4_proto.h
+
+svr4_syscallnames.c svr4_sysent.c svr4_syscall.h svr4_proto.h: \
+ ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+ -mv -f svr4_syscallnames.c svr4_syscallnames.c.bak
+ -mv -f svr4_sysent.c svr4_sysent.c.bak
+ -mv -f svr4_syscall.h svr4_syscall.h.bak
+ -mv -f svr4_proto.h svr4_proto.h.bak
+ sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+
diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c
new file mode 100644
index 0000000..c8b0e1f8
--- /dev/null
+++ b/sys/compat/svr4/imgact_svr4.c
@@ -0,0 +1,241 @@
+/*-
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * All rights reserved.
+ *
+ * Based heavily on /sys/kern/imgact_aout.c which is:
+ * Copyright (c) 1993, David Greenman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/imgact_aout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_extern.h>
+
+#include <compat/svr4/svr4.h>
+
+static int exec_svr4_imgact(struct image_params *iparams);
+
+static int
+exec_svr4_imgact(imgp)
+ struct image_params *imgp;
+{
+ const struct exec *a_out = (const struct exec *) imgp->image_header;
+ struct vmspace *vmspace;
+ vm_offset_t vmaddr;
+ unsigned long virtual_offset, file_offset;
+ vm_offset_t buffer;
+ unsigned long bss_size;
+ int error;
+
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413:
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314:
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+ bss_size = round_page(a_out->a_bss);
+#ifdef DEBUG
+ printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", a_out->a_text, a_out->a_data, bss_size);
+#endif
+
+ /*
+ * Check various fields in header for validity/bounds.
+ */
+ if (a_out->a_entry < virtual_offset ||
+ a_out->a_entry >= virtual_offset + a_out->a_text ||
+ a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
+ return (-1);
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
+ return (EFAULT);
+ /* For p_rlimit below. */
+ mtx_assert(&Giant, MA_OWNED);
+ /*
+ * text/data/bss must not exceed limits
+ */
+ if (a_out->a_text > maxtsiz ||
+ a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return (ENOMEM);
+
+ /* copy in arguments and/or environment from old process */
+ error = exec_extract_strings(imgp);
+ if (error)
+ return (error);
+
+ /*
+ * Destroy old process VM and create a new one (with a new stack)
+ */
+ exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK);
+ vmspace = imgp->proc->p_vmspace;
+
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PAGE_MASK) {
+#ifdef DEBUG
+ printf("imgact: Non page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * Map text+data+bss read/write/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ a_out->a_text + a_out->a_data + bss_size, FALSE,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, 0,
+ (caddr_t) imgp->vp, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text + a_out->a_data);
+
+ vm_map_remove(kernel_map, buffer,
+ buffer + round_page(a_out->a_text + a_out->a_data + file_offset));
+
+ if (error)
+ return error;
+
+ /*
+ * remove write enable on the 'text' part
+ */
+ error = vm_map_protect(&vmspace->vm_map,
+ vmaddr,
+ vmaddr + a_out->a_text,
+ VM_PROT_EXECUTE|VM_PROT_READ,
+ TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+ printf("imgact: Page aligned binary %lu\n", file_offset);
+#endif
+ /*
+ * Map text+data read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_PROT_ALL,
+ MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)imgp->vp, file_offset);
+ if (error)
+ return (error);
+
+#ifdef DEBUG
+ printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr,
+ a_out->a_text + a_out->a_data);
+#endif
+ /*
+ * allow read/write of data
+ */
+ error = vm_map_protect(&vmspace->vm_map,
+ vmaddr + a_out->a_text,
+ vmaddr + a_out->a_text + a_out->a_data,
+ VM_PROT_ALL,
+ FALSE);
+ if (error)
+ return (error);
+
+ /*
+ * Allocate anon demand-zeroed area for uninitialized data
+ */
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (error)
+ return (error);
+#ifdef DEBUG
+ printf("imgact: bssaddr=%08lx, length=%08lx\n",
+ (u_long)vmaddr, bss_size);
+#endif
+
+ }
+ /* Indicate that this file should not be modified */
+ mp_fixme("Unlocked vflag access.");
+ imgp->vp->v_vflag |= VV_TEXT;
+ }
+ /* Fill in process VM information */
+ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
+ vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t)virtual_offset;
+ vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
+
+ /* Fill in image_params */
+ imgp->interpreted = 0;
+ imgp->entry_addr = a_out->a_entry;
+
+ imgp->proc->p_sysent = &svr4_sysvec;
+ return (0);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ */
+struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" };
+EXEC_SET(execsw_set, svr4_execsw);
+
diff --git a/sys/compat/svr4/svr4.h b/sys/compat/svr4/svr4.h
new file mode 100644
index 0000000..4fbace6
--- /dev/null
+++ b/sys/compat/svr4/svr4.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_svr4.h"
+
+#if !defined(_SVR4_H)
+#define _SVR4_H
+
+extern struct sysentvec svr4_sysvec;
+
+#define memset(x,y,z) bzero(x,z)
+
+#define COMPAT_SVR4_SOLARIS2
+#define KTRACE
+
+/* These are currently unimplemented (see svr4_ipc.c) */
+#if defined(SYSVMSG)
+# undef SYSVMSG
+#endif
+#if defined(SYSVSHM)
+# undef SYSVSHM
+#endif
+#if defined(SYSVSEM)
+# undef SYSVSEM
+#endif
+
+#endif
diff --git a/sys/compat/svr4/svr4_acl.h b/sys/compat/svr4/svr4_acl.h
new file mode 100644
index 0000000..6d9454f
--- /dev/null
+++ b/sys/compat/svr4/svr4_acl.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SVR4_ACL_H_
+#define _SVR4_ACL_H_
+
+typedef struct svr4_aclent {
+ int a_type;
+ svr4_uid_t a_id;
+ svr4_o_mode_t a_perm;
+} svr4_aclent_t;
+
+#define SVR4_SYS_GETACL 1
+#define SVR4_SYS_SETACL 2
+#define SVR4_SYS_GETACLCNT 3
+
+#endif /* !_SVR4_ACL_H_ */
diff --git a/sys/compat/svr4/svr4_dirent.h b/sys/compat/svr4/svr4_dirent.h
new file mode 100644
index 0000000..2440782
--- /dev/null
+++ b/sys/compat/svr4/svr4_dirent.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_DIRENT_H_
+#define _SVR4_DIRENT_H_
+
+#define SVR4_MAXNAMLEN 512
+
+struct svr4_dirent {
+ svr4_ino_t d_ino;
+ svr4_off_t d_off;
+ u_short d_reclen;
+ char d_name[SVR4_MAXNAMLEN + 1];
+};
+
+struct svr4_dirent64 {
+ svr4_ino64_t d_ino;
+ svr4_off64_t d_off;
+ u_short d_reclen;
+ char d_name[SVR4_MAXNAMLEN + 1];
+};
+
+#define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
+#define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1))
+
+#endif /* !_SVR4_DIRENT_H_ */
diff --git a/sys/compat/svr4/svr4_errno.h b/sys/compat/svr4/svr4_errno.h
new file mode 100644
index 0000000..cc39929
--- /dev/null
+++ b/sys/compat/svr4/svr4_errno.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_ERRNO_H_
+#define _SVR4_ERRNO_H_
+
+#define SVR4_EPERM 1
+#define SVR4_ENOENT 2
+#define SVR4_ESRCH 3
+#define SVR4_EINTR 4
+#define SVR4_EIO 5
+#define SVR4_ENXIO 6
+#define SVR4_E2BIG 7
+#define SVR4_ENOEXEC 8
+#define SVR4_EBADF 9
+#define SVR4_ECHILD 10
+#define SVR4_EAGAIN 11
+#define SVR4_ENOMEM 12
+#define SVR4_EACCES 13
+#define SVR4_EFAULT 14
+#define SVR4_ENOTBLK 15
+#define SVR4_EBUSY 16
+#define SVR4_EEXIST 17
+#define SVR4_EXDEV 18
+#define SVR4_ENODEV 19
+#define SVR4_ENOTDIR 20
+#define SVR4_EISDIR 21
+#define SVR4_EINVAL 22
+#define SVR4_ENFILE 23
+#define SVR4_EMFILE 24
+#define SVR4_ENOTTY 25
+#define SVR4_ETXTBSY 26
+#define SVR4_EFBIG 27
+#define SVR4_ENOSPC 28
+#define SVR4_ESPIPE 29
+#define SVR4_EROFS 30
+#define SVR4_EMLINK 31
+#define SVR4_EPIPE 32
+#define SVR4_EDOM 33
+#define SVR4_ERANGE 34
+#define SVR4_ENOMSG 35
+#define SVR4_EIDRM 36
+#define SVR4_ECHRNG 37
+#define SVR4_EL2NSYNC 38
+#define SVR4_EL3HLT 39
+#define SVR4_EL3RST 40
+#define SVR4_ELNRNG 41
+#define SVR4_EUNATCH 42
+#define SVR4_ENOCSI 43
+#define SVR4_EL2HLT 44
+#define SVR4_EDEADLK 45
+#define SVR4_ENOLCK 46
+#define SVR4_EBADE 50
+#define SVR4_EBADR 51
+#define SVR4_EXFULL 52
+#define SVR4_ENOANO 53
+#define SVR4_EBADRQC 54
+#define SVR4_EBADSLT 55
+#define SVR4_EDEADLOCK 56
+#define SVR4_EBFONT 57
+#define SVR4_ENOSTR 60
+#define SVR4_ENODATA 61
+#define SVR4_ETIME 62
+#define SVR4_ENOSR 63
+#define SVR4_ENONET 64
+#define SVR4_ENOPKG 65
+#define SVR4_EREMOTE 66
+#define SVR4_ENOLINK 67
+#define SVR4_EADV 68
+#define SVR4_ESRMNT 69
+#define SVR4_ECOMM 70
+#define SVR4_EPROTO 71
+#define SVR4_EMULTIHOP 74
+#define SVR4_EBADMSG 77
+#define SVR4_ENAMETOOLONG 78
+#define SVR4_EOVERFLOW 79
+#define SVR4_ENOTUNIQ 80
+#define SVR4_EBADFD 81
+#define SVR4_EREMCHG 82
+#define SVR4_ELIBACC 83
+#define SVR4_ELIBBAD 84
+#define SVR4_ELIBSCN 85
+#define SVR4_ELIBMAX 86
+#define SVR4_ELIBEXEC 87
+#define SVR4_EILSEQ 88
+#define SVR4_ENOSYS 89
+#define SVR4_ELOOP 90
+#define SVR4_ERESTART 91
+#define SVR4_ESTRPIPE 92
+#define SVR4_ENOTEMPTY 93
+#define SVR4_EUSERS 94
+#define SVR4_ENOTSOCK 95
+#define SVR4_EDESTADDRREQ 96
+#define SVR4_EMSGSIZE 97
+#define SVR4_EPROTOTYPE 98
+#define SVR4_ENOPROTOOPT 99
+#define SVR4_EPROTONOSUPPORT 120
+#define SVR4_ESOCKTNOSUPPORT 121
+#define SVR4_EOPNOTSUPP 122
+#define SVR4_EPFNOSUPPORT 123
+#define SVR4_EAFNOSUPPORT 124
+#define SVR4_EADDRINUSE 125
+#define SVR4_EADDRNOTAVAIL 126
+#define SVR4_ENETDOWN 127
+#define SVR4_ENETUNREACH 128
+#define SVR4_ENETRESET 129
+#define SVR4_ECONNABORTED 130
+#define SVR4_ECONNRESET 131
+#define SVR4_ENOBUFS 132
+#define SVR4_EISCONN 133
+#define SVR4_ENOTCONN 134
+#define SVR4_EUCLEAN 135
+#define SVR4_ENOTNAM 137
+#define SVR4_ENAVAIL 138
+#define SVR4_EISNAM 139
+#define SVR4_EREMOTEIO 140
+#define SVR4_EINIT 141
+#define SVR4_EREMDEV 142
+#define SVR4_ESHUTDOWN 143
+#define SVR4_ETOOMANYREFS 144
+#define SVR4_ETIMEDOUT 145
+#define SVR4_ECONNREFUSED 146
+#define SVR4_EHOSTDOWN 147
+#define SVR4_EHOSTUNREACH 148
+#define SVR4_EWOULDBLOCK SVR4_EAGAIN
+#define SVR4_EALREADY 149
+#define SVR4_EINPROGRESS 150
+#define SVR4_ESTALE 151
+#define SVR4_EIORESID 500
+
+/*
+ * These ones are not translated...
+ */
+#define SVR4_EPROCLIM SVR4_ENOSYS
+#define SVR4_EDQUOT SVR4_ENOSYS
+#define SVR4_EBADRPC SVR4_ENOSYS
+#define SVR4_ERPCMISMATCH SVR4_ENOSYS
+#define SVR4_EPROGUNAVAIL SVR4_ENOSYS
+#define SVR4_EPROGMISMATCH SVR4_ENOSYS
+#define SVR4_EPROCUNAVAIL SVR4_ENOSYS
+#define SVR4_EFTYPE SVR4_ENOSYS
+#define SVR4_EAUTH SVR4_ENOSYS
+#define SVR4_ENEEDAUTH SVR4_ENOSYS
+
+#endif /* !_SVR4_ERRNO_H_ */
diff --git a/sys/compat/svr4/svr4_exec.h b/sys/compat/svr4/svr4_exec.h
new file mode 100644
index 0000000..672a360
--- /dev/null
+++ b/sys/compat/svr4/svr4_exec.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_EXEC_H_
+#define _SVR4_EXEC_H_
+
+#ifdef SVR4_COMPAT_SOLARIS2
+# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 12 / sizeof(char *))
+#else
+# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
+#endif
+
+#if 0
+/* Don't think we need all this NetBSD stuff */
+/*
+ * The following is horrible; there must be a better way. I need to
+ * play with brk(2) a bit more.
+ */
+#ifdef __i386__
+/*
+ * I cannot load the interpreter after the data segment because brk(2)
+ * breaks. I have to load it somewhere before. Programs start at
+ * 0x08000000 so I load the interpreter far before.
+ */
+#define SVR4_INTERP_ADDR 0x01000000
+#endif
+
+#ifdef sparc
+/*
+ * Here programs load at 0x00010000, so I load the interpreter far after
+ * the end of the data segment.
+ */
+#define SVR4_INTERP_ADDR 0x10000000
+#endif
+
+#ifndef SVR4_INTERP_ADDR
+# define SVR4_INTERP_ADDR 0
+#endif
+#endif
+
+/*void svr4_setregs(struct thread *, struct exec_package *, u_long);*/
+
+#endif /* !_SVR4_EXEC_H_ */
diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
new file mode 100644
index 0000000..cf2fa0a
--- /dev/null
+++ b/sys/compat/svr4/svr4_fcntl.c
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994, 1997 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+/*#include <sys/ioctl.h>*/
+#include <sys/lock.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/unistd.h>
+#include <sys/vnode.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_fcntl.h>
+
+static int svr4_to_bsd_flags(int);
+static u_long svr4_to_bsd_cmd(u_long);
+static int fd_revoke(struct thread *, int);
+static int fd_truncate(struct thread *, int, struct flock *);
+static int bsd_to_svr4_flags(int);
+static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
+static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
+static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
+static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
+
+static u_long
+svr4_to_bsd_cmd(cmd)
+ u_long cmd;
+{
+ switch (cmd) {
+ case SVR4_F_DUPFD:
+ return F_DUPFD;
+ case SVR4_F_GETFD:
+ return F_GETFD;
+ case SVR4_F_SETFD:
+ return F_SETFD;
+ case SVR4_F_GETFL:
+ return F_GETFL;
+ case SVR4_F_SETFL:
+ return F_SETFL;
+ case SVR4_F_GETLK:
+ return F_GETLK;
+ case SVR4_F_SETLK:
+ return F_SETLK;
+ case SVR4_F_SETLKW:
+ return F_SETLKW;
+ default:
+ return -1;
+ }
+}
+
+static int
+svr4_to_bsd_flags(l)
+ int l;
+{
+ int r = 0;
+ r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
+ r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
+ r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
+ r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
+ r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
+ r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
+ r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
+ r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
+ r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
+ r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
+ r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
+ r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
+ return r;
+}
+
+static int
+bsd_to_svr4_flags(l)
+ int l;
+{
+ int r = 0;
+ r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
+ r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
+ r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
+ r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
+ r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
+ r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
+ r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
+ r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
+ r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
+ r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
+ r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
+ r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
+ return r;
+}
+
+
+static void
+bsd_to_svr4_flock(iflp, oflp)
+ struct flock *iflp;
+ struct svr4_flock *oflp;
+{
+ switch (iflp->l_type) {
+ case F_RDLCK:
+ oflp->l_type = SVR4_F_RDLCK;
+ break;
+ case F_WRLCK:
+ oflp->l_type = SVR4_F_WRLCK;
+ break;
+ case F_UNLCK:
+ oflp->l_type = SVR4_F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = (short) iflp->l_whence;
+ oflp->l_start = (svr4_off_t) iflp->l_start;
+ oflp->l_len = (svr4_off_t) iflp->l_len;
+ oflp->l_sysid = 0;
+ oflp->l_pid = (svr4_pid_t) iflp->l_pid;
+}
+
+
+static void
+svr4_to_bsd_flock(iflp, oflp)
+ struct svr4_flock *iflp;
+ struct flock *oflp;
+{
+ switch (iflp->l_type) {
+ case SVR4_F_RDLCK:
+ oflp->l_type = F_RDLCK;
+ break;
+ case SVR4_F_WRLCK:
+ oflp->l_type = F_WRLCK;
+ break;
+ case SVR4_F_UNLCK:
+ oflp->l_type = F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = iflp->l_whence;
+ oflp->l_start = (off_t) iflp->l_start;
+ oflp->l_len = (off_t) iflp->l_len;
+ oflp->l_pid = (pid_t) iflp->l_pid;
+
+}
+
+static void
+bsd_to_svr4_flock64(iflp, oflp)
+ struct flock *iflp;
+ struct svr4_flock64 *oflp;
+{
+ switch (iflp->l_type) {
+ case F_RDLCK:
+ oflp->l_type = SVR4_F_RDLCK;
+ break;
+ case F_WRLCK:
+ oflp->l_type = SVR4_F_WRLCK;
+ break;
+ case F_UNLCK:
+ oflp->l_type = SVR4_F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = (short) iflp->l_whence;
+ oflp->l_start = (svr4_off64_t) iflp->l_start;
+ oflp->l_len = (svr4_off64_t) iflp->l_len;
+ oflp->l_sysid = 0;
+ oflp->l_pid = (svr4_pid_t) iflp->l_pid;
+}
+
+
+static void
+svr4_to_bsd_flock64(iflp, oflp)
+ struct svr4_flock64 *iflp;
+ struct flock *oflp;
+{
+ switch (iflp->l_type) {
+ case SVR4_F_RDLCK:
+ oflp->l_type = F_RDLCK;
+ break;
+ case SVR4_F_WRLCK:
+ oflp->l_type = F_WRLCK;
+ break;
+ case SVR4_F_UNLCK:
+ oflp->l_type = F_UNLCK;
+ break;
+ default:
+ oflp->l_type = -1;
+ break;
+ }
+
+ oflp->l_whence = iflp->l_whence;
+ oflp->l_start = (off_t) iflp->l_start;
+ oflp->l_len = (off_t) iflp->l_len;
+ oflp->l_pid = (pid_t) iflp->l_pid;
+
+}
+
+
+static int
+fd_revoke(td, fd)
+ struct thread *td;
+ int fd;
+{
+ struct vnode *vp;
+ struct mount *mp;
+ struct vattr vattr;
+ int error, *retval;
+
+ retval = td->td_retval;
+ if ((error = fgetvp(td, fd, &vp)) != 0)
+ return (error);
+
+ if (vp->v_type != VCHR && vp->v_type != VBLK) {
+ error = EINVAL;
+ goto out;
+ }
+
+ if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0)
+ goto out;
+
+ if (td->td_ucred->cr_uid != vattr.va_uid &&
+ (error = suser(td)) != 0)
+ goto out;
+
+ if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
+ goto out;
+ if (vcount(vp) > 1)
+ VOP_REVOKE(vp, REVOKEALL);
+ vn_finished_write(mp);
+out:
+ vrele(vp);
+ return error;
+}
+
+
+static int
+fd_truncate(td, fd, flp)
+ struct thread *td;
+ int fd;
+ struct flock *flp;
+{
+ off_t start, length;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr vattr;
+ int error, *retval;
+ struct ftruncate_args ft;
+
+ retval = td->td_retval;
+
+ /*
+ * We only support truncating the file.
+ */
+ if ((error = fget(td, fd, &fp)) != 0)
+ return (error);
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ fdrop(fp, td);
+ return ESPIPE;
+ }
+
+ if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) {
+ fdrop(fp, td);
+ return error;
+ }
+
+ length = vattr.va_size;
+
+ switch (flp->l_whence) {
+ case SEEK_CUR:
+ start = fp->f_offset + flp->l_start;
+ break;
+
+ case SEEK_END:
+ start = flp->l_start + length;
+ break;
+
+ case SEEK_SET:
+ start = flp->l_start;
+ break;
+
+ default:
+ fdrop(fp, td);
+ return EINVAL;
+ }
+
+ if (start + flp->l_len < length) {
+ /* We don't support free'ing in the middle of the file */
+ fdrop(fp, td);
+ return EINVAL;
+ }
+
+ SCARG(&ft, fd) = fd;
+ SCARG(&ft, length) = start;
+
+ error = ftruncate(td, &ft);
+
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+svr4_sys_open(td, uap)
+ register struct thread *td;
+ struct svr4_sys_open_args *uap;
+{
+ struct proc *p = td->td_proc;
+ int error, retval;
+ struct open_args cup;
+
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ (&cup)->path = uap->path;
+ (&cup)->flags = svr4_to_bsd_flags(uap->flags);
+ (&cup)->mode = uap->mode;
+ error = open(td, &cup);
+
+ if (error) {
+ /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
+ uap->flags, uap->mode, error);*/
+ return error;
+ }
+
+ retval = td->td_retval[0];
+
+ PROC_LOCK(p);
+ if (!(SCARG(&cup, flags) & O_NOCTTY) && SESS_LEADER(p) &&
+ !(td->td_proc->p_flag & P_CONTROLT)) {
+#if defined(NOTYET)
+ struct file *fp;
+
+ error = fget(td, retval, &fp);
+ PROC_UNLOCK(p);
+ /*
+ * we may have lost a race the above open() and
+ * another thread issuing a close()
+ */
+ if (error)
+ return (EBADF); /* XXX: correct errno? */
+ /* ignore any error, just give it a try */
+ if (fp->f_type == DTYPE_VNODE)
+ fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
+ fdrop(fp, td);
+ } else {
+ PROC_UNLOCK(p);
+ }
+#else
+ }
+ PROC_UNLOCK(p);
+#endif
+ return error;
+}
+
+int
+svr4_sys_open64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_open64_args *uap;
+{
+ return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
+}
+
+int
+svr4_sys_creat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_creat_args *uap;
+{
+ struct open_args cup;
+
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, mode) = SCARG(uap, mode);
+ SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC;
+
+ return open(td, &cup);
+}
+
+int
+svr4_sys_creat64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_creat64_args *uap;
+{
+ return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
+}
+
+int
+svr4_sys_llseek(td, uap)
+ register struct thread *td;
+ struct svr4_sys_llseek_args *uap;
+{
+ struct lseek_args ap;
+
+ SCARG(&ap, fd) = SCARG(uap, fd);
+
+#if BYTE_ORDER == BIG_ENDIAN
+ SCARG(&ap, offset) = (((u_int64_t) SCARG(uap, offset1)) << 32) |
+ SCARG(uap, offset2);
+#else
+ SCARG(&ap, offset) = (((u_int64_t) SCARG(uap, offset2)) << 32) |
+ SCARG(uap, offset1);
+#endif
+ SCARG(&ap, whence) = SCARG(uap, whence);
+
+ return lseek(td, &ap);
+}
+
+int
+svr4_sys_access(td, uap)
+ register struct thread *td;
+ struct svr4_sys_access_args *uap;
+{
+ struct access_args cup;
+ int *retval;
+
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ retval = td->td_retval;
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, flags) = SCARG(uap, flags);
+
+ return access(td, &cup);
+}
+
+#if defined(NOTYET)
+int
+svr4_sys_pread(td, uap)
+ register struct thread *td;
+ struct svr4_sys_pread_args *uap;
+{
+ struct pread_args pra;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pread(2) system call (offset type is 64-bit in NetBSD).
+ */
+ SCARG(&pra, fd) = SCARG(uap, fd);
+ SCARG(&pra, buf) = SCARG(uap, buf);
+ SCARG(&pra, nbyte) = SCARG(uap, nbyte);
+ SCARG(&pra, offset) = SCARG(uap, off);
+
+ return pread(td, &pra);
+}
+#endif
+
+#if defined(NOTYET)
+int
+svr4_sys_pread64(td, v, retval)
+ register struct thread *td;
+ void *v;
+ register_t *retval;
+{
+
+ struct svr4_sys_pread64_args *uap = v;
+ struct sys_pread_args pra;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pread(2) system call (offset type is 64-bit in NetBSD).
+ */
+ SCARG(&pra, fd) = SCARG(uap, fd);
+ SCARG(&pra, buf) = SCARG(uap, buf);
+ SCARG(&pra, nbyte) = SCARG(uap, nbyte);
+ SCARG(&pra, offset) = SCARG(uap, off);
+
+ return (sys_pread(td, &pra, retval));
+}
+#endif /* NOTYET */
+
+#if defined(NOTYET)
+int
+svr4_sys_pwrite(td, uap)
+ register struct thread *td;
+ struct svr4_sys_pwrite_args *uap;
+{
+ struct pwrite_args pwa;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pwrite(2) system call (offset type is 64-bit in NetBSD).
+ */
+ SCARG(&pwa, fd) = SCARG(uap, fd);
+ SCARG(&pwa, buf) = SCARG(uap, buf);
+ SCARG(&pwa, nbyte) = SCARG(uap, nbyte);
+ SCARG(&pwa, offset) = SCARG(uap, off);
+
+ return pwrite(td, &pwa);
+}
+#endif
+
+#if defined(NOTYET)
+int
+svr4_sys_pwrite64(td, v, retval)
+ register struct thread *td;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_pwrite64_args *uap = v;
+ struct sys_pwrite_args pwa;
+
+ /*
+ * Just translate the args structure and call the NetBSD
+ * pwrite(2) system call (offset type is 64-bit in NetBSD).
+ */
+ SCARG(&pwa, fd) = SCARG(uap, fd);
+ SCARG(&pwa, buf) = SCARG(uap, buf);
+ SCARG(&pwa, nbyte) = SCARG(uap, nbyte);
+ SCARG(&pwa, offset) = SCARG(uap, off);
+
+ return (sys_pwrite(td, &pwa, retval));
+}
+#endif /* NOTYET */
+
+int
+svr4_sys_fcntl(td, uap)
+ register struct thread *td;
+ struct svr4_sys_fcntl_args *uap;
+{
+ int error;
+ struct fcntl_args fa;
+ int *retval;
+
+ retval = td->td_retval;
+
+ SCARG(&fa, fd) = SCARG(uap, fd);
+ SCARG(&fa, cmd) = svr4_to_bsd_cmd(SCARG(uap, cmd));
+
+ switch (SCARG(&fa, cmd)) {
+ case F_DUPFD:
+ case F_GETFD:
+ case F_SETFD:
+ SCARG(&fa, arg) = (long) SCARG(uap, arg);
+ return fcntl(td, &fa);
+
+ case F_GETFL:
+ SCARG(&fa, arg) = (long) SCARG(uap, arg);
+ error = fcntl(td, &fa);
+ if (error)
+ return error;
+ *retval = bsd_to_svr4_flags(*retval);
+ return error;
+
+ case F_SETFL:
+ {
+ /*
+ * we must save the O_ASYNC flag, as that is
+ * handled by ioctl(_, I_SETSIG, _) emulation.
+ */
+ long cmd;
+ int flags;
+
+ DPRINTF(("Setting flags %p\n", SCARG(uap, arg)));
+ cmd = SCARG(&fa, cmd); /* save it for a while */
+
+ SCARG(&fa, cmd) = F_GETFL;
+ if ((error = fcntl(td, &fa)) != 0)
+ return error;
+ flags = *retval;
+ flags &= O_ASYNC;
+ flags |= svr4_to_bsd_flags((u_long) SCARG(uap, arg));
+ SCARG(&fa, cmd) = cmd;
+ SCARG(&fa, arg) = (long) flags;
+ return fcntl(td, &fa);
+ }
+
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ {
+ struct svr4_flock ifl;
+ struct flock *flp, fl;
+ caddr_t sg = stackgap_init();
+
+ flp = stackgap_alloc(&sg, sizeof(struct flock));
+ SCARG(&fa, arg) = (long) flp;
+
+ error = copyin(SCARG(uap, arg), &ifl, sizeof ifl);
+ if (error)
+ return error;
+
+ svr4_to_bsd_flock(&ifl, &fl);
+
+ error = copyout(&fl, flp, sizeof fl);
+ if (error)
+ return error;
+
+ error = fcntl(td, &fa);
+ if (error || SCARG(&fa, cmd) != F_GETLK)
+ return error;
+
+ error = copyin(flp, &fl, sizeof fl);
+ if (error)
+ return error;
+
+ bsd_to_svr4_flock(&fl, &ifl);
+
+ return copyout(&ifl, SCARG(uap, arg), sizeof ifl);
+ }
+ case -1:
+ switch (SCARG(uap, cmd)) {
+ case SVR4_F_DUP2FD:
+ {
+ struct dup2_args du;
+
+ SCARG(&du, from) = SCARG(uap, fd);
+ SCARG(&du, to) = (int)SCARG(uap, arg);
+ error = dup2(td, &du);
+ if (error)
+ return error;
+ *retval = SCARG(&du, to);
+ return 0;
+ }
+
+ case SVR4_F_FREESP:
+ {
+ struct svr4_flock ifl;
+ struct flock fl;
+
+ error = copyin(SCARG(uap, arg), &ifl,
+ sizeof ifl);
+ if (error)
+ return error;
+ svr4_to_bsd_flock(&ifl, &fl);
+ return fd_truncate(td, SCARG(uap, fd), &fl);
+ }
+
+ case SVR4_F_GETLK64:
+ case SVR4_F_SETLK64:
+ case SVR4_F_SETLKW64:
+ {
+ struct svr4_flock64 ifl;
+ struct flock *flp, fl;
+ caddr_t sg = stackgap_init();
+
+ flp = stackgap_alloc(&sg, sizeof(struct flock));
+ SCARG(&fa, arg) = (long) flp;
+
+ error = copyin(SCARG(uap, arg), &ifl,
+ sizeof ifl);
+ if (error)
+ return error;
+
+ svr4_to_bsd_flock64(&ifl, &fl);
+
+ error = copyout(&fl, flp, sizeof fl);
+ if (error)
+ return error;
+
+ error = fcntl(td, &fa);
+ if (error || SCARG(&fa, cmd) != F_GETLK)
+ return error;
+
+ error = copyin(flp, &fl, sizeof fl);
+ if (error)
+ return error;
+
+ bsd_to_svr4_flock64(&fl, &ifl);
+
+ return copyout(&ifl, SCARG(uap, arg),
+ sizeof ifl);
+ }
+
+ case SVR4_F_FREESP64:
+ {
+ struct svr4_flock64 ifl;
+ struct flock fl;
+
+ error = copyin(SCARG(uap, arg), &ifl,
+ sizeof ifl);
+ if (error)
+ return error;
+ svr4_to_bsd_flock64(&ifl, &fl);
+ return fd_truncate(td, SCARG(uap, fd), &fl);
+ }
+
+ case SVR4_F_REVOKE:
+ return fd_revoke(td, SCARG(uap, fd));
+
+ default:
+ return ENOSYS;
+ }
+
+ default:
+ return ENOSYS;
+ }
+}
diff --git a/sys/compat/svr4/svr4_fcntl.h b/sys/compat/svr4/svr4_fcntl.h
new file mode 100644
index 0000000..3309a4f
--- /dev/null
+++ b/sys/compat/svr4/svr4_fcntl.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_FCNTL_H_
+#define _SVR4_FCNTL_H_
+
+#include <compat/svr4/svr4_types.h>
+#include <sys/fcntl.h>
+
+#define SVR4_O_RDONLY 0x0000
+#define SVR4_O_WRONLY 0x0001
+#define SVR4_O_RDWR 0x0002
+#define SVR4_O_ACCMODE 0x0003
+#define SVR4_O_NDELAY 0x0004
+#define SVR4_O_APPEND 0x0008
+#define SVR4_O_SYNC 0x0010
+#define SVR4_O_NONBLOCK 0x0080
+#define SVR4_O_CREAT 0x0100
+#define SVR4_O_TRUNC 0x0200
+#define SVR4_O_EXCL 0x0400
+#define SVR4_O_NOCTTY 0x0800
+#define SVR4_O_PRIV 0x1000
+
+
+#define SVR4_FD_CLOEXEC 1
+
+#define SVR4_F_DUPFD 0
+#define SVR4_F_GETFD 1
+#define SVR4_F_SETFD 2
+#define SVR4_F_GETFL 3
+#define SVR4_F_SETFL 4
+#define SVR4_F_GETLK_SVR3 5
+#define SVR4_F_SETLK 6
+#define SVR4_F_SETLKW 7
+#define SVR4_F_CHKFL 8
+#define SVR4_F_DUP2FD 9
+#define SVR4_F_ALLOCSP 10
+#define SVR4_F_FREESP 11
+
+#define SVR4_F_ISSTREAM 13
+#define SVR4_F_GETLK 14
+#define SVR4_F_PRIV 15
+#define SVR4_F_NPRIV 16
+#define SVR4_F_QUOTACTL 17
+#define SVR4_F_BLOCKS 18
+#define SVR4_F_BLKSIZE 19
+#define SVR4_F_RSETLK 20
+#define SVR4_F_RGETLK 21
+#define SVR4_F_RSETLKW 22
+#define SVR4_F_GETOWN 23
+#define SVR4_F_SETOWN 24
+#define SVR4_F_REVOKE 25
+#define SVR4_F_HASREMOTELOCKS 26
+#define SVR4_F_FREESP64 27
+
+#define SVR4_F_GETLK64 33
+#define SVR4_F_SETLK64 34
+#define SVR4_F_SETLKW64 35
+
+#define SVR4_F_SHARE 40
+#define SVR4_F_UNSHARE 41
+
+#define SVR4_F_CHSIZE_XENIX 0x6000
+#define SVR4_F_RDCHK_XENIX 0x6001
+#define SVR4_F_LK_UNLCK_XENIX 0x6300
+#define SVR4_F_LK_LOCK_XENIX 0x7200
+#define SVR4_F_LK_NBLCK_XENIX 0x6200
+#define SVR4_F_LK_RLCK_XENIX 0x7100
+#define SVR4_F_LK_NBRLCK_XENIX 0x6100
+
+#define SVR4_LK_CMDTYPE(x) (((x) >> 12) & 0x7)
+#define SVR4_LK_LCKTYPE(x) (((x) >> 8) & 0x7)
+
+#define SVR4_F_RDLCK 1
+#define SVR4_F_WRLCK 2
+#define SVR4_F_UNLCK 3
+
+struct svr4_flock_svr3 {
+ short l_type;
+ short l_whence;
+ svr4_off_t l_start;
+ svr4_off_t l_len;
+ short l_sysid;
+ svr4_o_pid_t l_pid;
+};
+
+
+struct svr4_flock {
+ short l_type;
+ short l_whence;
+ svr4_off_t l_start;
+ svr4_off_t l_len;
+ long l_sysid;
+ svr4_pid_t l_pid;
+ long pad[4];
+};
+
+struct svr4_flock64 {
+ short l_type;
+ short l_whence;
+ svr4_off64_t l_start;
+ svr4_off64_t l_len;
+ long l_sysid;
+ svr4_pid_t l_pid;
+ long pad[4];
+};
+#endif /* !_SVR4_FCNTL_H_ */
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
new file mode 100644
index 0000000..ef9b8b6
--- /dev/null
+++ b/sys/compat/svr4/svr4_filio.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filio.h>
+#include <sys/lock.h>
+#include <sys/signal.h>
+#include <sys/filedesc.h>
+#include <sys/poll.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_filio.h>
+
+/*#define GROTTY_READ_HACK*/
+
+int
+svr4_sys_poll(td, uap)
+ struct thread *td;
+ struct svr4_sys_poll_args *uap;
+{
+ int error;
+ struct poll_args pa;
+ struct pollfd *pfd;
+ int idx = 0, cerr;
+ u_long siz;
+
+ SCARG(&pa, fds) = SCARG(uap, fds);
+ SCARG(&pa, nfds) = SCARG(uap, nfds);
+ SCARG(&pa, timeout) = SCARG(uap, timeout);
+
+ siz = SCARG(uap, nfds) * sizeof(struct pollfd);
+ pfd = (struct pollfd *)malloc(siz, M_TEMP, M_WAITOK);
+
+ error = poll(td, (struct poll_args *)uap);
+
+ if ((cerr = copyin(SCARG(uap, fds), pfd, siz)) != 0) {
+ error = cerr;
+ goto done;
+ }
+
+ for (idx = 0; idx < SCARG(uap, nfds); idx++) {
+ /* POLLWRNORM already equals POLLOUT, so we don't worry about that */
+ if (pfd[idx].revents & (POLLOUT | POLLWRNORM | POLLWRBAND))
+ pfd[idx].revents |= (POLLOUT | POLLWRNORM | POLLWRBAND);
+ }
+ if ((cerr = copyout(pfd, SCARG(uap, fds), siz)) != 0) {
+ error = cerr;
+ goto done; /* yeah, I know it's the next line, but this way I won't
+ forget to update it if I add more code */
+ }
+done:
+ free(pfd, M_TEMP);
+ return error;
+}
+
+#if defined(READ_TEST)
+int
+svr4_sys_read(td, uap)
+ struct thread *td;
+ struct svr4_sys_read_args *uap;
+{
+ struct read_args ra;
+ struct file *fp;
+ struct socket *so = NULL;
+ int so_state;
+ sigset_t sigmask;
+ int rv;
+
+ SCARG(&ra, fd) = SCARG(uap, fd);
+ SCARG(&ra, buf) = SCARG(uap, buf);
+ SCARG(&ra, nbyte) = SCARG(uap, nbyte);
+
+ if (fget(td, uap->fd, &fp) != 0) {
+ DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
+ return EBADF;
+ }
+
+ if (fp->f_type == DTYPE_SOCKET) {
+ so = (struct socket *)fp->f_data;
+ DPRINTF(("fd %d is a socket\n", SCARG(uap, fd)));
+ if (so->so_state & SS_ASYNC) {
+ DPRINTF(("fd %d is an ASYNC socket!\n", SCARG(uap, fd)));
+ }
+ DPRINTF(("Here are its flags: 0x%x\n", so->so_state));
+#if defined(GROTTY_READ_HACK)
+ so_state = so->so_state;
+ so->so_state &= ~SS_NBIO;
+#endif
+ }
+
+ rv = read(td, &ra);
+
+ DPRINTF(("svr4_read(%d, 0x%0x, %d) = %d\n",
+ SCARG(uap, fd), SCARG(uap, buf), SCARG(uap, nbyte), rv));
+ if (rv == EAGAIN) {
+ DPRINTF(("sigmask = 0x%x\n", td->td_proc->p_sigmask));
+ DPRINTF(("sigignore = 0x%x\n", td->td_proc->p_sigignore));
+ DPRINTF(("sigcaught = 0x%x\n", td->td_proc->p_sigcatch));
+ DPRINTF(("siglist = 0x%x\n", td->td_proc->p_siglist));
+ }
+
+#if defined(GROTTY_READ_HACK)
+ if (so) { /* We've already checked to see if this is a socket */
+ so->so_state = so_state;
+ }
+#endif
+ fdrop(fp, td);
+
+ return(rv);
+}
+#endif /* READ_TEST */
+
+#if defined(BOGUS)
+int
+svr4_sys_write(td, uap)
+ struct thread *td;
+ struct svr4_sys_write_args *uap;
+{
+ struct write_args wa;
+ struct file *fp;
+ int rv;
+
+ SCARG(&wa, fd) = SCARG(uap, fd);
+ SCARG(&wa, buf) = SCARG(uap, buf);
+ SCARG(&wa, nbyte) = SCARG(uap, nbyte);
+
+ rv = write(td, &wa);
+
+ DPRINTF(("svr4_write(%d, 0x%0x, %d) = %d\n",
+ SCARG(uap, fd), SCARG(uap, buf), SCARG(uap, nbyte), rv));
+
+ return(rv);
+}
+#endif /* BOGUS */
+
+int
+svr4_fil_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ int error;
+ int num;
+ struct filedesc *fdp = td->td_proc->p_fd;
+
+ *retval = 0;
+
+ FILEDESC_LOCK(fdp);
+ switch (cmd) {
+ case SVR4_FIOCLEX:
+ fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
+ FILEDESC_UNLOCK(fdp);
+ return 0;
+
+ case SVR4_FIONCLEX:
+ fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
+ FILEDESC_UNLOCK(fdp);
+ return 0;
+
+ case SVR4_FIOGETOWN:
+ case SVR4_FIOSETOWN:
+ case SVR4_FIOASYNC:
+ case SVR4_FIONBIO:
+ case SVR4_FIONREAD:
+ FILEDESC_UNLOCK(fdp);
+ if ((error = copyin(data, &num, sizeof(num))) != 0)
+ return error;
+
+ switch (cmd) {
+ case SVR4_FIOGETOWN: cmd = FIOGETOWN; break;
+ case SVR4_FIOSETOWN: cmd = FIOSETOWN; break;
+ case SVR4_FIOASYNC: cmd = FIOASYNC; break;
+ case SVR4_FIONBIO: cmd = FIONBIO; break;
+ case SVR4_FIONREAD: cmd = FIONREAD; break;
+ }
+
+#ifdef SVR4_DEBUG
+ if (cmd == FIOASYNC) DPRINTF(("FIOASYNC\n"));
+#endif
+ error = fo_ioctl(fp, cmd, (caddr_t) &num, td);
+
+ if (error)
+ return error;
+
+ return copyout(&num, data, sizeof(num));
+
+ default:
+ FILEDESC_UNLOCK(fdp);
+ DPRINTF(("Unknown svr4 filio %lx\n", cmd));
+ return 0; /* ENOSYS really */
+ }
+}
diff --git a/sys/compat/svr4/svr4_filio.h b/sys/compat/svr4/svr4_filio.h
new file mode 100644
index 0000000..37184cb
--- /dev/null
+++ b/sys/compat/svr4/svr4_filio.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_FILIO_H_
+#define _SVR4_FILIO_H_
+
+#define SVR4_FIOC ('f' << 8)
+
+#define SVR4_FIOCLEX SVR4_IO('f', 1)
+#define SVR4_FIONCLEX SVR4_IO('f', 2)
+
+#define SVR4_FIOGETOWN SVR4_IOR('f', 123, int)
+#define SVR4_FIOSETOWN SVR4_IOW('f', 124, int)
+#define SVR4_FIOASYNC SVR4_IOW('f', 125, int)
+#define SVR4_FIONBIO SVR4_IOW('f', 126, int)
+#define SVR4_FIONREAD SVR4_IOR('f', 127, int)
+
+#endif /* !_SVR4_FILIO_H_ */
diff --git a/sys/compat/svr4/svr4_fuser.h b/sys/compat/svr4/svr4_fuser.h
new file mode 100644
index 0000000..f828c84
--- /dev/null
+++ b/sys/compat/svr4/svr4_fuser.h
@@ -0,0 +1,97 @@
+/*
+ * $FreeBSD$
+ * Derived from:
+ * $NetBSD: svr4_fuser.h,v 1.4 1998/09/04 19:54:38 christos Exp $ */
+
+/*-
+ * Original Copyright:
+ *
+ * Copyright (c) 1994 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Portions of this code have been derived from code contributed to the
+ * FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SVR4_FUSER_H_
+#define _SVR4_FUSER_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_f_user {
+ svr4_pid_t fu_pid;
+ int fu_flags;
+ uid_t fu_uid;
+};
+
+
+#define SVR4_F_FILE_ONLY 1
+#define SVR4_F_CONTAINED 2
+
+#define SVR4_F_CDIR 0x01
+#define SVR4_F_RDIR 0x02
+#define SVR4_F_TEXT 0x04
+#define SVR4_F_MAP 0x08
+#define SVR4_F_OPEN 0x10
+#define SVR4_F_TRACE 0x20
+#define SVR4_F_TTY 0x40
+
+#endif /* !_SVR4_FUSER_H_ */
diff --git a/sys/compat/svr4/svr4_hrt.h b/sys/compat/svr4/svr4_hrt.h
new file mode 100644
index 0000000..c160b8e
--- /dev/null
+++ b/sys/compat/svr4/svr4_hrt.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_HRT_H_
+#define _SVR4_HRT_H_
+
+#define SVR4_HRT_CNTL 0
+#define SVR4_HRT_CNTL_RES 0
+#define SVR4_HRT_CNTL_TOFD 1
+#define SVR4_HRT_CNTL_START 2
+#define SVR4_HRT_CNTL_GET 3
+
+#define SVR4_HRT_ALRM 1
+#define SVR4_HRT_ALRM_DO 4
+#define SVR4_HRT_ALRM_REP 5
+#define SVR4_HRT_ALRM_TOD 6
+#define SVR4_HRT_ALRM_FUTREP 7
+#define SVR4_HRT_ALRM_TODREP 8
+#define SVR4_HRT_ALRM_PEND 9
+
+#define SVR4_HRT_SLP 2
+#define SVR4_HRT_SLP_INT 10
+#define SVR4_HRT_SLP_TOD 11
+
+#define SVR4_HRT_BSD 12
+#define SVR4_HRT_BSD_PEND 13
+#define SVR4_HRT_BSD_REP1 14
+#define SVR4_HRT_BSD_REP2 15
+#define SVR4_HRT_BSD_CANCEL 16
+
+#define SVR4_HRT_CAN 3
+
+#define SVR4_HRT_SEC 1
+#define SVR4_HRT_MSEC 1000
+#define SVR4_HRT_USEC 1000000
+#define SVR4_HRT_NSEC 1000000000
+
+#define SVR4_HRT_TRUNC 0
+#define SVR4_HRT_RND 1
+
+typedef struct {
+ u_long i_word1;
+ u_long i_word2;
+ int i_clock;
+} svr4_hrt_interval_t;
+
+typedef struct {
+ u_long h_sec;
+ long h_rem;
+ u_long h_res;
+} svr4_hrt_time_t;
+
+#define SVR4_HRT_DONE 1
+#define SVR4_HRT_ERROR 2
+
+#define SVR4_HRT_CLK_STD 1
+#define SVR4_HRT_CLK_USERVIRT 2
+#define SVR4_HRT_CLK_PROCVIRT 4
+
+#endif /* !_SVR4_HRT_H_ */
diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c
new file mode 100644
index 0000000..50d28ee
--- /dev/null
+++ b/sys/compat/svr4/svr4_ioctl.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/fcntl.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/systm.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_stropts.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_termios.h>
+#include <compat/svr4/svr4_ttold.h>
+#include <compat/svr4/svr4_filio.h>
+#include <compat/svr4/svr4_sockio.h>
+
+#ifdef DEBUG_SVR4
+static void svr4_decode_cmd(u_long, char *, char *, int *, int *);
+/*
+ * Decode an ioctl command symbolically
+ */
+static void
+svr4_decode_cmd(cmd, dir, c, num, argsiz)
+ u_long cmd;
+ char *dir, *c;
+ int *num, *argsiz;
+{
+ if (cmd & SVR4_IOC_VOID)
+ *dir++ = 'V';
+ if (cmd & SVR4_IOC_IN)
+ *dir++ = 'R';
+ if (cmd & SVR4_IOC_OUT)
+ *dir++ = 'W';
+ *dir = '\0';
+ if (cmd & SVR4_IOC_INOUT)
+ *argsiz = (cmd >> 16) & 0xff;
+ else
+ *argsiz = -1;
+
+ *c = (cmd >> 8) & 0xff;
+ *num = cmd & 0xff;
+}
+#endif
+
+int
+svr4_sys_ioctl(td, uap)
+ register struct thread *td;
+ struct svr4_sys_ioctl_args *uap;
+{
+ int *retval;
+ struct file *fp;
+ u_long cmd;
+ int (*fun)(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+ int error;
+#ifdef DEBUG_SVR4
+ char dir[4];
+ char c;
+ int num;
+ int argsiz;
+
+ svr4_decode_cmd(SCARG(uap, com), dir, &c, &num, &argsiz);
+
+ DPRINTF(("svr4_ioctl[%lx](%d, _IO%s(%c, %d, %d), %p);\n", SCARG(uap, com), SCARG(uap, fd),
+ dir, c, num, argsiz, SCARG(uap, data)));
+#endif
+ retval = td->td_retval;
+ cmd = SCARG(uap, com);
+
+ if ((error = fget(td, uap->fd, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
+ fdrop(fp, td);
+ return EBADF;
+ }
+
+#if defined(DEBUG_SVR4)
+ if (fp->f_type == DTYPE_SOCKET) {
+ struct socket *so = (struct socket *)fp->f_data;
+ DPRINTF(("<<< IN: so_state = 0x%x\n", so->so_state));
+ }
+#endif
+
+ switch (cmd & 0xff00) {
+ case SVR4_tIOC:
+ DPRINTF(("ttold\n"));
+ fun = svr4_ttold_ioctl;
+ break;
+
+ case SVR4_TIOC:
+ DPRINTF(("term\n"));
+ fun = svr4_term_ioctl;
+ break;
+
+ case SVR4_STR:
+ DPRINTF(("stream\n"));
+ fun = svr4_stream_ioctl;
+ break;
+
+ case SVR4_FIOC:
+ DPRINTF(("file\n"));
+ fun = svr4_fil_ioctl;
+ break;
+
+ case SVR4_SIOC:
+ DPRINTF(("socket\n"));
+ fun = svr4_sock_ioctl;
+ break;
+
+ case SVR4_XIOC:
+ /* We do not support those */
+ fdrop(fp, td);
+ return EINVAL;
+
+ default:
+ fdrop(fp, td);
+ DPRINTF(("Unimplemented ioctl %lx\n", cmd));
+ return 0; /* XXX: really ENOSYS */
+ }
+#if defined(DEBUG_SVR4)
+ if (fp->f_type == DTYPE_SOCKET) {
+ struct socket *so;
+
+ so = (struct socket *)fp->f_data;
+ DPRINTF((">>> OUT: so_state = 0x%x\n", so->so_state));
+ }
+#endif
+ error = (*fun)(fp, td, retval, SCARG(uap, fd), cmd, SCARG(uap, data));
+ fdrop(fp, td);
+ return (error);
+}
diff --git a/sys/compat/svr4/svr4_ioctl.h b/sys/compat/svr4/svr4_ioctl.h
new file mode 100644
index 0000000..54811b9
--- /dev/null
+++ b/sys/compat/svr4/svr4_ioctl.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_IOCTL_H_
+#define _SVR4_IOCTL_H_
+
+#define SVR4_IOC_VOID 0x20000000
+#define SVR4_IOC_OUT 0x40000000
+#define SVR4_IOC_IN 0x80000000
+#define SVR4_IOC_INOUT (SVR4_IOC_IN|SVR4_IOC_OUT)
+
+#define SVR4_IOC(inout,group,num,len) \
+ (inout | ((len & 0xff) << 16) | ((group) << 8) | (num))
+
+#define SVR4_XIOC ('X' << 8)
+
+#define SVR4_IO(g,n) SVR4_IOC(SVR4_IOC_VOID, (g), (n), 0)
+#define SVR4_IOR(g,n,t) SVR4_IOC(SVR4_IOC_OUT, (g), (n), sizeof(t))
+#define SVR4_IOW(g,n,t) SVR4_IOC(SVR4_IOC_IN, (g), (n), sizeof(t))
+#define SVR4_IOWR(g,n,t) SVR4_IOC(SVR4_IOC_INOUT,(g), (n), sizeof(t))
+
+int svr4_stream_ti_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_stream_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_term_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_ttold_ioctl(struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_fil_ioctl (struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+int svr4_sock_ioctl (struct file *, struct thread *, register_t *,
+ int, u_long, caddr_t);
+
+#endif /* !_SVR4_IOCTL_H_ */
diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c
new file mode 100644
index 0000000..17caaa5
--- /dev/null
+++ b/sys/compat/svr4/svr4_ipc.c
@@ -0,0 +1,821 @@
+/*
+ * $FreeBSD$
+ * Derived from:
+ * $NetBSD: svr4_ipc.c,v 1.7 1998/10/19 22:43:00 tron Exp $ */
+
+/*-
+ * Original copyright:
+ *
+ * Copyright (c) 1995 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Portions of this code have been derived from software contributed
+ * to the FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * XXX- This code is presently a no-op on FreeBSD (and isn't compiled due
+ * to preprocessor conditionals). A nice project for a kernel hacking
+ * novice might be to MakeItGo, but I have more important fish to fry
+ * at present.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ipc.h>
+
+#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
+static void svr4_to_bsd_ipc_perm(const struct svr4_ipc_perm *,
+ struct ipc_perm *);
+static void bsd_to_svr4_ipc_perm(const struct ipc_perm *,
+ struct svr4_ipc_perm *);
+#endif
+
+#ifdef SYSVSEM
+static void bsd_to_svr4_semid_ds(const struct semid_ds *,
+ struct svr4_semid_ds *);
+static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *,
+ struct semid_ds *);
+static int svr4_setsemun(caddr_t *sgp, union semun **argp,
+ union semun *usp);
+static int svr4_semop(struct proc *, void *, register_t *);
+static int svr4_semget(struct proc *, void *, register_t *);
+static int svr4_semctl(struct proc *, void *, register_t *);
+#endif
+
+#ifdef SYSVMSG
+static void bsd_to_svr4_msqid_ds(const struct msqid_ds *,
+ struct svr4_msqid_ds *);
+static void svr4_to_bsd_msqid_ds(const struct svr4_msqid_ds *,
+ struct msqid_ds *);
+static int svr4_msgsnd(struct proc *, void *, register_t *);
+static int svr4_msgrcv(struct proc *, void *, register_t *);
+static int svr4_msgget(struct proc *, void *, register_t *);
+static int svr4_msgctl(struct proc *, void *, register_t *);
+#endif
+
+#ifdef SYSVSHM
+static void bsd_to_svr4_shmid_ds(const struct shmid_ds *,
+ struct svr4_shmid_ds *);
+static void svr4_to_bsd_shmid_ds(const struct svr4_shmid_ds *,
+ struct shmid_ds *);
+static int svr4_shmat(struct proc *, void *, register_t *);
+static int svr4_shmdt(struct proc *, void *, register_t *);
+static int svr4_shmget(struct proc *, void *, register_t *);
+static int svr4_shmctl(struct proc *, void *, register_t *);
+#endif
+
+#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM)
+
+static void
+svr4_to_bsd_ipc_perm(spp, bpp)
+ const struct svr4_ipc_perm *spp;
+ struct ipc_perm *bpp;
+{
+ bpp->key = spp->key;
+ bpp->uid = spp->uid;
+ bpp->gid = spp->gid;
+ bpp->cuid = spp->cuid;
+ bpp->cgid = spp->cgid;
+ bpp->mode = spp->mode;
+ bpp->seq = spp->seq;
+}
+
+static void
+bsd_to_svr4_ipc_perm(bpp, spp)
+ const struct ipc_perm *bpp;
+ struct svr4_ipc_perm *spp;
+{
+ spp->key = bpp->key;
+ spp->uid = bpp->uid;
+ spp->gid = bpp->gid;
+ spp->cuid = bpp->cuid;
+ spp->cgid = bpp->cgid;
+ spp->mode = bpp->mode;
+ spp->seq = bpp->seq;
+}
+#endif
+
+#ifdef SYSVSEM
+static void
+bsd_to_svr4_semid_ds(bds, sds)
+ const struct semid_ds *bds;
+ struct svr4_semid_ds *sds;
+{
+ bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm);
+ sds->sem_base = (struct svr4_sem *) bds->sem_base;
+ sds->sem_nsems = bds->sem_nsems;
+ sds->sem_otime = bds->sem_otime;
+ sds->sem_pad1 = bds->sem_pad1;
+ sds->sem_ctime = bds->sem_ctime;
+ sds->sem_pad2 = bds->sem_pad2;
+}
+
+static void
+svr4_to_bsd_semid_ds(sds, bds)
+ const struct svr4_semid_ds *sds;
+ struct semid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->sem_perm, &bds->sem_perm);
+ bds->sem_base = (struct sem *) bds->sem_base;
+ bds->sem_nsems = sds->sem_nsems;
+ bds->sem_otime = sds->sem_otime;
+ bds->sem_pad1 = sds->sem_pad1;
+ bds->sem_ctime = sds->sem_ctime;
+ bds->sem_pad2 = sds->sem_pad2;
+}
+
+static int
+svr4_setsemun(sgp, argp, usp)
+ caddr_t *sgp;
+ union semun **argp;
+ union semun *usp;
+{
+ *argp = stackgap_alloc(sgp, sizeof(union semun));
+ return copyout((caddr_t)usp, *argp, sizeof(union semun));
+}
+
+struct svr4_sys_semctl_args {
+ syscallarg(int) what;
+ syscallarg(int) semid;
+ syscallarg(int) semnum;
+ syscallarg(int) cmd;
+ syscallarg(union semun) arg;
+};
+
+static int
+svr4_semctl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ int error;
+ struct svr4_sys_semctl_args *uap = v;
+ struct sys___semctl_args ap;
+ struct svr4_semid_ds ss;
+ struct semid_ds bs, *bsp;
+ caddr_t sg = stackgap_init();
+
+ SCARG(&ap, semid) = SCARG(uap, semid);
+ SCARG(&ap, semnum) = SCARG(uap, semnum);
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_SEM_GETZCNT:
+ case SVR4_SEM_GETNCNT:
+ case SVR4_SEM_GETPID:
+ case SVR4_SEM_GETVAL:
+ switch (SCARG(uap, cmd)) {
+ case SVR4_SEM_GETZCNT:
+ SCARG(&ap, cmd) = GETZCNT;
+ break;
+ case SVR4_SEM_GETNCNT:
+ SCARG(&ap, cmd) = GETNCNT;
+ break;
+ case SVR4_SEM_GETPID:
+ SCARG(&ap, cmd) = GETPID;
+ break;
+ case SVR4_SEM_GETVAL:
+ SCARG(&ap, cmd) = GETVAL;
+ break;
+ }
+ return sys___semctl(p, &ap, retval);
+
+ case SVR4_SEM_SETVAL:
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg));
+ if (error)
+ return error;
+ SCARG(&ap, cmd) = SETVAL;
+ return sys___semctl(p, &ap, retval);
+
+ case SVR4_SEM_GETALL:
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg));
+ if (error)
+ return error;
+ SCARG(&ap, cmd) = GETVAL;
+ return sys___semctl(p, &ap, retval);
+
+ case SVR4_SEM_SETALL:
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg));
+ if (error)
+ return error;
+ SCARG(&ap, cmd) = SETVAL;
+ return sys___semctl(p, &ap, retval);
+
+ case SVR4_IPC_STAT:
+ SCARG(&ap, cmd) = IPC_STAT;
+ bsp = stackgap_alloc(&sg, sizeof(bs));
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg),
+ (union semun *)&bsp);
+ if (error)
+ return error;
+ if ((error = sys___semctl(p, &ap, retval)) != 0)
+ return error;
+ error = copyin((caddr_t)bsp, (caddr_t)&bs, sizeof(bs));
+ if (error)
+ return error;
+ bsd_to_svr4_semid_ds(&bs, &ss);
+ return copyout(&ss, SCARG(uap, arg).buf, sizeof(ss));
+
+ case SVR4_IPC_SET:
+ SCARG(&ap, cmd) = IPC_SET;
+ bsp = stackgap_alloc(&sg, sizeof(bs));
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg),
+ (union semun *)&bsp);
+ if (error)
+ return error;
+ error = copyin(SCARG(uap, arg).buf, (caddr_t) &ss, sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_semid_ds(&ss, &bs);
+ error = copyout(&bs, bsp, sizeof(bs));
+ if (error)
+ return error;
+ return sys___semctl(p, &ap, retval);
+
+ case SVR4_IPC_RMID:
+ SCARG(&ap, cmd) = IPC_RMID;
+ bsp = stackgap_alloc(&sg, sizeof(bs));
+ error = svr4_setsemun(&sg, &SCARG(&ap, arg),
+ (union semun *)&bsp);
+ if (error)
+ return error;
+ error = copyin(SCARG(uap, arg).buf, &ss, sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_semid_ds(&ss, &bs);
+ error = copyout(&bs, bsp, sizeof(bs));
+ if (error)
+ return error;
+ return sys___semctl(p, &ap, retval);
+
+ default:
+ return EINVAL;
+ }
+}
+
+struct svr4_sys_semget_args {
+ syscallarg(int) what;
+ syscallarg(svr4_key_t) key;
+ syscallarg(int) nsems;
+ syscallarg(int) semflg;
+};
+
+static int
+svr4_semget(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_semget_args *uap = v;
+ struct sys_semget_args ap;
+
+ SCARG(&ap, key) = SCARG(uap, key);
+ SCARG(&ap, nsems) = SCARG(uap, nsems);
+ SCARG(&ap, semflg) = SCARG(uap, semflg);
+
+ return sys_semget(p, &ap, retval);
+}
+
+struct svr4_sys_semop_args {
+ syscallarg(int) what;
+ syscallarg(int) semid;
+ syscallarg(struct svr4_sembuf *) sops;
+ syscallarg(u_int) nsops;
+};
+
+static int
+svr4_semop(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_semop_args *uap = v;
+ struct sys_semop_args ap;
+
+ SCARG(&ap, semid) = SCARG(uap, semid);
+ /* These are the same */
+ SCARG(&ap, sops) = (struct sembuf *) SCARG(uap, sops);
+ SCARG(&ap, nsops) = SCARG(uap, nsops);
+
+ return sys_semop(p, &ap, retval);
+}
+
+int
+svr4_sys_semsys(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_semsys_args *uap = v;
+
+ DPRINTF(("svr4_semsys(%d)\n", SCARG(uap, what)));
+
+ switch (SCARG(uap, what)) {
+ case SVR4_semctl:
+ return svr4_semctl(p, v, retval);
+ case SVR4_semget:
+ return svr4_semget(p, v, retval);
+ case SVR4_semop:
+ return svr4_semop(p, v, retval);
+ default:
+ return EINVAL;
+ }
+}
+#endif
+
+#ifdef SYSVMSG
+static void
+bsd_to_svr4_msqid_ds(bds, sds)
+ const struct msqid_ds *bds;
+ struct svr4_msqid_ds *sds;
+{
+ bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm);
+ sds->msg_first = (struct svr4_msg *) bds->msg_first;
+ sds->msg_last = (struct svr4_msg *) bds->msg_last;
+ sds->msg_cbytes = bds->msg_cbytes;
+ sds->msg_qnum = bds->msg_qnum;
+ sds->msg_qbytes = bds->msg_qbytes;
+ sds->msg_lspid = bds->msg_lspid;
+ sds->msg_lrpid = bds->msg_lrpid;
+ sds->msg_stime = bds->msg_stime;
+ sds->msg_pad1 = bds->msg_pad1;
+ sds->msg_rtime = bds->msg_rtime;
+ sds->msg_pad2 = bds->msg_pad2;
+ sds->msg_ctime = bds->msg_ctime;
+ sds->msg_pad3 = bds->msg_pad3;
+
+ /* use the padding for the rest of the fields */
+ {
+ const short *pad = (const short *) bds->msg_pad4;
+ sds->msg_cv = pad[0];
+ sds->msg_qnum_cv = pad[1];
+ }
+}
+
+static void
+svr4_to_bsd_msqid_ds(sds, bds)
+ const struct svr4_msqid_ds *sds;
+ struct msqid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm);
+ bds->msg_first = (struct msg *) sds->msg_first;
+ bds->msg_last = (struct msg *) sds->msg_last;
+ bds->msg_cbytes = sds->msg_cbytes;
+ bds->msg_qnum = sds->msg_qnum;
+ bds->msg_qbytes = sds->msg_qbytes;
+ bds->msg_lspid = sds->msg_lspid;
+ bds->msg_lrpid = sds->msg_lrpid;
+ bds->msg_stime = sds->msg_stime;
+ bds->msg_pad1 = sds->msg_pad1;
+ bds->msg_rtime = sds->msg_rtime;
+ bds->msg_pad2 = sds->msg_pad2;
+ bds->msg_ctime = sds->msg_ctime;
+ bds->msg_pad3 = sds->msg_pad3;
+
+ /* use the padding for the rest of the fields */
+ {
+ short *pad = (short *) bds->msg_pad4;
+ pad[0] = sds->msg_cv;
+ pad[1] = sds->msg_qnum_cv;
+ }
+}
+
+struct svr4_sys_msgsnd_args {
+ syscallarg(int) what;
+ syscallarg(int) msqid;
+ syscallarg(void *) msgp;
+ syscallarg(size_t) msgsz;
+ syscallarg(int) msgflg;
+};
+
+static int
+svr4_msgsnd(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_msgsnd_args *uap = v;
+ struct sys_msgsnd_args ap;
+
+ SCARG(&ap, msqid) = SCARG(uap, msqid);
+ SCARG(&ap, msgp) = SCARG(uap, msgp);
+ SCARG(&ap, msgsz) = SCARG(uap, msgsz);
+ SCARG(&ap, msgflg) = SCARG(uap, msgflg);
+
+ return sys_msgsnd(p, &ap, retval);
+}
+
+struct svr4_sys_msgrcv_args {
+ syscallarg(int) what;
+ syscallarg(int) msqid;
+ syscallarg(void *) msgp;
+ syscallarg(size_t) msgsz;
+ syscallarg(long) msgtyp;
+ syscallarg(int) msgflg;
+};
+
+static int
+svr4_msgrcv(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_msgrcv_args *uap = v;
+ struct sys_msgrcv_args ap;
+
+ SCARG(&ap, msqid) = SCARG(uap, msqid);
+ SCARG(&ap, msgp) = SCARG(uap, msgp);
+ SCARG(&ap, msgsz) = SCARG(uap, msgsz);
+ SCARG(&ap, msgtyp) = SCARG(uap, msgtyp);
+ SCARG(&ap, msgflg) = SCARG(uap, msgflg);
+
+ return sys_msgrcv(p, &ap, retval);
+}
+
+struct svr4_sys_msgget_args {
+ syscallarg(int) what;
+ syscallarg(svr4_key_t) key;
+ syscallarg(int) msgflg;
+};
+
+static int
+svr4_msgget(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_msgget_args *uap = v;
+ struct sys_msgget_args ap;
+
+ SCARG(&ap, key) = SCARG(uap, key);
+ SCARG(&ap, msgflg) = SCARG(uap, msgflg);
+
+ return sys_msgget(p, &ap, retval);
+}
+
+struct svr4_sys_msgctl_args {
+ syscallarg(int) what;
+ syscallarg(int) msqid;
+ syscallarg(int) cmd;
+ syscallarg(struct svr4_msqid_ds *) buf;
+};
+
+static int
+svr4_msgctl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ int error;
+ struct svr4_sys_msgctl_args *uap = v;
+ struct sys_msgctl_args ap;
+ struct svr4_msqid_ds ss;
+ struct msqid_ds bs;
+ caddr_t sg = stackgap_init();
+
+ SCARG(&ap, msqid) = SCARG(uap, msqid);
+ SCARG(&ap, cmd) = SCARG(uap, cmd);
+ SCARG(&ap, buf) = stackgap_alloc(&sg, sizeof(bs));
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_IPC_STAT:
+ SCARG(&ap, cmd) = IPC_STAT;
+ if ((error = sys_msgctl(p, &ap, retval)) != 0)
+ return error;
+ error = copyin(&bs, SCARG(&ap, buf), sizeof bs);
+ if (error)
+ return error;
+ bsd_to_svr4_msqid_ds(&bs, &ss);
+ return copyout(&ss, SCARG(uap, buf), sizeof ss);
+
+ case SVR4_IPC_SET:
+ SCARG(&ap, cmd) = IPC_SET;
+ error = copyin(SCARG(uap, buf), &ss, sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_msqid_ds(&ss, &bs);
+ error = copyout(&bs, SCARG(&ap, buf), sizeof bs);
+ if (error)
+ return error;
+ return sys_msgctl(p, &ap, retval);
+
+ case SVR4_IPC_RMID:
+ SCARG(&ap, cmd) = IPC_RMID;
+ error = copyin(SCARG(uap, buf), &ss, sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_msqid_ds(&ss, &bs);
+ error = copyout(&bs, SCARG(&ap, buf), sizeof bs);
+ if (error)
+ return error;
+ return sys_msgctl(p, &ap, retval);
+
+ default:
+ return EINVAL;
+ }
+}
+
+int
+svr4_sys_msgsys(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_msgsys_args *uap = v;
+
+ DPRINTF(("svr4_msgsys(%d)\n", SCARG(uap, what)));
+
+ switch (SCARG(uap, what)) {
+ case SVR4_msgsnd:
+ return svr4_msgsnd(p, v, retval);
+ case SVR4_msgrcv:
+ return svr4_msgrcv(p, v, retval);
+ case SVR4_msgget:
+ return svr4_msgget(p, v, retval);
+ case SVR4_msgctl:
+ return svr4_msgctl(p, v, retval);
+ default:
+ return EINVAL;
+ }
+}
+#endif
+
+#ifdef SYSVSHM
+
+static void
+bsd_to_svr4_shmid_ds(bds, sds)
+ const struct shmid_ds *bds;
+ struct svr4_shmid_ds *sds;
+{
+ bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm);
+ sds->shm_segsz = bds->shm_segsz;
+ sds->shm_lkcnt = 0;
+ sds->shm_lpid = bds->shm_lpid;
+ sds->shm_cpid = bds->shm_cpid;
+ sds->shm_amp = bds->shm_internal;
+ sds->shm_nattch = bds->shm_nattch;
+ sds->shm_cnattch = 0;
+ sds->shm_atime = bds->shm_atime;
+ sds->shm_pad1 = 0;
+ sds->shm_dtime = bds->shm_dtime;
+ sds->shm_pad2 = 0;
+ sds->shm_ctime = bds->shm_ctime;
+ sds->shm_pad3 = 0;
+}
+
+static void
+svr4_to_bsd_shmid_ds(sds, bds)
+ const struct svr4_shmid_ds *sds;
+ struct shmid_ds *bds;
+{
+ svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm);
+ bds->shm_segsz = sds->shm_segsz;
+ bds->shm_lpid = sds->shm_lpid;
+ bds->shm_cpid = sds->shm_cpid;
+ bds->shm_internal = sds->shm_amp;
+ bds->shm_nattch = sds->shm_nattch;
+ bds->shm_atime = sds->shm_atime;
+ bds->shm_dtime = sds->shm_dtime;
+ bds->shm_ctime = sds->shm_ctime;
+}
+
+struct svr4_sys_shmat_args {
+ syscallarg(int) what;
+ syscallarg(int) shmid;
+ syscallarg(void *) shmaddr;
+ syscallarg(int) shmflg;
+};
+
+static int
+svr4_shmat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_shmat_args *uap = v;
+ struct sys_shmat_args ap;
+
+ SCARG(&ap, shmid) = SCARG(uap, shmid);
+ SCARG(&ap, shmaddr) = SCARG(uap, shmaddr);
+ SCARG(&ap, shmflg) = SCARG(uap, shmflg);
+
+ return sys_shmat(p, &ap, retval);
+}
+
+struct svr4_sys_shmdt_args {
+ syscallarg(int) what;
+ syscallarg(void *) shmaddr;
+};
+
+static int
+svr4_shmdt(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_shmdt_args *uap = v;
+ struct sys_shmdt_args ap;
+
+ SCARG(&ap, shmaddr) = SCARG(uap, shmaddr);
+
+ return sys_shmdt(p, &ap, retval);
+}
+
+struct svr4_sys_shmget_args {
+ syscallarg(int) what;
+ syscallarg(key_t) key;
+ syscallarg(int) size;
+ syscallarg(int) shmflg;
+};
+
+static int
+svr4_shmget(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_shmget_args *uap = v;
+ struct sys_shmget_args ap;
+
+ SCARG(&ap, key) = SCARG(uap, key);
+ SCARG(&ap, size) = SCARG(uap, size);
+ SCARG(&ap, shmflg) = SCARG(uap, shmflg);
+
+ return sys_shmget(p, &ap, retval);
+}
+
+struct svr4_sys_shmctl_args {
+ syscallarg(int) what;
+ syscallarg(int) shmid;
+ syscallarg(int) cmd;
+ syscallarg(struct svr4_shmid_ds *) buf;
+};
+
+int
+svr4_shmctl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_shmctl_args *uap = v;
+ int error;
+ caddr_t sg = stackgap_init();
+ struct sys_shmctl_args ap;
+ struct shmid_ds bs;
+ struct svr4_shmid_ds ss;
+
+ SCARG(&ap, shmid) = SCARG(uap, shmid);
+
+ if (SCARG(uap, buf) != NULL) {
+ SCARG(&ap, buf) = stackgap_alloc(&sg, sizeof (struct shmid_ds));
+ switch (SCARG(uap, cmd)) {
+ case SVR4_IPC_SET:
+ case SVR4_IPC_RMID:
+ case SVR4_SHM_LOCK:
+ case SVR4_SHM_UNLOCK:
+ error = copyin(SCARG(uap, buf), (caddr_t) &ss,
+ sizeof ss);
+ if (error)
+ return error;
+ svr4_to_bsd_shmid_ds(&ss, &bs);
+ error = copyout(&bs, SCARG(&ap, buf), sizeof bs);
+ if (error)
+ return error;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ SCARG(&ap, buf) = NULL;
+
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_IPC_STAT:
+ SCARG(&ap, cmd) = IPC_STAT;
+ if ((error = sys_shmctl(p, &ap, retval)) != 0)
+ return error;
+ if (SCARG(uap, buf) == NULL)
+ return 0;
+ error = copyin(&bs, SCARG(&ap, buf), sizeof bs);
+ if (error)
+ return error;
+ bsd_to_svr4_shmid_ds(&bs, &ss);
+ return copyout(&ss, SCARG(uap, buf), sizeof ss);
+
+ case SVR4_IPC_SET:
+ SCARG(&ap, cmd) = IPC_SET;
+ return sys_shmctl(p, &ap, retval);
+
+ case SVR4_IPC_RMID:
+ case SVR4_SHM_LOCK:
+ case SVR4_SHM_UNLOCK:
+ switch (SCARG(uap, cmd)) {
+ case SVR4_IPC_RMID:
+ SCARG(&ap, cmd) = IPC_RMID;
+ break;
+ case SVR4_SHM_LOCK:
+ SCARG(&ap, cmd) = SHM_LOCK;
+ break;
+ case SVR4_SHM_UNLOCK:
+ SCARG(&ap, cmd) = SHM_UNLOCK;
+ break;
+ default:
+ return EINVAL;
+ }
+ return sys_shmctl(p, &ap, retval);
+
+ default:
+ return EINVAL;
+ }
+}
+
+int
+svr4_sys_shmsys(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct svr4_sys_shmsys_args *uap = v;
+
+ DPRINTF(("svr4_shmsys(%d)\n", SCARG(uap, what)));
+
+ switch (SCARG(uap, what)) {
+ case SVR4_shmat:
+ return svr4_shmat(p, v, retval);
+ case SVR4_shmdt:
+ return svr4_shmdt(p, v, retval);
+ case SVR4_shmget:
+ return svr4_shmget(p, v, retval);
+ case SVR4_shmctl:
+ return svr4_shmctl(p, v, retval);
+ default:
+ return ENOSYS;
+ }
+}
+#endif /* SYSVSHM */
diff --git a/sys/compat/svr4/svr4_ipc.h b/sys/compat/svr4/svr4_ipc.h
new file mode 100644
index 0000000..6aadb7e
--- /dev/null
+++ b/sys/compat/svr4/svr4_ipc.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_IPC_H_
+#define _SVR4_IPC_H_
+
+/*
+ * General IPC
+ */
+#define SVR4_IPC_RMID 10
+#define SVR4_IPC_SET 11
+#define SVR4_IPC_STAT 12
+
+struct svr4_ipc_perm {
+ svr4_uid_t uid;
+ svr4_gid_t gid;
+ svr4_uid_t cuid;
+ svr4_gid_t cgid;
+ svr4_mode_t mode;
+ u_long seq;
+ svr4_key_t key;
+ long pad[4];
+};
+
+/*
+ * Message queues
+ */
+#define SVR4_msgget 0
+#define SVR4_msgctl 1
+#define SVR4_msgrcv 2
+#define SVR4_msgsnd 3
+
+struct svr4_msg {
+ struct svr4_msg *msg_next;
+ long msg_type;
+ u_short msg_ts;
+ short msg_spot;
+};
+
+struct svr4_msqid_ds {
+ struct svr4_ipc_perm msg_perm;
+ struct svr4_msg *msg_first;
+ struct svr4_msg *msg_last;
+ u_long msg_cbytes;
+ u_long msg_qnum;
+ u_long msg_qbytes;
+ svr4_pid_t msg_lspid;
+ svr4_pid_t msg_lrpid;
+ svr4_time_t msg_stime;
+ long msg_pad1;
+ svr4_time_t msg_rtime;
+ long msg_pad2;
+ svr4_time_t msg_ctime;
+ long msg_pad3;
+ short msg_cv;
+ short msg_qnum_cv;
+ long msg_pad4[3];
+};
+
+struct svr4_msgbuf {
+ long mtype; /* message type */
+ char mtext[1]; /* message text */
+};
+
+struct svr4_msginfo {
+ int msgmap;
+ int msgmax;
+ int msgmnb;
+ int msgmni;
+ int msgssz;
+ int msgtql;
+ u_short msgseg;
+};
+
+/*
+ * Shared memory
+ */
+#define SVR4_shmat 0
+#define SVR4_shmctl 1
+#define SVR4_shmdt 2
+#define SVR4_shmget 3
+
+/* shmctl() operations */
+#define SVR4_SHM_LOCK 3
+#define SVR4_SHM_UNLOCK 4
+
+struct svr4_shmid_ds {
+ struct svr4_ipc_perm shm_perm;
+ int shm_segsz;
+ void *shm_amp;
+ u_short shm_lkcnt;
+ svr4_pid_t shm_lpid;
+ svr4_pid_t shm_cpid;
+ u_long shm_nattch;
+ u_long shm_cnattch;
+ svr4_time_t shm_atime;
+ long shm_pad1;
+ svr4_time_t shm_dtime;
+ long shm_pad2;
+ svr4_time_t shm_ctime;
+ long shm_pad3;
+ long shm_pad4[4];
+};
+
+/*
+ * Semaphores
+ */
+#define SVR4_semctl 0
+#define SVR4_semget 1
+#define SVR4_semop 2
+
+/* semctl() operations */
+#define SVR4_SEM_GETNCNT 3
+#define SVR4_SEM_GETPID 4
+#define SVR4_SEM_GETVAL 5
+#define SVR4_SEM_GETALL 6
+#define SVR4_SEM_GETZCNT 7
+#define SVR4_SEM_SETVAL 8
+#define SVR4_SEM_SETALL 9
+
+struct svr4_sem {
+ u_short semval;
+ svr4_pid_t sempid;
+ u_short semncnt;
+ u_short semzcnt;
+ u_short semncnt_cv;
+ u_short semzcnt_cv;
+};
+
+struct svr4_semid_ds {
+ struct svr4_ipc_perm sem_perm;
+ struct svr4_sem *sem_base;
+ u_short sem_nsems;
+ svr4_time_t sem_otime;
+ long sem_pad1;
+ svr4_time_t sem_ctime;
+ long sem_pad2;
+ long sem_pad3[4];
+};
+
+struct svr4_sembuf {
+ u_short sem_num;
+ short sem_op;
+ short sem_flg;
+};
+
+#endif /* _SVR4_IPC_H */
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
new file mode 100644
index 0000000..f60d62c
--- /dev/null
+++ b/sys/compat/svr4/svr4_misc.c
@@ -0,0 +1,1744 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * SVR4 compatibility module.
+ *
+ * SVR4 system calls that are implemented differently in BSD are
+ * handled here.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dirent.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/msg.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <sys/sx.h>
+#include <sys/sysproto.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_sysconfig.h>
+#include <compat/svr4/svr4_dirent.h>
+#include <compat/svr4/svr4_acl.h>
+#include <compat/svr4/svr4_ulimit.h>
+#include <compat/svr4/svr4_statvfs.h>
+#include <compat/svr4/svr4_hrt.h>
+#include <compat/svr4/svr4_mman.h>
+#include <compat/svr4/svr4_wait.h>
+
+#include <machine/vmparam.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_map.h>
+#if defined(__FreeBSD__)
+#include <vm/uma.h>
+#endif
+
+#if defined(NetBSD)
+# if defined(UVM)
+# include <uvm/uvm_extern.h>
+# endif
+#endif
+
+#define BSD_DIRENT(cp) ((struct dirent *)(cp))
+
+static int svr4_mknod(struct thread *, register_t *, char *,
+ svr4_mode_t, svr4_dev_t);
+
+static __inline clock_t timeval_to_clock_t(struct timeval *);
+static int svr4_setinfo (struct proc *, int, svr4_siginfo_t *);
+
+struct svr4_hrtcntl_args;
+static int svr4_hrtcntl (struct thread *, struct svr4_hrtcntl_args *,
+ register_t *);
+static void bsd_statfs_to_svr4_statvfs(const struct statfs *,
+ struct svr4_statvfs *);
+static void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
+ struct svr4_statvfs64 *);
+static struct proc *svr4_pfind(pid_t pid);
+
+/* BOGUS noop */
+#if defined(BOGUS)
+int
+svr4_sys_setitimer(td, uap)
+ register struct thread *td;
+ struct svr4_sys_setitimer_args *uap;
+{
+ td->td_retval[0] = 0;
+ return 0;
+}
+#endif
+
+int
+svr4_sys_wait(td, uap)
+ struct thread *td;
+ struct svr4_sys_wait_args *uap;
+{
+ struct wait_args w4;
+ int error, *retval = td->td_retval, st, sig;
+ size_t sz = sizeof(*SCARG(&w4, status));
+
+ SCARG(&w4, rusage) = NULL;
+ SCARG(&w4, options) = 0;
+
+ if (SCARG(uap, status) == NULL) {
+ caddr_t sg = stackgap_init();
+
+ SCARG(&w4, status) = stackgap_alloc(&sg, sz);
+ }
+ else
+ SCARG(&w4, status) = SCARG(uap, status);
+
+ SCARG(&w4, pid) = WAIT_ANY;
+
+ if ((error = wait4(td, &w4)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&w4, status), &st, sizeof(st))) != 0)
+ return error;
+
+ if (WIFSIGNALED(st)) {
+ sig = WTERMSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
+ } else if (WIFSTOPPED(st)) {
+ sig = WSTOPSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
+ }
+
+ /*
+ * It looks like wait(2) on svr4/solaris/2.4 returns
+ * the status in retval[1], and the pid on retval[0].
+ */
+ retval[1] = st;
+
+ if (SCARG(uap, status))
+ if ((error = copyout(&st, SCARG(uap, status), sizeof(st))) != 0)
+ return error;
+
+ return 0;
+}
+
+int
+svr4_sys_execv(td, uap)
+ struct thread *td;
+ struct svr4_sys_execv_args *uap;
+{
+ struct execve_args ap;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&ap, fname) = SCARG(uap, path);
+ SCARG(&ap, argv) = SCARG(uap, argp);
+ SCARG(&ap, envv) = NULL;
+
+ return execve(td, &ap);
+}
+
+int
+svr4_sys_execve(td, uap)
+ struct thread *td;
+ struct svr4_sys_execve_args *uap;
+{
+ struct execve_args ap;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, uap->path);
+
+ SCARG(&ap, fname) = SCARG(uap, path);
+ SCARG(&ap, argv) = SCARG(uap, argp);
+ SCARG(&ap, envv) = SCARG(uap, envp);
+
+ return execve(td, &ap);
+}
+
+int
+svr4_sys_time(td, v)
+ struct thread *td;
+ struct svr4_sys_time_args *v;
+{
+ struct svr4_sys_time_args *uap = v;
+ int error = 0;
+ struct timeval tv;
+
+ microtime(&tv);
+ if (SCARG(uap, t))
+ error = copyout(&tv.tv_sec, SCARG(uap, t),
+ sizeof(*(SCARG(uap, t))));
+ td->td_retval[0] = (int) tv.tv_sec;
+
+ return error;
+}
+
+
+/*
+ * Read SVR4-style directory entries. We suck them into kernel space so
+ * that they can be massaged before being copied out to user code.
+ *
+ * This code is ported from the Linux emulator: Changes to the VFS interface
+ * between FreeBSD and NetBSD have made it simpler to port it from there than
+ * to adapt the NetBSD version.
+ */
+int
+svr4_sys_getdents64(td, uap)
+ struct thread *td;
+ struct svr4_sys_getdents64_args *uap;
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* SVR4-format */
+ int resid, svr4reclen=0; /* SVR4-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct svr4_dirent64 svr4_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+ u_long *cookies = NULL, *cookiep;
+ int ncookies;
+
+ DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
+ SCARG(uap, fd), SCARG(uap, nbytes)));
+ if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) {
+ return (error);
+ }
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (vp->v_type != VDIR) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) {
+ fdrop(fp, td);
+ return error;
+ }
+
+ nbytes = SCARG(uap, nbytes);
+ if (nbytes == 1) {
+ nbytes = sizeof (struct svr4_dirent64);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ off = fp->f_offset;
+#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
+ buflen = max(DIRBLKSIZ, nbytes);
+ buflen = min(buflen, MAXBSIZE);
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+
+ if (cookies) {
+ free(cookies, M_TEMP);
+ cookies = NULL;
+ }
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
+ &ncookies, &cookies);
+ if (error) {
+ goto out;
+ }
+
+ inp = buf;
+ outp = (caddr_t) SCARG(uap, dp);
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) <= 0) {
+ goto eof;
+ }
+
+ cookiep = cookies;
+
+ if (cookies) {
+ /*
+ * When using cookies, the vfs has the option of reading from
+ * a different offset than that supplied (UFS truncates the
+ * offset to a block boundary to make sure that it never reads
+ * partway through a directory entry, even if the directory
+ * has been compacted).
+ */
+ while (len > 0 && ncookies > 0 && *cookiep <= off) {
+ bdp = (struct dirent *) inp;
+ len -= bdp->d_reclen;
+ inp += bdp->d_reclen;
+ cookiep++;
+ ncookies--;
+ }
+ }
+
+ while (len > 0) {
+ if (cookiep && ncookies == 0)
+ break;
+ bdp = (struct dirent *) inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3) {
+ DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
+ error = EFAULT;
+ goto out;
+ }
+
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ len -= reclen;
+ continue;
+ }
+ svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
+ if (reclen > len || resid < svr4reclen) {
+ outp++;
+ break;
+ }
+ svr4_dirent.d_ino = (long) bdp->d_fileno;
+ if (justone) {
+ /*
+ * old svr4-style readdir usage.
+ */
+ svr4_dirent.d_off = (svr4_off_t) svr4reclen;
+ svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
+ } else {
+ svr4_dirent.d_off = (svr4_off_t)(off + reclen);
+ svr4_dirent.d_reclen = (u_short) svr4reclen;
+ }
+ strcpy(svr4_dirent.d_name, bdp->d_name);
+ if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
+ goto out;
+ inp += reclen;
+ if (cookiep) {
+ off = *cookiep++;
+ ncookies--;
+ } else
+ off += reclen;
+ outp += svr4reclen;
+ resid -= svr4reclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) SCARG(uap, dp))
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + svr4reclen;
+
+eof:
+ td->td_retval[0] = nbytes - resid;
+out:
+ VOP_UNLOCK(vp, 0, td);
+ fdrop(fp, td);
+ if (cookies)
+ free(cookies, M_TEMP);
+ free(buf, M_TEMP);
+ return error;
+}
+
+
+int
+svr4_sys_getdents(td, uap)
+ struct thread *td;
+ struct svr4_sys_getdents_args *uap;
+{
+ struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* SVR4-format */
+ int resid, svr4_reclen; /* SVR4-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct svr4_dirent idb;
+ off_t off; /* true file offset */
+ int buflen, error, eofflag;
+ u_long *cookiebuf = NULL, *cookie;
+ int ncookies = 0, *retval = td->td_retval;
+
+ if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
+
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VDIR) {
+ fdrop(fp, td);
+ return (EINVAL);
+ }
+
+ buflen = min(MAXBSIZE, SCARG(uap, nbytes));
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ off = fp->f_offset;
+again:
+ aiov.iov_base = buf;
+ aiov.iov_len = buflen;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_td = td;
+ auio.uio_resid = buflen;
+ auio.uio_offset = off;
+ /*
+ * First we read into the malloc'ed buffer, then
+ * we massage it into user space, one record at a time.
+ */
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
+ &cookiebuf);
+ if (error) {
+ goto out;
+ }
+
+ inp = buf;
+ outp = SCARG(uap, buf);
+ resid = SCARG(uap, nbytes);
+ if ((len = buflen - auio.uio_resid) == 0)
+ goto eof;
+
+ for (cookie = cookiebuf; len > 0; len -= reclen) {
+ bdp = (struct dirent *)inp;
+ reclen = bdp->d_reclen;
+ if (reclen & 3)
+ panic("svr4_sys_getdents64: bad reclen");
+ off = *cookie++; /* each entry points to the next */
+ if ((off >> 32) != 0) {
+ uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
+ error = EINVAL;
+ goto out;
+ }
+ if (bdp->d_fileno == 0) {
+ inp += reclen; /* it is a hole; squish it out */
+ continue;
+ }
+ svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
+ if (reclen > len || resid < svr4_reclen) {
+ /* entry too big for buffer, so just stop */
+ outp++;
+ break;
+ }
+ /*
+ * Massage in place to make a SVR4-shaped dirent (otherwise
+ * we have to worry about touching user memory outside of
+ * the copyout() call).
+ */
+ idb.d_ino = (svr4_ino_t)bdp->d_fileno;
+ idb.d_off = (svr4_off_t)off;
+ idb.d_reclen = (u_short)svr4_reclen;
+ strcpy(idb.d_name, bdp->d_name);
+ if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
+ goto out;
+ /* advance past this real entry */
+ inp += reclen;
+ /* advance output past SVR4-shaped entry */
+ outp += svr4_reclen;
+ resid -= svr4_reclen;
+ }
+
+ /* if we squished out the whole block, try again */
+ if (outp == SCARG(uap, buf))
+ goto again;
+ fp->f_offset = off; /* update the vnode offset */
+
+eof:
+ *retval = SCARG(uap, nbytes) - resid;
+out:
+ VOP_UNLOCK(vp, 0, td);
+ fdrop(fp, td);
+ if (cookiebuf)
+ free(cookiebuf, M_TEMP);
+ free(buf, M_TEMP);
+ return error;
+}
+
+
+int
+svr4_sys_mmap(td, uap)
+ struct thread *td;
+ struct svr4_sys_mmap_args *uap;
+{
+ struct mmap_args mm;
+ int *retval;
+
+ retval = td->td_retval;
+#define _MAP_NEW 0x80000000
+ /*
+ * Verify the arguments.
+ */
+ if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL; /* XXX still needed? */
+
+ if (SCARG(uap, len) == 0)
+ return EINVAL;
+
+ SCARG(&mm, prot) = SCARG(uap, prot);
+ SCARG(&mm, len) = SCARG(uap, len);
+ SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW;
+ SCARG(&mm, fd) = SCARG(uap, fd);
+ SCARG(&mm, addr) = SCARG(uap, addr);
+ SCARG(&mm, pos) = SCARG(uap, pos);
+
+ return mmap(td, &mm);
+}
+
+int
+svr4_sys_mmap64(td, uap)
+ struct thread *td;
+ struct svr4_sys_mmap64_args *uap;
+{
+ struct mmap_args mm;
+ void *rp;
+
+#define _MAP_NEW 0x80000000
+ /*
+ * Verify the arguments.
+ */
+ if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
+ return EINVAL; /* XXX still needed? */
+
+ if (SCARG(uap, len) == 0)
+ return EINVAL;
+
+ SCARG(&mm, prot) = SCARG(uap, prot);
+ SCARG(&mm, len) = SCARG(uap, len);
+ SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW;
+ SCARG(&mm, fd) = SCARG(uap, fd);
+ SCARG(&mm, addr) = SCARG(uap, addr);
+ SCARG(&mm, pos) = SCARG(uap, pos);
+
+ rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
+ if ((SCARG(&mm, flags) & MAP_FIXED) == 0 &&
+ SCARG(&mm, addr) != 0 && (void *)SCARG(&mm, addr) < rp)
+ SCARG(&mm, addr) = rp;
+
+ return mmap(td, &mm);
+}
+
+
+int
+svr4_sys_fchroot(td, uap)
+ struct thread *td;
+ struct svr4_sys_fchroot_args *uap;
+{
+ struct filedesc *fdp = td->td_proc->p_fd;
+ struct vnode *vp, *vpold;
+ struct file *fp;
+ int error;
+
+ if ((error = suser(td)) != 0)
+ return error;
+ if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
+ return error;
+ vp = (struct vnode *) fp->f_data;
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ if (vp->v_type != VDIR)
+ error = ENOTDIR;
+ else
+ error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
+ VOP_UNLOCK(vp, 0, td);
+ if (error) {
+ fdrop(fp, td);
+ return error;
+ }
+ VREF(vp);
+ FILEDESC_LOCK(fdp);
+ vpold = fdp->fd_rdir;
+ fdp->fd_rdir = vp;
+ FILEDESC_UNLOCK(fdp);
+ if (vpold != NULL)
+ vrele(vpold);
+ fdrop(fp, td);
+ return 0;
+}
+
+
+static int
+svr4_mknod(td, retval, path, mode, dev)
+ struct thread *td;
+ register_t *retval;
+ char *path;
+ svr4_mode_t mode;
+ svr4_dev_t dev;
+{
+ caddr_t sg = stackgap_init();
+
+ CHECKALTEXIST(td, &sg, path);
+
+ if (S_ISFIFO(mode)) {
+ struct mkfifo_args ap;
+ SCARG(&ap, path) = path;
+ SCARG(&ap, mode) = mode;
+ return mkfifo(td, &ap);
+ } else {
+ struct mknod_args ap;
+ SCARG(&ap, path) = path;
+ SCARG(&ap, mode) = mode;
+ SCARG(&ap, dev) = dev;
+ return mknod(td, &ap);
+ }
+}
+
+
+int
+svr4_sys_mknod(td, uap)
+ register struct thread *td;
+ struct svr4_sys_mknod_args *uap;
+{
+ int *retval = td->td_retval;
+ return svr4_mknod(td, retval,
+ SCARG(uap, path), SCARG(uap, mode),
+ (svr4_dev_t)svr4_to_bsd_odev_t(SCARG(uap, dev)));
+}
+
+
+int
+svr4_sys_xmknod(td, uap)
+ struct thread *td;
+ struct svr4_sys_xmknod_args *uap;
+{
+ int *retval = td->td_retval;
+ return svr4_mknod(td, retval,
+ SCARG(uap, path), SCARG(uap, mode),
+ (svr4_dev_t)svr4_to_bsd_dev_t(SCARG(uap, dev)));
+}
+
+
+int
+svr4_sys_vhangup(td, uap)
+ struct thread *td;
+ struct svr4_sys_vhangup_args *uap;
+{
+ return 0;
+}
+
+
+int
+svr4_sys_sysconfig(td, uap)
+ struct thread *td;
+ struct svr4_sys_sysconfig_args *uap;
+{
+ int *retval;
+
+ retval = &(td->td_retval[0]);
+
+ switch (SCARG(uap, name)) {
+ case SVR4_CONFIG_UNUSED:
+ *retval = 0;
+ break;
+ case SVR4_CONFIG_NGROUPS:
+ *retval = NGROUPS_MAX;
+ break;
+ case SVR4_CONFIG_CHILD_MAX:
+ *retval = maxproc;
+ break;
+ case SVR4_CONFIG_OPEN_FILES:
+ *retval = maxfiles;
+ break;
+ case SVR4_CONFIG_POSIX_VER:
+ *retval = 198808;
+ break;
+ case SVR4_CONFIG_PAGESIZE:
+ *retval = PAGE_SIZE;
+ break;
+ case SVR4_CONFIG_CLK_TCK:
+ *retval = 60; /* should this be `hz', ie. 100? */
+ break;
+ case SVR4_CONFIG_XOPEN_VER:
+ *retval = 2; /* XXX: What should that be? */
+ break;
+ case SVR4_CONFIG_PROF_TCK:
+ *retval = 60; /* XXX: What should that be? */
+ break;
+ case SVR4_CONFIG_NPROC_CONF:
+ *retval = 1; /* Only one processor for now */
+ break;
+ case SVR4_CONFIG_NPROC_ONLN:
+ *retval = 1; /* And it better be online */
+ break;
+ case SVR4_CONFIG_AIO_LISTIO_MAX:
+ case SVR4_CONFIG_AIO_MAX:
+ case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
+ *retval = 0; /* No aio support */
+ break;
+ case SVR4_CONFIG_DELAYTIMER_MAX:
+ *retval = 0; /* No delaytimer support */
+ break;
+ case SVR4_CONFIG_MQ_OPEN_MAX:
+ *retval = msginfo.msgmni;
+ break;
+ case SVR4_CONFIG_MQ_PRIO_MAX:
+ *retval = 0; /* XXX: Don't know */
+ break;
+ case SVR4_CONFIG_RTSIG_MAX:
+ *retval = 0;
+ break;
+ case SVR4_CONFIG_SEM_NSEMS_MAX:
+ *retval = seminfo.semmni;
+ break;
+ case SVR4_CONFIG_SEM_VALUE_MAX:
+ *retval = seminfo.semvmx;
+ break;
+ case SVR4_CONFIG_SIGQUEUE_MAX:
+ *retval = 0; /* XXX: Don't know */
+ break;
+ case SVR4_CONFIG_SIGRT_MIN:
+ case SVR4_CONFIG_SIGRT_MAX:
+ *retval = 0; /* No real time signals */
+ break;
+ case SVR4_CONFIG_TIMER_MAX:
+ *retval = 3; /* XXX: real, virtual, profiling */
+ break;
+#if defined(NOTYET)
+ case SVR4_CONFIG_PHYS_PAGES:
+#if defined(UVM)
+ *retval = uvmexp.free; /* XXX: free instead of total */
+#else
+ *retval = cnt.v_free_count; /* XXX: free instead of total */
+#endif
+ break;
+ case SVR4_CONFIG_AVPHYS_PAGES:
+#if defined(UVM)
+ *retval = uvmexp.active; /* XXX: active instead of avg */
+#else
+ *retval = cnt.v_active_count; /* XXX: active instead of avg */
+#endif
+ break;
+#endif /* NOTYET */
+
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+extern int swap_pager_full;
+
+/* ARGSUSED */
+int
+svr4_sys_break(td, uap)
+ struct thread *td;
+ struct svr4_sys_break_args *uap;
+{
+ struct vmspace *vm = td->td_proc->p_vmspace;
+ vm_offset_t new, old, base, ns;
+ int rv;
+
+ base = round_page((vm_offset_t) vm->vm_daddr);
+ ns = (vm_offset_t)SCARG(uap, nsize);
+ new = round_page(ns);
+ /* For p_rlimit. */
+ mtx_assert(&Giant, MA_OWNED);
+ if (new > base) {
+ if ((new - base) > (unsigned) td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur) {
+ return ENOMEM;
+ }
+ if (new >= VM_MAXUSER_ADDRESS) {
+ return (ENOMEM);
+ }
+ } else if (new < base) {
+ /*
+ * This is simply an invalid value. If someone wants to
+ * do fancy address space manipulations, mmap and munmap
+ * can do most of what the user would want.
+ */
+ return EINVAL;
+ }
+
+ old = base + ctob(vm->vm_dsize);
+
+ if (new > old) {
+ vm_size_t diff;
+ if (swap_pager_full) {
+ return (ENOMEM);
+ }
+ diff = new - old;
+ rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ if (rv != KERN_SUCCESS) {
+ return (ENOMEM);
+ }
+ vm->vm_dsize += btoc(diff);
+ } else if (new < old) {
+ rv = vm_map_remove(&vm->vm_map, new, old);
+ if (rv != KERN_SUCCESS) {
+ return (ENOMEM);
+ }
+ vm->vm_dsize -= btoc(old - new);
+ }
+
+ return (0);
+}
+
+static __inline clock_t
+timeval_to_clock_t(tv)
+ struct timeval *tv;
+{
+ return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
+}
+
+
+int
+svr4_sys_times(td, uap)
+ struct thread *td;
+ struct svr4_sys_times_args *uap;
+{
+ int error, *retval = td->td_retval;
+ struct tms tms;
+ struct timeval t;
+ struct rusage *ru;
+ struct rusage r;
+ struct getrusage_args ga;
+
+ caddr_t sg = stackgap_init();
+ ru = stackgap_alloc(&sg, sizeof(struct rusage));
+
+ SCARG(&ga, who) = RUSAGE_SELF;
+ SCARG(&ga, rusage) = ru;
+
+ error = getrusage(td, &ga);
+ if (error)
+ return error;
+
+ if ((error = copyin(ru, &r, sizeof r)) != 0)
+ return error;
+
+ tms.tms_utime = timeval_to_clock_t(&r.ru_utime);
+ tms.tms_stime = timeval_to_clock_t(&r.ru_stime);
+
+ SCARG(&ga, who) = RUSAGE_CHILDREN;
+ error = getrusage(td, &ga);
+ if (error)
+ return error;
+
+ if ((error = copyin(ru, &r, sizeof r)) != 0)
+ return error;
+
+ tms.tms_cutime = timeval_to_clock_t(&r.ru_utime);
+ tms.tms_cstime = timeval_to_clock_t(&r.ru_stime);
+
+ microtime(&t);
+ *retval = timeval_to_clock_t(&t);
+
+ return copyout(&tms, SCARG(uap, tp), sizeof(tms));
+}
+
+
+int
+svr4_sys_ulimit(td, uap)
+ struct thread *td;
+ struct svr4_sys_ulimit_args *uap;
+{
+ int *retval = td->td_retval;
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_GFILLIM:
+ /* For p_rlimit below. */
+ mtx_assert(&Giant, MA_OWNED);
+ *retval = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+
+ case SVR4_SFILLIM:
+ {
+ int error;
+ struct __setrlimit_args srl;
+ struct rlimit krl;
+ caddr_t sg = stackgap_init();
+ struct rlimit *url = (struct rlimit *)
+ stackgap_alloc(&sg, sizeof *url);
+
+ krl.rlim_cur = SCARG(uap, newlimit) * 512;
+ mtx_assert(&Giant, MA_OWNED);
+ krl.rlim_max = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_max;
+
+ error = copyout(&krl, url, sizeof(*url));
+ if (error)
+ return error;
+
+ SCARG(&srl, which) = RLIMIT_FSIZE;
+ SCARG(&srl, rlp) = url;
+
+ error = setrlimit(td, &srl);
+ if (error)
+ return error;
+
+ mtx_assert(&Giant, MA_OWNED);
+ *retval = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur;
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+ }
+
+ case SVR4_GMEMLIM:
+ {
+ struct vmspace *vm = td->td_proc->p_vmspace;
+ register_t r;
+
+ mtx_assert(&Giant, MA_OWNED);
+ r = td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur;
+
+ if (r == -1)
+ r = 0x7fffffff;
+ r += (long) vm->vm_daddr;
+ if (r < 0)
+ r = 0x7fffffff;
+ *retval = r;
+ return 0;
+ }
+
+ case SVR4_GDESLIM:
+ mtx_assert(&Giant, MA_OWNED);
+ *retval = td->td_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur;
+ if (*retval == -1)
+ *retval = 0x7fffffff;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
+
+static struct proc *
+svr4_pfind(pid)
+ pid_t pid;
+{
+ struct proc *p;
+
+ /* look in the live processes */
+ if ((p = pfind(pid)) == NULL)
+ /* look in the zombies */
+ p = zpfind(pid);
+
+ return p;
+}
+
+
+int
+svr4_sys_pgrpsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_pgrpsys_args *uap;
+{
+ int *retval = td->td_retval;
+ struct proc *p = td->td_proc;
+
+ switch (SCARG(uap, cmd)) {
+ case 1: /* setpgrp() */
+ /*
+ * SVR4 setpgrp() (which takes no arguments) has the
+ * semantics that the session ID is also created anew, so
+ * in almost every sense, setpgrp() is identical to
+ * setsid() for SVR4. (Under BSD, the difference is that
+ * a setpgid(0,0) will not create a new session.)
+ */
+ setsid(td, NULL);
+ /*FALLTHROUGH*/
+
+ case 0: /* getpgrp() */
+ PROC_LOCK(p);
+ *retval = p->p_pgrp->pg_id;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 2: /* getsid(pid) */
+ if (SCARG(uap, pid) == 0)
+ PROC_LOCK(p);
+ else if ((p = svr4_pfind(SCARG(uap, pid))) == NULL)
+ return ESRCH;
+ /*
+ * This has already been initialized to the pid of
+ * the session leader.
+ */
+ *retval = (register_t) p->p_session->s_sid;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 3: /* setsid() */
+ return setsid(td, NULL);
+
+ case 4: /* getpgid(pid) */
+
+ if (SCARG(uap, pid) == 0)
+ PROC_LOCK(p);
+ else if ((p = svr4_pfind(SCARG(uap, pid))) == NULL)
+ return ESRCH;
+
+ *retval = (int) p->p_pgrp->pg_id;
+ PROC_UNLOCK(p);
+ return 0;
+
+ case 5: /* setpgid(pid, pgid); */
+ {
+ struct setpgid_args sa;
+
+ SCARG(&sa, pid) = SCARG(uap, pid);
+ SCARG(&sa, pgid) = SCARG(uap, pgid);
+ return setpgid(td, &sa);
+ }
+
+ default:
+ return EINVAL;
+ }
+}
+
+#define syscallarg(x) union { x datum; register_t pad; }
+
+struct svr4_hrtcntl_args {
+ int cmd;
+ int fun;
+ int clk;
+ svr4_hrt_interval_t * iv;
+ svr4_hrt_time_t * ti;
+};
+
+
+static int
+svr4_hrtcntl(td, uap, retval)
+ struct thread *td;
+ struct svr4_hrtcntl_args *uap;
+ register_t *retval;
+{
+ switch (SCARG(uap, fun)) {
+ case SVR4_HRT_CNTL_RES:
+ DPRINTF(("htrcntl(RES)\n"));
+ *retval = SVR4_HRT_USEC;
+ return 0;
+
+ case SVR4_HRT_CNTL_TOFD:
+ DPRINTF(("htrcntl(TOFD)\n"));
+ {
+ struct timeval tv;
+ svr4_hrt_time_t t;
+ if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) {
+ DPRINTF(("clk == %d\n", SCARG(uap, clk)));
+ return EINVAL;
+ }
+ if (SCARG(uap, ti) == NULL) {
+ DPRINTF(("ti NULL\n"));
+ return EINVAL;
+ }
+ microtime(&tv);
+ t.h_sec = tv.tv_sec;
+ t.h_rem = tv.tv_usec;
+ t.h_res = SVR4_HRT_USEC;
+ return copyout(&t, SCARG(uap, ti), sizeof(t));
+ }
+
+ case SVR4_HRT_CNTL_START:
+ DPRINTF(("htrcntl(START)\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_CNTL_GET:
+ DPRINTF(("htrcntl(GET)\n"));
+ return ENOSYS;
+ default:
+ DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun)));
+ return ENOSYS;
+ }
+}
+
+
+int
+svr4_sys_hrtsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_hrtsys_args *uap;
+{
+ int *retval = td->td_retval;
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_HRT_CNTL:
+ return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
+ retval);
+
+ case SVR4_HRT_ALRM:
+ DPRINTF(("hrtalarm\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_SLP:
+ DPRINTF(("hrtsleep\n"));
+ return ENOSYS;
+
+ case SVR4_HRT_CAN:
+ DPRINTF(("hrtcancel\n"));
+ return ENOSYS;
+
+ default:
+ DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd)));
+ return EINVAL;
+ }
+}
+
+
+static int
+svr4_setinfo(p, st, s)
+ struct proc *p;
+ int st;
+ svr4_siginfo_t *s;
+{
+ svr4_siginfo_t i;
+ int sig;
+
+ memset(&i, 0, sizeof(i));
+
+ i.si_signo = SVR4_SIGCHLD;
+ i.si_errno = 0; /* XXX? */
+
+ if (p) {
+ i.si_pid = p->p_pid;
+ mtx_lock_spin(&sched_lock);
+ if (p->p_state == PRS_ZOMBIE) {
+ i.si_stime = p->p_ru->ru_stime.tv_sec;
+ i.si_utime = p->p_ru->ru_utime.tv_sec;
+ }
+ else {
+ i.si_stime = p->p_stats->p_ru.ru_stime.tv_sec;
+ i.si_utime = p->p_stats->p_ru.ru_utime.tv_sec;
+ }
+ mtx_unlock_spin(&sched_lock);
+ }
+
+ if (WIFEXITED(st)) {
+ i.si_status = WEXITSTATUS(st);
+ i.si_code = SVR4_CLD_EXITED;
+ } else if (WIFSTOPPED(st)) {
+ sig = WSTOPSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ i.si_status = SVR4_BSD2SVR4_SIG(sig);
+
+ if (i.si_status == SVR4_SIGCONT)
+ i.si_code = SVR4_CLD_CONTINUED;
+ else
+ i.si_code = SVR4_CLD_STOPPED;
+ } else {
+ sig = WTERMSIG(st);
+ if (sig >= 0 && sig < NSIG)
+ i.si_status = SVR4_BSD2SVR4_SIG(sig);
+
+ if (WCOREDUMP(st))
+ i.si_code = SVR4_CLD_DUMPED;
+ else
+ i.si_code = SVR4_CLD_KILLED;
+ }
+
+ DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
+ i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status));
+
+ return copyout(&i, s, sizeof(i));
+}
+
+
+int
+svr4_sys_waitsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_waitsys_args *uap;
+{
+ int nfound;
+ int error, *retval = td->td_retval;
+ struct proc *q, *t;
+
+
+ switch (SCARG(uap, grp)) {
+ case SVR4_P_PID:
+ break;
+
+ case SVR4_P_PGID:
+ PROC_LOCK(td->td_proc);
+ SCARG(uap, id) = -td->td_proc->p_pgid;
+ PROC_UNLOCK(td->td_proc);
+ break;
+
+ case SVR4_P_ALL:
+ SCARG(uap, id) = WAIT_ANY;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ DPRINTF(("waitsys(%d, %d, %p, %x)\n",
+ SCARG(uap, grp), SCARG(uap, id),
+ SCARG(uap, info), SCARG(uap, options)));
+
+loop:
+ nfound = 0;
+ sx_slock(&proctree_lock);
+ LIST_FOREACH(q, &td->td_proc->p_children, p_sibling) {
+ PROC_LOCK(q);
+ if (SCARG(uap, id) != WAIT_ANY &&
+ q->p_pid != SCARG(uap, id) &&
+ q->p_pgid != -SCARG(uap, id)) {
+ PROC_UNLOCK(q);
+ DPRINTF(("pid %d pgid %d != %d\n", q->p_pid,
+ q->p_pgid, SCARG(uap, id)));
+ continue;
+ }
+ nfound++;
+ mtx_lock_spin(&sched_lock);
+ if ((q->p_state == PRS_ZOMBIE) &&
+ ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(q);
+ sx_sunlock(&proctree_lock);
+ *retval = 0;
+ DPRINTF(("found %d\n", q->p_pid));
+ error = svr4_setinfo(q, q->p_xstat, SCARG(uap, info));
+ if (error != 0)
+ return error;
+
+
+ if ((SCARG(uap, options) & SVR4_WNOWAIT)) {
+ DPRINTF(("Don't wait\n"));
+ return 0;
+ }
+
+ /*
+ * If we got the child via ptrace(2) or procfs, and
+ * the parent is different (meaning the process was
+ * attached, rather than run as a child), then we need
+ * to give it back to the old parent, and send the
+ * parent a SIGCHLD. The rest of the cleanup will be
+ * done when the old parent waits on the child.
+ */
+ sx_xlock(&proctree_lock);
+ PROC_LOCK(q);
+ if (q->p_flag & P_TRACED) {
+ if (q->p_oppid != q->p_pptr->p_pid) {
+ PROC_UNLOCK(q);
+ t = pfind(q->p_oppid);
+ if (t == NULL) {
+ t = initproc;
+ PROC_LOCK(initproc);
+ }
+ PROC_LOCK(q);
+ proc_reparent(q, t);
+ q->p_oppid = 0;
+ q->p_flag &= ~(P_TRACED | P_WAITED);
+ PROC_UNLOCK(q);
+ psignal(t, SIGCHLD);
+ wakeup(t);
+ PROC_UNLOCK(t);
+ sx_xunlock(&proctree_lock);
+ return 0;
+ }
+ }
+ PROC_UNLOCK(q);
+ sx_xunlock(&proctree_lock);
+ q->p_xstat = 0;
+ ruadd(&td->td_proc->p_stats->p_cru, q->p_ru);
+ FREE(q->p_ru, M_ZOMBIE);
+ q->p_ru = 0;
+
+ /*
+ * Decrement the count of procs running with this uid.
+ */
+ (void)chgproccnt(q->p_ucred->cr_ruidinfo, -1, 0);
+
+ /*
+ * Release reference to text vnode.
+ */
+ if (q->p_textvp)
+ vrele(q->p_textvp);
+
+ /*
+ * Free up credentials.
+ */
+ crfree(q->p_ucred);
+ q->p_ucred = NULL;
+
+ /*
+ * Remove unused arguments
+ */
+ pargs_drop(q->p_args);
+ PROC_UNLOCK(q);
+
+ /*
+ * Finally finished with old proc entry.
+ * Unlink it from its process group and free it.
+ */
+ sx_xlock(&proctree_lock);
+ leavepgrp(q);
+
+ sx_xlock(&allproc_lock);
+ LIST_REMOVE(q, p_list); /* off zombproc */
+ sx_xunlock(&allproc_lock);
+
+ LIST_REMOVE(q, p_sibling);
+ sx_xunlock(&proctree_lock);
+
+ PROC_LOCK(q);
+ if (--q->p_procsig->ps_refcnt == 0) {
+ if (q->p_sigacts != &q->p_uarea->u_sigacts)
+ FREE(q->p_sigacts, M_SUBPROC);
+ FREE(q->p_procsig, M_SUBPROC);
+ q->p_procsig = NULL;
+ }
+ PROC_UNLOCK(q);
+
+ /*
+ * Give machine-dependent layer a chance
+ * to free anything that cpu_exit couldn't
+ * release while still running in process context.
+ */
+ cpu_wait(q);
+#if defined(__NetBSD__)
+ pool_put(&proc_pool, q);
+#endif
+#ifdef __FreeBSD__
+ mtx_destroy(&q->p_mtx);
+ uma_zfree(proc_zone, q);
+#endif
+ nprocs--;
+ return 0;
+ }
+ /* XXXKSE this needs clarification */
+ if (P_SHOULDSTOP(q) && ((q->p_flag & P_WAITED) == 0) &&
+ (q->p_flag & P_TRACED ||
+ (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED)))) {
+ mtx_unlock_spin(&sched_lock);
+ DPRINTF(("jobcontrol %d\n", q->p_pid));
+ if (((SCARG(uap, options) & SVR4_WNOWAIT)) == 0)
+ q->p_flag |= P_WAITED;
+ PROC_UNLOCK(q);
+ *retval = 0;
+ return svr4_setinfo(q, W_STOPCODE(q->p_xstat),
+ SCARG(uap, info));
+ }
+ mtx_unlock_spin(&sched_lock);
+ PROC_UNLOCK(q);
+ }
+
+ if (nfound == 0)
+ return ECHILD;
+
+ if (SCARG(uap, options) & SVR4_WNOHANG) {
+ *retval = 0;
+ if ((error = svr4_setinfo(NULL, 0, SCARG(uap, info))) != 0)
+ return error;
+ return 0;
+ }
+
+ if ((error = tsleep((caddr_t)td->td_proc, PWAIT | PCATCH, "svr4_wait", 0)) != 0)
+ return error;
+ goto loop;
+}
+
+
+static void
+bsd_statfs_to_svr4_statvfs(bfs, sfs)
+ const struct statfs *bfs;
+ struct svr4_statvfs *sfs;
+{
+ sfs->f_bsize = bfs->f_iosize; /* XXX */
+ sfs->f_frsize = bfs->f_bsize;
+ sfs->f_blocks = bfs->f_blocks;
+ sfs->f_bfree = bfs->f_bfree;
+ sfs->f_bavail = bfs->f_bavail;
+ sfs->f_files = bfs->f_files;
+ sfs->f_ffree = bfs->f_ffree;
+ sfs->f_favail = bfs->f_ffree;
+ sfs->f_fsid = bfs->f_fsid.val[0];
+ memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
+ sfs->f_flag = 0;
+ if (bfs->f_flags & MNT_RDONLY)
+ sfs->f_flag |= SVR4_ST_RDONLY;
+ if (bfs->f_flags & MNT_NOSUID)
+ sfs->f_flag |= SVR4_ST_NOSUID;
+ sfs->f_namemax = MAXNAMLEN;
+ memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
+ memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
+}
+
+
+static void
+bsd_statfs_to_svr4_statvfs64(bfs, sfs)
+ const struct statfs *bfs;
+ struct svr4_statvfs64 *sfs;
+{
+ sfs->f_bsize = bfs->f_iosize; /* XXX */
+ sfs->f_frsize = bfs->f_bsize;
+ sfs->f_blocks = bfs->f_blocks;
+ sfs->f_bfree = bfs->f_bfree;
+ sfs->f_bavail = bfs->f_bavail;
+ sfs->f_files = bfs->f_files;
+ sfs->f_ffree = bfs->f_ffree;
+ sfs->f_favail = bfs->f_ffree;
+ sfs->f_fsid = bfs->f_fsid.val[0];
+ memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
+ sfs->f_flag = 0;
+ if (bfs->f_flags & MNT_RDONLY)
+ sfs->f_flag |= SVR4_ST_RDONLY;
+ if (bfs->f_flags & MNT_NOSUID)
+ sfs->f_flag |= SVR4_ST_NOSUID;
+ sfs->f_namemax = MAXNAMLEN;
+ memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
+ memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
+}
+
+
+int
+svr4_sys_statvfs(td, uap)
+ struct thread *td;
+ struct svr4_sys_statvfs_args *uap;
+{
+ struct statfs_args fs_args;
+ caddr_t sg = stackgap_init();
+ struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
+ struct statfs bfs;
+ struct svr4_statvfs sfs;
+ int error;
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+ SCARG(&fs_args, path) = SCARG(uap, path);
+ SCARG(&fs_args, buf) = fs;
+
+ if ((error = statfs(td, &fs_args)) != 0)
+ return error;
+
+ if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
+ return error;
+
+ bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
+
+ return copyout(&sfs, SCARG(uap, fs), sizeof(sfs));
+}
+
+
+int
+svr4_sys_fstatvfs(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstatvfs_args *uap;
+{
+ struct fstatfs_args fs_args;
+ caddr_t sg = stackgap_init();
+ struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
+ struct statfs bfs;
+ struct svr4_statvfs sfs;
+ int error;
+
+ SCARG(&fs_args, fd) = SCARG(uap, fd);
+ SCARG(&fs_args, buf) = fs;
+
+ if ((error = fstatfs(td, &fs_args)) != 0)
+ return error;
+
+ if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
+ return error;
+
+ bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
+
+ return copyout(&sfs, SCARG(uap, fs), sizeof(sfs));
+}
+
+
+int
+svr4_sys_statvfs64(td, uap)
+ struct thread *td;
+ struct svr4_sys_statvfs64_args *uap;
+{
+ struct statfs_args fs_args;
+ caddr_t sg = stackgap_init();
+ struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
+ struct statfs bfs;
+ struct svr4_statvfs64 sfs;
+ int error;
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+ SCARG(&fs_args, path) = SCARG(uap, path);
+ SCARG(&fs_args, buf) = fs;
+
+ if ((error = statfs(td, &fs_args)) != 0)
+ return error;
+
+ if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
+ return error;
+
+ bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
+
+ return copyout(&sfs, SCARG(uap, fs), sizeof(sfs));
+}
+
+
+int
+svr4_sys_fstatvfs64(td, uap)
+ struct thread *td;
+ struct svr4_sys_fstatvfs64_args *uap;
+{
+ struct fstatfs_args fs_args;
+ caddr_t sg = stackgap_init();
+ struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
+ struct statfs bfs;
+ struct svr4_statvfs64 sfs;
+ int error;
+
+ SCARG(&fs_args, fd) = SCARG(uap, fd);
+ SCARG(&fs_args, buf) = fs;
+
+ if ((error = fstatfs(td, &fs_args)) != 0)
+ return error;
+
+ if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
+ return error;
+
+ bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
+
+ return copyout(&sfs, SCARG(uap, fs), sizeof(sfs));
+}
+
+int
+svr4_sys_alarm(td, uap)
+ struct thread *td;
+ struct svr4_sys_alarm_args *uap;
+{
+ int error;
+ struct itimerval *itp, *oitp;
+ struct setitimer_args sa;
+ caddr_t sg = stackgap_init();
+
+ itp = stackgap_alloc(&sg, sizeof(*itp));
+ oitp = stackgap_alloc(&sg, sizeof(*oitp));
+ timevalclear(&itp->it_interval);
+ itp->it_value.tv_sec = SCARG(uap, sec);
+ itp->it_value.tv_usec = 0;
+
+ SCARG(&sa, which) = ITIMER_REAL;
+ SCARG(&sa, itv) = itp;
+ SCARG(&sa, oitv) = oitp;
+ error = setitimer(td, &sa);
+ if (error)
+ return error;
+ if (oitp->it_value.tv_usec)
+ oitp->it_value.tv_sec++;
+ td->td_retval[0] = oitp->it_value.tv_sec;
+ return 0;
+
+}
+
+int
+svr4_sys_gettimeofday(td, uap)
+ struct thread *td;
+ struct svr4_sys_gettimeofday_args *uap;
+{
+ if (SCARG(uap, tp)) {
+ struct timeval atv;
+
+ microtime(&atv);
+ return copyout(&atv, SCARG(uap, tp), sizeof (atv));
+ }
+
+ return 0;
+}
+
+int
+svr4_sys_facl(td, uap)
+ struct thread *td;
+ struct svr4_sys_facl_args *uap;
+{
+ int *retval;
+
+ retval = td->td_retval;
+ *retval = 0;
+
+ switch (SCARG(uap, cmd)) {
+ case SVR4_SYS_SETACL:
+ /* We don't support acls on any filesystem */
+ return ENOSYS;
+
+ case SVR4_SYS_GETACL:
+ return copyout(retval, &SCARG(uap, num),
+ sizeof(SCARG(uap, num)));
+
+ case SVR4_SYS_GETACLCNT:
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
+
+
+int
+svr4_sys_acl(td, uap)
+ struct thread *td;
+ struct svr4_sys_acl_args *uap;
+{
+ /* XXX: for now the same */
+ return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
+}
+
+int
+svr4_sys_auditsys(td, uap)
+ struct thread *td;
+ struct svr4_sys_auditsys_args *uap;
+{
+ /*
+ * XXX: Big brother is *not* watching.
+ */
+ return 0;
+}
+
+int
+svr4_sys_memcntl(td, uap)
+ struct thread *td;
+ struct svr4_sys_memcntl_args *uap;
+{
+ switch (SCARG(uap, cmd)) {
+ case SVR4_MC_SYNC:
+ {
+ struct msync_args msa;
+
+ SCARG(&msa, addr) = SCARG(uap, addr);
+ SCARG(&msa, len) = SCARG(uap, len);
+ SCARG(&msa, flags) = (int)SCARG(uap, arg);
+
+ return msync(td, &msa);
+ }
+ case SVR4_MC_ADVISE:
+ {
+ struct madvise_args maa;
+
+ SCARG(&maa, addr) = SCARG(uap, addr);
+ SCARG(&maa, len) = SCARG(uap, len);
+ SCARG(&maa, behav) = (int)SCARG(uap, arg);
+
+ return madvise(td, &maa);
+ }
+ case SVR4_MC_LOCK:
+ case SVR4_MC_UNLOCK:
+ case SVR4_MC_LOCKAS:
+ case SVR4_MC_UNLOCKAS:
+ return EOPNOTSUPP;
+ default:
+ return ENOSYS;
+ }
+}
+
+
+int
+svr4_sys_nice(td, uap)
+ struct thread *td;
+ struct svr4_sys_nice_args *uap;
+{
+ struct setpriority_args ap;
+ int error;
+
+ SCARG(&ap, which) = PRIO_PROCESS;
+ SCARG(&ap, who) = 0;
+ SCARG(&ap, prio) = SCARG(uap, prio);
+
+ if ((error = setpriority(td, &ap)) != 0)
+ return error;
+
+ /* the cast is stupid, but the structures are the same */
+ if ((error = getpriority(td, (struct getpriority_args *)&ap)) != 0)
+ return error;
+
+ return 0;
+}
+
+int
+svr4_sys_resolvepath(td, uap)
+ struct thread *td;
+ struct svr4_sys_resolvepath_args *uap;
+{
+ struct nameidata nd;
+ int error, *retval = td->td_retval;
+
+ NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE,
+ SCARG(uap, path), td);
+
+ if ((error = namei(&nd)) != 0)
+ return error;
+
+ if ((error = copyout(nd.ni_cnd.cn_pnbuf, SCARG(uap, buf),
+ SCARG(uap, bufsiz))) != 0)
+ goto bad;
+
+ *retval = strlen(nd.ni_cnd.cn_pnbuf) < SCARG(uap, bufsiz) ?
+ strlen(nd.ni_cnd.cn_pnbuf) + 1 : SCARG(uap, bufsiz);
+bad:
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vput(nd.ni_vp);
+ return error;
+}
diff --git a/sys/compat/svr4/svr4_mman.h b/sys/compat/svr4/svr4_mman.h
new file mode 100644
index 0000000..db7c3da
--- /dev/null
+++ b/sys/compat/svr4/svr4_mman.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1997 Todd Vierling
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_MMAN_H_
+#define _SVR4_MMAN_H_
+
+/*
+ * Commands and flags passed to memcntl().
+ * Most of them are the same as <sys/mman.h>, but we need the MC_
+ * memcntl command definitions.
+ */
+
+#define SVR4_MC_SYNC 1
+#define SVR4_MC_LOCK 2
+#define SVR4_MC_UNLOCK 3
+#define SVR4_MC_ADVISE 4
+#define SVR4_MC_LOCKAS 5
+#define SVR4_MC_UNLOCKAS 6
+
+#endif /* !_SVR4_MMAN_H */
diff --git a/sys/compat/svr4/svr4_proto.h b/sys/compat/svr4/svr4_proto.h
new file mode 100644
index 0000000..15f66de
--- /dev/null
+++ b/sys/compat/svr4/svr4_proto.h
@@ -0,0 +1,477 @@
+/*
+ * System call prototypes.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp
+ */
+
+#ifndef _SVR4_SYSPROTO_H_
+#define _SVR4_SYSPROTO_H_
+
+#include <sys/signal.h>
+
+#include <sys/acl.h>
+
+struct proc;
+
+struct thread;
+
+#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \
+ 0 : sizeof(register_t) - sizeof(t))
+
+struct svr4_sys_open_args {
+ char * path; char path_[PAD_(char *)];
+ int flags; char flags_[PAD_(int)];
+ int mode; char mode_[PAD_(int)];
+};
+struct svr4_sys_wait_args {
+ int * status; char status_[PAD_(int *)];
+};
+struct svr4_sys_creat_args {
+ char * path; char path_[PAD_(char *)];
+ int mode; char mode_[PAD_(int)];
+};
+struct svr4_sys_execv_args {
+ char * path; char path_[PAD_(char *)];
+ char ** argp; char argp_[PAD_(char **)];
+};
+struct svr4_sys_time_args {
+ time_t * t; char t_[PAD_(time_t *)];
+};
+struct svr4_sys_mknod_args {
+ char * path; char path_[PAD_(char *)];
+ int mode; char mode_[PAD_(int)];
+ int dev; char dev_[PAD_(int)];
+};
+struct svr4_sys_break_args {
+ caddr_t nsize; char nsize_[PAD_(caddr_t)];
+};
+struct svr4_sys_stat_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_stat * ub; char ub_[PAD_(struct svr4_stat *)];
+};
+struct svr4_sys_alarm_args {
+ unsigned sec; char sec_[PAD_(unsigned)];
+};
+struct svr4_sys_fstat_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_stat * sb; char sb_[PAD_(struct svr4_stat *)];
+};
+struct svr4_sys_pause_args {
+ register_t dummy;
+};
+struct svr4_sys_utime_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_utimbuf * ubuf; char ubuf_[PAD_(struct svr4_utimbuf *)];
+};
+struct svr4_sys_access_args {
+ char * path; char path_[PAD_(char *)];
+ int flags; char flags_[PAD_(int)];
+};
+struct svr4_sys_nice_args {
+ int prio; char prio_[PAD_(int)];
+};
+struct svr4_sys_kill_args {
+ int pid; char pid_[PAD_(int)];
+ int signum; char signum_[PAD_(int)];
+};
+struct svr4_sys_pgrpsys_args {
+ int cmd; char cmd_[PAD_(int)];
+ int pid; char pid_[PAD_(int)];
+ int pgid; char pgid_[PAD_(int)];
+};
+struct svr4_sys_times_args {
+ struct tms * tp; char tp_[PAD_(struct tms *)];
+};
+struct svr4_sys_signal_args {
+ int signum; char signum_[PAD_(int)];
+ svr4_sig_t handler; char handler_[PAD_(svr4_sig_t)];
+};
+#if defined(NOTYET)
+struct svr4_sys_msgsys_args {
+ int what; char what_[PAD_(int)];
+ int a2; char a2_[PAD_(int)];
+ int a3; char a3_[PAD_(int)];
+ int a4; char a4_[PAD_(int)];
+ int a5; char a5_[PAD_(int)];
+};
+#else
+#endif
+struct svr4_sys_sysarch_args {
+ int op; char op_[PAD_(int)];
+ void * a1; char a1_[PAD_(void *)];
+};
+struct svr4_sys_ioctl_args {
+ int fd; char fd_[PAD_(int)];
+ u_long com; char com_[PAD_(u_long)];
+ caddr_t data; char data_[PAD_(caddr_t)];
+};
+struct svr4_sys_utssys_args {
+ void * a1; char a1_[PAD_(void *)];
+ void * a2; char a2_[PAD_(void *)];
+ int sel; char sel_[PAD_(int)];
+ void * a3; char a3_[PAD_(void *)];
+};
+struct svr4_sys_execve_args {
+ char * path; char path_[PAD_(char *)];
+ char ** argp; char argp_[PAD_(char **)];
+ char ** envp; char envp_[PAD_(char **)];
+};
+struct svr4_sys_fcntl_args {
+ int fd; char fd_[PAD_(int)];
+ int cmd; char cmd_[PAD_(int)];
+ char * arg; char arg_[PAD_(char *)];
+};
+struct svr4_sys_ulimit_args {
+ int cmd; char cmd_[PAD_(int)];
+ long newlimit; char newlimit_[PAD_(long)];
+};
+struct svr4_sys_getdents_args {
+ int fd; char fd_[PAD_(int)];
+ char * buf; char buf_[PAD_(char *)];
+ int nbytes; char nbytes_[PAD_(int)];
+};
+struct svr4_sys_getmsg_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_strbuf * ctl; char ctl_[PAD_(struct svr4_strbuf *)];
+ struct svr4_strbuf * dat; char dat_[PAD_(struct svr4_strbuf *)];
+ int * flags; char flags_[PAD_(int *)];
+};
+struct svr4_sys_putmsg_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_strbuf * ctl; char ctl_[PAD_(struct svr4_strbuf *)];
+ struct svr4_strbuf * dat; char dat_[PAD_(struct svr4_strbuf *)];
+ int flags; char flags_[PAD_(int)];
+};
+struct svr4_sys_poll_args {
+ struct pollfd * fds; char fds_[PAD_(struct pollfd *)];
+ unsigned int nfds; char nfds_[PAD_(unsigned int)];
+ int timeout; char timeout_[PAD_(int)];
+};
+struct svr4_sys_lstat_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_stat * ub; char ub_[PAD_(struct svr4_stat *)];
+};
+struct svr4_sys_sigprocmask_args {
+ int how; char how_[PAD_(int)];
+ svr4_sigset_t * set; char set_[PAD_(svr4_sigset_t *)];
+ svr4_sigset_t * oset; char oset_[PAD_(svr4_sigset_t *)];
+};
+struct svr4_sys_sigsuspend_args {
+ svr4_sigset_t * ss; char ss_[PAD_(svr4_sigset_t *)];
+};
+struct svr4_sys_sigaltstack_args {
+ struct svr4_sigaltstack * nss; char nss_[PAD_(struct svr4_sigaltstack *)];
+ struct svr4_sigaltstack * oss; char oss_[PAD_(struct svr4_sigaltstack *)];
+};
+struct svr4_sys_sigaction_args {
+ int signum; char signum_[PAD_(int)];
+ struct svr4_sigaction * nsa; char nsa_[PAD_(struct svr4_sigaction *)];
+ struct svr4_sigaction * osa; char osa_[PAD_(struct svr4_sigaction *)];
+};
+struct svr4_sys_sigpending_args {
+ int what; char what_[PAD_(int)];
+ svr4_sigset_t * mask; char mask_[PAD_(svr4_sigset_t *)];
+};
+struct svr4_sys_context_args {
+ int func; char func_[PAD_(int)];
+ struct svr4_ucontext * uc; char uc_[PAD_(struct svr4_ucontext *)];
+};
+struct svr4_sys_statvfs_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_statvfs * fs; char fs_[PAD_(struct svr4_statvfs *)];
+};
+struct svr4_sys_fstatvfs_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_statvfs * fs; char fs_[PAD_(struct svr4_statvfs *)];
+};
+struct svr4_sys_waitsys_args {
+ int grp; char grp_[PAD_(int)];
+ int id; char id_[PAD_(int)];
+ union svr4_siginfo * info; char info_[PAD_(union svr4_siginfo *)];
+ int options; char options_[PAD_(int)];
+};
+struct svr4_sys_hrtsys_args {
+ int cmd; char cmd_[PAD_(int)];
+ int fun; char fun_[PAD_(int)];
+ int sub; char sub_[PAD_(int)];
+ void * rv1; char rv1_[PAD_(void *)];
+ void * rv2; char rv2_[PAD_(void *)];
+};
+struct svr4_sys_pathconf_args {
+ char * path; char path_[PAD_(char *)];
+ int name; char name_[PAD_(int)];
+};
+struct svr4_sys_mmap_args {
+ caddr_t addr; char addr_[PAD_(caddr_t)];
+ svr4_size_t len; char len_[PAD_(svr4_size_t)];
+ int prot; char prot_[PAD_(int)];
+ int flags; char flags_[PAD_(int)];
+ int fd; char fd_[PAD_(int)];
+ svr4_off_t pos; char pos_[PAD_(svr4_off_t)];
+};
+struct svr4_sys_fpathconf_args {
+ int fd; char fd_[PAD_(int)];
+ int name; char name_[PAD_(int)];
+};
+struct svr4_sys_xstat_args {
+ int two; char two_[PAD_(int)];
+ char * path; char path_[PAD_(char *)];
+ struct svr4_xstat * ub; char ub_[PAD_(struct svr4_xstat *)];
+};
+struct svr4_sys_lxstat_args {
+ int two; char two_[PAD_(int)];
+ char * path; char path_[PAD_(char *)];
+ struct svr4_xstat * ub; char ub_[PAD_(struct svr4_xstat *)];
+};
+struct svr4_sys_fxstat_args {
+ int two; char two_[PAD_(int)];
+ int fd; char fd_[PAD_(int)];
+ struct svr4_xstat * sb; char sb_[PAD_(struct svr4_xstat *)];
+};
+struct svr4_sys_xmknod_args {
+ int two; char two_[PAD_(int)];
+ char * path; char path_[PAD_(char *)];
+ svr4_mode_t mode; char mode_[PAD_(svr4_mode_t)];
+ svr4_dev_t dev; char dev_[PAD_(svr4_dev_t)];
+};
+struct svr4_sys_setrlimit_args {
+ int which; char which_[PAD_(int)];
+ const struct svr4_rlimit * rlp; char rlp_[PAD_(const struct svr4_rlimit *)];
+};
+struct svr4_sys_getrlimit_args {
+ int which; char which_[PAD_(int)];
+ struct svr4_rlimit * rlp; char rlp_[PAD_(struct svr4_rlimit *)];
+};
+struct svr4_sys_memcntl_args {
+ void * addr; char addr_[PAD_(void *)];
+ svr4_size_t len; char len_[PAD_(svr4_size_t)];
+ int cmd; char cmd_[PAD_(int)];
+ void * arg; char arg_[PAD_(void *)];
+ int attr; char attr_[PAD_(int)];
+ int mask; char mask_[PAD_(int)];
+};
+struct svr4_sys_uname_args {
+ struct svr4_utsname * name; char name_[PAD_(struct svr4_utsname *)];
+ int dummy; char dummy_[PAD_(int)];
+};
+struct svr4_sys_sysconfig_args {
+ int name; char name_[PAD_(int)];
+};
+struct svr4_sys_systeminfo_args {
+ int what; char what_[PAD_(int)];
+ char * buf; char buf_[PAD_(char *)];
+ long len; char len_[PAD_(long)];
+};
+struct svr4_sys_fchroot_args {
+ int fd; char fd_[PAD_(int)];
+};
+struct svr4_sys_utimes_args {
+ char * path; char path_[PAD_(char *)];
+ struct timeval * tptr; char tptr_[PAD_(struct timeval *)];
+};
+struct svr4_sys_vhangup_args {
+ register_t dummy;
+};
+struct svr4_sys_gettimeofday_args {
+ struct timeval * tp; char tp_[PAD_(struct timeval *)];
+};
+struct svr4_sys_llseek_args {
+ int fd; char fd_[PAD_(int)];
+ long offset1; char offset1_[PAD_(long)];
+ long offset2; char offset2_[PAD_(long)];
+ int whence; char whence_[PAD_(int)];
+};
+struct svr4_sys_acl_args {
+ char * path; char path_[PAD_(char *)];
+ int cmd; char cmd_[PAD_(int)];
+ int num; char num_[PAD_(int)];
+ struct svr4_aclent * buf; char buf_[PAD_(struct svr4_aclent *)];
+};
+struct svr4_sys_auditsys_args {
+ int code; char code_[PAD_(int)];
+ int a1; char a1_[PAD_(int)];
+ int a2; char a2_[PAD_(int)];
+ int a3; char a3_[PAD_(int)];
+ int a4; char a4_[PAD_(int)];
+ int a5; char a5_[PAD_(int)];
+};
+struct svr4_sys_facl_args {
+ int fd; char fd_[PAD_(int)];
+ int cmd; char cmd_[PAD_(int)];
+ int num; char num_[PAD_(int)];
+ struct svr4_aclent * buf; char buf_[PAD_(struct svr4_aclent *)];
+};
+struct svr4_sys_resolvepath_args {
+ const char * path; char path_[PAD_(const char *)];
+ char * buf; char buf_[PAD_(char *)];
+ size_t bufsiz; char bufsiz_[PAD_(size_t)];
+};
+struct svr4_sys_getdents64_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_dirent64 * dp; char dp_[PAD_(struct svr4_dirent64 *)];
+ int nbytes; char nbytes_[PAD_(int)];
+};
+struct svr4_sys_mmap64_args {
+ void * addr; char addr_[PAD_(void *)];
+ svr4_size_t len; char len_[PAD_(svr4_size_t)];
+ int prot; char prot_[PAD_(int)];
+ int flags; char flags_[PAD_(int)];
+ int fd; char fd_[PAD_(int)];
+ svr4_off64_t pos; char pos_[PAD_(svr4_off64_t)];
+};
+struct svr4_sys_stat64_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)];
+};
+struct svr4_sys_lstat64_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)];
+};
+struct svr4_sys_fstat64_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)];
+};
+struct svr4_sys_statvfs64_args {
+ char * path; char path_[PAD_(char *)];
+ struct svr4_statvfs64 * fs; char fs_[PAD_(struct svr4_statvfs64 *)];
+};
+struct svr4_sys_fstatvfs64_args {
+ int fd; char fd_[PAD_(int)];
+ struct svr4_statvfs64 * fs; char fs_[PAD_(struct svr4_statvfs64 *)];
+};
+struct svr4_sys_setrlimit64_args {
+ int which; char which_[PAD_(int)];
+ const struct svr4_rlimit64 * rlp; char rlp_[PAD_(const struct svr4_rlimit64 *)];
+};
+struct svr4_sys_getrlimit64_args {
+ int which; char which_[PAD_(int)];
+ struct svr4_rlimit64 * rlp; char rlp_[PAD_(struct svr4_rlimit64 *)];
+};
+struct svr4_sys_creat64_args {
+ char * path; char path_[PAD_(char *)];
+ int mode; char mode_[PAD_(int)];
+};
+struct svr4_sys_open64_args {
+ char * path; char path_[PAD_(char *)];
+ int flags; char flags_[PAD_(int)];
+ int mode; char mode_[PAD_(int)];
+};
+struct svr4_sys_socket_args {
+ int domain; char domain_[PAD_(int)];
+ int type; char type_[PAD_(int)];
+ int protocol; char protocol_[PAD_(int)];
+};
+struct svr4_sys_recv_args {
+ int s; char s_[PAD_(int)];
+ caddr_t buf; char buf_[PAD_(caddr_t)];
+ int len; char len_[PAD_(int)];
+ int flags; char flags_[PAD_(int)];
+};
+struct svr4_sys_send_args {
+ int s; char s_[PAD_(int)];
+ caddr_t buf; char buf_[PAD_(caddr_t)];
+ int len; char len_[PAD_(int)];
+ int flags; char flags_[PAD_(int)];
+};
+struct svr4_sys_sendto_args {
+ int s; char s_[PAD_(int)];
+ void * buf; char buf_[PAD_(void *)];
+ size_t len; char len_[PAD_(size_t)];
+ int flags; char flags_[PAD_(int)];
+ struct sockaddr * to; char to_[PAD_(struct sockaddr *)];
+ int tolen; char tolen_[PAD_(int)];
+};
+int svr4_sys_open(struct thread *, struct svr4_sys_open_args *);
+int svr4_sys_wait(struct thread *, struct svr4_sys_wait_args *);
+int svr4_sys_creat(struct thread *, struct svr4_sys_creat_args *);
+int svr4_sys_execv(struct thread *, struct svr4_sys_execv_args *);
+int svr4_sys_time(struct thread *, struct svr4_sys_time_args *);
+int svr4_sys_mknod(struct thread *, struct svr4_sys_mknod_args *);
+int svr4_sys_break(struct thread *, struct svr4_sys_break_args *);
+int svr4_sys_stat(struct thread *, struct svr4_sys_stat_args *);
+int svr4_sys_alarm(struct thread *, struct svr4_sys_alarm_args *);
+int svr4_sys_fstat(struct thread *, struct svr4_sys_fstat_args *);
+int svr4_sys_pause(struct thread *, struct svr4_sys_pause_args *);
+int svr4_sys_utime(struct thread *, struct svr4_sys_utime_args *);
+int svr4_sys_access(struct thread *, struct svr4_sys_access_args *);
+int svr4_sys_nice(struct thread *, struct svr4_sys_nice_args *);
+int svr4_sys_kill(struct thread *, struct svr4_sys_kill_args *);
+int svr4_sys_pgrpsys(struct thread *, struct svr4_sys_pgrpsys_args *);
+int svr4_sys_times(struct thread *, struct svr4_sys_times_args *);
+int svr4_sys_signal(struct thread *, struct svr4_sys_signal_args *);
+#if defined(NOTYET)
+int svr4_sys_msgsys(struct thread *, struct svr4_sys_msgsys_args *);
+#else
+#endif
+int svr4_sys_sysarch(struct thread *, struct svr4_sys_sysarch_args *);
+int svr4_sys_ioctl(struct thread *, struct svr4_sys_ioctl_args *);
+int svr4_sys_utssys(struct thread *, struct svr4_sys_utssys_args *);
+int svr4_sys_execve(struct thread *, struct svr4_sys_execve_args *);
+int svr4_sys_fcntl(struct thread *, struct svr4_sys_fcntl_args *);
+int svr4_sys_ulimit(struct thread *, struct svr4_sys_ulimit_args *);
+int svr4_sys_getdents(struct thread *, struct svr4_sys_getdents_args *);
+int svr4_sys_getmsg(struct thread *, struct svr4_sys_getmsg_args *);
+int svr4_sys_putmsg(struct thread *, struct svr4_sys_putmsg_args *);
+int svr4_sys_poll(struct thread *, struct svr4_sys_poll_args *);
+int svr4_sys_lstat(struct thread *, struct svr4_sys_lstat_args *);
+int svr4_sys_sigprocmask(struct thread *, struct svr4_sys_sigprocmask_args *);
+int svr4_sys_sigsuspend(struct thread *, struct svr4_sys_sigsuspend_args *);
+int svr4_sys_sigaltstack(struct thread *, struct svr4_sys_sigaltstack_args *);
+int svr4_sys_sigaction(struct thread *, struct svr4_sys_sigaction_args *);
+int svr4_sys_sigpending(struct thread *, struct svr4_sys_sigpending_args *);
+int svr4_sys_context(struct thread *, struct svr4_sys_context_args *);
+int svr4_sys_statvfs(struct thread *, struct svr4_sys_statvfs_args *);
+int svr4_sys_fstatvfs(struct thread *, struct svr4_sys_fstatvfs_args *);
+int svr4_sys_waitsys(struct thread *, struct svr4_sys_waitsys_args *);
+int svr4_sys_hrtsys(struct thread *, struct svr4_sys_hrtsys_args *);
+int svr4_sys_pathconf(struct thread *, struct svr4_sys_pathconf_args *);
+int svr4_sys_mmap(struct thread *, struct svr4_sys_mmap_args *);
+int svr4_sys_fpathconf(struct thread *, struct svr4_sys_fpathconf_args *);
+int svr4_sys_xstat(struct thread *, struct svr4_sys_xstat_args *);
+int svr4_sys_lxstat(struct thread *, struct svr4_sys_lxstat_args *);
+int svr4_sys_fxstat(struct thread *, struct svr4_sys_fxstat_args *);
+int svr4_sys_xmknod(struct thread *, struct svr4_sys_xmknod_args *);
+int svr4_sys_setrlimit(struct thread *, struct svr4_sys_setrlimit_args *);
+int svr4_sys_getrlimit(struct thread *, struct svr4_sys_getrlimit_args *);
+int svr4_sys_memcntl(struct thread *, struct svr4_sys_memcntl_args *);
+int svr4_sys_uname(struct thread *, struct svr4_sys_uname_args *);
+int svr4_sys_sysconfig(struct thread *, struct svr4_sys_sysconfig_args *);
+int svr4_sys_systeminfo(struct thread *, struct svr4_sys_systeminfo_args *);
+int svr4_sys_fchroot(struct thread *, struct svr4_sys_fchroot_args *);
+int svr4_sys_utimes(struct thread *, struct svr4_sys_utimes_args *);
+int svr4_sys_vhangup(struct thread *, struct svr4_sys_vhangup_args *);
+int svr4_sys_gettimeofday(struct thread *, struct svr4_sys_gettimeofday_args *);
+int svr4_sys_llseek(struct thread *, struct svr4_sys_llseek_args *);
+int svr4_sys_acl(struct thread *, struct svr4_sys_acl_args *);
+int svr4_sys_auditsys(struct thread *, struct svr4_sys_auditsys_args *);
+int svr4_sys_facl(struct thread *, struct svr4_sys_facl_args *);
+int svr4_sys_resolvepath(struct thread *, struct svr4_sys_resolvepath_args *);
+int svr4_sys_getdents64(struct thread *, struct svr4_sys_getdents64_args *);
+int svr4_sys_mmap64(struct thread *, struct svr4_sys_mmap64_args *);
+int svr4_sys_stat64(struct thread *, struct svr4_sys_stat64_args *);
+int svr4_sys_lstat64(struct thread *, struct svr4_sys_lstat64_args *);
+int svr4_sys_fstat64(struct thread *, struct svr4_sys_fstat64_args *);
+int svr4_sys_statvfs64(struct thread *, struct svr4_sys_statvfs64_args *);
+int svr4_sys_fstatvfs64(struct thread *, struct svr4_sys_fstatvfs64_args *);
+int svr4_sys_setrlimit64(struct thread *, struct svr4_sys_setrlimit64_args *);
+int svr4_sys_getrlimit64(struct thread *, struct svr4_sys_getrlimit64_args *);
+int svr4_sys_creat64(struct thread *, struct svr4_sys_creat64_args *);
+int svr4_sys_open64(struct thread *, struct svr4_sys_open64_args *);
+int svr4_sys_socket(struct thread *, struct svr4_sys_socket_args *);
+int svr4_sys_recv(struct thread *, struct svr4_sys_recv_args *);
+int svr4_sys_send(struct thread *, struct svr4_sys_send_args *);
+int svr4_sys_sendto(struct thread *, struct svr4_sys_sendto_args *);
+
+#ifdef COMPAT_43
+
+#if defined(NOTYET)
+#else
+#endif
+
+#endif /* COMPAT_43 */
+
+#undef PAD_
+
+#endif /* !_SVR4_SYSPROTO_H_ */
diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c
new file mode 100644
index 0000000..289e6fa
--- /dev/null
+++ b/sys/compat/svr4/svr4_resource.c
@@ -0,0 +1,324 @@
+/* Derived from:
+ * $NetBSD: svr4_resource.c,v 1.3 1998/12/13 18:00:52 christos Exp $
+ */
+
+/*-
+ * Original copyright:
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions of this software have been derived from software contributed
+ * to the FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_resource.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+
+static __inline int svr4_to_native_rl(int);
+
+static __inline int
+svr4_to_native_rl(rl)
+ int rl;
+{
+ switch (rl) {
+ case SVR4_RLIMIT_CPU:
+ return RLIMIT_CPU;
+ case SVR4_RLIMIT_FSIZE:
+ return RLIMIT_FSIZE;
+ case SVR4_RLIMIT_DATA:
+ return RLIMIT_DATA;
+ case SVR4_RLIMIT_STACK:
+ return RLIMIT_STACK;
+ case SVR4_RLIMIT_CORE:
+ return RLIMIT_CORE;
+ case SVR4_RLIMIT_NOFILE:
+ return RLIMIT_NOFILE;
+ case SVR4_RLIMIT_VMEM:
+ return RLIMIT_RSS;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Check if the resource limit fits within the BSD range and it is not
+ * one of the magic SVR4 limit values
+ */
+#define OKLIMIT(l) (((int32_t)(l)) >= 0 && ((int32_t)(l)) < 0x7fffffff && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_INFINITY && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_CUR && \
+ ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_MAX)
+
+#define OKLIMIT64(l) (((rlim_t)(l)) >= 0 && ((rlim_t)(l)) < RLIM_INFINITY && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_INFINITY && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_CUR && \
+ ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_MAX)
+
+int
+svr4_sys_getrlimit(td, uap)
+ register struct thread *td;
+ struct svr4_sys_getrlimit_args *uap;
+{
+ int rl = svr4_to_native_rl(SCARG(uap, which));
+ struct rlimit blim;
+ struct svr4_rlimit slim;
+
+ if (rl == -1)
+ return EINVAL;
+
+ /* For p_rlimit. */
+ mtx_assert(&Giant, MA_OWNED);
+ blim = td->td_proc->p_rlimit[rl];
+
+ /*
+ * Our infinity, is their maxfiles.
+ */
+ if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
+ blim.rlim_max = maxfiles;
+
+ /*
+ * If the limit can be be represented, it is returned.
+ * Otherwise, if rlim_cur == rlim_max, return RLIM_SAVED_MAX
+ * else return RLIM_SAVED_CUR
+ */
+ if (blim.rlim_max == RLIM_INFINITY)
+ slim.rlim_max = SVR4_RLIM_INFINITY;
+ else if (OKLIMIT(blim.rlim_max))
+ slim.rlim_max = (svr4_rlim_t) blim.rlim_max;
+ else
+ slim.rlim_max = SVR4_RLIM_SAVED_MAX;
+
+ if (blim.rlim_cur == RLIM_INFINITY)
+ slim.rlim_cur = SVR4_RLIM_INFINITY;
+ else if (OKLIMIT(blim.rlim_cur))
+ slim.rlim_cur = (svr4_rlim_t) blim.rlim_cur;
+ else if (blim.rlim_max == blim.rlim_cur)
+ slim.rlim_cur = SVR4_RLIM_SAVED_MAX;
+ else
+ slim.rlim_cur = SVR4_RLIM_SAVED_CUR;
+
+ return copyout(&slim, SCARG(uap, rlp), sizeof(*SCARG(uap, rlp)));
+}
+
+
+int
+svr4_sys_setrlimit(td, uap)
+ register struct thread *td;
+ struct svr4_sys_setrlimit_args *uap;
+{
+ int rl = svr4_to_native_rl(SCARG(uap, which));
+ struct rlimit blim, *limp;
+ struct svr4_rlimit slim;
+ int error;
+
+ if (rl == -1)
+ return EINVAL;
+
+ /* For p_rlimit. */
+ mtx_assert(&Giant, MA_OWNED);
+ limp = &td->td_proc->p_rlimit[rl];
+
+ if ((error = copyin(SCARG(uap, rlp), &slim, sizeof(slim))) != 0)
+ return error;
+
+ /*
+ * if the limit is SVR4_RLIM_INFINITY, then we set it to our
+ * unlimited.
+ * We should also: If it is SVR4_RLIM_SAVED_MAX, we should set the
+ * new limit to the corresponding saved hard limit, and if
+ * it is equal to SVR4_RLIM_SAVED_CUR, we should set it to the
+ * corresponding saved soft limit.
+ *
+ */
+ if (slim.rlim_max == SVR4_RLIM_INFINITY)
+ blim.rlim_max = RLIM_INFINITY;
+ else if (OKLIMIT(slim.rlim_max))
+ blim.rlim_max = (rlim_t) slim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM_SAVED_MAX)
+ blim.rlim_max = limp->rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM_SAVED_CUR)
+ blim.rlim_max = limp->rlim_cur;
+
+ if (slim.rlim_cur == SVR4_RLIM_INFINITY)
+ blim.rlim_cur = RLIM_INFINITY;
+ else if (OKLIMIT(slim.rlim_cur))
+ blim.rlim_cur = (rlim_t) slim.rlim_cur;
+ else if (slim.rlim_cur == SVR4_RLIM_SAVED_MAX)
+ blim.rlim_cur = limp->rlim_max;
+ else if (slim.rlim_cur == SVR4_RLIM_SAVED_CUR)
+ blim.rlim_cur = limp->rlim_cur;
+
+ return dosetrlimit(td, rl, &blim);
+}
+
+
+int
+svr4_sys_getrlimit64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_getrlimit64_args *uap;
+{
+ int rl = svr4_to_native_rl(SCARG(uap, which));
+ struct rlimit blim;
+ struct svr4_rlimit64 slim;
+
+ if (rl == -1)
+ return EINVAL;
+
+ /* For p_rlimit. */
+ mtx_assert(&Giant, MA_OWNED);
+ blim = td->td_proc->p_rlimit[rl];
+
+ /*
+ * Our infinity, is their maxfiles.
+ */
+ if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY)
+ blim.rlim_max = maxfiles;
+
+ /*
+ * If the limit can be be represented, it is returned.
+ * Otherwise, if rlim_cur == rlim_max, return SVR4_RLIM_SAVED_MAX
+ * else return SVR4_RLIM_SAVED_CUR
+ */
+ if (blim.rlim_max == RLIM_INFINITY)
+ slim.rlim_max = SVR4_RLIM64_INFINITY;
+ else if (OKLIMIT64(blim.rlim_max))
+ slim.rlim_max = (svr4_rlim64_t) blim.rlim_max;
+ else
+ slim.rlim_max = SVR4_RLIM64_SAVED_MAX;
+
+ if (blim.rlim_cur == RLIM_INFINITY)
+ slim.rlim_cur = SVR4_RLIM64_INFINITY;
+ else if (OKLIMIT64(blim.rlim_cur))
+ slim.rlim_cur = (svr4_rlim64_t) blim.rlim_cur;
+ else if (blim.rlim_max == blim.rlim_cur)
+ slim.rlim_cur = SVR4_RLIM64_SAVED_MAX;
+ else
+ slim.rlim_cur = SVR4_RLIM64_SAVED_CUR;
+
+ return copyout(&slim, SCARG(uap, rlp), sizeof(*SCARG(uap, rlp)));
+}
+
+
+int
+svr4_sys_setrlimit64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_setrlimit64_args *uap;
+{
+ int rl = svr4_to_native_rl(SCARG(uap, which));
+ struct rlimit blim, *limp;
+ struct svr4_rlimit64 slim;
+ int error;
+
+ if (rl == -1)
+ return EINVAL;
+
+ /* For p_rlimit. */
+ mtx_assert(&Giant, MA_OWNED);
+ limp = &td->td_proc->p_rlimit[rl];
+
+ if ((error = copyin(SCARG(uap, rlp), &slim, sizeof(slim))) != 0)
+ return error;
+
+ /*
+ * if the limit is SVR4_RLIM64_INFINITY, then we set it to our
+ * unlimited.
+ * We should also: If it is SVR4_RLIM64_SAVED_MAX, we should set the
+ * new limit to the corresponding saved hard limit, and if
+ * it is equal to SVR4_RLIM64_SAVED_CUR, we should set it to the
+ * corresponding saved soft limit.
+ *
+ */
+ if (slim.rlim_max == SVR4_RLIM64_INFINITY)
+ blim.rlim_max = RLIM_INFINITY;
+ else if (OKLIMIT64(slim.rlim_max))
+ blim.rlim_max = (rlim_t) slim.rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM64_SAVED_MAX)
+ blim.rlim_max = limp->rlim_max;
+ else if (slim.rlim_max == SVR4_RLIM64_SAVED_CUR)
+ blim.rlim_max = limp->rlim_cur;
+
+ if (slim.rlim_cur == SVR4_RLIM64_INFINITY)
+ blim.rlim_cur = RLIM_INFINITY;
+ else if (OKLIMIT64(slim.rlim_cur))
+ blim.rlim_cur = (rlim_t) slim.rlim_cur;
+ else if (slim.rlim_cur == SVR4_RLIM64_SAVED_MAX)
+ blim.rlim_cur = limp->rlim_max;
+ else if (slim.rlim_cur == SVR4_RLIM64_SAVED_CUR)
+ blim.rlim_cur = limp->rlim_cur;
+
+ return dosetrlimit(td, rl, &blim);
+}
diff --git a/sys/compat/svr4/svr4_resource.h b/sys/compat/svr4/svr4_resource.h
new file mode 100644
index 0000000..3512df3
--- /dev/null
+++ b/sys/compat/svr4/svr4_resource.h
@@ -0,0 +1,109 @@
+/* Derived from:
+ * $NetBSD: svr4_resource.h,v 1.1 1998/11/28 21:53:02 christos Exp $ */
+
+/*-
+ * Original copyright:
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Portions of this code derived from software contributed to the
+ * FreeBSD Project by Mark Newton.
+ *
+ * Copyright (c) 1999 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SVR4_RESOURCE_H_
+#define _SVR4_RESOURCE_H_
+
+#define SVR4_RLIMIT_CPU 0
+#define SVR4_RLIMIT_FSIZE 1
+#define SVR4_RLIMIT_DATA 2
+#define SVR4_RLIMIT_STACK 3
+#define SVR4_RLIMIT_CORE 4
+#define SVR4_RLIMIT_NOFILE 5
+#define SVR4_RLIMIT_VMEM 6
+#define SVR4_RLIMIT_AS SVR4_RLIMIT_VMEM
+#define SVR4_RLIM_NLIMITS 7
+
+typedef u_int32_t svr4_rlim_t;
+
+#define SVR4_RLIM_SAVED_CUR 0x7ffffffd
+#define SVR4_RLIM_SAVED_MAX 0x7ffffffe
+#define SVR4_RLIM_INFINITY 0x7fffffff
+
+struct svr4_rlimit {
+ svr4_rlim_t rlim_cur;
+ svr4_rlim_t rlim_max;
+};
+
+typedef u_int64_t svr4_rlim64_t;
+
+#define SVR4_RLIM64_SAVED_CUR ((svr4_rlim64_t) -1)
+#define SVR4_RLIM64_SAVED_MAX ((svr4_rlim64_t) -2)
+#define SVR4_RLIM64_INFINITY ((svr4_rlim64_t) -3)
+
+struct svr4_rlimit64 {
+ svr4_rlim64_t rlim_cur;
+ svr4_rlim64_t rlim_max;
+};
+
+#endif /* !_SVR4_RESOURCE_H_ */
diff --git a/sys/compat/svr4/svr4_siginfo.h b/sys/compat/svr4/svr4_siginfo.h
new file mode 100644
index 0000000..be89837
--- /dev/null
+++ b/sys/compat/svr4/svr4_siginfo.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SIGINFO_H_
+#define _SVR4_SIGINFO_H_
+
+#define SVR4_ILL_ILLOPC 1
+#define SVR4_ILL_ILLOPN 2
+#define SVR4_ILL_ILLADR 3
+#define SVR4_ILL_ILLTRP 4
+#define SVR4_ILL_PRVOPC 5
+#define SVR4_ILL_PRVREG 6
+#define SVR4_ILL_COPROC 7
+#define SVR4_ILL_BADSTK 8
+
+#define SVR4_FPE_INTDIV 1
+#define SVR4_FPE_INTOVF 2
+#define SVR4_FPE_FLTDIV 3
+#define SVR4_FPE_FLTOVF 4
+#define SVR4_FPE_FLTUND 5
+#define SVR4_FPE_FLTRES 6
+#define SVR4_FPE_FLTINV 7
+#define SVR4_FPE_FLTSUB 8
+
+#define SVR4_SEGV_MAPERR 1
+#define SVR4_SEGV_ACCERR 2
+
+#define SVR4_BUS_ADRALN 1
+#define SVR4_BUS_ADRERR 2
+#define SVR4_BUS_OBJERR 3
+
+#define SVR4_TRAP_BRKPT 1
+#define SVR4_TRAP_TRACE 2
+
+#define SVR4_POLL_IN 1
+#define SVR4_POLL_OUT 2
+#define SVR4_POLL_MSG 3
+#define SVR4_POLL_ERR 4
+#define SVR4_POLL_PRI 5
+
+#define SVR4_CLD_EXITED 1
+#define SVR4_CLD_KILLED 2
+#define SVR4_CLD_DUMPED 3
+#define SVR4_CLD_TRAPPED 4
+#define SVR4_CLD_STOPPED 5
+#define SVR4_CLD_CONTINUED 6
+
+#define SVR4_EMT_TAGOVF 1
+
+typedef union svr4_siginfo {
+ char si_pad[128]; /* Total size; for future expansion */
+ struct {
+ int _signo;
+ int _code;
+ int _errno;
+ union {
+ struct {
+ svr4_pid_t _pid;
+ svr4_clock_t _utime;
+ int _status;
+ svr4_clock_t _stime;
+ } _child;
+
+ struct {
+ caddr_t _addr;
+ int _trap;
+ } _fault;
+ } _reason;
+ } _info;
+} svr4_siginfo_t;
+
+#define si_signo _info._signo
+#define si_code _info._code
+#define si_errno _info._errno
+
+#define si_pid _info._reason._child._pid
+#define si_stime _info._reason._child._stime
+#define si_status _info._reason._child._status
+#define si_utime _info._reason._child._utime
+
+#define si_addr _info._reason._fault._addr
+#define si_trap _info._reason._fault._trap
+
+#endif /* !_SVR4_SIGINFO_H_ */
diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c
new file mode 100644
index 0000000..fea5317
--- /dev/null
+++ b/sys/compat/svr4/svr4_signal.c
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/sysproto.h>
+
+#include <machine/cpu.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ucontext.h>
+
+#define svr4_sigmask(n) (1 << (((n) - 1) & 31))
+#define svr4_sigword(n) (((n) - 1) >> 5)
+#define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s)))
+#define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n))
+#define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n))
+
+void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *);
+void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *);
+void svr4_sigfillset(svr4_sigset_t *);
+
+int bsd_to_svr4_sig[SVR4_SIGTBLSZ] = {
+ SVR4_SIGHUP,
+ SVR4_SIGINT,
+ SVR4_SIGQUIT,
+ SVR4_SIGILL,
+ SVR4_SIGTRAP,
+ SVR4_SIGABRT,
+ SVR4_SIGEMT,
+ SVR4_SIGFPE,
+ SVR4_SIGKILL,
+ SVR4_SIGBUS,
+ SVR4_SIGSEGV,
+ SVR4_SIGSYS,
+ SVR4_SIGPIPE,
+ SVR4_SIGALRM,
+ SVR4_SIGTERM,
+ SVR4_SIGURG,
+ SVR4_SIGSTOP,
+ SVR4_SIGTSTP,
+ SVR4_SIGCONT,
+ SVR4_SIGCHLD,
+ SVR4_SIGTTIN,
+ SVR4_SIGTTOU,
+ SVR4_SIGIO,
+ SVR4_SIGXCPU,
+ SVR4_SIGXFSZ,
+ SVR4_SIGVTALRM,
+ SVR4_SIGPROF,
+ SVR4_SIGWINCH,
+ 0, /* SIGINFO */
+ SVR4_SIGUSR1,
+ SVR4_SIGUSR2,
+};
+
+int svr4_to_bsd_sig[SVR4_SIGTBLSZ] = {
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGEMT,
+ SIGFPE,
+ SIGKILL,
+ SIGBUS,
+ SIGSEGV,
+ SIGSYS,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ SIGUSR1,
+ SIGUSR2,
+ SIGCHLD,
+ 0, /* XXX NetBSD uses SIGPWR here, but we don't seem to have one */
+ SIGWINCH,
+ SIGURG,
+ SIGIO,
+ SIGSTOP,
+ SIGTSTP,
+ SIGCONT,
+ SIGTTIN,
+ SIGTTOU,
+ SIGVTALRM,
+ SIGPROF,
+ SIGXCPU,
+ SIGXFSZ,
+};
+
+void
+svr4_sigfillset(s)
+ svr4_sigset_t *s;
+{
+ int i;
+
+ svr4_sigemptyset(s);
+ for (i = 0; i < SVR4_NSIG; i++)
+ if (svr4_to_bsd_sig[i] != 0)
+ svr4_sigaddset(s, i);
+}
+
+void
+svr4_to_bsd_sigset(sss, bss)
+ const svr4_sigset_t *sss;
+ sigset_t *bss;
+{
+ int i, newsig;
+
+ SIGEMPTYSET(*bss);
+ for (i = 0; i < SVR4_NSIG; i++)
+ if (svr4_sigismember(sss, i + 1)) {
+ newsig = svr4_to_bsd_sig[i];
+ if (newsig)
+ SIGADDSET(*bss, newsig);
+ }
+}
+
+void
+bsd_to_svr4_sigset(bss, sss)
+ const sigset_t *bss;
+ svr4_sigset_t *sss;
+{
+ int i, newsig;
+
+ svr4_sigemptyset(sss);
+ sss->bits[0] = bss->__bits[0] & ~((1U << SVR4_SIGTBLSZ) - 1);
+ sss->bits[1] = bss->__bits[1];
+ sss->bits[2] = bss->__bits[2];
+ sss->bits[3] = bss->__bits[3];
+ for (i = 1; i <= SVR4_SIGTBLSZ; i++) {
+ if (SIGISMEMBER(*bss, i)) {
+ newsig = bsd_to_svr4_sig[_SIG_IDX(i)];
+ if (newsig)
+ svr4_sigaddset(sss, newsig);
+ }
+ }
+}
+
+/*
+ * XXX: Only a subset of the flags is currently implemented.
+ */
+void
+svr4_to_bsd_sigaction(ssa, bsa)
+ const struct svr4_sigaction *ssa;
+ struct sigaction *bsa;
+{
+
+ bsa->sa_handler = (sig_t) ssa->ssa_handler;
+ svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask);
+ bsa->sa_flags = 0;
+ if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0)
+ bsa->sa_flags |= SA_ONSTACK;
+ if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0)
+ bsa->sa_flags |= SA_RESETHAND;
+ if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0)
+ bsa->sa_flags |= SA_RESTART;
+ if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0)
+ DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n"));
+ if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0)
+ bsa->sa_flags |= SA_NODEFER;
+ if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0)
+ bsa->sa_flags |= SA_NOCLDWAIT;
+ if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0)
+ DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n"));
+}
+
+void
+bsd_to_svr4_sigaction(bsa, ssa)
+ const struct sigaction *bsa;
+ struct svr4_sigaction *ssa;
+{
+
+ ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler;
+ bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask);
+ ssa->ssa_flags = 0;
+ if ((bsa->sa_flags & SA_ONSTACK) != 0)
+ ssa->ssa_flags |= SVR4_SA_ONSTACK;
+ if ((bsa->sa_flags & SA_RESETHAND) != 0)
+ ssa->ssa_flags |= SVR4_SA_RESETHAND;
+ if ((bsa->sa_flags & SA_RESTART) != 0)
+ ssa->ssa_flags |= SVR4_SA_RESTART;
+ if ((bsa->sa_flags & SA_NODEFER) != 0)
+ ssa->ssa_flags |= SVR4_SA_NODEFER;
+ if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
+ ssa->ssa_flags |= SVR4_SA_NOCLDSTOP;
+}
+
+void
+svr4_to_bsd_sigaltstack(sss, bss)
+ const struct svr4_sigaltstack *sss;
+ struct sigaltstack *bss;
+{
+
+ bss->ss_sp = sss->ss_sp;
+ bss->ss_size = sss->ss_size;
+ bss->ss_flags = 0;
+ if ((sss->ss_flags & SVR4_SS_DISABLE) != 0)
+ bss->ss_flags |= SS_DISABLE;
+ if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0)
+ bss->ss_flags |= SS_ONSTACK;
+ if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0)
+ /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n");
+}
+
+void
+bsd_to_svr4_sigaltstack(bss, sss)
+ const struct sigaltstack *bss;
+ struct svr4_sigaltstack *sss;
+{
+
+ sss->ss_sp = bss->ss_sp;
+ sss->ss_size = bss->ss_size;
+ sss->ss_flags = 0;
+ if ((bss->ss_flags & SS_DISABLE) != 0)
+ sss->ss_flags |= SVR4_SS_DISABLE;
+ if ((bss->ss_flags & SS_ONSTACK) != 0)
+ sss->ss_flags |= SVR4_SS_ONSTACK;
+}
+
+int
+svr4_sys_sigaction(td, uap)
+ register struct thread *td;
+ struct svr4_sys_sigaction_args *uap;
+{
+ struct svr4_sigaction *nisa, *oisa, tmpisa;
+ struct sigaction *nbsa, *obsa, tmpbsa;
+ struct sigaction_args sa;
+ caddr_t sg;
+ int error;
+
+ DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid,
+ SCARG(uap, signum),
+ SVR4_SVR42BSD_SIG(SCARG(uap, signum))));
+
+ sg = stackgap_init();
+ nisa = SCARG(uap, nsa);
+ oisa = SCARG(uap, osa);
+
+ if (oisa != NULL)
+ obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ else
+ obsa = NULL;
+
+ if (nisa != NULL) {
+ nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0)
+ return error;
+ svr4_to_bsd_sigaction(&tmpisa, &tmpbsa);
+ if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
+ return error;
+ } else
+ nbsa = NULL;
+
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("\tssa_mask[%d] = %lx\n", i,
+ nisa->ssa_mask.bits[i]));
+ DPRINTF(("\tssa_handler = %p\n", nisa->ssa_handler));
+ }
+#endif
+
+ SCARG(&sa, sig) = SVR4_SVR42BSD_SIG(SCARG(uap, signum));
+ SCARG(&sa, act) = nbsa;
+ SCARG(&sa, oact) = obsa;
+
+ if ((error = sigaction(td, &sa)) != 0)
+ return error;
+
+ if (oisa != NULL) {
+ if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
+ return error;
+ bsd_to_svr4_sigaction(&tmpbsa, &tmpisa);
+ if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0)
+ return error;
+ }
+
+ return 0;
+}
+
+int
+svr4_sys_sigaltstack(td, uap)
+ register struct thread *td;
+ struct svr4_sys_sigaltstack_args *uap;
+{
+ struct svr4_sigaltstack *nsss, *osss, tmpsss;
+ struct sigaltstack *nbss, *obss, tmpbss;
+ struct sigaltstack_args sa;
+ caddr_t sg;
+ int error, *retval;
+
+ retval = td->td_retval;
+ sg = stackgap_init();
+ nsss = SCARG(uap, nss);
+ osss = SCARG(uap, oss);
+
+ if (osss != NULL)
+ obss = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ else
+ obss = NULL;
+
+ if (nsss != NULL) {
+ nbss = stackgap_alloc(&sg, sizeof(struct sigaltstack));
+ if ((error = copyin(nsss, &tmpsss, sizeof(tmpsss))) != 0)
+ return error;
+ svr4_to_bsd_sigaltstack(&tmpsss, &tmpbss);
+ if ((error = copyout(&tmpbss, nbss, sizeof(tmpbss))) != 0)
+ return error;
+ } else
+ nbss = NULL;
+
+ SCARG(&sa, ss) = nbss;
+ SCARG(&sa, oss) = obss;
+
+ if ((error = sigaltstack(td, &sa)) != 0)
+ return error;
+
+ if (obss != NULL) {
+ if ((error = copyin(obss, &tmpbss, sizeof(tmpbss))) != 0)
+ return error;
+ bsd_to_svr4_sigaltstack(&tmpbss, &tmpsss);
+ if ((error = copyout(&tmpsss, osss, sizeof(tmpsss))) != 0)
+ return error;
+ }
+
+ return 0;
+}
+
+/*
+ * Stolen from the ibcs2 one
+ */
+int
+svr4_sys_signal(td, uap)
+ register struct thread *td;
+ struct svr4_sys_signal_args *uap;
+{
+ int signum;
+ int error, *retval = td->td_retval;
+ caddr_t sg = stackgap_init();
+
+ DPRINTF(("@@@ svr4_sys_signal(%d)\n", td->td_proc->p_pid));
+
+ signum = SVR4_SVR42BSD_SIG(SVR4_SIGNO(SCARG(uap, signum)));
+ if (signum <= 0 || signum > SVR4_NSIG)
+ return (EINVAL);
+
+ switch (SVR4_SIGCALL(SCARG(uap, signum))) {
+ case SVR4_SIGDEFER_MASK:
+ if (SCARG(uap, handler) == SVR4_SIG_HOLD)
+ goto sighold;
+ /* FALLTHROUGH */
+
+ case SVR4_SIGNAL_MASK:
+ {
+ struct sigaction_args sa_args;
+ struct sigaction *nbsa, *obsa, sa;
+
+ nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(&sa_args, sig) = signum;
+ SCARG(&sa_args, act) = nbsa;
+ SCARG(&sa_args, oact) = obsa;
+
+ sa.sa_handler = (sig_t) SCARG(uap, handler);
+ SIGEMPTYSET(sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (signum != SIGALRM)
+ sa.sa_flags = SA_RESTART;
+
+ if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
+ return error;
+ if ((error = sigaction(td, &sa_args)) != 0) {
+ DPRINTF(("signal: sigaction failed: %d\n",
+ error));
+ *retval = (int)SVR4_SIG_ERR;
+ return error;
+ }
+ if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
+ return error;
+ *retval = (int)sa.sa_handler;
+ return 0;
+ }
+
+ case SVR4_SIGHOLD_MASK:
+sighold:
+ {
+ struct sigprocmask_args sa;
+ sigset_t *set;
+
+ set = stackgap_alloc(&sg, sizeof(sigset_t));
+ SIGEMPTYSET(*set);
+ SIGADDSET(*set, signum);
+ SCARG(&sa, how) = SIG_BLOCK;
+ SCARG(&sa, set) = set;
+ SCARG(&sa, oset) = NULL;
+ return sigprocmask(td, &sa);
+ }
+
+ case SVR4_SIGRELSE_MASK:
+ {
+ struct sigprocmask_args sa;
+ sigset_t *set;
+
+ set = stackgap_alloc(&sg, sizeof(sigset_t));
+ SIGEMPTYSET(*set);
+ SIGADDSET(*set, signum);
+ SCARG(&sa, how) = SIG_UNBLOCK;
+ SCARG(&sa, set) = set;
+ SCARG(&sa, oset) = NULL;
+ return sigprocmask(td, &sa);
+ }
+
+ case SVR4_SIGIGNORE_MASK:
+ {
+ struct sigaction_args sa_args;
+ struct sigaction *bsa, sa;
+
+ bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ SCARG(&sa_args, sig) = signum;
+ SCARG(&sa_args, act) = bsa;
+ SCARG(&sa_args, oact) = NULL;
+
+ sa.sa_handler = SIG_IGN;
+ SIGEMPTYSET(sa.sa_mask);
+ sa.sa_flags = 0;
+ if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
+ return error;
+ if ((error = sigaction(td, &sa_args)) != 0) {
+ DPRINTF(("sigignore: sigaction failed\n"));
+ return error;
+ }
+ return 0;
+ }
+
+ case SVR4_SIGPAUSE_MASK:
+ {
+ struct sigsuspend_args sa;
+ sigset_t *set;
+
+ set = stackgap_alloc(&sg, sizeof(sigset_t));
+ PROC_LOCK(td->td_proc);
+ *set = td->td_proc->p_sigmask;
+ PROC_UNLOCK(td->td_proc);
+ SIGDELSET(*set, signum);
+ SCARG(&sa, sigmask) = set;
+ return sigsuspend(td, &sa);
+ }
+
+ default:
+ return (ENOSYS);
+ }
+}
+
+
+int
+svr4_sys_sigprocmask(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigprocmask_args *uap;
+{
+ svr4_sigset_t sss;
+ sigset_t bss;
+ int error = 0, *retval;
+
+ retval = td->td_retval;
+ if (SCARG(uap, oset) != NULL) {
+ /* Fix the return value first if needed */
+ PROC_LOCK(td->td_proc);
+ bsd_to_svr4_sigset(&td->td_proc->p_sigmask, &sss);
+ PROC_UNLOCK(td->td_proc);
+ if ((error = copyout(&sss, SCARG(uap, oset), sizeof(sss))) != 0)
+ return error;
+ }
+
+ if (SCARG(uap, set) == NULL)
+ /* Just examine */
+ return 0;
+
+ if ((error = copyin(SCARG(uap, set), &sss, sizeof(sss))) != 0)
+ return error;
+
+ svr4_to_bsd_sigset(&sss, &bss);
+
+ PROC_LOCK(td->td_proc);
+ switch (SCARG(uap, how)) {
+ case SVR4_SIG_BLOCK:
+ SIGSETOR(td->td_proc->p_sigmask, bss);
+ SIG_CANTMASK(td->td_proc->p_sigmask);
+ break;
+
+ case SVR4_SIG_UNBLOCK:
+ SIGSETNAND(td->td_proc->p_sigmask, bss);
+ signotify(td->td_proc);
+ break;
+
+ case SVR4_SIG_SETMASK:
+ td->td_proc->p_sigmask = bss;
+ SIG_CANTMASK(td->td_proc->p_sigmask);
+ signotify(td->td_proc);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ PROC_UNLOCK(td->td_proc);
+
+ return error;
+}
+
+int
+svr4_sys_sigpending(td, uap)
+ struct thread *td;
+ struct svr4_sys_sigpending_args *uap;
+{
+ sigset_t bss;
+ int *retval;
+ svr4_sigset_t sss;
+
+ DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", td->td_proc->p_pid));
+ retval = td->td_retval;
+ switch (SCARG(uap, what)) {
+ case 1: /* sigpending */
+ if (SCARG(uap, mask) == NULL)
+ return 0;
+ PROC_LOCK(td->td_proc);
+ bss = td->td_proc->p_siglist;
+ SIGSETAND(bss, td->td_proc->p_sigmask);
+ PROC_UNLOCK(td->td_proc);
+ bsd_to_svr4_sigset(&bss, &sss);
+ break;
+
+ case 2: /* sigfillset */
+ svr4_sigfillset(&sss);
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i]));
+ }
+#endif
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ return copyout(&sss, SCARG(uap, mask), sizeof(sss));
+}
+
+int
+svr4_sys_sigsuspend(td, uap)
+ register struct thread *td;
+ struct svr4_sys_sigsuspend_args *uap;
+{
+ svr4_sigset_t sss;
+ sigset_t *bss;
+ struct sigsuspend_args sa;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ if ((error = copyin(SCARG(uap, ss), &sss, sizeof(sss))) != 0)
+ return error;
+
+ bss = stackgap_alloc(&sg, sizeof(sigset_t));
+ svr4_to_bsd_sigset(&sss, bss);
+
+ SCARG(&sa, sigmask) = bss;
+ return sigsuspend(td, &sa);
+}
+
+
+int
+svr4_sys_kill(td, uap)
+ register struct thread *td;
+ struct svr4_sys_kill_args *uap;
+{
+ struct kill_args ka;
+
+ SCARG(&ka, pid) = SCARG(uap, pid);
+ SCARG(&ka, signum) = SVR4_SVR42BSD_SIG(SCARG(uap, signum));
+ return kill(td, &ka);
+}
+
+
+int
+svr4_sys_context(td, uap)
+ register struct thread *td;
+ struct svr4_sys_context_args *uap;
+{
+ struct svr4_ucontext uc;
+ int error;
+
+ switch (uap->func) {
+ case 0:
+ PROC_LOCK(td->td_proc);
+ DPRINTF(("getcontext(%p)\n", uap->uc));
+ svr4_getcontext(td, &uc, &td->td_proc->p_sigmask,
+ sigonstack(cpu_getstack(td)));
+ PROC_UNLOCK(td->td_proc);
+ return copyout(&uc, uap->uc, sizeof(uc));
+
+ case 1:
+ DPRINTF(("setcontext(%p)\n", uap->uc));
+ if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0)
+ return error;
+ DPRINTF(("uc_flags = %lx\n", uc.uc_flags));
+#if defined(DEBUG_SVR4)
+ {
+ int i;
+ for (i = 0; i < 4; i++)
+ DPRINTF(("uc_sigmask[%d] = %lx\n", i,
+ uc.uc_sigmask.bits[i]));
+ }
+#endif
+ return svr4_setcontext(td, &uc);
+
+ default:
+ DPRINTF(("context(%d, %p)\n", uap->func,
+ uap->uc));
+ return ENOSYS;
+ }
+ return 0;
+}
+
+int
+svr4_sys_pause(td, uap)
+ register struct thread *td;
+ struct svr4_sys_pause_args *uap;
+{
+ struct sigsuspend_args bsa;
+
+ SCARG(&bsa, sigmask) = &td->td_proc->p_sigmask;
+ return sigsuspend(td, &bsa);
+}
diff --git a/sys/compat/svr4/svr4_signal.h b/sys/compat/svr4/svr4_signal.h
new file mode 100644
index 0000000..5a01a8f
--- /dev/null
+++ b/sys/compat/svr4/svr4_signal.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SIGNAL_H_
+#define _SVR4_SIGNAL_H_
+
+#include <i386/svr4/svr4_machdep.h>
+#include <compat/svr4/svr4_siginfo.h>
+
+#define SVR4_SIGHUP 1
+#define SVR4_SIGINT 2
+#define SVR4_SIGQUIT 3
+#define SVR4_SIGILL 4
+#define SVR4_SIGTRAP 5
+#define SVR4_SIGIOT 6
+#define SVR4_SIGABRT 6
+#define SVR4_SIGEMT 7
+#define SVR4_SIGFPE 8
+#define SVR4_SIGKILL 9
+#define SVR4_SIGBUS 10
+#define SVR4_SIGSEGV 11
+#define SVR4_SIGSYS 12
+#define SVR4_SIGPIPE 13
+#define SVR4_SIGALRM 14
+#define SVR4_SIGTERM 15
+#define SVR4_SIGUSR1 16
+#define SVR4_SIGUSR2 17
+#define SVR4_SIGCLD 18
+#define SVR4_SIGCHLD 18
+#define SVR4_SIGPWR 19
+#define SVR4_SIGWINCH 20
+#define SVR4_SIGURG 21
+#define SVR4_SIGPOLL 22
+#define SVR4_SIGIO 22
+#define SVR4_SIGSTOP 23
+#define SVR4_SIGTSTP 24
+#define SVR4_SIGCONT 25
+#define SVR4_SIGTTIN 26
+#define SVR4_SIGTTOU 27
+#define SVR4_SIGVTALRM 28
+#define SVR4_SIGPROF 29
+#define SVR4_SIGXCPU 30
+#define SVR4_SIGXFSZ 31
+#define SVR4_NSIG 32
+#define SVR4_SIGTBLSZ 31
+
+#define SVR4_SIGNO_MASK 0x00FF
+#define SVR4_SIGNAL_MASK 0x0000
+#define SVR4_SIGDEFER_MASK 0x0100
+#define SVR4_SIGHOLD_MASK 0x0200
+#define SVR4_SIGRELSE_MASK 0x0400
+#define SVR4_SIGIGNORE_MASK 0x0800
+#define SVR4_SIGPAUSE_MASK 0x1000
+
+typedef void (*svr4_sig_t)(int, svr4_siginfo_t *, void *);
+#define SVR4_SIG_DFL (svr4_sig_t) 0
+#define SVR4_SIG_ERR (svr4_sig_t) -1
+#define SVR4_SIG_IGN (svr4_sig_t) 1
+#define SVR4_SIG_HOLD (svr4_sig_t) 2
+
+#define SVR4_SIGNO(a) ((a) & SVR4_SIGNO_MASK)
+#define SVR4_SIGCALL(a) ((a) & ~SVR4_SIGNO_MASK)
+
+#define SVR4_SIG_BLOCK 1
+#define SVR4_SIG_UNBLOCK 2
+#define SVR4_SIG_SETMASK 3
+
+extern int bsd_to_svr4_sig[];
+extern int svr4_to_bsd_sig[];
+
+#define SVR4_BSD2SVR4_SIG(sig) \
+ (((sig) <= SVR4_SIGTBLSZ) ? bsd_to_svr4_sig[_SIG_IDX(sig)] : sig)
+#define SVR4_SVR42BSD_SIG(sig) \
+ (((sig) <= SVR4_SIGTBLSZ) ? svr4_to_bsd_sig[_SIG_IDX(sig)] : sig)
+
+typedef struct {
+ u_long bits[4];
+} svr4_sigset_t;
+
+struct svr4_sigaction {
+ int ssa_flags;
+ svr4_sig_t ssa_handler;
+ svr4_sigset_t ssa_mask;
+ int ssa_reserved[2];
+};
+
+struct svr4_sigaltstack {
+ char *ss_sp;
+ int ss_size;
+ int ss_flags;
+};
+
+/* sa_flags */
+#define SVR4_SA_ONSTACK 0x00000001
+#define SVR4_SA_RESETHAND 0x00000002
+#define SVR4_SA_RESTART 0x00000004
+#define SVR4_SA_SIGINFO 0x00000008
+#define SVR4_SA_NODEFER 0x00000010
+#define SVR4_SA_NOCLDWAIT 0x00010000 /* No zombies */
+#define SVR4_SA_NOCLDSTOP 0x00020000 /* No jcl */
+#define SVR4_SA_ALLBITS 0x0003001f
+
+/* ss_flags */
+#define SVR4_SS_ONSTACK 0x00000001
+#define SVR4_SS_DISABLE 0x00000002
+#define SVR4_SS_ALLBITS 0x00000003
+
+#define SVR4_MINSIGSTKSZ 8192
+
+void bsd_to_svr4_sigaltstack(const struct sigaltstack *, struct svr4_sigaltstack *);
+void bsd_to_svr4_sigset(const sigset_t *, svr4_sigset_t *);
+void svr4_to_bsd_sigaltstack(const struct svr4_sigaltstack *, struct sigaltstack *);
+void svr4_to_bsd_sigset(const svr4_sigset_t *, sigset_t *);
+void svr4_sendsig(sig_t, int, sigset_t *, u_long);
+
+#endif /* !_SVR4_SIGNAL_H_ */
diff --git a/sys/compat/svr4/svr4_socket.c b/sys/compat/svr4/svr4_socket.c
new file mode 100644
index 0000000..b4f2b55
--- /dev/null
+++ b/sys/compat/svr4/svr4_socket.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * In SVR4 unix domain sockets are referenced sometimes
+ * (in putmsg(2) for example) as a [device, inode] pair instead of a pathname.
+ * Since there is no iname() routine in the kernel, and we need access to
+ * a mapping from inode to pathname, we keep our own table. This is a simple
+ * linked list that contains the pathname, the [device, inode] pair, the
+ * file corresponding to that socket and the process. When the
+ * socket gets closed we remove the item from the list. The list gets loaded
+ * every time a stat(2) call finds a socket.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysproto.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_sockmod.h>
+#include <compat/svr4/svr4_proto.h>
+
+struct svr4_sockcache_entry {
+ struct proc *p; /* Process for the socket */
+ void *cookie; /* Internal cookie used for matching */
+ struct sockaddr_un sock;/* Pathname for the socket */
+ udev_t dev; /* Device where the socket lives on */
+ ino_t ino; /* Inode where the socket lives on */
+ TAILQ_ENTRY(svr4_sockcache_entry) entries;
+};
+
+extern TAILQ_HEAD(svr4_sockcache_head, svr4_sockcache_entry) svr4_head;
+extern int svr4_str_initialized;
+
+struct sockaddr_un *
+svr4_find_socket(td, fp, dev, ino)
+ struct thread *td;
+ struct file *fp;
+ udev_t dev;
+ ino_t ino;
+{
+ struct svr4_sockcache_entry *e;
+ void *cookie = ((struct socket *) fp->f_data)->so_emuldata;
+
+ if (svr4_str_initialized != 2) {
+ if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) {
+ DPRINTF(("svr4_find_socket: uninitialized [%p,%d,%d]\n",
+ td, dev, ino));
+ TAILQ_INIT(&svr4_head);
+ atomic_store_rel_int(&svr4_str_initialized, 2);
+ }
+ return NULL;
+ }
+
+
+ DPRINTF(("svr4_find_socket: [%p,%d,%d]: ", td, dev, ino));
+ TAILQ_FOREACH(e, &svr4_head, entries)
+ if (e->p == td->td_proc && e->dev == dev && e->ino == ino) {
+#ifdef DIAGNOSTIC
+ if (e->cookie != NULL && e->cookie != cookie)
+ panic("svr4 socket cookie mismatch");
+#endif
+ e->cookie = cookie;
+ DPRINTF(("%s\n", e->sock.sun_path));
+ return &e->sock;
+ }
+
+ DPRINTF(("not found\n"));
+ return NULL;
+}
+
+
+/*
+ * svr4_delete_socket() is in sys/dev/streams.c (because it's called by
+ * the streams "soo_close()" routine).
+ */
+int
+svr4_add_socket(td, path, st)
+ struct thread *td;
+ const char *path;
+ struct stat *st;
+{
+ struct svr4_sockcache_entry *e;
+ int len, error;
+
+ /*
+ * Wait for the TAILQ to be initialized. Only the very first CPU
+ * will succeed on the atomic_cmpset(). The other CPU's will spin
+ * until the first one finishes the initialization. Once the
+ * initialization is complete, the condition will always fail
+ * avoiding expensive atomic operations in the common case.
+ */
+ while (svr4_str_initialized != 2)
+ if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) {
+ TAILQ_INIT(&svr4_head);
+ atomic_store_rel_int(&svr4_str_initialized, 2);
+ }
+
+ e = malloc(sizeof(*e), M_TEMP, M_WAITOK);
+ e->cookie = NULL;
+ e->dev = st->st_dev;
+ e->ino = st->st_ino;
+ e->p = td->td_proc;
+
+ if ((error = copyinstr(path, e->sock.sun_path,
+ sizeof(e->sock.sun_path), &len)) != 0) {
+ DPRINTF(("svr4_add_socket: copyinstr failed %d\n", error));
+ free(e, M_TEMP);
+ return error;
+ }
+
+ e->sock.sun_family = AF_LOCAL;
+ e->sock.sun_len = len;
+
+ TAILQ_INSERT_HEAD(&svr4_head, e, entries);
+ DPRINTF(("svr4_add_socket: %s [%p,%d,%d]\n", e->sock.sun_path,
+ td->td_proc, e->dev, e->ino));
+ return 0;
+}
+
+
+int
+svr4_sys_socket(td, uap)
+ struct thread *td;
+ struct svr4_sys_socket_args *uap;
+{
+ switch (SCARG(uap, type)) {
+ case SVR4_SOCK_DGRAM:
+ SCARG(uap, type) = SOCK_DGRAM;
+ break;
+
+ case SVR4_SOCK_STREAM:
+ SCARG(uap, type) = SOCK_STREAM;
+ break;
+
+ case SVR4_SOCK_RAW:
+ SCARG(uap, type) = SOCK_RAW;
+ break;
+
+ case SVR4_SOCK_RDM:
+ SCARG(uap, type) = SOCK_RDM;
+ break;
+
+ case SVR4_SOCK_SEQPACKET:
+ SCARG(uap, type) = SOCK_SEQPACKET;
+ break;
+ default:
+ return EINVAL;
+ }
+ return socket(td, (struct socket_args *)uap);
+}
diff --git a/sys/compat/svr4/svr4_socket.h b/sys/compat/svr4/svr4_socket.h
new file mode 100644
index 0000000..434f1f2
--- /dev/null
+++ b/sys/compat/svr4/svr4_socket.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1996 Christos Zoulas.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKET_H_
+#define _SVR4_SOCKET_H_
+
+#include <netinet/in.h>
+
+struct sockaddr_un;
+struct proc;
+struct thread;
+struct file;
+
+struct svr4_sockaddr_in {
+ u_char sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ u_char sin_zero[8];
+};
+
+struct sockaddr_un *svr4_find_socket(struct thread *, struct file *,
+ udev_t, ino_t);
+void svr4_delete_socket(struct proc *, struct file *);
+int svr4_add_socket(struct thread *, const char *, struct stat *);
+
+#endif /* _SVR4_SOCKET_H_ */
diff --git a/sys/compat/svr4/svr4_sockio.c b/sys/compat/svr4/svr4_sockio.c
new file mode 100644
index 0000000..9f41e10
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockio.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/sockio.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_sockio.h>
+
+static int bsd_to_svr4_flags(int);
+
+#define bsd_to_svr4_flag(a) \
+ if (bf & __CONCAT(I,a)) sf |= __CONCAT(SVR4_I,a)
+
+static int
+bsd_to_svr4_flags(bf)
+ int bf;
+{
+ int sf = 0;
+ bsd_to_svr4_flag(FF_UP);
+ bsd_to_svr4_flag(FF_BROADCAST);
+ bsd_to_svr4_flag(FF_DEBUG);
+ bsd_to_svr4_flag(FF_LOOPBACK);
+ bsd_to_svr4_flag(FF_POINTOPOINT);
+#if defined(IFF_NOTRAILERS)
+ bsd_to_svr4_flag(FF_NOTRAILERS);
+#endif
+ bsd_to_svr4_flag(FF_RUNNING);
+ bsd_to_svr4_flag(FF_NOARP);
+ bsd_to_svr4_flag(FF_PROMISC);
+ bsd_to_svr4_flag(FF_ALLMULTI);
+ bsd_to_svr4_flag(FF_MULTICAST);
+ return sf;
+}
+
+int
+svr4_sock_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ int error;
+
+ *retval = 0;
+
+ switch (cmd) {
+ case SVR4_SIOCGIFNUM:
+ {
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ int ifnum = 0;
+
+ /*
+ * This does not return the number of physical
+ * interfaces (if_index), but the number of interfaces
+ * + addresses like ifconf() does, because this number
+ * is used by code that will call SVR4_SIOCGIFCONF to
+ * find the space needed for SVR4_SIOCGIFCONF. So we
+ * count the number of ifreq entries that the next
+ * SVR4_SIOCGIFCONF will return. Maybe a more correct
+ * fix is to make SVR4_SIOCGIFCONF return only one
+ * entry per physical interface?
+ */
+
+ TAILQ_FOREACH(ifp, &ifnet, if_link)
+ if (TAILQ_FIRST(&ifp->if_addrhead) == NULL)
+ ifnum++;
+ else
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead,
+ ifa_link)
+ ifnum++;
+
+
+ DPRINTF(("SIOCGIFNUM %d\n", ifnum));
+ return copyout(&ifnum, data, sizeof(ifnum));
+ }
+
+ case SVR4_SIOCGIFFLAGS:
+ {
+ struct ifreq br;
+ struct svr4_ifreq sr;
+
+ if ((error = copyin(data, &sr, sizeof(sr))) != 0)
+ return error;
+
+ (void) strncpy(br.ifr_name, sr.svr4_ifr_name,
+ sizeof(br.ifr_name));
+ if ((error = fo_ioctl(fp, SIOCGIFFLAGS,
+ (caddr_t) &br, td)) != 0) {
+ DPRINTF(("SIOCGIFFLAGS (%s) %s: error %d\n",
+ br.ifr_name, sr.svr4_ifr_name, error));
+ return error;
+ }
+
+ sr.svr4_ifr_flags = bsd_to_svr4_flags(br.ifr_flags);
+ DPRINTF(("SIOCGIFFLAGS %s = %x\n",
+ sr.svr4_ifr_name, sr.svr4_ifr_flags));
+ return copyout(&sr, data, sizeof(sr));
+ }
+
+ case SVR4_SIOCGIFCONF:
+ {
+ struct svr4_ifconf sc;
+
+ if ((error = copyin(data, &sc, sizeof(sc))) != 0)
+ return error;
+
+ DPRINTF(("ifreq %d svr4_ifreq %d ifc_len %d\n",
+ sizeof(struct ifreq), sizeof(struct svr4_ifreq),
+ sc.svr4_ifc_len));
+
+ if ((error = fo_ioctl(fp, OSIOCGIFCONF,
+ (caddr_t) &sc, td)) != 0)
+ return error;
+
+ DPRINTF(("SIOCGIFCONF\n"));
+ return 0;
+ }
+
+
+ default:
+ DPRINTF(("Unknown svr4 sockio %lx\n", cmd));
+ return 0; /* ENOSYS really */
+ }
+}
diff --git a/sys/compat/svr4/svr4_sockio.h b/sys/compat/svr4/svr4_sockio.h
new file mode 100644
index 0000000..dd4e220
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockio.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKIO_H_
+#define _SVR4_SOCKIO_H_
+
+#define SVR4_IFF_UP 0x0001
+#define SVR4_IFF_BROADCAST 0x0002
+#define SVR4_IFF_DEBUG 0x0004
+#define SVR4_IFF_LOOPBACK 0x0008
+#define SVR4_IFF_POINTOPOINT 0x0010
+#define SVR4_IFF_NOTRAILERS 0x0020
+#define SVR4_IFF_RUNNING 0x0040
+#define SVR4_IFF_NOARP 0x0080
+#define SVR4_IFF_PROMISC 0x0100
+#define SVR4_IFF_ALLMULTI 0x0200
+#define SVR4_IFF_INTELLIGENT 0x0400
+#define SVR4_IFF_MULTICAST 0x0800
+#define SVR4_IFF_MULTI_BCAST 0x1000
+#define SVR4_IFF_UNNUMBERED 0x2000
+#define SVR4_IFF_PRIVATE 0x8000
+
+struct svr4_ifreq {
+#define SVR4_IFNAMSIZ 16
+ char svr4_ifr_name[SVR4_IFNAMSIZ];
+ union {
+ struct osockaddr ifru_addr;
+ struct osockaddr ifru_dstaddr;
+ struct osockaddr ifru_broadaddr;
+ short ifru_flags;
+ int ifru_metric;
+ char ifru_data;
+ char ifru_enaddr[6];
+ int if_muxid[2];
+
+ } ifr_ifru;
+
+#define svr4_ifr_addr ifr_ifru.ifru_addr
+#define svr4_ifr_dstaddr ifr_ifru.ifru_dstaddr
+#define svr4_ifr_broadaddr ifr_ifru.ifru_broadaddr
+#define svr4_ifr_flags ifr_ifru.ifru_flags
+#define svr4_ifr_metric ifr_ifru.ifru_metric
+#define svr4_ifr_data ifr_ifru.ifru_data
+#define svr4_ifr_enaddr ifr_ifru.ifru_enaddr
+#define svr4_ifr_muxid ifr_ifru.ifru_muxid
+
+};
+
+struct svr4_ifconf {
+ int svr4_ifc_len;
+ union {
+ caddr_t ifcu_buf;
+ struct svr4_ifreq *ifcu_req;
+ } ifc_ifcu;
+
+#define svr4_ifc_buf ifc_ifcu.ifcu_buf
+#define svr4_ifc_req ifc_ifcu.ifcu_req
+};
+
+#define SVR4_SIOC ('i' << 8)
+
+#define SVR4_SIOCGIFFLAGS SVR4_IOWR('i', 17, struct svr4_ifreq)
+#define SVR4_SIOCGIFCONF SVR4_IOWR('i', 20, struct svr4_ifconf)
+#define SVR4_SIOCGIFNUM SVR4_IOR('i', 87, int)
+
+#endif /* !_SVR4_SOCKIO_H_ */
diff --git a/sys/compat/svr4/svr4_sockmod.h b/sys/compat/svr4/svr4_sockmod.h
new file mode 100644
index 0000000..927ba0d
--- /dev/null
+++ b/sys/compat/svr4/svr4_sockmod.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SOCKMOD_H_
+#define _SVR4_SOCKMOD_H_
+
+#define SVR4_SIMOD ('I' << 8)
+
+#define SVR4_SI_OGETUDATA (SVR4_SIMOD|101)
+#define SVR4_SI_SHUTDOWN (SVR4_SIMOD|102)
+#define SVR4_SI_LISTEN (SVR4_SIMOD|103)
+#define SVR4_SI_SETMYNAME (SVR4_SIMOD|104)
+#define SVR4_SI_SETPEERNAME (SVR4_SIMOD|105)
+#define SVR4_SI_GETINTRANSIT (SVR4_SIMOD|106)
+#define SVR4_SI_TCL_LINK (SVR4_SIMOD|107)
+#define SVR4_SI_TCL_UNLINK (SVR4_SIMOD|108)
+#define SVR4_SI_SOCKPARAMS (SVR4_SIMOD|109)
+#define SVR4_SI_GETUDATA (SVR4_SIMOD|110)
+
+
+#define SVR4_SOCK_DGRAM 1
+#define SVR4_SOCK_STREAM 2
+#define SVR4_SOCK_STREAM_ORD 3
+#define SVR4_SOCK_RAW 4
+#define SVR4_SOCK_RDM 5
+#define SVR4_SOCK_SEQPACKET 6
+
+struct svr4_si_sockparms {
+ int family;
+ int type;
+ int protocol;
+};
+
+struct svr4_si_oudata {
+ int tidusize;
+ int addrsize;
+ int optsize;
+ int etsdusize;
+ int servtype;
+ int so_state;
+ int so_options;
+ int tsdusize;
+};
+
+struct svr4_si_udata {
+ int tidusize;
+ int addrsize;
+ int optsize;
+ int etsdusize;
+ int servtype;
+ int so_state;
+ int so_options;
+ int tsdusize;
+ struct svr4_si_sockparms sockparms;
+};
+#endif /* !_SVR4_SOCKMOD_H_ */
diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c
new file mode 100644
index 0000000..b1d63ec
--- /dev/null
+++ b/sys/compat/svr4/svr4_stat.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
+#include <sys/kernel.h>
+#include <sys/unistd.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/sysproto.h>
+
+#include <vm/vm.h>
+
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_stat.h>
+#include <compat/svr4/svr4_ustat.h>
+#include <compat/svr4/svr4_utsname.h>
+#include <compat/svr4/svr4_systeminfo.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_time.h>
+#if defined(NOTYET)
+#include "svr4_fuser.h"
+#endif
+
+#ifdef sparc
+/*
+ * Solaris-2.4 on the sparc has the old stat call using the new
+ * stat data structure...
+ */
+# define SVR4_NO_OSTAT
+#endif
+
+struct svr4_ustat_args {
+ svr4_dev_t dev;
+ struct svr4_ustat * name;
+};
+
+static void bsd_to_svr4_xstat(struct stat *, struct svr4_xstat *);
+static void bsd_to_svr4_stat64(struct stat *, struct svr4_stat64 *);
+int svr4_ustat(struct thread *, struct svr4_ustat_args *);
+static int svr4_to_bsd_pathconf(int);
+
+/*
+ * SVR4 uses named pipes as named sockets, so we tell programs
+ * that sockets are named pipes with mode 0
+ */
+#define BSD_TO_SVR4_MODE(mode) (S_ISSOCK(mode) ? S_IFIFO : (mode))
+
+
+#ifndef SVR4_NO_OSTAT
+static void bsd_to_svr4_stat(struct stat *, struct svr4_stat *);
+
+static void
+bsd_to_svr4_stat(st, st4)
+ struct stat *st;
+ struct svr4_stat *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_odev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atimespec.tv_sec;
+ st4->st_mtim = st->st_mtimespec.tv_sec;
+ st4->st_ctim = st->st_ctimespec.tv_sec;
+}
+#endif
+
+
+static void
+bsd_to_svr4_xstat(st, st4)
+ struct stat *st;
+ struct svr4_xstat *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atimespec;
+ st4->st_mtim = st->st_mtimespec;
+ st4->st_ctim = st->st_ctimespec;
+ st4->st_blksize = st->st_blksize;
+ st4->st_blocks = st->st_blocks;
+ strcpy(st4->st_fstype, "unknown");
+}
+
+
+static void
+bsd_to_svr4_stat64(st, st4)
+ struct stat *st;
+ struct svr4_stat64 *st4;
+{
+ memset(st4, 0, sizeof(*st4));
+ st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
+ st4->st_ino = st->st_ino;
+ st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
+ st4->st_nlink = st->st_nlink;
+ st4->st_uid = st->st_uid;
+ st4->st_gid = st->st_gid;
+ st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
+ st4->st_size = st->st_size;
+ st4->st_atim = st->st_atimespec;
+ st4->st_mtim = st->st_mtimespec;
+ st4->st_ctim = st->st_ctimespec;
+ st4->st_blksize = st->st_blksize;
+ st4->st_blocks = st->st_blocks;
+ strcpy(st4->st_fstype, "unknown");
+}
+
+int
+svr4_sys_stat(td, uap)
+ struct thread *td;
+ struct svr4_sys_stat_args *uap;
+{
+ struct stat st;
+ struct svr4_stat svr4_st;
+ struct stat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+
+ if ((error = stat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_lstat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_lstat_args *uap;
+{
+ struct stat st;
+ struct svr4_stat svr4_st;
+ struct lstat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = lstat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_fstat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_fstat_args *uap;
+{
+ struct stat st;
+ struct svr4_stat svr4_st;
+ struct fstat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ SCARG(&cup, fd) = SCARG(uap, fd);
+ SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = fstat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat(&st, &svr4_st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_xstat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_xstat_args *uap;
+{
+ struct stat st;
+ struct svr4_xstat svr4_st;
+ struct stat_args cup;
+ int error;
+
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = stat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_xstat(&st, &svr4_st);
+
+#if defined(SOCKET_NOTYET)
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+#endif
+
+ if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+int
+svr4_sys_lxstat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_lxstat_args *uap;
+{
+ struct stat st;
+ struct svr4_xstat svr4_st;
+ struct lstat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = lstat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_xstat(&st, &svr4_st);
+
+#if defined(SOCKET_NOTYET)
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+#endif
+ if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_fxstat(td, uap)
+ register struct thread *td;
+ struct svr4_sys_fxstat_args *uap;
+{
+ struct stat st;
+ struct svr4_xstat svr4_st;
+ struct fstat_args cup;
+ int error;
+
+ caddr_t sg = stackgap_init();
+
+ SCARG(&cup, fd) = SCARG(uap, fd);
+ SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = fstat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_xstat(&st, &svr4_st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+int
+svr4_sys_stat64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_stat64_args *uap;
+{
+ struct stat st;
+ struct svr4_stat64 svr4_st;
+ struct stat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = stat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat64(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_lstat64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_lstat64_args *uap;
+{
+ struct stat st;
+ struct svr4_stat64 svr4_st;
+ struct stat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ CHECKALTEXIST(td, &sg, (char *) SCARG(uap, path));
+
+ SCARG(&cup, path) = SCARG(uap, path);
+ SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = lstat(td, (struct lstat_args *)&cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat64(&st, &svr4_st);
+
+ if (S_ISSOCK(st.st_mode))
+ (void) svr4_add_socket(td, SCARG(uap, path), &st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_sys_fstat64(td, uap)
+ register struct thread *td;
+ struct svr4_sys_fstat64_args *uap;
+{
+ struct stat st;
+ struct svr4_stat64 svr4_st;
+ struct fstat_args cup;
+ int error;
+ caddr_t sg = stackgap_init();
+
+ SCARG(&cup, fd) = SCARG(uap, fd);
+ SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = fstat(td, &cup)) != 0)
+ return error;
+
+ if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0)
+ return error;
+
+ bsd_to_svr4_stat64(&st, &svr4_st);
+
+ if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+int
+svr4_ustat(td, uap)
+ register struct thread *td;
+ struct svr4_ustat_args *uap;
+{
+ struct svr4_ustat us;
+ int error;
+
+ memset(&us, 0, sizeof us);
+
+ /*
+ * XXX: should set f_tfree and f_tinode at least
+ * How do we translate dev -> fstat? (and then to svr4_ustat)
+ */
+ if ((error = copyout(&us, SCARG(uap, name), sizeof us)) != 0)
+ return (error);
+
+ return 0;
+}
+
+/*extern char ostype[], hostname[], osrelease[], version[], machine[];*/
+
+int
+svr4_sys_uname(td, uap)
+ register struct thread *td;
+ struct svr4_sys_uname_args *uap;
+{
+ struct svr4_utsname sut;
+
+ memset(&sut, 0, sizeof(sut));
+
+ strncpy(sut.sysname, ostype, sizeof(sut.sysname));
+ sut.sysname[sizeof(sut.sysname) - 1] = '\0';
+
+ getcredhostname(td->td_ucred, sut.nodename, sizeof(sut.nodename));
+
+ strncpy(sut.release, osrelease, sizeof(sut.release));
+ sut.release[sizeof(sut.release) - 1] = '\0';
+
+ strncpy(sut.version, version, sizeof(sut.version));
+ sut.version[sizeof(sut.version) - 1] = '\0';
+
+ strncpy(sut.machine, machine, sizeof(sut.machine));
+ sut.machine[sizeof(sut.machine) - 1] = '\0';
+
+ return copyout((caddr_t) &sut, (caddr_t) SCARG(uap, name),
+ sizeof(struct svr4_utsname));
+}
+
+int
+svr4_sys_systeminfo(td, uap)
+ struct thread *td;
+ struct svr4_sys_systeminfo_args *uap;
+{
+ char *str = NULL;
+ int error = 0;
+ register_t *retval = td->td_retval;
+ size_t len = 0;
+ char buf[1]; /* XXX NetBSD uses 256, but that seems
+ like awfully excessive kstack usage
+ for an empty string... */
+ u_int rlen = SCARG(uap, len);
+
+ switch (SCARG(uap, what)) {
+ case SVR4_SI_SYSNAME:
+ str = ostype;
+ break;
+
+ case SVR4_SI_HOSTNAME:
+ str = hostname;
+ break;
+
+ case SVR4_SI_RELEASE:
+ str = osrelease;
+ break;
+
+ case SVR4_SI_VERSION:
+ str = version;
+ break;
+
+ case SVR4_SI_MACHINE:
+ str = machine;
+ break;
+
+ case SVR4_SI_ARCHITECTURE:
+ str = machine;
+ break;
+
+ case SVR4_SI_HW_SERIAL:
+ str = "0";
+ break;
+
+ case SVR4_SI_HW_PROVIDER:
+ str = ostype;
+ break;
+
+ case SVR4_SI_SRPC_DOMAIN:
+ str = domainname;
+ break;
+
+ case SVR4_SI_PLATFORM:
+#ifdef __i386__
+ str = "i86pc";
+#else
+ str = "unknown";
+#endif
+ break;
+
+ case SVR4_SI_KERB_REALM:
+ str = "unsupported";
+ break;
+#if defined(WHY_DOES_AN_EMULATOR_WANT_TO_SET_HOSTNAMES)
+ case SVR4_SI_SET_HOSTNAME:
+ if ((error = suser(td)) != 0)
+ return error;
+ name = KERN_HOSTNAME;
+ return kern_sysctl(&name, 1, 0, 0, SCARG(uap, buf), rlen, td);
+
+ case SVR4_SI_SET_SRPC_DOMAIN:
+ if ((error = suser(td)) != 0)
+ return error;
+ name = KERN_NISDOMAINNAME;
+ return kern_sysctl(&name, 1, 0, 0, SCARG(uap, buf), rlen, td);
+#else
+ case SVR4_SI_SET_HOSTNAME:
+ case SVR4_SI_SET_SRPC_DOMAIN:
+ /* FALLTHROUGH */
+#endif
+ case SVR4_SI_SET_KERB_REALM:
+ return 0;
+
+ default:
+ DPRINTF(("Bad systeminfo command %d\n", SCARG(uap, what)));
+ return ENOSYS;
+ }
+
+ if (str) {
+ len = strlen(str) + 1;
+ if (len > rlen)
+ len = rlen;
+
+ if (SCARG(uap, buf)) {
+ error = copyout(str, SCARG(uap, buf), len);
+ if (error)
+ return error;
+ /* make sure we are NULL terminated */
+ buf[0] = '\0';
+ error = copyout(buf, &(SCARG(uap, buf)[len - 1]), 1);
+ }
+ else
+ error = 0;
+ }
+ /* XXX NetBSD has hostname setting stuff here. Why would an emulator
+ want to do that? */
+
+ *retval = len;
+ return error;
+}
+
+int
+svr4_sys_utssys(td, uap)
+ register struct thread *td;
+ struct svr4_sys_utssys_args *uap;
+{
+ switch (SCARG(uap, sel)) {
+ case 0: /* uname(2) */
+ {
+ struct svr4_sys_uname_args ua;
+ SCARG(&ua, name) = SCARG(uap, a1);
+ return svr4_sys_uname(td, &ua);
+ }
+
+ case 2: /* ustat(2) */
+ {
+ struct svr4_ustat_args ua;
+ SCARG(&ua, dev) = (svr4_dev_t) SCARG(uap, a2);
+ SCARG(&ua, name) = SCARG(uap, a1);
+ return svr4_ustat(td, &ua);
+ }
+
+ case 3: /* fusers(2) */
+ return ENOSYS;
+
+ default:
+ return ENOSYS;
+ }
+ return ENOSYS;
+}
+
+
+int
+svr4_sys_utime(td, uap)
+ register struct thread *td;
+ struct svr4_sys_utime_args *uap;
+{
+ struct svr4_utimbuf ub;
+ struct timeval tbuf[2];
+ struct utimes_args ap;
+ int error;
+ caddr_t sg = stackgap_init();
+ void *ttp;
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+ SCARG(&ap, path) = SCARG(uap, path);
+ if (SCARG(uap, ubuf) != NULL) {
+ if ((error = copyin(SCARG(uap, ubuf), &ub, sizeof(ub))) != 0)
+ return error;
+ tbuf[0].tv_sec = ub.actime;
+ tbuf[0].tv_usec = 0;
+ tbuf[1].tv_sec = ub.modtime;
+ tbuf[1].tv_usec = 0;
+ ttp = stackgap_alloc(&sg, sizeof(tbuf));
+ error = copyout(tbuf, ttp, sizeof(tbuf));
+ if (error)
+ return error;
+ SCARG(&ap, tptr) = ttp;
+ }
+ else
+ SCARG(&ap, tptr) = NULL;
+ return utimes(td, &ap);
+}
+
+
+int
+svr4_sys_utimes(td, uap)
+ register struct thread *td;
+ struct svr4_sys_utimes_args *uap;
+{
+ caddr_t sg = stackgap_init();
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+ return utimes(td, (struct utimes_args *)uap);
+}
+
+static int
+svr4_to_bsd_pathconf(name)
+ int name;
+{
+ switch (name) {
+ case SVR4_PC_LINK_MAX:
+ return _PC_LINK_MAX;
+
+ case SVR4_PC_MAX_CANON:
+ return _PC_MAX_CANON;
+
+ case SVR4_PC_MAX_INPUT:
+ return _PC_MAX_INPUT;
+
+ case SVR4_PC_NAME_MAX:
+ return _PC_NAME_MAX;
+
+ case SVR4_PC_PATH_MAX:
+ return _PC_PATH_MAX;
+
+ case SVR4_PC_PIPE_BUF:
+ return _PC_PIPE_BUF;
+
+ case SVR4_PC_NO_TRUNC:
+ return _PC_NO_TRUNC;
+
+ case SVR4_PC_VDISABLE:
+ return _PC_VDISABLE;
+
+ case SVR4_PC_CHOWN_RESTRICTED:
+ return _PC_CHOWN_RESTRICTED;
+ case SVR4_PC_SYNC_IO:
+#if defined(_PC_SYNC_IO)
+ return _PC_SYNC_IO;
+#else
+ return 0;
+#endif
+ case SVR4_PC_ASYNC_IO:
+ case SVR4_PC_PRIO_IO:
+ /* Not supported */
+ return 0;
+
+ default:
+ /* Invalid */
+ return -1;
+ }
+}
+
+
+int
+svr4_sys_pathconf(td, uap)
+ register struct thread *td;
+ struct svr4_sys_pathconf_args *uap;
+{
+ caddr_t sg = stackgap_init();
+ register_t *retval = td->td_retval;
+
+ CHECKALTEXIST(td, &sg, SCARG(uap, path));
+
+ SCARG(uap, name) = svr4_to_bsd_pathconf(SCARG(uap, name));
+
+ switch (SCARG(uap, name)) {
+ case -1:
+ *retval = -1;
+ return EINVAL;
+ case 0:
+ *retval = 0;
+ return 0;
+ default:
+ return pathconf(td, (struct pathconf_args *)uap);
+ }
+}
+
+
+int
+svr4_sys_fpathconf(td, uap)
+ register struct thread *td;
+ struct svr4_sys_fpathconf_args *uap;
+{
+ register_t *retval = td->td_retval;
+
+ SCARG(uap, name) = svr4_to_bsd_pathconf(SCARG(uap, name));
+
+ switch (SCARG(uap, name)) {
+ case -1:
+ *retval = -1;
+ return EINVAL;
+ case 0:
+ *retval = 0;
+ return 0;
+ default:
+ return fpathconf(td, (struct fpathconf_args *)uap);
+ }
+}
diff --git a/sys/compat/svr4/svr4_stat.h b/sys/compat/svr4/svr4_stat.h
new file mode 100644
index 0000000..e92aea6
--- /dev/null
+++ b/sys/compat/svr4/svr4_stat.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STAT_H_
+#define _SVR4_STAT_H_
+
+#include <compat/svr4/svr4_types.h>
+#include <sys/stat.h>
+
+struct svr4_stat {
+ svr4_o_dev_t st_dev;
+ svr4_o_ino_t st_ino;
+ svr4_o_mode_t st_mode;
+ svr4_o_nlink_t st_nlink;
+ svr4_o_uid_t st_uid;
+ svr4_o_gid_t st_gid;
+ svr4_o_dev_t st_rdev;
+ svr4_off_t st_size;
+ svr4_time_t st_atim;
+ svr4_time_t st_mtim;
+ svr4_time_t st_ctim;
+};
+
+struct svr4_xstat {
+ svr4_dev_t st_dev;
+ long st_pad1[3];
+ svr4_ino_t st_ino;
+ svr4_mode_t st_mode;
+ svr4_nlink_t st_nlink;
+ svr4_uid_t st_uid;
+ svr4_gid_t st_gid;
+ svr4_dev_t st_rdev;
+ long st_pad2[2];
+ svr4_off_t st_size;
+ long st_pad3;
+ svr4_timestruc_t st_atim;
+ svr4_timestruc_t st_mtim;
+ svr4_timestruc_t st_ctim;
+ long st_blksize;
+ svr4_blkcnt_t st_blocks;
+ char st_fstype[16];
+ long st_pad4[8];
+};
+
+struct svr4_stat64 {
+ svr4_dev_t st_dev;
+ long st_pad1[3];
+ svr4_ino64_t st_ino;
+ svr4_mode_t st_mode;
+ svr4_nlink_t st_nlink;
+ svr4_uid_t st_uid;
+ svr4_gid_t st_gid;
+ svr4_dev_t st_rdev;
+ long st_pad2[2];
+ svr4_off64_t st_size;
+ svr4_timestruc_t st_atim;
+ svr4_timestruc_t st_mtim;
+ svr4_timestruc_t st_ctim;
+ long st_blksize;
+ svr4_blkcnt64_t st_blocks;
+ char st_fstype[16];
+ long st_pad4[8];
+};
+
+#define SVR4_PC_LINK_MAX 1
+#define SVR4_PC_MAX_CANON 2
+#define SVR4_PC_MAX_INPUT 3
+#define SVR4_PC_NAME_MAX 4
+#define SVR4_PC_PATH_MAX 5
+#define SVR4_PC_PIPE_BUF 6
+#define SVR4_PC_NO_TRUNC 7
+#define SVR4_PC_VDISABLE 8
+#define SVR4_PC_CHOWN_RESTRICTED 9
+#define SVR4_PC_ASYNC_IO 10
+#define SVR4_PC_PRIO_IO 11
+#define SVR4_PC_SYNC_IO 12
+
+#endif /* !_SVR4_STAT_H_ */
diff --git a/sys/compat/svr4/svr4_statvfs.h b/sys/compat/svr4/svr4_statvfs.h
new file mode 100644
index 0000000..b3bf473
--- /dev/null
+++ b/sys/compat/svr4/svr4_statvfs.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STATVFS_H_
+#define _SVR4_STATVFS_H_
+
+typedef struct svr4_statvfs {
+ u_long f_bsize;
+ u_long f_frsize;
+ svr4_fsblkcnt_t f_blocks;
+ svr4_fsblkcnt_t f_bfree;
+ svr4_fsblkcnt_t f_bavail;
+ svr4_fsblkcnt_t f_files;
+ svr4_fsblkcnt_t f_ffree;
+ svr4_fsblkcnt_t f_favail;
+ u_long f_fsid;
+ char f_basetype[16];
+ u_long f_flag;
+ u_long f_namemax;
+ char f_fstr[32];
+ u_long f_filler[16];
+} svr4_statvfs_t;
+
+typedef struct svr4_statvfs64 {
+ u_long f_bsize;
+ u_long f_frsize;
+ svr4_fsblkcnt64_t f_blocks;
+ svr4_fsblkcnt64_t f_bfree;
+ svr4_fsblkcnt64_t f_bavail;
+ svr4_fsblkcnt64_t f_files;
+ svr4_fsblkcnt64_t f_ffree;
+ svr4_fsblkcnt64_t f_favail;
+ u_long f_fsid;
+ char f_basetype[16];
+ u_long f_flag;
+ u_long f_namemax;
+ char f_fstr[32];
+ u_long f_filler[16];
+} svr4_statvfs64_t;
+
+#define SVR4_ST_RDONLY 0x01
+#define SVR4_ST_NOSUID 0x02
+#define SVR4_ST_NOTRUNC 0x04
+
+#endif /* !_SVR4_STATVFS_H_ */
diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
new file mode 100644
index 0000000..2f0d5e3
--- /dev/null
+++ b/sys/compat/svr4/svr4_stream.c
@@ -0,0 +1,2295 @@
+/*
+ * Copyright (c) 1998 Mark Newton. All rights reserved.
+ * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Pretend that we have streams...
+ * Yes, this is gross.
+ *
+ * ToDo: The state machine for getmsg needs re-thinking
+ */
+
+#define COMPAT_43 1
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/filedesc.h>
+#include <sys/filio.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/file.h> /* Must come after sys/malloc.h */
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/protosw.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/stat.h>
+#include <sys/sysproto.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h> /* Must come after sys/uio.h */
+#include <sys/un.h>
+
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_stropts.h>
+#include <compat/svr4/svr4_timod.h>
+#include <compat/svr4/svr4_sockmod.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_socket.h>
+
+/* Utils */
+static int clean_pipe(struct thread *, const char *);
+static void getparm(struct file *, struct svr4_si_sockparms *);
+static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *,
+ struct file *);
+static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *,
+ struct file *);
+
+/* Address Conversions */
+static void sockaddr_to_netaddr_in(struct svr4_strmcmd *,
+ const struct sockaddr_in *);
+static void sockaddr_to_netaddr_un(struct svr4_strmcmd *,
+ const struct sockaddr_un *);
+static void netaddr_to_sockaddr_in(struct sockaddr_in *,
+ const struct svr4_strmcmd *);
+static void netaddr_to_sockaddr_un(struct sockaddr_un *,
+ const struct svr4_strmcmd *);
+
+/* stream ioctls */
+static int i_nread(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_fdinsert(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_str(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_setsig(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int i_getsig(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int,
+ u_long, caddr_t);
+
+/* i_str sockmod calls */
+static int sockmod(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_listen(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_ogetudata(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_sockparams(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_shutdown (struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int si_getudata(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+
+/* i_str timod calls */
+static int timod(struct file *, int, struct svr4_strioctl *, struct thread *);
+static int ti_getinfo(struct file *, int, struct svr4_strioctl *,
+ struct thread *);
+static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *);
+
+/* infrastructure */
+static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags);
+
+static int svr4_recvit(struct thread *td, int s, struct msghdr *mp,
+ caddr_t namelenp);
+
+/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because
+ * it isn't part of a "public" interface; We're supposed to use
+ * pru_sosend instead. Same goes for recvit()/pru_soreceive() for
+ * that matter. Solution: Suck sendit()/recvit() into here where we
+ * can do what we like.
+ *
+ * I hate code duplication.
+ *
+ * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though.
+ */
+static int
+svr4_sendit(td, s, mp, flags)
+ register struct thread *td;
+ int s;
+ register struct msghdr *mp;
+ int flags;
+{
+ struct uio auio;
+ register struct iovec *iov;
+ register int i;
+ struct mbuf *control;
+ struct sockaddr *to;
+ int len, error;
+ struct socket *so;
+#ifdef KTRACE
+ struct iovec *ktriov = NULL;
+ struct uio ktruio;
+#endif
+
+ if ((error = fgetsock(td, s, &so, NULL)) != 0)
+ return (error);
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_td = td;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+ if ((auio.uio_resid += iov->iov_len) < 0) {
+ error = EINVAL;
+ goto done1;
+ }
+ }
+ if (mp->msg_name) {
+ error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
+ if (error)
+ goto done1;
+ } else {
+ to = 0;
+ }
+ if (mp->msg_control) {
+ if (mp->msg_controllen < sizeof(struct cmsghdr)) {
+ error = EINVAL;
+ goto bad;
+ }
+ error = sockargs(&control, mp->msg_control,
+ mp->msg_controllen, MT_CONTROL);
+ if (error)
+ goto bad;
+ } else {
+ control = 0;
+ }
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_GENIO)) {
+ int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
+
+ MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
+ bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
+ ktruio = auio;
+ }
+#endif
+ len = auio.uio_resid;
+ error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
+ flags, td);
+ if (error) {
+ if (auio.uio_resid != len && (error == ERESTART ||
+ error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ if (error == EPIPE) {
+ PROC_LOCK(td->td_proc);
+ psignal(td->td_proc, SIGPIPE);
+ PROC_UNLOCK(td->td_proc);
+ }
+ }
+ if (error == 0)
+ td->td_retval[0] = len - auio.uio_resid;
+#ifdef KTRACE
+ if (ktriov != NULL) {
+ if (error == 0) {
+ ktruio.uio_iov = ktriov;
+ ktruio.uio_resid = td->td_retval[0];
+ ktrgenio(s, UIO_WRITE, &ktruio, error);
+ }
+ FREE(ktriov, M_TEMP);
+ }
+#endif
+bad:
+ if (to)
+ FREE(to, M_SONAME);
+done1:
+ fputsock(so);
+ return (error);
+}
+
+static int
+svr4_recvit(td, s, mp, namelenp)
+ register struct thread *td;
+ int s;
+ register struct msghdr *mp;
+ caddr_t namelenp;
+{
+ struct uio auio;
+ register struct iovec *iov;
+ register int i;
+ int len, error;
+ struct mbuf *m, *control = 0;
+ caddr_t ctlbuf;
+ struct socket *so;
+ struct sockaddr *fromsa = 0;
+#ifdef KTRACE
+ struct iovec *ktriov = NULL;
+ struct uio ktruio;
+#endif
+
+ if ((error = fgetsock(td, s, &so, NULL)) != 0)
+ return (error);
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_READ;
+ auio.uio_td = td;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+ if ((auio.uio_resid += iov->iov_len) < 0) {
+ error = EINVAL;
+ goto done1;
+ }
+ }
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_GENIO)) {
+ int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
+
+ MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
+ bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
+ ktruio = auio;
+ }
+#endif
+ len = auio.uio_resid;
+ error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
+ (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
+ &mp->msg_flags);
+ if (error) {
+ if (auio.uio_resid != len && (error == ERESTART ||
+ error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ }
+#ifdef KTRACE
+ if (ktriov != NULL) {
+ if (error == 0) {
+ ktruio.uio_iov = ktriov;
+ ktruio.uio_resid = len - auio.uio_resid;
+ ktrgenio(s, UIO_READ, &ktruio, error);
+ }
+ FREE(ktriov, M_TEMP);
+ }
+#endif
+ if (error)
+ goto out;
+ td->td_retval[0] = len - auio.uio_resid;
+ if (mp->msg_name) {
+ len = mp->msg_namelen;
+ if (len <= 0 || fromsa == 0)
+ len = 0;
+ else {
+#ifndef MIN
+#define MIN(a,b) ((a)>(b)?(b):(a))
+#endif
+ /* save sa_len before it is destroyed by MSG_COMPAT */
+ len = MIN(len, fromsa->sa_len);
+ error = copyout(fromsa,
+ (caddr_t)mp->msg_name, (unsigned)len);
+ if (error)
+ goto out;
+ }
+ mp->msg_namelen = len;
+ if (namelenp &&
+ (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
+ goto out;
+ }
+ }
+ if (mp->msg_control) {
+ len = mp->msg_controllen;
+ m = control;
+ mp->msg_controllen = 0;
+ ctlbuf = (caddr_t) mp->msg_control;
+
+ while (m && len > 0) {
+ unsigned int tocopy;
+
+ if (len >= m->m_len)
+ tocopy = m->m_len;
+ else {
+ mp->msg_flags |= MSG_CTRUNC;
+ tocopy = len;
+ }
+
+ if ((error = copyout((caddr_t)mtod(m, caddr_t),
+ ctlbuf, tocopy)) != 0)
+ goto out;
+
+ ctlbuf += tocopy;
+ len -= tocopy;
+ m = m->m_next;
+ }
+ mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
+ }
+out:
+ if (fromsa)
+ FREE(fromsa, M_SONAME);
+ if (control)
+ m_freem(control);
+done1:
+ fputsock(so);
+ return (error);
+}
+
+#ifdef DEBUG_SVR4
+static void bufprint(u_char *, size_t);
+static int show_ioc(const char *, struct svr4_strioctl *);
+static int show_strbuf(struct svr4_strbuf *);
+static void show_msg(const char *, int, struct svr4_strbuf *,
+ struct svr4_strbuf *, int);
+
+static void
+bufprint(buf, len)
+ u_char *buf;
+ size_t len;
+{
+ size_t i;
+
+ uprintf("\n\t");
+ for (i = 0; i < len; i++) {
+ uprintf("%x ", buf[i]);
+ if (i && (i % 16) == 0)
+ uprintf("\n\t");
+ }
+}
+
+static int
+show_ioc(str, ioc)
+ const char *str;
+ struct svr4_strioctl *ioc;
+{
+ u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK);
+ int error;
+
+ uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ",
+ str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf);
+
+ if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) {
+ free((char *) ptr, M_TEMP);
+ return error;
+ }
+
+ bufprint(ptr, ioc->len);
+
+ uprintf("}\n");
+
+ free((char *) ptr, M_TEMP);
+ return 0;
+}
+
+
+static int
+show_strbuf(str)
+ struct svr4_strbuf *str;
+{
+ int error;
+ u_char *ptr = NULL;
+ int maxlen = str->maxlen;
+ int len = str->len;
+
+ if (maxlen < 0)
+ maxlen = 0;
+
+ if (len >= maxlen)
+ len = maxlen;
+
+ if (len > 0) {
+ ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK);
+
+ if ((error = copyin(str->buf, ptr, len)) != 0) {
+ free((char *) ptr, M_TEMP);
+ return error;
+ }
+ }
+
+ uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf);
+
+ if (ptr)
+ bufprint(ptr, len);
+
+ uprintf("]}");
+
+ if (ptr)
+ free((char *) ptr, M_TEMP);
+
+ return 0;
+}
+
+
+static void
+show_msg(str, fd, ctl, dat, flags)
+ const char *str;
+ int fd;
+ struct svr4_strbuf *ctl;
+ struct svr4_strbuf *dat;
+ int flags;
+{
+ struct svr4_strbuf buf;
+ int error;
+
+ uprintf("%s(%d", str, fd);
+ if (ctl != NULL) {
+ if ((error = copyin(ctl, &buf, sizeof(buf))) != 0)
+ return;
+ show_strbuf(&buf);
+ }
+ else
+ uprintf(", NULL");
+
+ if (dat != NULL) {
+ if ((error = copyin(dat, &buf, sizeof(buf))) != 0)
+ return;
+ show_strbuf(&buf);
+ }
+ else
+ uprintf(", NULL");
+
+ uprintf(", %x);\n", flags);
+}
+
+#endif /* DEBUG_SVR4 */
+
+/*
+ * We are faced with an interesting situation. On svr4 unix sockets
+ * are really pipes. But we really have sockets, and we might as
+ * well use them. At the point where svr4 calls TI_BIND, it has
+ * already created a named pipe for the socket using mknod(2).
+ * We need to create a socket with the same name when we bind,
+ * so we need to remove the pipe before, otherwise we'll get address
+ * already in use. So we *carefully* remove the pipe, to avoid
+ * using this as a random file removal tool. We use system calls
+ * to avoid code duplication.
+ */
+static int
+clean_pipe(td, path)
+ struct thread *td;
+ const char *path;
+{
+ struct lstat_args la;
+ struct unlink_args ua;
+ struct stat st;
+ int error;
+ caddr_t sg = stackgap_init();
+ size_t l = strlen(path) + 1;
+ void *tpath;
+
+ tpath = stackgap_alloc(&sg, l);
+ SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat));
+
+ if ((error = copyout(path, tpath, l)) != 0)
+ return error;
+
+ SCARG(&la, path) = tpath;
+
+ if ((error = lstat(td, &la)) != 0)
+ return 0;
+
+ if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0)
+ return 0;
+
+ /*
+ * Make sure we are dealing with a mode 0 named pipe.
+ */
+ if ((st.st_mode & S_IFMT) != S_IFIFO)
+ return 0;
+
+ if ((st.st_mode & ALLPERMS) != 0)
+ return 0;
+
+ SCARG(&ua, path) = SCARG(&la, path);
+
+ if ((error = unlink(td, &ua)) != 0) {
+ DPRINTF(("clean_pipe: unlink failed %d\n", error));
+ return error;
+ }
+
+ return 0;
+}
+
+
+static void
+sockaddr_to_netaddr_in(sc, sain)
+ struct svr4_strmcmd *sc;
+ const struct sockaddr_in *sain;
+{
+ struct svr4_netaddr_in *na;
+ na = SVR4_ADDROF(sc);
+
+ na->family = sain->sin_family;
+ na->port = sain->sin_port;
+ na->addr = sain->sin_addr.s_addr;
+ DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port,
+ na->addr));
+}
+
+
+static void
+sockaddr_to_netaddr_un(sc, saun)
+ struct svr4_strmcmd *sc;
+ const struct sockaddr_un *saun;
+{
+ struct svr4_netaddr_un *na;
+ char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 -
+ sizeof(*sc);
+ const char *src;
+
+ na = SVR4_ADDROF(sc);
+ na->family = saun->sun_family;
+ for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; )
+ if (dst == edst)
+ break;
+ DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path));
+}
+
+
+static void
+netaddr_to_sockaddr_in(sain, sc)
+ struct sockaddr_in *sain;
+ const struct svr4_strmcmd *sc;
+{
+ const struct svr4_netaddr_in *na;
+
+
+ na = SVR4_C_ADDROF(sc);
+ memset(sain, 0, sizeof(*sain));
+ sain->sin_len = sizeof(*sain);
+ sain->sin_family = na->family;
+ sain->sin_port = na->port;
+ sain->sin_addr.s_addr = na->addr;
+ DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family,
+ sain->sin_port, sain->sin_addr.s_addr));
+}
+
+
+static void
+netaddr_to_sockaddr_un(saun, sc)
+ struct sockaddr_un *saun;
+ const struct svr4_strmcmd *sc;
+{
+ const struct svr4_netaddr_un *na;
+ char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1];
+ const char *src;
+
+ na = SVR4_C_ADDROF(sc);
+ memset(saun, 0, sizeof(*saun));
+ saun->sun_family = na->family;
+ for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; )
+ if (dst == edst)
+ break;
+ saun->sun_len = dst - saun->sun_path;
+ DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family,
+ saun->sun_path));
+}
+
+
+static void
+getparm(fp, pa)
+ struct file *fp;
+ struct svr4_si_sockparms *pa;
+{
+ struct svr4_strm *st;
+ struct socket *so;
+
+ st = svr4_stream_get(fp);
+ if (st == NULL)
+ return;
+
+ so = (struct socket *) fp->f_data;
+
+ pa->family = st->s_family;
+
+ switch (so->so_type) {
+ case SOCK_DGRAM:
+ pa->type = SVR4_T_CLTS;
+ pa->protocol = IPPROTO_UDP;
+ DPRINTF(("getparm(dgram)\n"));
+ return;
+
+ case SOCK_STREAM:
+ pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */
+ pa->protocol = IPPROTO_IP;
+ DPRINTF(("getparm(stream)\n"));
+ return;
+
+ case SOCK_RAW:
+ pa->type = SVR4_T_CLTS;
+ pa->protocol = IPPROTO_RAW;
+ DPRINTF(("getparm(raw)\n"));
+ return;
+
+ default:
+ pa->type = 0;
+ pa->protocol = 0;
+ DPRINTF(("getparm(type %d?)\n", so->so_type));
+ return;
+ }
+}
+
+
+static int
+si_ogetudata(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_si_oudata ud;
+ struct svr4_si_sockparms pa;
+
+ if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) {
+ DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n",
+ sizeof(ud), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
+ return error;
+
+ getparm(fp, &pa);
+
+ switch (pa.family) {
+ case AF_INET:
+ ud.tidusize = 16384;
+ ud.addrsize = sizeof(struct svr4_sockaddr_in);
+ if (pa.type == SVR4_SOCK_STREAM)
+ ud.etsdusize = 1;
+ else
+ ud.etsdusize = 0;
+ break;
+
+ case AF_LOCAL:
+ ud.tidusize = 65536;
+ ud.addrsize = 128;
+ ud.etsdusize = 128;
+ break;
+
+ default:
+ DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n",
+ pa.family));
+ return ENOSYS;
+ }
+
+ /* I have no idea what these should be! */
+ ud.optsize = 128;
+ ud.tsdusize = 128;
+
+ ud.servtype = pa.type;
+
+ /* XXX: Fixme */
+ ud.so_state = 0;
+ ud.so_options = 0;
+ return copyout(&ud, ioc->buf, ioc->len);
+}
+
+
+static int
+si_sockparams(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ struct svr4_si_sockparms pa;
+
+ getparm(fp, &pa);
+ return copyout(&pa, ioc->buf, sizeof(pa));
+}
+
+
+static int
+si_listen(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct svr4_strmcmd lst;
+ struct listen_args la;
+
+ if (st == NULL)
+ return EINVAL;
+
+ if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0)
+ return error;
+
+ if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) {
+ DPRINTF(("si_listen: bad request %ld\n", lst.cmd));
+ return EINVAL;
+ }
+
+ /*
+ * We are making assumptions again...
+ */
+ SCARG(&la, s) = fd;
+ DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5));
+ SCARG(&la, backlog) = 5;
+
+ if ((error = listen(td, &la)) != 0) {
+ DPRINTF(("SI_LISTEN: listen failed %d\n", error));
+ return error;
+ }
+
+ st->s_cmd = SVR4_TI__ACCEPT_WAIT;
+ lst.cmd = SVR4_TI_BIND_REPLY;
+
+ switch (st->s_family) {
+ case AF_INET:
+ /* XXX: Fill the length here */
+ break;
+
+ case AF_LOCAL:
+ lst.len = 140;
+ lst.pad[28] = 0x00000000; /* magic again */
+ lst.pad[29] = 0x00000800; /* magic again */
+ lst.pad[30] = 0x80001400; /* magic again */
+ break;
+
+ default:
+ DPRINTF(("SI_LISTEN: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+
+ if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+si_getudata(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_si_udata ud;
+
+ if (sizeof(ud) != ioc->len) {
+ DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n",
+ sizeof(ud), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0)
+ return error;
+
+ getparm(fp, &ud.sockparms);
+
+ switch (ud.sockparms.family) {
+ case AF_INET:
+ DPRINTF(("getudata_inet\n"));
+ ud.tidusize = 16384;
+ ud.tsdusize = 16384;
+ ud.addrsize = sizeof(struct svr4_sockaddr_in);
+ if (ud.sockparms.type == SVR4_SOCK_STREAM)
+ ud.etsdusize = 1;
+ else
+ ud.etsdusize = 0;
+ ud.optsize = 0;
+ break;
+
+ case AF_LOCAL:
+ DPRINTF(("getudata_local\n"));
+ ud.tidusize = 65536;
+ ud.tsdusize = 128;
+ ud.addrsize = 128;
+ ud.etsdusize = 128;
+ ud.optsize = 128;
+ break;
+
+ default:
+ DPRINTF(("SI_GETUDATA: Unsupported address family %d\n",
+ ud.sockparms.family));
+ return ENOSYS;
+ }
+
+
+ ud.servtype = ud.sockparms.type;
+ DPRINTF(("ud.servtype = %d\n", ud.servtype));
+ /* XXX: Fixme */
+ ud.so_state = 0;
+ ud.so_options = 0;
+ return copyout(&ud, ioc->buf, sizeof(ud));
+}
+
+
+static int
+si_shutdown(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct shutdown_args ap;
+
+ if (ioc->len != sizeof(SCARG(&ap, how))) {
+ DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n",
+ sizeof(SCARG(&ap, how)), ioc->len));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0)
+ return error;
+
+ SCARG(&ap, s) = fd;
+
+ return shutdown(td, &ap);
+}
+
+
+static int
+sockmod(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ switch (ioc->cmd) {
+ case SVR4_SI_OGETUDATA:
+ DPRINTF(("SI_OGETUDATA\n"));
+ return si_ogetudata(fp, fd, ioc, td);
+
+ case SVR4_SI_SHUTDOWN:
+ DPRINTF(("SI_SHUTDOWN\n"));
+ return si_shutdown(fp, fd, ioc, td);
+
+ case SVR4_SI_LISTEN:
+ DPRINTF(("SI_LISTEN\n"));
+ return si_listen(fp, fd, ioc, td);
+
+ case SVR4_SI_SETMYNAME:
+ DPRINTF(("SI_SETMYNAME\n"));
+ return 0;
+
+ case SVR4_SI_SETPEERNAME:
+ DPRINTF(("SI_SETPEERNAME\n"));
+ return 0;
+
+ case SVR4_SI_GETINTRANSIT:
+ DPRINTF(("SI_GETINTRANSIT\n"));
+ return 0;
+
+ case SVR4_SI_TCL_LINK:
+ DPRINTF(("SI_TCL_LINK\n"));
+ return 0;
+
+ case SVR4_SI_TCL_UNLINK:
+ DPRINTF(("SI_TCL_UNLINK\n"));
+ return 0;
+
+ case SVR4_SI_SOCKPARAMS:
+ DPRINTF(("SI_SOCKPARAMS\n"));
+ return si_sockparams(fp, fd, ioc, td);
+
+ case SVR4_SI_GETUDATA:
+ DPRINTF(("SI_GETUDATA\n"));
+ return si_getudata(fp, fd, ioc, td);
+
+ default:
+ DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd));
+ return 0;
+
+ }
+}
+
+
+static int
+ti_getinfo(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_infocmd info;
+
+ memset(&info, 0, sizeof(info));
+
+ if ((error = copyin(ioc->buf, &info, ioc->len)) != 0)
+ return error;
+
+ if (info.cmd != SVR4_TI_INFO_REQUEST)
+ return EINVAL;
+
+ info.cmd = SVR4_TI_INFO_REPLY;
+ info.tsdu = 0;
+ info.etsdu = 1;
+ info.cdata = -2;
+ info.ddata = -2;
+ info.addr = 16;
+ info.opt = -1;
+ info.tidu = 16384;
+ info.serv = 2;
+ info.current = 0;
+ info.provider = 2;
+
+ ioc->len = sizeof(info);
+ if ((error = copyout(&info, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+ti_bind(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ caddr_t sg;
+ void *skp, *sup = NULL;
+ int sasize;
+ struct svr4_strmcmd bnd;
+ struct bind_args ba;
+
+ if (st == NULL) {
+ DPRINTF(("ti_bind: bad file descriptor\n"));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0)
+ return error;
+
+ if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) {
+ DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd));
+ return EINVAL;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ skp = &sain;
+ sasize = sizeof(sain);
+
+ if (bnd.offs == 0)
+ goto reply;
+
+ netaddr_to_sockaddr_in(&sain, &bnd);
+
+ DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n",
+ sain.sin_family, sain.sin_port,
+ sain.sin_addr.s_addr));
+ break;
+
+ case AF_LOCAL:
+ skp = &saun;
+ sasize = sizeof(saun);
+ if (bnd.offs == 0)
+ goto reply;
+
+ netaddr_to_sockaddr_un(&saun, &bnd);
+
+ if (saun.sun_path[0] == '\0')
+ goto reply;
+
+ DPRINTF(("TI_BIND: fam %d, path %s\n",
+ saun.sun_family, saun.sun_path));
+
+ if ((error = clean_pipe(td, saun.sun_path)) != 0)
+ return error;
+
+ bnd.pad[28] = 0x00001000; /* magic again */
+ break;
+
+ default:
+ DPRINTF(("TI_BIND: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ sg = stackgap_init();
+ sup = stackgap_alloc(&sg, sasize);
+
+ if ((error = copyout(skp, sup, sasize)) != 0)
+ return error;
+
+ SCARG(&ba, s) = fd;
+ DPRINTF(("TI_BIND: fileno %d\n", fd));
+ SCARG(&ba, name) = (void *) sup;
+ SCARG(&ba, namelen) = sasize;
+
+ if ((error = bind(td, &ba)) != 0) {
+ DPRINTF(("TI_BIND: bind failed %d\n", error));
+ return error;
+ }
+
+reply:
+ if (sup == NULL) {
+ memset(&bnd, 0, sizeof(bnd));
+ bnd.len = sasize + 4;
+ bnd.offs = 0x10; /* XXX */
+ }
+
+ bnd.cmd = SVR4_TI_BIND_REPLY;
+
+ if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0)
+ return error;
+
+ return 0;
+}
+
+
+static int
+timod(fp, fd, ioc, td)
+ struct file *fp;
+ int fd;
+ struct svr4_strioctl *ioc;
+ struct thread *td;
+{
+ switch (ioc->cmd) {
+ case SVR4_TI_GETINFO:
+ DPRINTF(("TI_GETINFO\n"));
+ return ti_getinfo(fp, fd, ioc, td);
+
+ case SVR4_TI_OPTMGMT:
+ DPRINTF(("TI_OPTMGMT\n"));
+ return 0;
+
+ case SVR4_TI_BIND:
+ DPRINTF(("TI_BIND\n"));
+ return ti_bind(fp, fd, ioc, td);
+
+ case SVR4_TI_UNBIND:
+ DPRINTF(("TI_UNBIND\n"));
+ return 0;
+
+ default:
+ DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd));
+ return 0;
+ }
+}
+
+
+int
+svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ int error;
+ void *skp, *sup;
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ struct svr4_strmcmd sc;
+ int sasize;
+ caddr_t sg;
+ int *lenp;
+
+ DPRINTF(("svr4_stream_ti_ioctl\n"));
+
+ if (st == NULL)
+ return EINVAL;
+
+ sc.offs = 0x10;
+
+ if ((error = copyin(sub, &skb, sizeof(skb))) != 0) {
+ DPRINTF(("ti_ioctl: error copying in strbuf\n"));
+ return error;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ skp = &sain;
+ sasize = sizeof(sain);
+ break;
+
+ case AF_LOCAL:
+ skp = &saun;
+ sasize = sizeof(saun);
+ break;
+
+ default:
+ DPRINTF(("ti_ioctl: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ sg = stackgap_init();
+ sup = stackgap_alloc(&sg, sasize);
+ lenp = stackgap_alloc(&sg, sizeof(*lenp));
+
+ if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
+ DPRINTF(("ti_ioctl: error copying out lenp\n"));
+ return error;
+ }
+
+ switch (cmd) {
+ case SVR4_TI_GETMYNAME:
+ DPRINTF(("TI_GETMYNAME\n"));
+ {
+ struct getsockname_args ap;
+ SCARG(&ap, fdes) = fd;
+ SCARG(&ap, asa) = sup;
+ SCARG(&ap, alen) = lenp;
+ if ((error = getsockname(td, &ap)) != 0) {
+ DPRINTF(("ti_ioctl: getsockname error\n"));
+ return error;
+ }
+ }
+ break;
+
+ case SVR4_TI_GETPEERNAME:
+ DPRINTF(("TI_GETPEERNAME\n"));
+ {
+ struct getpeername_args ap;
+ SCARG(&ap, fdes) = fd;
+ SCARG(&ap, asa) = sup;
+ SCARG(&ap, alen) = lenp;
+ if ((error = getpeername(td, &ap)) != 0) {
+ DPRINTF(("ti_ioctl: getpeername error\n"));
+ return error;
+ }
+ }
+ break;
+
+ case SVR4_TI_SETMYNAME:
+ DPRINTF(("TI_SETMYNAME\n"));
+ return 0;
+
+ case SVR4_TI_SETPEERNAME:
+ DPRINTF(("TI_SETPEERNAME\n"));
+ return 0;
+ default:
+ DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd));
+ return ENOSYS;
+ }
+
+ if ((error = copyin(sup, skp, sasize)) != 0) {
+ DPRINTF(("ti_ioctl: error copying in socket data\n"));
+ return error;
+ }
+
+ if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
+ DPRINTF(("ti_ioctl: error copying in socket size\n"));
+ return error;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ sockaddr_to_netaddr_in(&sc, &sain);
+ skb.len = sasize;
+ break;
+
+ case AF_LOCAL:
+ sockaddr_to_netaddr_un(&sc, &saun);
+ skb.len = sasize + 4;
+ break;
+
+ default:
+ return ENOSYS;
+ }
+
+
+ if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
+ DPRINTF(("ti_ioctl: error copying out socket data\n"));
+ return error;
+ }
+
+
+ if ((error = copyout(&skb, sub, sizeof(skb))) != 0) {
+ DPRINTF(("ti_ioctl: error copying out strbuf\n"));
+ return error;
+ }
+
+ return error;
+}
+
+
+
+
+static int
+i_nread(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error;
+ int nread = 0;
+
+ /*
+ * We are supposed to return the message length in nread, and the
+ * number of messages in retval. We don't have the notion of number
+ * of stream messages, so we just find out if we have any bytes waiting
+ * for us, and if we do, then we assume that we have at least one
+ * message waiting for us.
+ */
+ if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0)
+ return error;
+
+ if (nread != 0)
+ *retval = 1;
+ else
+ *retval = 0;
+
+ return copyout(&nread, dat, sizeof(nread));
+}
+
+static int
+i_fdinsert(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ /*
+ * Major hack again here. We assume that we are using this to
+ * implement accept(2). If that is the case, we have already
+ * called accept, and we have stored the file descriptor in
+ * afd. We find the file descriptor that the code wants to use
+ * in fd insert, and then we dup2() our accepted file descriptor
+ * to it.
+ */
+ int error;
+ struct svr4_strm *st = svr4_stream_get(fp);
+ struct svr4_strfdinsert fdi;
+ struct dup2_args d2p;
+ struct close_args clp;
+
+ if (st == NULL) {
+ DPRINTF(("fdinsert: bad file type\n"));
+ return EINVAL;
+ }
+
+ if (st->s_afd == -1) {
+ DPRINTF(("fdinsert: accept fd not found\n"));
+ return ENOENT;
+ }
+
+ if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) {
+ DPRINTF(("fdinsert: copyin failed %d\n", error));
+ return error;
+ }
+
+ SCARG(&d2p, from) = st->s_afd;
+ SCARG(&d2p, to) = fdi.fd;
+
+ if ((error = dup2(td, &d2p)) != 0) {
+ DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n",
+ st->s_afd, fdi.fd, error));
+ return error;
+ }
+
+ SCARG(&clp, fd) = st->s_afd;
+
+ if ((error = close(td, &clp)) != 0) {
+ DPRINTF(("fdinsert: close(%d) failed %d\n",
+ st->s_afd, error));
+ return error;
+ }
+
+ st->s_afd = -1;
+
+ *retval = 0;
+ return 0;
+}
+
+
+static int
+_i_bind_rsvd(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct mkfifo_args ap;
+
+ /*
+ * This is a supposed to be a kernel and library only ioctl.
+ * It gets called before ti_bind, when we have a unix
+ * socket, to physically create the socket transport and
+ * ``reserve'' it. I don't know how this get reserved inside
+ * the kernel, but we are going to create it nevertheless.
+ */
+ SCARG(&ap, path) = dat;
+ SCARG(&ap, mode) = S_IFIFO;
+
+ return mkfifo(td, &ap);
+}
+
+static int
+_i_rele_rsvd(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ struct unlink_args ap;
+
+ /*
+ * This is a supposed to be a kernel and library only ioctl.
+ * I guess it is supposed to release the socket.
+ */
+ SCARG(&ap, path) = dat;
+
+ return unlink(td, &ap);
+}
+
+static int
+i_str(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error;
+ struct svr4_strioctl ioc;
+
+ if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0)
+ return error;
+
+#ifdef DEBUG_SVR4
+ if ((error = show_ioc(">", &ioc)) != 0)
+ return error;
+#endif /* DEBUG_SVR4 */
+
+ switch (ioc.cmd & 0xff00) {
+ case SVR4_SIMOD:
+ if ((error = sockmod(fp, fd, &ioc, td)) != 0)
+ return error;
+ break;
+
+ case SVR4_TIMOD:
+ if ((error = timod(fp, fd, &ioc, td)) != 0)
+ return error;
+ break;
+
+ default:
+ DPRINTF(("Unimplemented module %c %ld\n",
+ (char) (cmd >> 8), cmd & 0xff));
+ return 0;
+ }
+
+#ifdef DEBUG_SVR4
+ if ((error = show_ioc("<", &ioc)) != 0)
+ return error;
+#endif /* DEBUG_SVR4 */
+ return copyout(&ioc, dat, sizeof(ioc));
+}
+
+static int
+i_setsig(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ /*
+ * This is the best we can do for now; we cannot generate
+ * signals only for specific events so the signal mask gets
+ * ignored; we save it just to pass it to a possible I_GETSIG...
+ *
+ * We alse have to fix the O_ASYNC fcntl bit, so the
+ * process will get SIGPOLLs.
+ */
+ struct fcntl_args fa;
+ int error;
+ register_t oflags, flags;
+ struct svr4_strm *st = svr4_stream_get(fp);
+
+ if (st == NULL) {
+ DPRINTF(("i_setsig: bad file descriptor\n"));
+ return EINVAL;
+ }
+ /* get old status flags */
+ SCARG(&fa, fd) = fd;
+ SCARG(&fa, cmd) = F_GETFL;
+ if ((error = fcntl(td, &fa)) != 0)
+ return error;
+
+ oflags = td->td_retval[0];
+
+ /* update the flags */
+ if (dat != NULL) {
+ int mask;
+
+ flags = oflags | O_ASYNC;
+ if ((error = copyin(dat, &mask, sizeof(mask))) != 0) {
+ DPRINTF(("i_setsig: bad eventmask pointer\n"));
+ return error;
+ }
+ if (mask & SVR4_S_ALLMASK) {
+ DPRINTF(("i_setsig: bad eventmask data %x\n", mask));
+ return EINVAL;
+ }
+ st->s_eventmask = mask;
+ }
+ else {
+ flags = oflags & ~O_ASYNC;
+ st->s_eventmask = 0;
+ }
+
+ /* set the new flags, if changed */
+ if (flags != oflags) {
+ SCARG(&fa, cmd) = F_SETFL;
+ SCARG(&fa, arg) = (long) flags;
+ if ((error = fcntl(td, &fa)) != 0)
+ return error;
+ flags = td->td_retval[0];
+ }
+
+ /* set up SIGIO receiver if needed */
+ if (dat != NULL) {
+ SCARG(&fa, cmd) = F_SETOWN;
+ SCARG(&fa, arg) = (long) td->td_proc->p_pid;
+ return fcntl(td, &fa);
+ }
+ return 0;
+}
+
+static int
+i_getsig(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ int error;
+
+ if (dat != NULL) {
+ struct svr4_strm *st = svr4_stream_get(fp);
+
+ if (st == NULL) {
+ DPRINTF(("i_getsig: bad file descriptor\n"));
+ return EINVAL;
+ }
+ if ((error = copyout(&st->s_eventmask, dat,
+ sizeof(st->s_eventmask))) != 0) {
+ DPRINTF(("i_getsig: bad eventmask pointer\n"));
+ return error;
+ }
+ }
+ return 0;
+}
+
+int
+svr4_stream_ioctl(fp, td, retval, fd, cmd, dat)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t dat;
+{
+ *retval = 0;
+
+ /*
+ * All the following stuff assumes "sockmod" is pushed...
+ */
+ switch (cmd) {
+ case SVR4_I_NREAD:
+ DPRINTF(("I_NREAD\n"));
+ return i_nread(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_PUSH:
+ DPRINTF(("I_PUSH %p\n", dat));
+#if defined(DEBUG_SVR4)
+ show_strbuf((struct svr4_strbuf *)dat);
+#endif
+ return 0;
+
+ case SVR4_I_POP:
+ DPRINTF(("I_POP\n"));
+ return 0;
+
+ case SVR4_I_LOOK:
+ DPRINTF(("I_LOOK\n"));
+ return 0;
+
+ case SVR4_I_FLUSH:
+ DPRINTF(("I_FLUSH\n"));
+ return 0;
+
+ case SVR4_I_SRDOPT:
+ DPRINTF(("I_SRDOPT\n"));
+ return 0;
+
+ case SVR4_I_GRDOPT:
+ DPRINTF(("I_GRDOPT\n"));
+ return 0;
+
+ case SVR4_I_STR:
+ DPRINTF(("I_STR\n"));
+ return i_str(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_SETSIG:
+ DPRINTF(("I_SETSIG\n"));
+ return i_setsig(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_GETSIG:
+ DPRINTF(("I_GETSIG\n"));
+ return i_getsig(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_FIND:
+ DPRINTF(("I_FIND\n"));
+ /*
+ * Here we are not pushing modules really, we just
+ * pretend all are present
+ */
+ *retval = 0;
+ return 0;
+
+ case SVR4_I_LINK:
+ DPRINTF(("I_LINK\n"));
+ return 0;
+
+ case SVR4_I_UNLINK:
+ DPRINTF(("I_UNLINK\n"));
+ return 0;
+
+ case SVR4_I_ERECVFD:
+ DPRINTF(("I_ERECVFD\n"));
+ return 0;
+
+ case SVR4_I_PEEK:
+ DPRINTF(("I_PEEK\n"));
+ return 0;
+
+ case SVR4_I_FDINSERT:
+ DPRINTF(("I_FDINSERT\n"));
+ return i_fdinsert(fp, td, retval, fd, cmd, dat);
+
+ case SVR4_I_SENDFD:
+ DPRINTF(("I_SENDFD\n"));
+ return 0;
+
+ case SVR4_I_RECVFD:
+ DPRINTF(("I_RECVFD\n"));
+ return 0;
+
+ case SVR4_I_SWROPT:
+ DPRINTF(("I_SWROPT\n"));
+ return 0;
+
+ case SVR4_I_GWROPT:
+ DPRINTF(("I_GWROPT\n"));
+ return 0;
+
+ case SVR4_I_LIST:
+ DPRINTF(("I_LIST\n"));
+ return 0;
+
+ case SVR4_I_PLINK:
+ DPRINTF(("I_PLINK\n"));
+ return 0;
+
+ case SVR4_I_PUNLINK:
+ DPRINTF(("I_PUNLINK\n"));
+ return 0;
+
+ case SVR4_I_SETEV:
+ DPRINTF(("I_SETEV\n"));
+ return 0;
+
+ case SVR4_I_GETEV:
+ DPRINTF(("I_GETEV\n"));
+ return 0;
+
+ case SVR4_I_STREV:
+ DPRINTF(("I_STREV\n"));
+ return 0;
+
+ case SVR4_I_UNSTREV:
+ DPRINTF(("I_UNSTREV\n"));
+ return 0;
+
+ case SVR4_I_FLUSHBAND:
+ DPRINTF(("I_FLUSHBAND\n"));
+ return 0;
+
+ case SVR4_I_CKBAND:
+ DPRINTF(("I_CKBAND\n"));
+ return 0;
+
+ case SVR4_I_GETBAND:
+ DPRINTF(("I_GETBANK\n"));
+ return 0;
+
+ case SVR4_I_ATMARK:
+ DPRINTF(("I_ATMARK\n"));
+ return 0;
+
+ case SVR4_I_SETCLTIME:
+ DPRINTF(("I_SETCLTIME\n"));
+ return 0;
+
+ case SVR4_I_GETCLTIME:
+ DPRINTF(("I_GETCLTIME\n"));
+ return 0;
+
+ case SVR4_I_CANPUT:
+ DPRINTF(("I_CANPUT\n"));
+ return 0;
+
+ case SVR4__I_BIND_RSVD:
+ DPRINTF(("_I_BIND_RSVD\n"));
+ return _i_bind_rsvd(fp, td, retval, fd, cmd, dat);
+
+ case SVR4__I_RELE_RSVD:
+ DPRINTF(("_I_RELE_RSVD\n"));
+ return _i_rele_rsvd(fp, td, retval, fd, cmd, dat);
+
+ default:
+ DPRINTF(("unimpl cmd = %lx\n", cmd));
+ break;
+ }
+
+ return 0;
+}
+
+
+
+int
+svr4_sys_putmsg(td, uap)
+ register struct thread *td;
+ struct svr4_sys_putmsg_args *uap;
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, uap->fd, &fp)) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: bad fp\n");
+#endif
+ return EBADF;
+ }
+ error = svr4_do_putmsg(td, uap, fp);
+ fdrop(fp, td);
+ return (error);
+}
+
+static int
+svr4_do_putmsg(td, uap, fp)
+ struct thread *td;
+ struct svr4_sys_putmsg_args *uap;
+ struct file *fp;
+{
+ struct svr4_strbuf dat, ctl;
+ struct svr4_strmcmd sc;
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ void *skp, *sup;
+ int sasize, *retval;
+ struct svr4_strm *st;
+ int error;
+ caddr_t sg;
+
+ retval = td->td_retval;
+
+#ifdef DEBUG_SVR4
+ show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl),
+ SCARG(uap, dat), SCARG(uap, flags));
+#endif /* DEBUG_SVR4 */
+
+ FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
+
+ if (SCARG(uap, ctl) != NULL) {
+ if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: copyin(): %d\n", error);
+#endif
+ return error;
+ }
+ }
+ else
+ ctl.len = -1;
+
+ if (SCARG(uap, dat) != NULL) {
+ if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("putmsg: copyin(): %d (2)\n", error);
+#endif
+ return error;
+ }
+ }
+ else
+ dat.len = -1;
+
+ /*
+ * Only for sockets for now.
+ */
+ if ((st = svr4_stream_get(fp)) == NULL) {
+ DPRINTF(("putmsg: bad file type\n"));
+ return EINVAL;
+ }
+
+ if (ctl.len > sizeof(sc)) {
+ DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len,
+ sizeof(struct svr4_strmcmd)));
+ return EINVAL;
+ }
+
+ if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
+ return error;
+
+ switch (st->s_family) {
+ case AF_INET:
+ if (sc.len != sizeof(sain)) {
+ if (sc.cmd == SVR4_TI_DATA_REQUEST) {
+ struct write_args wa;
+
+ /* Solaris seems to use sc.cmd = 3 to
+ * send "expedited" data. telnet uses
+ * this for options processing, sending EOF,
+ * etc. I'm sure other things use it too.
+ * I don't have any documentation
+ * on it, so I'm making a guess that this
+ * is how it works. newton@atdot.dotat.org XXX
+ */
+ DPRINTF(("sending expedited data ??\n"));
+ SCARG(&wa, fd) = SCARG(uap, fd);
+ SCARG(&wa, buf) = dat.buf;
+ SCARG(&wa, nbyte) = dat.len;
+ return write(td, &wa);
+ }
+ DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len));
+ return EINVAL;
+ }
+ netaddr_to_sockaddr_in(&sain, &sc);
+ skp = &sain;
+ sasize = sizeof(sain);
+ error = sain.sin_family != st->s_family;
+ break;
+
+ case AF_LOCAL:
+ if (ctl.len == 8) {
+ /* We are doing an accept; succeed */
+ DPRINTF(("putmsg: Do nothing\n"));
+ *retval = 0;
+ return 0;
+ }
+ else {
+ /* Maybe we've been given a device/inode pair */
+ udev_t *dev = SVR4_ADDROF(&sc);
+ ino_t *ino = (ino_t *) &dev[1];
+ skp = svr4_find_socket(td, fp, *dev, *ino);
+ if (skp == NULL) {
+ skp = &saun;
+ /* I guess we have it by name */
+ netaddr_to_sockaddr_un(skp, &sc);
+ }
+ sasize = sizeof(saun);
+ }
+ break;
+
+ default:
+ DPRINTF(("putmsg: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ sg = stackgap_init();
+ sup = stackgap_alloc(&sg, sasize);
+
+ if ((error = copyout(skp, sup, sasize)) != 0)
+ return error;
+
+ switch (st->s_cmd = sc.cmd) {
+ case SVR4_TI_CONNECT_REQUEST: /* connect */
+ {
+ struct connect_args co;
+
+ SCARG(&co, s) = SCARG(uap, fd);
+ SCARG(&co, name) = (void *) sup;
+ SCARG(&co, namelen) = (int) sasize;
+
+ return connect(td, &co);
+ }
+
+ case SVR4_TI_SENDTO_REQUEST: /* sendto */
+ {
+ struct msghdr msg;
+ struct iovec aiov;
+
+ msg.msg_name = (caddr_t) sup;
+ msg.msg_namelen = sasize;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = 0;
+ msg.msg_flags = 0;
+ aiov.iov_base = dat.buf;
+ aiov.iov_len = dat.len;
+#if 0
+ error = so->so_proto->pr_usrreqs->pru_sosend(so, 0,
+ uio, 0, 0, 0, uio->uio_td);
+#endif
+ error = svr4_sendit(td, SCARG(uap, fd), &msg,
+ SCARG(uap, flags));
+ DPRINTF(("sendto_request error: %d\n", error));
+ *retval = 0;
+ return error;
+ }
+
+ default:
+ DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd));
+ return ENOSYS;
+ }
+}
+
+int
+svr4_sys_getmsg(td, uap)
+ struct thread *td;
+ struct svr4_sys_getmsg_args *uap;
+{
+ struct file *fp;
+ int error;
+
+ if ((error = fget(td, uap->fd, &fp)) != 0) {
+#ifdef DEBUG_SVR4
+ uprintf("getmsg: bad fp\n");
+#endif
+ return EBADF;
+ }
+ error = svr4_do_getmsg(td, uap, fp);
+ fdrop(fp, td);
+ return (error);
+}
+
+int
+svr4_do_getmsg(td, uap, fp)
+ register struct thread *td;
+ struct svr4_sys_getmsg_args *uap;
+ struct file *fp;
+{
+ struct getpeername_args ga;
+ struct accept_args aa;
+ struct svr4_strbuf dat, ctl;
+ struct svr4_strmcmd sc;
+ int error, *retval;
+ struct msghdr msg;
+ struct iovec aiov;
+ struct sockaddr_in sain;
+ struct sockaddr_un saun;
+ void *skp, *sup;
+ int sasize;
+ struct svr4_strm *st;
+ int *flen;
+ int fl;
+ caddr_t sg;
+
+ retval = td->td_retval;
+
+ FILE_LOCK_ASSERT(fp, MA_NOTOWNED);
+
+ memset(&sc, 0, sizeof(sc));
+
+#ifdef DEBUG_SVR4
+ show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl),
+ SCARG(uap, dat), 0);
+#endif /* DEBUG_SVR4 */
+
+ if (SCARG(uap, ctl) != NULL) {
+ if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0)
+ return error;
+ }
+ else {
+ ctl.len = -1;
+ ctl.maxlen = 0;
+ }
+
+ if (SCARG(uap, dat) != NULL) {
+ if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0)
+ return error;
+ }
+ else {
+ dat.len = -1;
+ dat.maxlen = 0;
+ }
+
+ /*
+ * Only for sockets for now.
+ */
+ if ((st = svr4_stream_get(fp)) == NULL) {
+ DPRINTF(("getmsg: bad file type\n"));
+ return EINVAL;
+ }
+
+ if (ctl.maxlen == -1 || dat.maxlen == -1) {
+ DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n"));
+ return ENOSYS;
+ }
+
+ switch (st->s_family) {
+ case AF_INET:
+ skp = &sain;
+ sasize = sizeof(sain);
+ break;
+
+ case AF_LOCAL:
+ skp = &saun;
+ sasize = sizeof(saun);
+ break;
+
+ default:
+ DPRINTF(("getmsg: Unsupported address family %d\n",
+ st->s_family));
+ return ENOSYS;
+ }
+
+ sg = stackgap_init();
+ sup = stackgap_alloc(&sg, sasize);
+ flen = (int *) stackgap_alloc(&sg, sizeof(*flen));
+
+ fl = sasize;
+ if ((error = copyout(&fl, flen, sizeof(fl))) != 0)
+ return error;
+
+ switch (st->s_cmd) {
+ case SVR4_TI_CONNECT_REQUEST:
+ DPRINTF(("getmsg: TI_CONNECT_REQUEST\n"));
+ /*
+ * We do the connect in one step, so the putmsg should
+ * have gotten the error.
+ */
+ sc.cmd = SVR4_TI_OK_REPLY;
+ sc.len = 0;
+
+ ctl.len = 8;
+ dat.len = -1;
+ fl = 1;
+ st->s_cmd = sc.cmd;
+ break;
+
+ case SVR4_TI_OK_REPLY:
+ DPRINTF(("getmsg: TI_OK_REPLY\n"));
+ /*
+ * We are immediately after a connect reply, so we send
+ * a connect verification.
+ */
+
+ SCARG(&ga, fdes) = SCARG(uap, fd);
+ SCARG(&ga, asa) = (void *) sup;
+ SCARG(&ga, alen) = flen;
+
+ if ((error = getpeername(td, &ga)) != 0) {
+ DPRINTF(("getmsg: getpeername failed %d\n", error));
+ return error;
+ }
+
+ if ((error = copyin(sup, skp, sasize)) != 0)
+ return error;
+
+ sc.cmd = SVR4_TI_CONNECT_REPLY;
+ sc.pad[0] = 0x4;
+ sc.offs = 0x18;
+ sc.pad[1] = 0x14;
+ sc.pad[2] = 0x04000402;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.len = sasize;
+ sockaddr_to_netaddr_in(&sc, &sain);
+ break;
+
+ case AF_LOCAL:
+ sc.len = sasize + 4;
+ sockaddr_to_netaddr_un(&sc, &saun);
+ break;
+
+ default:
+ return ENOSYS;
+ }
+
+ ctl.len = 40;
+ dat.len = -1;
+ fl = 0;
+ st->s_cmd = sc.cmd;
+ break;
+
+ case SVR4_TI__ACCEPT_OK:
+ DPRINTF(("getmsg: TI__ACCEPT_OK\n"));
+ /*
+ * We do the connect in one step, so the putmsg should
+ * have gotten the error.
+ */
+ sc.cmd = SVR4_TI_OK_REPLY;
+ sc.len = 1;
+
+ ctl.len = 8;
+ dat.len = -1;
+ fl = 1;
+ st->s_cmd = SVR4_TI__ACCEPT_WAIT;
+ break;
+
+ case SVR4_TI__ACCEPT_WAIT:
+ DPRINTF(("getmsg: TI__ACCEPT_WAIT\n"));
+ /*
+ * We are after a listen, so we try to accept...
+ */
+ SCARG(&aa, s) = SCARG(uap, fd);
+ SCARG(&aa, name) = (void *) sup;
+ SCARG(&aa, anamelen) = flen;
+
+ if ((error = accept(td, &aa)) != 0) {
+ DPRINTF(("getmsg: accept failed %d\n", error));
+ return error;
+ }
+
+ st->s_afd = *retval;
+
+ DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd));
+
+ if ((error = copyin(sup, skp, sasize)) != 0)
+ return error;
+
+ sc.cmd = SVR4_TI_ACCEPT_REPLY;
+ sc.offs = 0x18;
+ sc.pad[0] = 0x0;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.pad[1] = 0x28;
+ sockaddr_to_netaddr_in(&sc, &sain);
+ ctl.len = 40;
+ sc.len = sasize;
+ break;
+
+ case AF_LOCAL:
+ sc.pad[1] = 0x00010000;
+ sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */
+ sc.pad[3] = 0x00010000;
+ ctl.len = 134;
+ sc.len = sasize + 4;
+ break;
+
+ default:
+ return ENOSYS;
+ }
+
+ dat.len = -1;
+ fl = 0;
+ st->s_cmd = SVR4_TI__ACCEPT_OK;
+ break;
+
+ case SVR4_TI_SENDTO_REQUEST:
+ DPRINTF(("getmsg: TI_SENDTO_REQUEST\n"));
+ if (ctl.maxlen > 36 && ctl.len < 36)
+ ctl.len = 36;
+
+ if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0)
+ return error;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sockaddr_to_netaddr_in(&sc, &sain);
+ break;
+
+ case AF_LOCAL:
+ sockaddr_to_netaddr_un(&sc, &saun);
+ break;
+
+ default:
+ return ENOSYS;
+ }
+
+ msg.msg_name = (caddr_t) sup;
+ msg.msg_namelen = sasize;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = 0;
+ aiov.iov_base = dat.buf;
+ aiov.iov_len = dat.maxlen;
+ msg.msg_flags = 0;
+
+ error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen);
+
+ if (error) {
+ DPRINTF(("getmsg: recvit failed %d\n", error));
+ return error;
+ }
+
+ if ((error = copyin(msg.msg_name, skp, sasize)) != 0)
+ return error;
+
+ sc.cmd = SVR4_TI_RECVFROM_IND;
+
+ switch (st->s_family) {
+ case AF_INET:
+ sc.len = sasize;
+ sockaddr_to_netaddr_in(&sc, &sain);
+ break;
+
+ case AF_LOCAL:
+ sc.len = sasize + 4;
+ sockaddr_to_netaddr_un(&sc, &saun);
+ break;
+
+ default:
+ return ENOSYS;
+ }
+
+ dat.len = *retval;
+ fl = 0;
+ st->s_cmd = sc.cmd;
+ break;
+
+ default:
+ st->s_cmd = sc.cmd;
+ if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) {
+ struct read_args ra;
+
+ /* More weirdness: Again, I can't find documentation
+ * to back this up, but when a process does a generic
+ * "getmsg()" call it seems that the command field is
+ * zero and the length of the data area is zero. I
+ * think processes expect getmsg() to fill in dat.len
+ * after reading at most dat.maxlen octets from the
+ * stream. Since we're using sockets I can let
+ * read() look after it and frob return values
+ * appropriately (or inappropriately :-)
+ * -- newton@atdot.dotat.org XXX
+ */
+ SCARG(&ra, fd) = SCARG(uap, fd);
+ SCARG(&ra, buf) = dat.buf;
+ SCARG(&ra, nbyte) = dat.maxlen;
+ if ((error = read(td, &ra)) != 0) {
+ return error;
+ }
+ dat.len = *retval;
+ *retval = 0;
+ st->s_cmd = SVR4_TI_SENDTO_REQUEST;
+ break;
+ }
+ DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd));
+ return EINVAL;
+ }
+
+ if (SCARG(uap, ctl)) {
+ if (ctl.len != -1)
+ if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0)
+ return error;
+
+ if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0)
+ return error;
+ }
+
+ if (SCARG(uap, dat)) {
+ if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0)
+ return error;
+ }
+
+ if (SCARG(uap, flags)) { /* XXX: Need translation */
+ if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0)
+ return error;
+ }
+
+ *retval = 0;
+
+#ifdef DEBUG_SVR4
+ show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl),
+ SCARG(uap, dat), fl);
+#endif /* DEBUG_SVR4 */
+ return error;
+}
+
+int svr4_sys_send(td, uap)
+ struct thread *td;
+ struct svr4_sys_send_args *uap;
+{
+ struct osend_args osa;
+ SCARG(&osa, s) = SCARG(uap, s);
+ SCARG(&osa, buf) = SCARG(uap, buf);
+ SCARG(&osa, len) = SCARG(uap, len);
+ SCARG(&osa, flags) = SCARG(uap, flags);
+ return osend(td, &osa);
+}
+
+int svr4_sys_recv(td, uap)
+ struct thread *td;
+ struct svr4_sys_recv_args *uap;
+{
+ struct orecv_args ora;
+ SCARG(&ora, s) = SCARG(uap, s);
+ SCARG(&ora, buf) = SCARG(uap, buf);
+ SCARG(&ora, len) = SCARG(uap, len);
+ SCARG(&ora, flags) = SCARG(uap, flags);
+ return orecv(td, &ora);
+}
+
+/*
+ * XXX This isn't necessary, but it's handy for inserting debug code into
+ * sendto(). Let's leave it here for now...
+ */
+int
+svr4_sys_sendto(td, uap)
+ struct thread *td;
+ struct svr4_sys_sendto_args *uap;
+{
+ struct sendto_args sa;
+
+ SCARG(&sa, s) = SCARG(uap, s);
+ SCARG(&sa, buf) = SCARG(uap, buf);
+ SCARG(&sa, len) = SCARG(uap, len);
+ SCARG(&sa, flags) = SCARG(uap, flags);
+ SCARG(&sa, to) = (caddr_t)SCARG(uap, to);
+ SCARG(&sa, tolen) = SCARG(uap, tolen);
+
+ DPRINTF(("calling sendto()\n"));
+ return sendto(td, &sa);
+}
+
diff --git a/sys/compat/svr4/svr4_stropts.h b/sys/compat/svr4/svr4_stropts.h
new file mode 100644
index 0000000..e5a39e9
--- /dev/null
+++ b/sys/compat/svr4/svr4_stropts.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_STROPTS_H_
+#define _SVR4_STROPTS_H_
+
+
+struct svr4_strbuf {
+ int maxlen;
+ int len;
+ char *buf;
+};
+
+#define SVR4_STR ('S' << 8)
+#define SVR4_I_NREAD (SVR4_STR| 1)
+#define SVR4_I_PUSH (SVR4_STR| 2)
+#define SVR4_I_POP (SVR4_STR| 3)
+#define SVR4_I_LOOK (SVR4_STR| 4)
+#define SVR4_I_FLUSH (SVR4_STR| 5)
+#define SVR4_I_SRDOPT (SVR4_STR| 6)
+#define SVR4_I_GRDOPT (SVR4_STR| 7)
+#define SVR4_I_STR (SVR4_STR| 8)
+#define SVR4_I_SETSIG (SVR4_STR| 9)
+#define SVR4_I_GETSIG (SVR4_STR|10)
+#define SVR4_I_FIND (SVR4_STR|11)
+#define SVR4_I_LINK (SVR4_STR|12)
+#define SVR4_I_UNLINK (SVR4_STR|13)
+#define SVR4_I_ERECVFD (SVR4_STR|14)
+#define SVR4_I_PEEK (SVR4_STR|15)
+#define SVR4_I_FDINSERT (SVR4_STR|16)
+#define SVR4_I_SENDFD (SVR4_STR|17)
+#define SVR4_I_RECVFD (SVR4_STR|18)
+#define SVR4_I_SWROPT (SVR4_STR|19)
+#define SVR4_I_GWROPT (SVR4_STR|20)
+#define SVR4_I_LIST (SVR4_STR|21)
+#define SVR4_I_PLINK (SVR4_STR|22)
+#define SVR4_I_PUNLINK (SVR4_STR|23)
+#define SVR4_I_SETEV (SVR4_STR|24)
+#define SVR4_I_GETEV (SVR4_STR|25)
+#define SVR4_I_STREV (SVR4_STR|26)
+#define SVR4_I_UNSTREV (SVR4_STR|27)
+#define SVR4_I_FLUSHBAND (SVR4_STR|28)
+#define SVR4_I_CKBAND (SVR4_STR|29)
+#define SVR4_I_GETBAND (SVR4_STR|30)
+#define SVR4_I_ATMARK (SVR4_STR|31)
+#define SVR4_I_SETCLTIME (SVR4_STR|32)
+#define SVR4_I_GETCLTIME (SVR4_STR|33)
+#define SVR4_I_CANPUT (SVR4_STR|34)
+
+/*
+ * The following two ioctls are OS specific and
+ * undocumented.
+ */
+#define SVR4__I_BIND_RSVD (SVR4_STR|242)
+#define SVR4__I_RELE_RSVD (SVR4_STR|243)
+
+/*
+ * Service type definitions
+ */
+#define SVR4_T_COTS 1 /* Connection-orieted */
+#define SVR4_T_COTS_ORD 2 /* Local connection-oriented */
+#define SVR4_T_CLTS 3 /* Connectionless */
+
+/* Struct passed for SVR4_I_STR */
+struct svr4_strioctl {
+ u_long cmd;
+ int timeout;
+ int len;
+ char *buf;
+};
+
+/*
+ * Bits for I_{G,S}ETSIG
+ */
+#define SVR4_S_INPUT 0x0001 /* any message on read queue no HIPRI */
+#define SVR4_S_HIPRI 0x0002 /* high prio message on read queue */
+#define SVR4_S_OUTPUT 0x0004 /* write queue has free space */
+#define SVR4_S_MSG 0x0008 /* signal message in read queue head */
+#define SVR4_S_ERROR 0x0010 /* error message in read queue head */
+#define SVR4_S_HANGUP 0x0020 /* hangup message in read queue head */
+#define SVR4_S_RDNORM 0x0040 /* normal message on read queue */
+#define SVR4_S_WRNORM S_OUTPUT /* write queue has free space */
+#define SVR4_S_RDBAND 0x0080 /* out of band message on read queue */
+#define SVR4_S_WRBAND 0x0100 /* write queue has free space for oob */
+#define SVR4_S_BANDURG 0x0200 /* generate SIGURG instead of SIGPOLL */
+#define SVR4_S_ALLMASK 0x03ff /* all events mask */
+
+/*
+ * Our internal state for the stream
+ * For now we keep almost nothing... In the future we can keep more
+ * streams state.
+ */
+struct svr4_strm {
+ int s_family; /* socket family */
+ int s_cmd; /* last getmsg reply or putmsg request */
+ int s_afd; /* last accepted fd; [for fd_insert] */
+ int s_eventmask; /* state info from I_SETSIG et al */
+};
+
+/*
+ * The following structures are determined empirically.
+ */
+struct svr4_strmcmd {
+ long cmd; /* command ? */
+ long len; /* Address len */
+ long offs; /* Address offset */
+ long pad[61];
+};
+
+struct svr4_infocmd {
+ long cmd;
+ long tsdu;
+ long etsdu;
+ long cdata;
+ long ddata;
+ long addr;
+ long opt;
+ long tidu;
+ long serv;
+ long current;
+ long provider;
+};
+
+struct svr4_strfdinsert {
+ struct svr4_strbuf ctl;
+ struct svr4_strbuf data;
+ long flags;
+ int fd;
+ int offset;
+};
+
+struct svr4_netaddr_in {
+ u_short family;
+ u_short port;
+ u_long addr;
+};
+
+struct svr4_netaddr_un {
+ u_short family;
+ char path[1];
+};
+
+#define SVR4_ADDROF(sc) (void *) (((char *) (sc)) + (sc)->offs)
+#define SVR4_C_ADDROF(sc) (const void *) (((const char *) (sc)) + (sc)->offs)
+
+struct svr4_strm *svr4_stream_get(struct file *fp);
+
+#endif /* !_SVR4_STROPTS */
diff --git a/sys/compat/svr4/svr4_syscall.h b/sys/compat/svr4/svr4_syscall.h
new file mode 100644
index 0000000..b1898b5
--- /dev/null
+++ b/sys/compat/svr4/svr4_syscall.h
@@ -0,0 +1,145 @@
+/*
+ * System call numbers.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp
+ */
+
+#define SVR4_SYS_exit 1
+#define SVR4_SYS_fork 2
+#define SVR4_SYS_read 3
+#define SVR4_SYS_write 4
+#define SVR4_SYS_svr4_sys_open 5
+#define SVR4_SYS_close 6
+#define SVR4_SYS_svr4_sys_wait 7
+#define SVR4_SYS_svr4_sys_creat 8
+#define SVR4_SYS_link 9
+#define SVR4_SYS_unlink 10
+#define SVR4_SYS_svr4_sys_execv 11
+#define SVR4_SYS_chdir 12
+#define SVR4_SYS_svr4_sys_time 13
+#define SVR4_SYS_svr4_sys_mknod 14
+#define SVR4_SYS_chmod 15
+#define SVR4_SYS_chown 16
+#define SVR4_SYS_svr4_sys_break 17
+#define SVR4_SYS_svr4_sys_stat 18
+#define SVR4_SYS_lseek 19
+#define SVR4_SYS_getpid 20
+#define SVR4_SYS_setuid 23
+#define SVR4_SYS_getuid 24
+#define SVR4_SYS_svr4_sys_alarm 27
+#define SVR4_SYS_svr4_sys_fstat 28
+#define SVR4_SYS_svr4_sys_pause 29
+#define SVR4_SYS_svr4_sys_utime 30
+#define SVR4_SYS_svr4_sys_access 33
+#define SVR4_SYS_svr4_sys_nice 34
+#define SVR4_SYS_sync 36
+#define SVR4_SYS_svr4_sys_kill 37
+#define SVR4_SYS_svr4_sys_pgrpsys 39
+#define SVR4_SYS_dup 41
+#define SVR4_SYS_pipe 42
+#define SVR4_SYS_svr4_sys_times 43
+#define SVR4_SYS_setgid 46
+#define SVR4_SYS_getgid 47
+#define SVR4_SYS_svr4_sys_signal 48
+#define SVR4_SYS_svr4_sys_msgsys 49
+#define SVR4_SYS_svr4_sys_sysarch 50
+#define SVR4_SYS_svr4_sys_ioctl 54
+#define SVR4_SYS_svr4_sys_utssys 57
+#define SVR4_SYS_fsync 58
+#define SVR4_SYS_svr4_sys_execve 59
+#define SVR4_SYS_umask 60
+#define SVR4_SYS_chroot 61
+#define SVR4_SYS_svr4_sys_fcntl 62
+#define SVR4_SYS_svr4_sys_ulimit 63
+#define SVR4_SYS_rmdir 79
+#define SVR4_SYS_mkdir 80
+#define SVR4_SYS_svr4_sys_getdents 81
+#define SVR4_SYS_svr4_sys_getmsg 85
+#define SVR4_SYS_svr4_sys_putmsg 86
+#define SVR4_SYS_svr4_sys_poll 87
+#define SVR4_SYS_svr4_sys_lstat 88
+#define SVR4_SYS_symlink 89
+#define SVR4_SYS_readlink 90
+#define SVR4_SYS_getgroups 91
+#define SVR4_SYS_setgroups 92
+#define SVR4_SYS_fchmod 93
+#define SVR4_SYS_fchown 94
+#define SVR4_SYS_svr4_sys_sigprocmask 95
+#define SVR4_SYS_svr4_sys_sigsuspend 96
+#define SVR4_SYS_svr4_sys_sigaltstack 97
+#define SVR4_SYS_svr4_sys_sigaction 98
+#define SVR4_SYS_svr4_sys_sigpending 99
+#define SVR4_SYS_svr4_sys_context 100
+#define SVR4_SYS_svr4_sys_statvfs 103
+#define SVR4_SYS_svr4_sys_fstatvfs 104
+#define SVR4_SYS_svr4_sys_waitsys 107
+#define SVR4_SYS_svr4_sys_hrtsys 109
+#define SVR4_SYS_svr4_sys_pathconf 113
+#define SVR4_SYS_svr4_sys_mmap 115
+#define SVR4_SYS_mprotect 116
+#define SVR4_SYS_munmap 117
+#define SVR4_SYS_svr4_sys_fpathconf 118
+#define SVR4_SYS_vfork 119
+#define SVR4_SYS_fchdir 120
+#define SVR4_SYS_readv 121
+#define SVR4_SYS_writev 122
+#define SVR4_SYS_svr4_sys_xstat 123
+#define SVR4_SYS_svr4_sys_lxstat 124
+#define SVR4_SYS_svr4_sys_fxstat 125
+#define SVR4_SYS_svr4_sys_xmknod 126
+#define SVR4_SYS_svr4_sys_setrlimit 128
+#define SVR4_SYS_svr4_sys_getrlimit 129
+#define SVR4_SYS_lchown 130
+#define SVR4_SYS_svr4_sys_memcntl 131
+#define SVR4_SYS_rename 134
+#define SVR4_SYS_svr4_sys_uname 135
+#define SVR4_SYS_setegid 136
+#define SVR4_SYS_svr4_sys_sysconfig 137
+#define SVR4_SYS_adjtime 138
+#define SVR4_SYS_svr4_sys_systeminfo 139
+#define SVR4_SYS_seteuid 141
+#define SVR4_SYS_svr4_sys_fchroot 153
+#define SVR4_SYS_svr4_sys_utimes 154
+#define SVR4_SYS_svr4_sys_vhangup 155
+#define SVR4_SYS_svr4_sys_gettimeofday 156
+#define SVR4_SYS_getitimer 157
+#define SVR4_SYS_setitimer 158
+#define SVR4_SYS_svr4_sys_llseek 175
+#define SVR4_SYS_svr4_sys_acl 185
+#define SVR4_SYS_svr4_sys_auditsys 186
+#define SVR4_SYS_nanosleep 199
+#define SVR4_SYS_svr4_sys_facl 200
+#define SVR4_SYS_setreuid 202
+#define SVR4_SYS_setregid 203
+#define SVR4_SYS_svr4_sys_resolvepath 209
+#define SVR4_SYS_svr4_sys_getdents64 213
+#define SVR4_SYS_svr4_sys_mmap64 214
+#define SVR4_SYS_svr4_sys_stat64 215
+#define SVR4_SYS_svr4_sys_lstat64 216
+#define SVR4_SYS_svr4_sys_fstat64 217
+#define SVR4_SYS_svr4_sys_statvfs64 218
+#define SVR4_SYS_svr4_sys_fstatvfs64 219
+#define SVR4_SYS_svr4_sys_setrlimit64 220
+#define SVR4_SYS_svr4_sys_getrlimit64 221
+#define SVR4_SYS_svr4_sys_creat64 224
+#define SVR4_SYS_svr4_sys_open64 225
+#define SVR4_SYS_svr4_sys_socket 230
+#define SVR4_SYS_socketpair 231
+#define SVR4_SYS_bind 232
+#define SVR4_SYS_listen 233
+#define SVR4_SYS_accept 234
+#define SVR4_SYS_connect 235
+#define SVR4_SYS_shutdown 236
+#define SVR4_SYS_svr4_sys_recv 237
+#define SVR4_SYS_recvfrom 238
+#define SVR4_SYS_recvmsg 239
+#define SVR4_SYS_svr4_sys_send 240
+#define SVR4_SYS_sendmsg 241
+#define SVR4_SYS_svr4_sys_sendto 242
+#define SVR4_SYS_getpeername 243
+#define SVR4_SYS_getsockname 244
+#define SVR4_SYS_getsockopt 245
+#define SVR4_SYS_setsockopt 246
+#define SVR4_SYS_MAXSYSCALL 250
diff --git a/sys/compat/svr4/svr4_syscallnames.c b/sys/compat/svr4/svr4_syscallnames.c
new file mode 100644
index 0000000..1f9add4
--- /dev/null
+++ b/sys/compat/svr4/svr4_syscallnames.c
@@ -0,0 +1,264 @@
+/*
+ * System call names.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp
+ */
+
+char *svr4_syscallnames[] = {
+ "#0", /* 0 = unused */
+ "exit", /* 1 = exit */
+ "fork", /* 2 = fork */
+ "read", /* 3 = read */
+ "write", /* 4 = write */
+ "svr4_sys_open", /* 5 = svr4_sys_open */
+ "close", /* 6 = close */
+ "svr4_sys_wait", /* 7 = svr4_sys_wait */
+ "svr4_sys_creat", /* 8 = svr4_sys_creat */
+ "link", /* 9 = link */
+ "unlink", /* 10 = unlink */
+ "svr4_sys_execv", /* 11 = svr4_sys_execv */
+ "chdir", /* 12 = chdir */
+ "svr4_sys_time", /* 13 = svr4_sys_time */
+ "svr4_sys_mknod", /* 14 = svr4_sys_mknod */
+ "chmod", /* 15 = chmod */
+ "chown", /* 16 = chown */
+ "svr4_sys_break", /* 17 = svr4_sys_break */
+ "svr4_sys_stat", /* 18 = svr4_sys_stat */
+ "lseek", /* 19 = lseek */
+ "getpid", /* 20 = getpid */
+ "#21", /* 21 = old_mount */
+ "#22", /* 22 = sysv_umount */
+ "setuid", /* 23 = setuid */
+ "getuid", /* 24 = getuid */
+ "#25", /* 25 = stime */
+ "#26", /* 26 = ptrace */
+ "svr4_sys_alarm", /* 27 = svr4_sys_alarm */
+ "svr4_sys_fstat", /* 28 = svr4_sys_fstat */
+ "svr4_sys_pause", /* 29 = svr4_sys_pause */
+ "svr4_sys_utime", /* 30 = svr4_sys_utime */
+ "#31", /* 31 = stty */
+ "#32", /* 32 = gtty */
+ "svr4_sys_access", /* 33 = svr4_sys_access */
+ "svr4_sys_nice", /* 34 = svr4_sys_nice */
+ "#35", /* 35 = statfs */
+ "sync", /* 36 = sync */
+ "svr4_sys_kill", /* 37 = svr4_sys_kill */
+ "#38", /* 38 = fstatfs */
+ "svr4_sys_pgrpsys", /* 39 = svr4_sys_pgrpsys */
+ "#40", /* 40 = xenix */
+ "dup", /* 41 = dup */
+ "pipe", /* 42 = pipe */
+ "svr4_sys_times", /* 43 = svr4_sys_times */
+ "#44", /* 44 = profil */
+ "#45", /* 45 = plock */
+ "setgid", /* 46 = setgid */
+ "getgid", /* 47 = getgid */
+ "svr4_sys_signal", /* 48 = svr4_sys_signal */
+#if defined(NOTYET)
+ "svr4_sys_msgsys", /* 49 = svr4_sys_msgsys */
+#else
+ "#49", /* 49 = msgsys */
+#endif
+ "svr4_sys_sysarch", /* 50 = svr4_sys_sysarch */
+ "#51", /* 51 = acct */
+ "#52", /* 52 = shmsys */
+ "#53", /* 53 = semsys */
+ "svr4_sys_ioctl", /* 54 = svr4_sys_ioctl */
+ "#55", /* 55 = uadmin */
+ "#56", /* 56 = exch */
+ "svr4_sys_utssys", /* 57 = svr4_sys_utssys */
+ "fsync", /* 58 = fsync */
+ "svr4_sys_execve", /* 59 = svr4_sys_execve */
+ "umask", /* 60 = umask */
+ "chroot", /* 61 = chroot */
+ "svr4_sys_fcntl", /* 62 = svr4_sys_fcntl */
+ "svr4_sys_ulimit", /* 63 = svr4_sys_ulimit */
+ "#64", /* 64 = reserved */
+ "#65", /* 65 = reserved */
+ "#66", /* 66 = reserved */
+ "#67", /* 67 = reserved */
+ "#68", /* 68 = reserved */
+ "#69", /* 69 = reserved */
+ "#70", /* 70 = advfs */
+ "#71", /* 71 = unadvfs */
+ "#72", /* 72 = rmount */
+ "#73", /* 73 = rumount */
+ "#74", /* 74 = rfstart */
+ "#75", /* 75 = sigret */
+ "#76", /* 76 = rdebug */
+ "#77", /* 77 = rfstop */
+ "#78", /* 78 = rfsys */
+ "rmdir", /* 79 = rmdir */
+ "mkdir", /* 80 = mkdir */
+ "svr4_sys_getdents", /* 81 = svr4_sys_getdents */
+ "#82", /* 82 = libattach */
+ "#83", /* 83 = libdetach */
+ "#84", /* 84 = sysfs */
+ "svr4_sys_getmsg", /* 85 = svr4_sys_getmsg */
+ "svr4_sys_putmsg", /* 86 = svr4_sys_putmsg */
+ "svr4_sys_poll", /* 87 = svr4_sys_poll */
+ "svr4_sys_lstat", /* 88 = svr4_sys_lstat */
+ "symlink", /* 89 = symlink */
+ "readlink", /* 90 = readlink */
+ "getgroups", /* 91 = getgroups */
+ "setgroups", /* 92 = setgroups */
+ "fchmod", /* 93 = fchmod */
+ "fchown", /* 94 = fchown */
+ "svr4_sys_sigprocmask", /* 95 = svr4_sys_sigprocmask */
+ "svr4_sys_sigsuspend", /* 96 = svr4_sys_sigsuspend */
+ "svr4_sys_sigaltstack", /* 97 = svr4_sys_sigaltstack */
+ "svr4_sys_sigaction", /* 98 = svr4_sys_sigaction */
+ "svr4_sys_sigpending", /* 99 = svr4_sys_sigpending */
+ "svr4_sys_context", /* 100 = svr4_sys_context */
+ "#101", /* 101 = evsys */
+ "#102", /* 102 = evtrapret */
+ "svr4_sys_statvfs", /* 103 = svr4_sys_statvfs */
+ "svr4_sys_fstatvfs", /* 104 = svr4_sys_fstatvfs */
+ "#105", /* 105 = whoknows */
+ "#106", /* 106 = nfssvc */
+ "svr4_sys_waitsys", /* 107 = svr4_sys_waitsys */
+ "#108", /* 108 = sigsendsys */
+ "svr4_sys_hrtsys", /* 109 = svr4_sys_hrtsys */
+ "#110", /* 110 = acancel */
+ "#111", /* 111 = async */
+ "#112", /* 112 = priocntlsys */
+ "svr4_sys_pathconf", /* 113 = svr4_sys_pathconf */
+ "#114", /* 114 = mincore */
+ "svr4_sys_mmap", /* 115 = svr4_sys_mmap */
+ "mprotect", /* 116 = mprotect */
+ "munmap", /* 117 = munmap */
+ "svr4_sys_fpathconf", /* 118 = svr4_sys_fpathconf */
+ "vfork", /* 119 = vfork */
+ "fchdir", /* 120 = fchdir */
+ "readv", /* 121 = readv */
+ "writev", /* 122 = writev */
+ "svr4_sys_xstat", /* 123 = svr4_sys_xstat */
+ "svr4_sys_lxstat", /* 124 = svr4_sys_lxstat */
+ "svr4_sys_fxstat", /* 125 = svr4_sys_fxstat */
+ "svr4_sys_xmknod", /* 126 = svr4_sys_xmknod */
+ "#127", /* 127 = clocal */
+ "svr4_sys_setrlimit", /* 128 = svr4_sys_setrlimit */
+ "svr4_sys_getrlimit", /* 129 = svr4_sys_getrlimit */
+ "lchown", /* 130 = lchown */
+ "svr4_sys_memcntl", /* 131 = svr4_sys_memcntl */
+ "#132", /* 132 = getpmsg */
+ "#133", /* 133 = putpmsg */
+ "rename", /* 134 = rename */
+ "svr4_sys_uname", /* 135 = svr4_sys_uname */
+ "setegid", /* 136 = setegid */
+ "svr4_sys_sysconfig", /* 137 = svr4_sys_sysconfig */
+ "adjtime", /* 138 = adjtime */
+ "svr4_sys_systeminfo", /* 139 = svr4_sys_systeminfo */
+ "#140", /* 140 = notused */
+ "seteuid", /* 141 = seteuid */
+ "#142", /* 142 = vtrace */
+ "#143", /* 143 = { */
+ "#144", /* 144 = sigtimedwait */
+ "#145", /* 145 = lwp_info */
+ "#146", /* 146 = yield */
+ "#147", /* 147 = lwp_sema_wait */
+ "#148", /* 148 = lwp_sema_post */
+ "#149", /* 149 = lwp_sema_trywait */
+ "#150", /* 150 = notused */
+ "#151", /* 151 = notused */
+ "#152", /* 152 = modctl */
+ "svr4_sys_fchroot", /* 153 = svr4_sys_fchroot */
+ "svr4_sys_utimes", /* 154 = svr4_sys_utimes */
+ "svr4_sys_vhangup", /* 155 = svr4_sys_vhangup */
+ "svr4_sys_gettimeofday", /* 156 = svr4_sys_gettimeofday */
+ "getitimer", /* 157 = getitimer */
+ "setitimer", /* 158 = setitimer */
+ "#159", /* 159 = lwp_create */
+ "#160", /* 160 = lwp_exit */
+ "#161", /* 161 = lwp_suspend */
+ "#162", /* 162 = lwp_continue */
+ "#163", /* 163 = lwp_kill */
+ "#164", /* 164 = lwp_self */
+ "#165", /* 165 = lwp_getprivate */
+ "#166", /* 166 = lwp_setprivate */
+ "#167", /* 167 = lwp_wait */
+ "#168", /* 168 = lwp_mutex_unlock */
+ "#169", /* 169 = lwp_mutex_lock */
+ "#170", /* 170 = lwp_cond_wait */
+ "#171", /* 171 = lwp_cond_signal */
+ "#172", /* 172 = lwp_cond_broadcast */
+ "#173", /* 173 = { */
+ "#174", /* 174 = { */
+ "svr4_sys_llseek", /* 175 = svr4_sys_llseek */
+ "#176", /* 176 = inst_sync */
+ "#177", /* 177 = whoknows */
+ "#178", /* 178 = kaio */
+ "#179", /* 179 = whoknows */
+ "#180", /* 180 = whoknows */
+ "#181", /* 181 = whoknows */
+ "#182", /* 182 = whoknows */
+ "#183", /* 183 = whoknows */
+ "#184", /* 184 = tsolsys */
+ "svr4_sys_acl", /* 185 = svr4_sys_acl */
+ "svr4_sys_auditsys", /* 186 = svr4_sys_auditsys */
+ "#187", /* 187 = processor_bind */
+ "#188", /* 188 = processor_info */
+ "#189", /* 189 = p_online */
+ "#190", /* 190 = sigqueue */
+ "#191", /* 191 = clock_gettime */
+ "#192", /* 192 = clock_settime */
+ "#193", /* 193 = clock_getres */
+ "#194", /* 194 = timer_create */
+ "#195", /* 195 = timer_delete */
+ "#196", /* 196 = timer_settime */
+ "#197", /* 197 = timer_gettime */
+ "#198", /* 198 = timer_overrun */
+ "nanosleep", /* 199 = nanosleep */
+ "svr4_sys_facl", /* 200 = svr4_sys_facl */
+ "#201", /* 201 = door */
+ "setreuid", /* 202 = setreuid */
+ "setregid", /* 203 = setregid */
+ "#204", /* 204 = install_utrap */
+ "#205", /* 205 = signotify */
+ "#206", /* 206 = schedctl */
+ "#207", /* 207 = pset */
+ "#208", /* 208 = whoknows */
+ "svr4_sys_resolvepath", /* 209 = svr4_sys_resolvepath */
+ "#210", /* 210 = signotifywait */
+ "#211", /* 211 = lwp_sigredirect */
+ "#212", /* 212 = lwp_alarm */
+ "svr4_sys_getdents64", /* 213 = svr4_sys_getdents64 */
+ "svr4_sys_mmap64", /* 214 = svr4_sys_mmap64 */
+ "svr4_sys_stat64", /* 215 = svr4_sys_stat64 */
+ "svr4_sys_lstat64", /* 216 = svr4_sys_lstat64 */
+ "svr4_sys_fstat64", /* 217 = svr4_sys_fstat64 */
+ "svr4_sys_statvfs64", /* 218 = svr4_sys_statvfs64 */
+ "svr4_sys_fstatvfs64", /* 219 = svr4_sys_fstatvfs64 */
+ "svr4_sys_setrlimit64", /* 220 = svr4_sys_setrlimit64 */
+ "svr4_sys_getrlimit64", /* 221 = svr4_sys_getrlimit64 */
+ "#222", /* 222 = pread64 */
+ "#223", /* 223 = pwrite64 */
+ "svr4_sys_creat64", /* 224 = svr4_sys_creat64 */
+ "svr4_sys_open64", /* 225 = svr4_sys_open64 */
+ "#226", /* 226 = rpcsys */
+ "#227", /* 227 = whoknows */
+ "#228", /* 228 = whoknows */
+ "#229", /* 229 = whoknows */
+ "svr4_sys_socket", /* 230 = svr4_sys_socket */
+ "socketpair", /* 231 = socketpair */
+ "bind", /* 232 = bind */
+ "listen", /* 233 = listen */
+ "accept", /* 234 = accept */
+ "connect", /* 235 = connect */
+ "shutdown", /* 236 = shutdown */
+ "svr4_sys_recv", /* 237 = svr4_sys_recv */
+ "recvfrom", /* 238 = recvfrom */
+ "recvmsg", /* 239 = recvmsg */
+ "svr4_sys_send", /* 240 = svr4_sys_send */
+ "sendmsg", /* 241 = sendmsg */
+ "svr4_sys_sendto", /* 242 = svr4_sys_sendto */
+ "getpeername", /* 243 = getpeername */
+ "getsockname", /* 244 = getsockname */
+ "getsockopt", /* 245 = getsockopt */
+ "setsockopt", /* 246 = setsockopt */
+ "#247", /* 247 = sockconfig */
+ "#248", /* 248 = { */
+ "#249", /* 249 = { */
+};
diff --git a/sys/compat/svr4/svr4_sysconfig.h b/sys/compat/svr4/svr4_sysconfig.h
new file mode 100644
index 0000000..874c565
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysconfig.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1995 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SYSCONFIG_H_
+#define _SVR4_SYSCONFIG_H_
+
+#define SVR4_CONFIG_UNUSED 0x01
+#define SVR4_CONFIG_NGROUPS 0x02
+#define SVR4_CONFIG_CHILD_MAX 0x03
+#define SVR4_CONFIG_OPEN_FILES 0x04
+#define SVR4_CONFIG_POSIX_VER 0x05
+#define SVR4_CONFIG_PAGESIZE 0x06
+#define SVR4_CONFIG_CLK_TCK 0x07
+#define SVR4_CONFIG_XOPEN_VER 0x08
+#define SVR4_CONFIG_UNUSED_9 0x09
+#define SVR4_CONFIG_PROF_TCK 0x0a
+#define SVR4_CONFIG_NPROC_CONF 0x0b
+#define SVR4_CONFIG_NPROC_ONLN 0x0c
+#define SVR4_CONFIG_AIO_LISTIO_MAX 0x0e
+#define SVR4_CONFIG_AIO_MAX 0x0f
+#define SVR4_CONFIG_AIO_PRIO_DELTA_MAX 0x10
+#define SVR4_CONFIG_DELAYTIMER_MAX 0x11
+#define SVR4_CONFIG_MQ_OPEN_MAX 0x12
+#define SVR4_CONFIG_MQ_PRIO_MAX 0x13
+#define SVR4_CONFIG_RTSIG_MAX 0x14
+#define SVR4_CONFIG_SEM_NSEMS_MAX 0x15
+#define SVR4_CONFIG_SEM_VALUE_MAX 0x16
+#define SVR4_CONFIG_SIGQUEUE_MAX 0x17
+#define SVR4_CONFIG_SIGRT_MIN 0x18
+#define SVR4_CONFIG_SIGRT_MAX 0x19
+#define SVR4_CONFIG_TIMER_MAX 0x20
+#define SVR4_CONFIG_PHYS_PAGES 0x21
+#define SVR4_CONFIG_AVPHYS_PAGES 0x22
+
+#endif /* !_SVR4_SYSCONFIG_H_ */
diff --git a/sys/compat/svr4/svr4_sysent.c b/sys/compat/svr4/svr4_sysent.c
new file mode 100644
index 0000000..2bb003e
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysent.c
@@ -0,0 +1,276 @@
+/*
+ * System call switch table.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * $FreeBSD$
+ * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp
+ */
+
+#include <sys/types.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <netinet/in.h>
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+
+#define AS(name) (sizeof(struct name) / sizeof(register_t))
+
+/* The casts are bogus but will do for now. */
+struct sysent svr4_sysent[] = {
+ { 0, (sy_call_t *)nosys }, /* 0 = unused */
+ { AS(sys_exit_args), (sy_call_t *)sys_exit }, /* 1 = exit */
+ { 0, (sy_call_t *)fork }, /* 2 = fork */
+ { AS(read_args), (sy_call_t *)read }, /* 3 = read */
+ { AS(write_args), (sy_call_t *)write }, /* 4 = write */
+ { AS(svr4_sys_open_args), (sy_call_t *)svr4_sys_open }, /* 5 = svr4_sys_open */
+ { AS(close_args), (sy_call_t *)close }, /* 6 = close */
+ { AS(svr4_sys_wait_args), (sy_call_t *)svr4_sys_wait }, /* 7 = svr4_sys_wait */
+ { AS(svr4_sys_creat_args), (sy_call_t *)svr4_sys_creat }, /* 8 = svr4_sys_creat */
+ { AS(link_args), (sy_call_t *)link }, /* 9 = link */
+ { AS(unlink_args), (sy_call_t *)unlink }, /* 10 = unlink */
+ { AS(svr4_sys_execv_args), (sy_call_t *)svr4_sys_execv }, /* 11 = svr4_sys_execv */
+ { AS(chdir_args), (sy_call_t *)chdir }, /* 12 = chdir */
+ { AS(svr4_sys_time_args), (sy_call_t *)svr4_sys_time }, /* 13 = svr4_sys_time */
+ { AS(svr4_sys_mknod_args), (sy_call_t *)svr4_sys_mknod }, /* 14 = svr4_sys_mknod */
+ { AS(chmod_args), (sy_call_t *)chmod }, /* 15 = chmod */
+ { AS(chown_args), (sy_call_t *)chown }, /* 16 = chown */
+ { AS(svr4_sys_break_args), (sy_call_t *)svr4_sys_break }, /* 17 = svr4_sys_break */
+ { AS(svr4_sys_stat_args), (sy_call_t *)svr4_sys_stat }, /* 18 = svr4_sys_stat */
+ { AS(lseek_args), (sy_call_t *)lseek }, /* 19 = lseek */
+ { 0, (sy_call_t *)getpid }, /* 20 = getpid */
+ { 0, (sy_call_t *)nosys }, /* 21 = old_mount */
+ { 0, (sy_call_t *)nosys }, /* 22 = sysv_umount */
+ { AS(setuid_args), (sy_call_t *)setuid }, /* 23 = setuid */
+ { 0, (sy_call_t *)getuid }, /* 24 = getuid */
+ { 0, (sy_call_t *)nosys }, /* 25 = stime */
+ { 0, (sy_call_t *)nosys }, /* 26 = ptrace */
+ { AS(svr4_sys_alarm_args), (sy_call_t *)svr4_sys_alarm }, /* 27 = svr4_sys_alarm */
+ { AS(svr4_sys_fstat_args), (sy_call_t *)svr4_sys_fstat }, /* 28 = svr4_sys_fstat */
+ { 0, (sy_call_t *)svr4_sys_pause }, /* 29 = svr4_sys_pause */
+ { AS(svr4_sys_utime_args), (sy_call_t *)svr4_sys_utime }, /* 30 = svr4_sys_utime */
+ { 0, (sy_call_t *)nosys }, /* 31 = stty */
+ { 0, (sy_call_t *)nosys }, /* 32 = gtty */
+ { AS(svr4_sys_access_args), (sy_call_t *)svr4_sys_access }, /* 33 = svr4_sys_access */
+ { AS(svr4_sys_nice_args), (sy_call_t *)svr4_sys_nice }, /* 34 = svr4_sys_nice */
+ { 0, (sy_call_t *)nosys }, /* 35 = statfs */
+ { 0, (sy_call_t *)sync }, /* 36 = sync */
+ { AS(svr4_sys_kill_args), (sy_call_t *)svr4_sys_kill }, /* 37 = svr4_sys_kill */
+ { 0, (sy_call_t *)nosys }, /* 38 = fstatfs */
+ { AS(svr4_sys_pgrpsys_args), (sy_call_t *)svr4_sys_pgrpsys }, /* 39 = svr4_sys_pgrpsys */
+ { 0, (sy_call_t *)nosys }, /* 40 = xenix */
+ { AS(dup_args), (sy_call_t *)dup }, /* 41 = dup */
+ { 0, (sy_call_t *)pipe }, /* 42 = pipe */
+ { AS(svr4_sys_times_args), (sy_call_t *)svr4_sys_times }, /* 43 = svr4_sys_times */
+ { 0, (sy_call_t *)nosys }, /* 44 = profil */
+ { 0, (sy_call_t *)nosys }, /* 45 = plock */
+ { AS(setgid_args), (sy_call_t *)setgid }, /* 46 = setgid */
+ { 0, (sy_call_t *)getgid }, /* 47 = getgid */
+ { AS(svr4_sys_signal_args), (sy_call_t *)svr4_sys_signal }, /* 48 = svr4_sys_signal */
+#if defined(NOTYET)
+ { AS(svr4_sys_msgsys_args), (sy_call_t *)svr4_sys_msgsys }, /* 49 = svr4_sys_msgsys */
+#else
+ { 0, (sy_call_t *)nosys }, /* 49 = msgsys */
+#endif
+ { AS(svr4_sys_sysarch_args), (sy_call_t *)svr4_sys_sysarch }, /* 50 = svr4_sys_sysarch */
+ { 0, (sy_call_t *)nosys }, /* 51 = acct */
+ { 0, (sy_call_t *)nosys }, /* 52 = shmsys */
+ { 0, (sy_call_t *)nosys }, /* 53 = semsys */
+ { AS(svr4_sys_ioctl_args), (sy_call_t *)svr4_sys_ioctl }, /* 54 = svr4_sys_ioctl */
+ { 0, (sy_call_t *)nosys }, /* 55 = uadmin */
+ { 0, (sy_call_t *)nosys }, /* 56 = exch */
+ { AS(svr4_sys_utssys_args), (sy_call_t *)svr4_sys_utssys }, /* 57 = svr4_sys_utssys */
+ { AS(fsync_args), (sy_call_t *)fsync }, /* 58 = fsync */
+ { AS(svr4_sys_execve_args), (sy_call_t *)svr4_sys_execve }, /* 59 = svr4_sys_execve */
+ { AS(umask_args), (sy_call_t *)umask }, /* 60 = umask */
+ { AS(chroot_args), (sy_call_t *)chroot }, /* 61 = chroot */
+ { AS(svr4_sys_fcntl_args), (sy_call_t *)svr4_sys_fcntl }, /* 62 = svr4_sys_fcntl */
+ { AS(svr4_sys_ulimit_args), (sy_call_t *)svr4_sys_ulimit }, /* 63 = svr4_sys_ulimit */
+ { 0, (sy_call_t *)nosys }, /* 64 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 65 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 66 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 67 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 68 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 69 = reserved */
+ { 0, (sy_call_t *)nosys }, /* 70 = advfs */
+ { 0, (sy_call_t *)nosys }, /* 71 = unadvfs */
+ { 0, (sy_call_t *)nosys }, /* 72 = rmount */
+ { 0, (sy_call_t *)nosys }, /* 73 = rumount */
+ { 0, (sy_call_t *)nosys }, /* 74 = rfstart */
+ { 0, (sy_call_t *)nosys }, /* 75 = sigret */
+ { 0, (sy_call_t *)nosys }, /* 76 = rdebug */
+ { 0, (sy_call_t *)nosys }, /* 77 = rfstop */
+ { 0, (sy_call_t *)nosys }, /* 78 = rfsys */
+ { AS(rmdir_args), (sy_call_t *)rmdir }, /* 79 = rmdir */
+ { AS(mkdir_args), (sy_call_t *)mkdir }, /* 80 = mkdir */
+ { AS(svr4_sys_getdents_args), (sy_call_t *)svr4_sys_getdents }, /* 81 = svr4_sys_getdents */
+ { 0, (sy_call_t *)nosys }, /* 82 = libattach */
+ { 0, (sy_call_t *)nosys }, /* 83 = libdetach */
+ { 0, (sy_call_t *)nosys }, /* 84 = sysfs */
+ { AS(svr4_sys_getmsg_args), (sy_call_t *)svr4_sys_getmsg }, /* 85 = svr4_sys_getmsg */
+ { AS(svr4_sys_putmsg_args), (sy_call_t *)svr4_sys_putmsg }, /* 86 = svr4_sys_putmsg */
+ { AS(svr4_sys_poll_args), (sy_call_t *)svr4_sys_poll }, /* 87 = svr4_sys_poll */
+ { AS(svr4_sys_lstat_args), (sy_call_t *)svr4_sys_lstat }, /* 88 = svr4_sys_lstat */
+ { AS(symlink_args), (sy_call_t *)symlink }, /* 89 = symlink */
+ { AS(readlink_args), (sy_call_t *)readlink }, /* 90 = readlink */
+ { AS(getgroups_args), (sy_call_t *)getgroups }, /* 91 = getgroups */
+ { AS(setgroups_args), (sy_call_t *)setgroups }, /* 92 = setgroups */
+ { AS(fchmod_args), (sy_call_t *)fchmod }, /* 93 = fchmod */
+ { AS(fchown_args), (sy_call_t *)fchown }, /* 94 = fchown */
+ { AS(svr4_sys_sigprocmask_args), (sy_call_t *)svr4_sys_sigprocmask }, /* 95 = svr4_sys_sigprocmask */
+ { AS(svr4_sys_sigsuspend_args), (sy_call_t *)svr4_sys_sigsuspend }, /* 96 = svr4_sys_sigsuspend */
+ { AS(svr4_sys_sigaltstack_args), (sy_call_t *)svr4_sys_sigaltstack }, /* 97 = svr4_sys_sigaltstack */
+ { AS(svr4_sys_sigaction_args), (sy_call_t *)svr4_sys_sigaction }, /* 98 = svr4_sys_sigaction */
+ { AS(svr4_sys_sigpending_args), (sy_call_t *)svr4_sys_sigpending }, /* 99 = svr4_sys_sigpending */
+ { AS(svr4_sys_context_args), (sy_call_t *)svr4_sys_context }, /* 100 = svr4_sys_context */
+ { 0, (sy_call_t *)nosys }, /* 101 = evsys */
+ { 0, (sy_call_t *)nosys }, /* 102 = evtrapret */
+ { AS(svr4_sys_statvfs_args), (sy_call_t *)svr4_sys_statvfs }, /* 103 = svr4_sys_statvfs */
+ { AS(svr4_sys_fstatvfs_args), (sy_call_t *)svr4_sys_fstatvfs }, /* 104 = svr4_sys_fstatvfs */
+ { 0, (sy_call_t *)nosys }, /* 105 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 106 = nfssvc */
+ { AS(svr4_sys_waitsys_args), (sy_call_t *)svr4_sys_waitsys }, /* 107 = svr4_sys_waitsys */
+ { 0, (sy_call_t *)nosys }, /* 108 = sigsendsys */
+ { AS(svr4_sys_hrtsys_args), (sy_call_t *)svr4_sys_hrtsys }, /* 109 = svr4_sys_hrtsys */
+ { 0, (sy_call_t *)nosys }, /* 110 = acancel */
+ { 0, (sy_call_t *)nosys }, /* 111 = async */
+ { 0, (sy_call_t *)nosys }, /* 112 = priocntlsys */
+ { AS(svr4_sys_pathconf_args), (sy_call_t *)svr4_sys_pathconf }, /* 113 = svr4_sys_pathconf */
+ { 0, (sy_call_t *)nosys }, /* 114 = mincore */
+ { AS(svr4_sys_mmap_args), (sy_call_t *)svr4_sys_mmap }, /* 115 = svr4_sys_mmap */
+ { AS(mprotect_args), (sy_call_t *)mprotect }, /* 116 = mprotect */
+ { AS(munmap_args), (sy_call_t *)munmap }, /* 117 = munmap */
+ { AS(svr4_sys_fpathconf_args), (sy_call_t *)svr4_sys_fpathconf }, /* 118 = svr4_sys_fpathconf */
+ { 0, (sy_call_t *)vfork }, /* 119 = vfork */
+ { AS(fchdir_args), (sy_call_t *)fchdir }, /* 120 = fchdir */
+ { AS(readv_args), (sy_call_t *)readv }, /* 121 = readv */
+ { AS(writev_args), (sy_call_t *)writev }, /* 122 = writev */
+ { AS(svr4_sys_xstat_args), (sy_call_t *)svr4_sys_xstat }, /* 123 = svr4_sys_xstat */
+ { AS(svr4_sys_lxstat_args), (sy_call_t *)svr4_sys_lxstat }, /* 124 = svr4_sys_lxstat */
+ { AS(svr4_sys_fxstat_args), (sy_call_t *)svr4_sys_fxstat }, /* 125 = svr4_sys_fxstat */
+ { AS(svr4_sys_xmknod_args), (sy_call_t *)svr4_sys_xmknod }, /* 126 = svr4_sys_xmknod */
+ { 0, (sy_call_t *)nosys }, /* 127 = clocal */
+ { AS(svr4_sys_setrlimit_args), (sy_call_t *)svr4_sys_setrlimit }, /* 128 = svr4_sys_setrlimit */
+ { AS(svr4_sys_getrlimit_args), (sy_call_t *)svr4_sys_getrlimit }, /* 129 = svr4_sys_getrlimit */
+ { AS(lchown_args), (sy_call_t *)lchown }, /* 130 = lchown */
+ { AS(svr4_sys_memcntl_args), (sy_call_t *)svr4_sys_memcntl }, /* 131 = svr4_sys_memcntl */
+ { 0, (sy_call_t *)nosys }, /* 132 = getpmsg */
+ { 0, (sy_call_t *)nosys }, /* 133 = putpmsg */
+ { AS(rename_args), (sy_call_t *)rename }, /* 134 = rename */
+ { AS(svr4_sys_uname_args), (sy_call_t *)svr4_sys_uname }, /* 135 = svr4_sys_uname */
+ { AS(setegid_args), (sy_call_t *)setegid }, /* 136 = setegid */
+ { AS(svr4_sys_sysconfig_args), (sy_call_t *)svr4_sys_sysconfig }, /* 137 = svr4_sys_sysconfig */
+ { AS(adjtime_args), (sy_call_t *)adjtime }, /* 138 = adjtime */
+ { AS(svr4_sys_systeminfo_args), (sy_call_t *)svr4_sys_systeminfo }, /* 139 = svr4_sys_systeminfo */
+ { 0, (sy_call_t *)nosys }, /* 140 = notused */
+ { AS(seteuid_args), (sy_call_t *)seteuid }, /* 141 = seteuid */
+ { 0, (sy_call_t *)nosys }, /* 142 = vtrace */
+ { 0, (sy_call_t *)nosys }, /* 143 = { */
+ { 0, (sy_call_t *)nosys }, /* 144 = sigtimedwait */
+ { 0, (sy_call_t *)nosys }, /* 145 = lwp_info */
+ { 0, (sy_call_t *)nosys }, /* 146 = yield */
+ { 0, (sy_call_t *)nosys }, /* 147 = lwp_sema_wait */
+ { 0, (sy_call_t *)nosys }, /* 148 = lwp_sema_post */
+ { 0, (sy_call_t *)nosys }, /* 149 = lwp_sema_trywait */
+ { 0, (sy_call_t *)nosys }, /* 150 = notused */
+ { 0, (sy_call_t *)nosys }, /* 151 = notused */
+ { 0, (sy_call_t *)nosys }, /* 152 = modctl */
+ { AS(svr4_sys_fchroot_args), (sy_call_t *)svr4_sys_fchroot }, /* 153 = svr4_sys_fchroot */
+ { AS(svr4_sys_utimes_args), (sy_call_t *)svr4_sys_utimes }, /* 154 = svr4_sys_utimes */
+ { 0, (sy_call_t *)svr4_sys_vhangup }, /* 155 = svr4_sys_vhangup */
+ { AS(svr4_sys_gettimeofday_args), (sy_call_t *)svr4_sys_gettimeofday }, /* 156 = svr4_sys_gettimeofday */
+ { AS(getitimer_args), (sy_call_t *)getitimer }, /* 157 = getitimer */
+ { AS(setitimer_args), (sy_call_t *)setitimer }, /* 158 = setitimer */
+ { 0, (sy_call_t *)nosys }, /* 159 = lwp_create */
+ { 0, (sy_call_t *)nosys }, /* 160 = lwp_exit */
+ { 0, (sy_call_t *)nosys }, /* 161 = lwp_suspend */
+ { 0, (sy_call_t *)nosys }, /* 162 = lwp_continue */
+ { 0, (sy_call_t *)nosys }, /* 163 = lwp_kill */
+ { 0, (sy_call_t *)nosys }, /* 164 = lwp_self */
+ { 0, (sy_call_t *)nosys }, /* 165 = lwp_getprivate */
+ { 0, (sy_call_t *)nosys }, /* 166 = lwp_setprivate */
+ { 0, (sy_call_t *)nosys }, /* 167 = lwp_wait */
+ { 0, (sy_call_t *)nosys }, /* 168 = lwp_mutex_unlock */
+ { 0, (sy_call_t *)nosys }, /* 169 = lwp_mutex_lock */
+ { 0, (sy_call_t *)nosys }, /* 170 = lwp_cond_wait */
+ { 0, (sy_call_t *)nosys }, /* 171 = lwp_cond_signal */
+ { 0, (sy_call_t *)nosys }, /* 172 = lwp_cond_broadcast */
+ { 0, (sy_call_t *)nosys }, /* 173 = { */
+ { 0, (sy_call_t *)nosys }, /* 174 = { */
+ { AS(svr4_sys_llseek_args), (sy_call_t *)svr4_sys_llseek }, /* 175 = svr4_sys_llseek */
+ { 0, (sy_call_t *)nosys }, /* 176 = inst_sync */
+ { 0, (sy_call_t *)nosys }, /* 177 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 178 = kaio */
+ { 0, (sy_call_t *)nosys }, /* 179 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 180 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 181 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 182 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 183 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 184 = tsolsys */
+ { AS(svr4_sys_acl_args), (sy_call_t *)svr4_sys_acl }, /* 185 = svr4_sys_acl */
+ { AS(svr4_sys_auditsys_args), (sy_call_t *)svr4_sys_auditsys }, /* 186 = svr4_sys_auditsys */
+ { 0, (sy_call_t *)nosys }, /* 187 = processor_bind */
+ { 0, (sy_call_t *)nosys }, /* 188 = processor_info */
+ { 0, (sy_call_t *)nosys }, /* 189 = p_online */
+ { 0, (sy_call_t *)nosys }, /* 190 = sigqueue */
+ { 0, (sy_call_t *)nosys }, /* 191 = clock_gettime */
+ { 0, (sy_call_t *)nosys }, /* 192 = clock_settime */
+ { 0, (sy_call_t *)nosys }, /* 193 = clock_getres */
+ { 0, (sy_call_t *)nosys }, /* 194 = timer_create */
+ { 0, (sy_call_t *)nosys }, /* 195 = timer_delete */
+ { 0, (sy_call_t *)nosys }, /* 196 = timer_settime */
+ { 0, (sy_call_t *)nosys }, /* 197 = timer_gettime */
+ { 0, (sy_call_t *)nosys }, /* 198 = timer_overrun */
+ { AS(nanosleep_args), (sy_call_t *)nanosleep }, /* 199 = nanosleep */
+ { AS(svr4_sys_facl_args), (sy_call_t *)svr4_sys_facl }, /* 200 = svr4_sys_facl */
+ { 0, (sy_call_t *)nosys }, /* 201 = door */
+ { AS(setreuid_args), (sy_call_t *)setreuid }, /* 202 = setreuid */
+ { AS(setregid_args), (sy_call_t *)setregid }, /* 203 = setregid */
+ { 0, (sy_call_t *)nosys }, /* 204 = install_utrap */
+ { 0, (sy_call_t *)nosys }, /* 205 = signotify */
+ { 0, (sy_call_t *)nosys }, /* 206 = schedctl */
+ { 0, (sy_call_t *)nosys }, /* 207 = pset */
+ { 0, (sy_call_t *)nosys }, /* 208 = whoknows */
+ { AS(svr4_sys_resolvepath_args), (sy_call_t *)svr4_sys_resolvepath }, /* 209 = svr4_sys_resolvepath */
+ { 0, (sy_call_t *)nosys }, /* 210 = signotifywait */
+ { 0, (sy_call_t *)nosys }, /* 211 = lwp_sigredirect */
+ { 0, (sy_call_t *)nosys }, /* 212 = lwp_alarm */
+ { AS(svr4_sys_getdents64_args), (sy_call_t *)svr4_sys_getdents64 }, /* 213 = svr4_sys_getdents64 */
+ { AS(svr4_sys_mmap64_args), (sy_call_t *)svr4_sys_mmap64 }, /* 214 = svr4_sys_mmap64 */
+ { AS(svr4_sys_stat64_args), (sy_call_t *)svr4_sys_stat64 }, /* 215 = svr4_sys_stat64 */
+ { AS(svr4_sys_lstat64_args), (sy_call_t *)svr4_sys_lstat64 }, /* 216 = svr4_sys_lstat64 */
+ { AS(svr4_sys_fstat64_args), (sy_call_t *)svr4_sys_fstat64 }, /* 217 = svr4_sys_fstat64 */
+ { AS(svr4_sys_statvfs64_args), (sy_call_t *)svr4_sys_statvfs64 }, /* 218 = svr4_sys_statvfs64 */
+ { AS(svr4_sys_fstatvfs64_args), (sy_call_t *)svr4_sys_fstatvfs64 }, /* 219 = svr4_sys_fstatvfs64 */
+ { AS(svr4_sys_setrlimit64_args), (sy_call_t *)svr4_sys_setrlimit64 }, /* 220 = svr4_sys_setrlimit64 */
+ { AS(svr4_sys_getrlimit64_args), (sy_call_t *)svr4_sys_getrlimit64 }, /* 221 = svr4_sys_getrlimit64 */
+ { 0, (sy_call_t *)nosys }, /* 222 = pread64 */
+ { 0, (sy_call_t *)nosys }, /* 223 = pwrite64 */
+ { AS(svr4_sys_creat64_args), (sy_call_t *)svr4_sys_creat64 }, /* 224 = svr4_sys_creat64 */
+ { AS(svr4_sys_open64_args), (sy_call_t *)svr4_sys_open64 }, /* 225 = svr4_sys_open64 */
+ { 0, (sy_call_t *)nosys }, /* 226 = rpcsys */
+ { 0, (sy_call_t *)nosys }, /* 227 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 228 = whoknows */
+ { 0, (sy_call_t *)nosys }, /* 229 = whoknows */
+ { AS(svr4_sys_socket_args), (sy_call_t *)svr4_sys_socket }, /* 230 = svr4_sys_socket */
+ { AS(socketpair_args), (sy_call_t *)socketpair }, /* 231 = socketpair */
+ { AS(bind_args), (sy_call_t *)bind }, /* 232 = bind */
+ { AS(listen_args), (sy_call_t *)listen }, /* 233 = listen */
+ { AS(accept_args), (sy_call_t *)accept }, /* 234 = accept */
+ { AS(connect_args), (sy_call_t *)connect }, /* 235 = connect */
+ { AS(shutdown_args), (sy_call_t *)shutdown }, /* 236 = shutdown */
+ { AS(svr4_sys_recv_args), (sy_call_t *)svr4_sys_recv }, /* 237 = svr4_sys_recv */
+ { AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 238 = recvfrom */
+ { AS(recvmsg_args), (sy_call_t *)recvmsg }, /* 239 = recvmsg */
+ { AS(svr4_sys_send_args), (sy_call_t *)svr4_sys_send }, /* 240 = svr4_sys_send */
+ { AS(sendmsg_args), (sy_call_t *)sendmsg }, /* 241 = sendmsg */
+ { AS(svr4_sys_sendto_args), (sy_call_t *)svr4_sys_sendto }, /* 242 = svr4_sys_sendto */
+ { AS(getpeername_args), (sy_call_t *)getpeername }, /* 243 = getpeername */
+ { AS(getsockname_args), (sy_call_t *)getsockname }, /* 244 = getsockname */
+ { AS(getsockopt_args), (sy_call_t *)getsockopt }, /* 245 = getsockopt */
+ { AS(setsockopt_args), (sy_call_t *)setsockopt }, /* 246 = setsockopt */
+ { 0, (sy_call_t *)nosys }, /* 247 = sockconfig */
+ { 0, (sy_call_t *)nosys }, /* 248 = { */
+ { 0, (sy_call_t *)nosys }, /* 249 = { */
+};
diff --git a/sys/compat/svr4/svr4_systeminfo.h b/sys/compat/svr4/svr4_systeminfo.h
new file mode 100644
index 0000000..40bc2b8
--- /dev/null
+++ b/sys/compat/svr4/svr4_systeminfo.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_SYSTEMINFO_H_
+#define _SVR4_SYSTEMINFO_H_
+
+#define SVR4_SI_SYSNAME 1
+#define SVR4_SI_HOSTNAME 2
+#define SVR4_SI_RELEASE 3
+#define SVR4_SI_VERSION 4
+#define SVR4_SI_MACHINE 5
+#define SVR4_SI_ARCHITECTURE 6
+#define SVR4_SI_HW_SERIAL 7
+#define SVR4_SI_HW_PROVIDER 8
+#define SVR4_SI_SRPC_DOMAIN 9
+#define SVR4_SI_SET_HOSTNAME 258
+#define SVR4_SI_SET_SRPC_DOMAIN 265
+#define SVR4_SI_SET_KERB_REALM 266
+#define SVR4_SI_KERB_REALM 267
+#define SVR4_SI_PLATFORM 513
+#define SVR4_SI_ISALIST 514
+
+#endif /* !_SVR4_SYSTEMINFO_H_ */
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
new file mode 100644
index 0000000..c7d67ff
--- /dev/null
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/* XXX we use functions that might not exist. */
+#include "opt_compat.h"
+
+#ifndef COMPAT_43
+#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/imgact_elf.h>
+#include <sys/socket.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/module.h>
+#include <vm/vm.h>
+#include <sys/exec.h>
+#include <sys/kernel.h>
+#include <machine/cpu.h>
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_syscall.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_sockio.h>
+#include <compat/svr4/svr4_socket.h>
+#include <compat/svr4/svr4_errno.h>
+#include <compat/svr4/svr4_proto.h>
+#include <compat/svr4/svr4_siginfo.h>
+#include <compat/svr4/svr4_util.h>
+
+int bsd_to_svr4_errno[ELAST+1] = {
+ 0,
+ SVR4_EPERM,
+ SVR4_ENOENT,
+ SVR4_ESRCH,
+ SVR4_EINTR,
+ SVR4_EIO,
+ SVR4_ENXIO,
+ SVR4_E2BIG,
+ SVR4_ENOEXEC,
+ SVR4_EBADF,
+ SVR4_ECHILD,
+ SVR4_EDEADLK,
+ SVR4_ENOMEM,
+ SVR4_EACCES,
+ SVR4_EFAULT,
+ SVR4_ENOTBLK,
+ SVR4_EBUSY,
+ SVR4_EEXIST,
+ SVR4_EXDEV,
+ SVR4_ENODEV,
+ SVR4_ENOTDIR,
+ SVR4_EISDIR,
+ SVR4_EINVAL,
+ SVR4_ENFILE,
+ SVR4_EMFILE,
+ SVR4_ENOTTY,
+ SVR4_ETXTBSY,
+ SVR4_EFBIG,
+ SVR4_ENOSPC,
+ SVR4_ESPIPE,
+ SVR4_EROFS,
+ SVR4_EMLINK,
+ SVR4_EPIPE,
+ SVR4_EDOM,
+ SVR4_ERANGE,
+ SVR4_EAGAIN,
+ SVR4_EINPROGRESS,
+ SVR4_EALREADY,
+ SVR4_ENOTSOCK,
+ SVR4_EDESTADDRREQ,
+ SVR4_EMSGSIZE,
+ SVR4_EPROTOTYPE,
+ SVR4_ENOPROTOOPT,
+ SVR4_EPROTONOSUPPORT,
+ SVR4_ESOCKTNOSUPPORT,
+ SVR4_EOPNOTSUPP,
+ SVR4_EPFNOSUPPORT,
+ SVR4_EAFNOSUPPORT,
+ SVR4_EADDRINUSE,
+ SVR4_EADDRNOTAVAIL,
+ SVR4_ENETDOWN,
+ SVR4_ENETUNREACH,
+ SVR4_ENETRESET,
+ SVR4_ECONNABORTED,
+ SVR4_ECONNRESET,
+ SVR4_ENOBUFS,
+ SVR4_EISCONN,
+ SVR4_ENOTCONN,
+ SVR4_ESHUTDOWN,
+ SVR4_ETOOMANYREFS,
+ SVR4_ETIMEDOUT,
+ SVR4_ECONNREFUSED,
+ SVR4_ELOOP,
+ SVR4_ENAMETOOLONG,
+ SVR4_EHOSTDOWN,
+ SVR4_EHOSTUNREACH,
+ SVR4_ENOTEMPTY,
+ SVR4_EPROCLIM,
+ SVR4_EUSERS,
+ SVR4_EDQUOT,
+ SVR4_ESTALE,
+ SVR4_EREMOTE,
+ SVR4_EBADRPC,
+ SVR4_ERPCMISMATCH,
+ SVR4_EPROGUNAVAIL,
+ SVR4_EPROGMISMATCH,
+ SVR4_EPROCUNAVAIL,
+ SVR4_ENOLCK,
+ SVR4_ENOSYS,
+ SVR4_EFTYPE,
+ SVR4_EAUTH,
+ SVR4_ENEEDAUTH,
+ SVR4_EIDRM,
+ SVR4_ENOMSG,
+};
+
+
+static int svr4_fixup(register_t **stack_base, struct image_params *imgp);
+
+extern struct sysent svr4_sysent[];
+#undef szsigcode
+#undef sigcode
+
+extern int svr4_szsigcode;
+extern char svr4_sigcode[];
+
+struct sysentvec svr4_sysvec = {
+ SVR4_SYS_MAXSYSCALL,
+ svr4_sysent,
+ 0xff,
+ SVR4_SIGTBLSZ,
+ bsd_to_svr4_sig,
+ ELAST, /* ELAST */
+ bsd_to_svr4_errno,
+ 0,
+ svr4_fixup,
+ svr4_sendsig,
+ svr4_sigcode,
+ &svr4_szsigcode,
+ NULL,
+ "SVR4",
+ elf32_coredump,
+ NULL,
+ SVR4_MINSIGSTKSZ
+};
+
+Elf32_Brandinfo svr4_brand = {
+ ELFOSABI_SYSV,
+ EM_386, /* XXX only implemented for x86 so far. */
+ "SVR4",
+ svr4_emul_path,
+ "/lib/libc.so.1",
+ &svr4_sysvec
+};
+
+const char svr4_emul_path[] = "/compat/svr4";
+
+static int
+svr4_fixup(register_t **stack_base, struct image_params *imgp)
+{
+ Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
+ register_t *pos;
+
+ pos = *stack_base + (imgp->argc + imgp->envc + 2);
+
+ if (args->trace) {
+ AUXARGS_ENTRY(pos, AT_DEBUG, 1);
+ }
+ if (args->execfd != -1) {
+ AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
+ }
+ AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
+ AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
+ AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
+ AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
+ AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
+ AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
+ AUXARGS_ENTRY(pos, AT_BASE, args->base);
+ PROC_LOCK(imgp->proc);
+ AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+ AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+ AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+ AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+ PROC_UNLOCK(imgp->proc);
+ AUXARGS_ENTRY(pos, AT_NULL, 0);
+
+ free(imgp->auxargs, M_TEMP);
+ imgp->auxargs = NULL;
+
+ (*stack_base)--;
+ **stack_base = (int)imgp->argc;
+ return 0;
+}
+
+/*
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a separate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ *
+ * Code shamelessly stolen by Mark Newton from IBCS2 emulation code.
+ */
+int
+svr4_emul_find(td, sgp, prefix, path, pbuf, cflag)
+ struct thread *td;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+ int error;
+ char *ptr, *buf, *cp;
+ size_t sz, len;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--);
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ *cp = '/';
+ }
+ else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+
+ /*
+ * We now compare the vnode of the svr4_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path,
+ td);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+ NDFREE(&ndroot, NDF_ONLY_PNBUF);
+
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) {
+ goto done;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td))
+ != 0) {
+ goto done;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto done;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+
+done:
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+ return error;
+}
+
+static int
+svr4_elf_modevent(module_t mod, int type, void *data)
+{
+ int error;
+
+ error = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ if (elf32_insert_brand_entry(&svr4_brand) < 0)
+ error = EINVAL;
+ if (error)
+ printf("cannot insert svr4 elf brand handler\n");
+ else if (bootverbose)
+ printf("svr4 ELF exec handler installed\n");
+ break;
+ case MOD_UNLOAD:
+ /* Only allow the emulator to be removed if it isn't in use. */
+ if (elf32_brand_inuse(&svr4_brand) != 0) {
+ error = EBUSY;
+ } else if (elf32_remove_brand_entry(&svr4_brand) < 0) {
+ error = EINVAL;
+ }
+
+ if (error)
+ printf("Could not deinstall ELF interpreter entry (error %d)\n",
+ error);
+ else if (bootverbose)
+ printf("svr4 ELF exec handler removed\n");
+ break;
+ default:
+ break;
+ }
+ return error;
+}
+
+static moduledata_t svr4_elf_mod = {
+ "svr4elf",
+ svr4_elf_modevent,
+ 0
+};
+DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
+MODULE_DEPEND(svr4elf, streams, 1, 1, 1);
diff --git a/sys/compat/svr4/svr4_termios.c b/sys/compat/svr4/svr4_termios.c
new file mode 100644
index 0000000..5fdd5a6
--- /dev/null
+++ b/sys/compat/svr4/svr4_termios.c
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/termios.h>
+
+#include <sys/sysproto.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ioctl.h>
+#include <compat/svr4/svr4_termios.h>
+
+#ifndef __CONCAT3
+# if __STDC__
+# define __CONCAT3(a,b,c) a ## b ## c
+# else
+# define __CONCAT3(a,b,c) a/**/b/**/c
+# endif
+#endif
+
+static u_long bsd_to_svr4_speed(u_long, u_long);
+static u_long svr4_to_bsd_speed(u_long, u_long);
+static void svr4_to_bsd_termios(const struct svr4_termios *,
+ struct termios *, int);
+static void bsd_to_svr4_termios(const struct termios *,
+ struct svr4_termios *);
+static void svr4_termio_to_termios(const struct svr4_termio *,
+ struct svr4_termios *);
+static void svr4_termios_to_termio(const struct svr4_termios *,
+ struct svr4_termio *);
+#ifdef DEBUG_SVR4
+static void print_svr4_termios(const struct svr4_termios *);
+static void print_bsd_termios(const struct termios *);
+#endif /* DEBUG_SVR4 */
+
+#define undefined_char(a,b) /**/
+#define undefined_flag1(f,a,b) /**/
+#define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/
+#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/
+
+#define svr4_to_bsd_char(a,b) \
+ if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \
+ if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \
+ bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \
+ else \
+ bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \
+ }
+
+#define svr4_to_bsd_flag1(f,a,b) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ if (st->f & __CONCAT3(SVR4_,a,b)) \
+ bt->f |= __CONCAT(a,b); \
+ else \
+ bt->f &= ~__CONCAT(a,b); \
+ }
+
+#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ bt->f &= ~__CONCAT(a,b); \
+ switch (st->f & __CONCAT3(SVR4_,a,b)) { \
+ case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
+ case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
+ } \
+ }
+
+#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
+ if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \
+ bt->f &= ~__CONCAT(a,b); \
+ switch (st->f & __CONCAT3(SVR4_,a,b)) { \
+ case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \
+ case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \
+ case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \
+ case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \
+ } \
+ }
+
+
+#define bsd_to_svr4_char(a,b) \
+ if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \
+ st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \
+ else \
+ st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)]
+
+#define bsd_to_svr4_flag1(f,a,b) \
+ if (bt->f & __CONCAT(a,b)) \
+ st->f |= __CONCAT3(SVR4_,a,b); \
+ else \
+ st->f &= ~__CONCAT3(SVR4_,a,b)
+
+#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \
+ st->f &= ~__CONCAT(a,b); \
+ switch (bt->f & __CONCAT(a,b)) { \
+ case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
+ case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
+ }
+
+#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \
+ st->f &= ~__CONCAT(a,b); \
+ switch (bt->f & __CONCAT(a,b)) { \
+ case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \
+ case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \
+ case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \
+ case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \
+ }
+
+#ifdef DEBUG_SVR4
+static void
+print_svr4_termios(st)
+ const struct svr4_termios *st;
+{
+ int i;
+ DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n",
+ st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag));
+ DPRINTF(("cc: "));
+ for (i = 0; i < SVR4_NCCS; i++)
+ DPRINTF(("%o ", st->c_cc[i]));
+ DPRINTF(("\n"));
+}
+
+
+static void
+print_bsd_termios(bt)
+ const struct termios *bt;
+{
+ int i;
+ uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n",
+ bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag);
+ uprintf("cc: ");
+ for (i = 0; i < NCCS; i++)
+ uprintf("%o ", bt->c_cc[i]);
+ uprintf("\n");
+}
+#endif /* DEBUG_SVR4 */
+
+static u_long
+bsd_to_svr4_speed(sp, mask)
+ u_long sp;
+ u_long mask;
+{
+ switch (sp) {
+#undef getval
+#define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b)
+ getval(B,0);
+ getval(B,50);
+ getval(B,75);
+ getval(B,110);
+ getval(B,134);
+ getval(B,150);
+ getval(B,200);
+ getval(B,300);
+ getval(B,600);
+ getval(B,1200);
+ getval(B,1800);
+ getval(B,2400);
+ getval(B,4800);
+ getval(B,9600);
+ getval(B,19200);
+ getval(B,38400);
+ getval(B,57600);
+ getval(B,115200);
+ default: sp = SVR4_B9600; /* XXX */
+ }
+
+ while ((mask & 1) == 0) {
+ mask >>= 1;
+ sp <<= 1;
+ }
+
+ return sp;
+}
+
+
+static u_long
+svr4_to_bsd_speed(sp, mask)
+ u_long sp;
+ u_long mask;
+{
+ while ((mask & 1) == 0) {
+ mask >>= 1;
+ sp >>= 1;
+ }
+
+ switch (sp & mask) {
+#undef getval
+#define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b)
+ getval(B,0);
+ getval(B,50);
+ getval(B,75);
+ getval(B,110);
+ getval(B,134);
+ getval(B,150);
+ getval(B,200);
+ getval(B,300);
+ getval(B,600);
+ getval(B,1200);
+ getval(B,1800);
+ getval(B,2400);
+ getval(B,4800);
+ getval(B,9600);
+ getval(B,19200);
+ getval(B,38400);
+ getval(B,57600);
+ getval(B,115200);
+ default: return B9600; /* XXX */
+ }
+}
+
+
+static void
+svr4_to_bsd_termios(st, bt, new)
+ const struct svr4_termios *st;
+ struct termios *bt;
+ int new;
+{
+ /* control characters */
+ /*
+ * We process VMIN and VTIME first,
+ * because they are shared with VEOF and VEOL
+ */
+ svr4_to_bsd_char(V,MIN);
+ svr4_to_bsd_char(V,TIME);
+
+ svr4_to_bsd_char(V,INTR);
+ svr4_to_bsd_char(V,QUIT);
+ svr4_to_bsd_char(V,ERASE);
+ svr4_to_bsd_char(V,KILL);
+ svr4_to_bsd_char(V,EOF);
+ svr4_to_bsd_char(V,EOL);
+ svr4_to_bsd_char(V,EOL2);
+ undefined_char(V,SWTCH);
+ svr4_to_bsd_char(V,START);
+ svr4_to_bsd_char(V,STOP);
+ svr4_to_bsd_char(V,SUSP);
+ svr4_to_bsd_char(V,DSUSP);
+ svr4_to_bsd_char(V,REPRINT);
+ svr4_to_bsd_char(V,DISCARD);
+ svr4_to_bsd_char(V,WERASE);
+ svr4_to_bsd_char(V,LNEXT);
+
+ /* Input modes */
+ svr4_to_bsd_flag1(c_iflag,I,GNBRK);
+ svr4_to_bsd_flag1(c_iflag,B,RKINT);
+ svr4_to_bsd_flag1(c_iflag,I,GNPAR);
+ svr4_to_bsd_flag1(c_iflag,P,ARMRK);
+ svr4_to_bsd_flag1(c_iflag,I,NPCK);
+ svr4_to_bsd_flag1(c_iflag,I,STRIP);
+ svr4_to_bsd_flag1(c_iflag,I,NLCR);
+ svr4_to_bsd_flag1(c_iflag,I,GNCR);
+ svr4_to_bsd_flag1(c_iflag,I,CRNL);
+ undefined_flag1(c_iflag,I,UCLC);
+ svr4_to_bsd_flag1(c_iflag,I,XON);
+ svr4_to_bsd_flag1(c_iflag,I,XANY);
+ svr4_to_bsd_flag1(c_iflag,I,XOFF);
+ svr4_to_bsd_flag1(c_iflag,I,MAXBEL);
+ undefined_flag1(c_iflag,D,OSMODE);
+
+ /* Output modes */
+ svr4_to_bsd_flag1(c_oflag,O,POST);
+ undefined_flag1(c_oflag,O,LCUC);
+ svr4_to_bsd_flag1(c_oflag,O,NLCR);
+ undefined_flag1(c_oflag,O,CRNL);
+ undefined_flag1(c_oflag,O,NOCR);
+ undefined_flag1(c_oflag,O,NLRET);
+ undefined_flag1(c_oflag,O,FILL);
+ undefined_flag1(c_oflag,O,FDEL);
+ undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
+ undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
+ undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
+ undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
+ undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
+ undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
+ undefined_flag1(c_oflag,P,AGEOUT);
+ undefined_flag1(c_oflag,W,RAP);
+
+ /* Control modes */
+ bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD);
+ svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
+ svr4_to_bsd_flag1(c_cflag,C,STOPB);
+ svr4_to_bsd_flag1(c_cflag,C,READ);
+ svr4_to_bsd_flag1(c_cflag,P,ARENB);
+ svr4_to_bsd_flag1(c_cflag,P,ARODD);
+ svr4_to_bsd_flag1(c_cflag,H,UPCL);
+ svr4_to_bsd_flag1(c_cflag,C,LOCAL);
+ undefined_flag1(c_cflag,R,CV1EN);
+ undefined_flag1(c_cflag,X,MT1EN);
+ undefined_flag1(c_cflag,L,OBLK);
+ undefined_flag1(c_cflag,X,CLUDE);
+ bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD);
+ undefined_flag1(c_cflag,P,AREXT);
+
+ /* line discipline modes */
+ svr4_to_bsd_flag1(c_lflag,I,SIG);
+ svr4_to_bsd_flag1(c_lflag,I,CANON);
+ undefined_flag1(c_lflag,X,CASE);
+ svr4_to_bsd_flag1(c_lflag,E,CHO);
+ svr4_to_bsd_flag1(c_lflag,E,CHOE);
+ svr4_to_bsd_flag1(c_lflag,E,CHOK);
+ svr4_to_bsd_flag1(c_lflag,E,CHONL);
+ svr4_to_bsd_flag1(c_lflag,N,OFLSH);
+ svr4_to_bsd_flag1(c_lflag,T,OSTOP);
+ svr4_to_bsd_flag1(c_lflag,E,CHOCTL);
+ svr4_to_bsd_flag1(c_lflag,E,CHOPRT);
+ svr4_to_bsd_flag1(c_lflag,E,CHOKE);
+ undefined_flag1(c_lflag,D,EFECHO);
+ svr4_to_bsd_flag1(c_lflag,F,LUSHO);
+ svr4_to_bsd_flag1(c_lflag,P,ENDIN);
+ svr4_to_bsd_flag1(c_lflag,I,EXTEN);
+}
+
+
+static void
+bsd_to_svr4_termios(bt, st)
+ const struct termios *bt;
+ struct svr4_termios *st;
+{
+ /* control characters */
+ /*
+ * We process VMIN and VTIME first,
+ * because they are shared with VEOF and VEOL
+ */
+ bsd_to_svr4_char(V,MIN);
+ bsd_to_svr4_char(V,TIME);
+ bsd_to_svr4_char(V,INTR);
+ bsd_to_svr4_char(V,QUIT);
+ bsd_to_svr4_char(V,ERASE);
+ bsd_to_svr4_char(V,KILL);
+ bsd_to_svr4_char(V,EOF);
+ bsd_to_svr4_char(V,EOL);
+ bsd_to_svr4_char(V,EOL2);
+ undefined_char(V,SWTCH);
+ bsd_to_svr4_char(V,START);
+ bsd_to_svr4_char(V,STOP);
+ bsd_to_svr4_char(V,SUSP);
+ bsd_to_svr4_char(V,DSUSP);
+ bsd_to_svr4_char(V,REPRINT);
+ bsd_to_svr4_char(V,DISCARD);
+ bsd_to_svr4_char(V,WERASE);
+ bsd_to_svr4_char(V,LNEXT);
+
+ /* Input modes */
+ bsd_to_svr4_flag1(c_iflag,I,GNBRK);
+ bsd_to_svr4_flag1(c_iflag,B,RKINT);
+ bsd_to_svr4_flag1(c_iflag,I,GNPAR);
+ bsd_to_svr4_flag1(c_iflag,P,ARMRK);
+ bsd_to_svr4_flag1(c_iflag,I,NPCK);
+ bsd_to_svr4_flag1(c_iflag,I,STRIP);
+ bsd_to_svr4_flag1(c_iflag,I,NLCR);
+ bsd_to_svr4_flag1(c_iflag,I,GNCR);
+ bsd_to_svr4_flag1(c_iflag,I,CRNL);
+ undefined_flag1(c_iflag,I,UCLC);
+ bsd_to_svr4_flag1(c_iflag,I,XON);
+ bsd_to_svr4_flag1(c_iflag,I,XANY);
+ bsd_to_svr4_flag1(c_iflag,I,XOFF);
+ bsd_to_svr4_flag1(c_iflag,I,MAXBEL);
+ undefined_flag1(c_iflag,D,OSMODE);
+
+ /* Output modes */
+ bsd_to_svr4_flag1(c_oflag,O,POST);
+ undefined_flag1(c_oflag,O,LCUC);
+ bsd_to_svr4_flag1(c_oflag,O,NLCR);
+ undefined_flag1(c_oflag,O,CRNL);
+ undefined_flag1(c_oflag,O,NOCR);
+ undefined_flag1(c_oflag,O,NLRET);
+ undefined_flag1(c_oflag,O,FILL);
+ undefined_flag1(c_oflag,O,FDEL);
+ undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1);
+ undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3);
+ undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3);
+ undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1);
+ undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1);
+ undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1);
+ undefined_flag1(c_oflag,P,AGEOUT);
+ undefined_flag1(c_oflag,W,RAP);
+
+ /* Control modes */
+ st->c_cflag &= ~SVR4_CBAUD;
+ st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD);
+ bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8)
+ bsd_to_svr4_flag1(c_cflag,C,STOPB);
+ bsd_to_svr4_flag1(c_cflag,C,READ);
+ bsd_to_svr4_flag1(c_cflag,P,ARENB);
+ bsd_to_svr4_flag1(c_cflag,P,ARODD);
+ bsd_to_svr4_flag1(c_cflag,H,UPCL);
+ bsd_to_svr4_flag1(c_cflag,C,LOCAL);
+ undefined_flag1(c_cflag,R,CV1EN);
+ undefined_flag1(c_cflag,X,MT1EN);
+ undefined_flag1(c_cflag,L,OBLK);
+ undefined_flag1(c_cflag,X,CLUDE);
+ st->c_cflag &= ~SVR4_CIBAUD;
+ st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD);
+
+ undefined_flag1(c_oflag,P,AREXT);
+
+ /* line discipline modes */
+ bsd_to_svr4_flag1(c_lflag,I,SIG);
+ bsd_to_svr4_flag1(c_lflag,I,CANON);
+ undefined_flag1(c_lflag,X,CASE);
+ bsd_to_svr4_flag1(c_lflag,E,CHO);
+ bsd_to_svr4_flag1(c_lflag,E,CHOE);
+ bsd_to_svr4_flag1(c_lflag,E,CHOK);
+ bsd_to_svr4_flag1(c_lflag,E,CHONL);
+ bsd_to_svr4_flag1(c_lflag,N,OFLSH);
+ bsd_to_svr4_flag1(c_lflag,T,OSTOP);
+ bsd_to_svr4_flag1(c_lflag,E,CHOCTL);
+ bsd_to_svr4_flag1(c_lflag,E,CHOPRT);
+ bsd_to_svr4_flag1(c_lflag,E,CHOKE);
+ undefined_flag1(c_lflag,D,EFECHO);
+ bsd_to_svr4_flag1(c_lflag,F,LUSHO);
+ bsd_to_svr4_flag1(c_lflag,P,ENDIN);
+ bsd_to_svr4_flag1(c_lflag,I,EXTEN);
+}
+
+
+static void
+svr4_termio_to_termios(t, ts)
+ const struct svr4_termio *t;
+ struct svr4_termios *ts;
+{
+ int i;
+
+ ts->c_iflag = (svr4_tcflag_t) t->c_iflag;
+ ts->c_oflag = (svr4_tcflag_t) t->c_oflag;
+ ts->c_cflag = (svr4_tcflag_t) t->c_cflag;
+ ts->c_lflag = (svr4_tcflag_t) t->c_lflag;
+
+ for (i = 0; i < SVR4_NCC; i++)
+ ts->c_cc[i] = (svr4_cc_t) t->c_cc[i];
+}
+
+
+static void
+svr4_termios_to_termio(ts, t)
+ const struct svr4_termios *ts;
+ struct svr4_termio *t;
+{
+ int i;
+
+ t->c_iflag = (u_short) ts->c_iflag;
+ t->c_oflag = (u_short) ts->c_oflag;
+ t->c_cflag = (u_short) ts->c_cflag;
+ t->c_lflag = (u_short) ts->c_lflag;
+ t->c_line = 0; /* XXX */
+
+ for (i = 0; i < SVR4_NCC; i++)
+ t->c_cc[i] = (u_char) ts->c_cc[i];
+}
+
+int
+svr4_term_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ struct termios bt;
+ struct svr4_termios st;
+ struct svr4_termio t;
+ int error, new;
+
+ *retval = 0;
+
+ DPRINTF(("TERM ioctl %lx\n", cmd));
+
+ switch (cmd) {
+ case SVR4_TCGETA:
+ case SVR4_TCGETS:
+ DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S'));
+ if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
+ return error;
+
+ memset(&st, 0, sizeof(st));
+ bsd_to_svr4_termios(&bt, &st);
+
+#ifdef DEBUG_SVR4
+ print_bsd_termios(&bt);
+ print_svr4_termios(&st);
+#endif /* DEBUG_SVR4 */
+
+ if (cmd == SVR4_TCGETA) {
+ svr4_termios_to_termio(&st, &t);
+ return copyout(&t, data, sizeof(t));
+ }
+ else {
+ return copyout(&st, data, sizeof(st));
+ }
+
+ case SVR4_TCSETA:
+ case SVR4_TCSETS:
+ case SVR4_TCSETAW:
+ case SVR4_TCSETSW:
+ case SVR4_TCSETAF:
+ case SVR4_TCSETSF:
+ DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n"));
+ /* get full BSD termios so we don't lose information */
+ if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0)
+ return error;
+
+ switch (cmd) {
+ case SVR4_TCSETS:
+ case SVR4_TCSETSW:
+ case SVR4_TCSETSF:
+ if ((error = copyin(data, &st, sizeof(st))) != 0)
+ return error;
+ new = 1;
+ break;
+
+ case SVR4_TCSETA:
+ case SVR4_TCSETAW:
+ case SVR4_TCSETAF:
+ if ((error = copyin(data, &t, sizeof(t))) != 0)
+ return error;
+
+ svr4_termio_to_termios(&t, &st);
+ new = 0;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ svr4_to_bsd_termios(&st, &bt, new);
+
+ switch (cmd) {
+ case SVR4_TCSETA:
+ case SVR4_TCSETS:
+ DPRINTF(("ioctl(TCSET[A|S]);\n"));
+ cmd = TIOCSETA;
+ break;
+ case SVR4_TCSETAW:
+ case SVR4_TCSETSW:
+ DPRINTF(("ioctl(TCSET[A|S]W);\n"));
+ cmd = TIOCSETAW;
+ break;
+ case SVR4_TCSETAF:
+ case SVR4_TCSETSF:
+ DPRINTF(("ioctl(TCSET[A|S]F);\n"));
+ cmd = TIOCSETAF;
+ break;
+ }
+
+#ifdef DEBUG_SVR4
+ print_bsd_termios(&bt);
+ print_svr4_termios(&st);
+#endif /* DEBUG_SVR4 */
+
+ return fo_ioctl(fp, cmd, (caddr_t) &bt, td);
+
+ case SVR4_TIOCGWINSZ:
+ DPRINTF(("TIOCGWINSZ\n"));
+ {
+ struct svr4_winsize ws;
+
+ error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, td);
+ if (error)
+ return error;
+ return copyout(&ws, data, sizeof(ws));
+ }
+
+ case SVR4_TIOCSWINSZ:
+ DPRINTF(("TIOCSWINSZ\n"));
+ {
+ struct svr4_winsize ws;
+
+ if ((error = copyin(data, &ws, sizeof(ws))) != 0)
+ return error;
+ return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, td);
+ }
+
+ default:
+ DPRINTF(("teleport to STREAMS ioctls...\n"));
+ return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data);
+ }
+}
diff --git a/sys/compat/svr4/svr4_termios.h b/sys/compat/svr4/svr4_termios.h
new file mode 100644
index 0000000..8afa4f3
--- /dev/null
+++ b/sys/compat/svr4/svr4_termios.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TERMIOS_H_
+#define _SVR4_TERMIOS_H_
+
+#define SVR4_POSIX_VDISABLE 0
+#define SVR4_NCC 8
+#define SVR4_NCCS 19
+
+typedef u_long svr4_tcflag_t;
+typedef u_char svr4_cc_t;
+typedef u_long svr4_speed_t;
+
+struct svr4_termios {
+ svr4_tcflag_t c_iflag;
+ svr4_tcflag_t c_oflag;
+ svr4_tcflag_t c_cflag;
+ svr4_tcflag_t c_lflag;
+ svr4_cc_t c_cc[SVR4_NCCS];
+};
+
+struct svr4_termio {
+ u_short c_iflag;
+ u_short c_oflag;
+ u_short c_cflag;
+ u_short c_lflag;
+ char c_line;
+ u_char c_cc[SVR4_NCC];
+};
+
+/* control characters */
+#define SVR4_VINTR 0
+#define SVR4_VQUIT 1
+#define SVR4_VERASE 2
+#define SVR4_VKILL 3
+#define SVR4_VEOF 4
+#define SVR4_VEOL 5
+#define SVR4_VEOL2 6
+#define SVR4_VMIN 4
+#define SVR4_VTIME 5
+#define SVR4_VSWTCH 7
+#define SVR4_VSTART 8
+#define SVR4_VSTOP 9
+#define SVR4_VSUSP 10
+#define SVR4_VDSUSP 11
+#define SVR4_VREPRINT 12
+#define SVR4_VDISCARD 13
+#define SVR4_VWERASE 14
+#define SVR4_VLNEXT 15
+
+/* Input modes */
+#define SVR4_IGNBRK 00000001
+#define SVR4_BRKINT 00000002
+#define SVR4_IGNPAR 00000004
+#define SVR4_PARMRK 00000010
+#define SVR4_INPCK 00000020
+#define SVR4_ISTRIP 00000040
+#define SVR4_INLCR 00000100
+#define SVR4_IGNCR 00000200
+#define SVR4_ICRNL 00000400
+#define SVR4_IUCLC 00001000
+#define SVR4_IXON 00002000
+#define SVR4_IXANY 00004000
+#define SVR4_IXOFF 00010000
+#define SVR4_IMAXBEL 00020000
+#define SVR4_DOSMODE 00100000
+
+/* Output modes */
+#define SVR4_OPOST 00000001
+#define SVR4_OLCUC 00000002
+#define SVR4_ONLCR 00000004
+#define SVR4_OCRNL 00000010
+#define SVR4_ONOCR 00000020
+#define SVR4_ONLRET 00000040
+#define SVR4_OFILL 00000100
+#define SVR4_OFDEL 00000200
+#define SVR4_NLDLY 00000400
+#define SVR4_NL0 00000000
+#define SVR4_NL1 00000400
+#define SVR4_CRDLY 00003000
+#define SVR4_CR0 00000000
+#define SVR4_CR1 00001000
+#define SVR4_CR2 00002000
+#define SVR4_CR3 00003000
+#define SVR4_TABDLY 00014000
+#define SVR4_TAB0 00000000
+#define SVR4_TAB1 00004000
+#define SVR4_TAB2 00010000
+#define SVR4_TAB3 00014000
+#define SVR4_XTABS 00014000
+#define SVR4_BSDLY 00020000
+#define SVR4_BS0 00000000
+#define SVR4_BS1 00020000
+#define SVR4_VTDLY 00040000
+#define SVR4_VT0 00000000
+#define SVR4_VT1 00040000
+#define SVR4_FFDLY 00100000
+#define SVR4_FF0 00000000
+#define SVR4_FF1 00100000
+#define SVR4_PAGEOUT 00200000
+#define SVR4_WRAP 00400000
+
+/* Control modes */
+#define SVR4_CBAUD 00000017
+#define SVR4_CSIZE 00000060
+#define SVR4_CS5 00000000
+#define SVR4_CS6 00000200
+#define SVR4_CS7 00000040
+#define SVR4_CS8 00000006
+#define SVR4_CSTOPB 00000100
+#define SVR4_CREAD 00000200
+#define SVR4_PARENB 00000400
+#define SVR4_PARODD 00001000
+#define SVR4_HUPCL 00002000
+#define SVR4_CLOCAL 00004000
+#define SVR4_RCV1EN 00010000
+#define SVR4_XMT1EN 00020000
+#define SVR4_LOBLK 00040000
+#define SVR4_XCLUDE 00100000
+#define SVR4_CIBAUD 03600000
+#define SVR4_PAREXT 04000000
+
+/* line discipline modes */
+#define SVR4_ISIG 00000001
+#define SVR4_ICANON 00000002
+#define SVR4_XCASE 00000004
+#define SVR4_ECHO 00000010
+#define SVR4_ECHOE 00000020
+#define SVR4_ECHOK 00000040
+#define SVR4_ECHONL 00000100
+#define SVR4_NOFLSH 00000200
+#define SVR4_TOSTOP 00000400
+#define SVR4_ECHOCTL 00001000
+#define SVR4_ECHOPRT 00002000
+#define SVR4_ECHOKE 00004000
+#define SVR4_DEFECHO 00010000
+#define SVR4_FLUSHO 00020000
+#define SVR4_PENDIN 00040000
+#define SVR4_IEXTEN 00100000
+
+#define SVR4_TIOC ('T' << 8)
+
+#define SVR4_TCGETA (SVR4_TIOC| 1)
+#define SVR4_TCSETA (SVR4_TIOC| 2)
+#define SVR4_TCSETAW (SVR4_TIOC| 3)
+#define SVR4_TCSETAF (SVR4_TIOC| 4)
+#define SVR4_TCSBRK (SVR4_TIOC| 5)
+#define SVR4_TCXONC (SVR4_TIOC| 6)
+#define SVR4_TCFLSH (SVR4_TIOC| 7)
+#define SVR4_TIOCKBON (SVR4_TIOC| 8)
+#define SVR4_TIOCKBOF (SVR4_TIOC| 9)
+#define SVR4_KBENABLED (SVR4_TIOC|10)
+#define SVR4_TCGETS (SVR4_TIOC|13)
+#define SVR4_TCSETS (SVR4_TIOC|14)
+#define SVR4_TCSETSW (SVR4_TIOC|15)
+#define SVR4_TCSETSF (SVR4_TIOC|16)
+#define SVR4_TCDSET (SVR4_TIOC|32)
+#define SVR4_RTS_TOG (SVR4_TIOC|33)
+#define SVR4_TCGETSC (SVR4_TIOC|34)
+#define SVR4_TCSETSC (SVR4_TIOC|35)
+#define SVR4_TCMOUSE (SVR4_TIOC|36)
+#define SVR4_TIOCGWINSZ (SVR4_TIOC|104)
+#define SVR4_TIOCSWINSZ (SVR4_TIOC|103)
+
+struct svr4_winsize {
+ u_short ws_row;
+ u_short ws_col;
+ u_short ws_xpixel;
+ u_short ws_ypixel;
+};
+
+#define SVR4_B0 0
+#define SVR4_B50 1
+#define SVR4_B75 2
+#define SVR4_B110 3
+#define SVR4_B134 4
+#define SVR4_B150 5
+#define SVR4_B200 6
+#define SVR4_B300 7
+#define SVR4_B600 8
+#define SVR4_B1200 9
+#define SVR4_B1800 10
+#define SVR4_B2400 11
+#define SVR4_B4800 12
+#define SVR4_B9600 13
+#define SVR4_B19200 14
+#define SVR4_B38400 15
+#define SVR4_B57600 16
+#define SVR4_B76800 17
+#define SVR4_B115200 18
+#define SVR4_B153600 19
+#define SVR4_B230400 20
+#define SVR4_B307200 21
+#define SVR4_B460800 22
+
+#endif /* !_SVR4_TERMIOS_H_ */
diff --git a/sys/compat/svr4/svr4_time.h b/sys/compat/svr4/svr4_time.h
new file mode 100644
index 0000000..3d61771
--- /dev/null
+++ b/sys/compat/svr4/svr4_time.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TIME_H_
+#define _SVR4_TIME_H_
+
+#include <sys/time.h>
+
+struct svr4_utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+
+#endif /* !_SVR4_TIME_H_ */
diff --git a/sys/compat/svr4/svr4_timod.h b/sys/compat/svr4/svr4_timod.h
new file mode 100644
index 0000000..f0c508f
--- /dev/null
+++ b/sys/compat/svr4/svr4_timod.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TIMOD_H_
+#define _SVR4_TIMOD_H_
+
+#define SVR4_TIMOD ('T' << 8)
+#define SVR4_TI_GETINFO (SVR4_TIMOD|140)
+#define SVR4_TI_OPTMGMT (SVR4_TIMOD|141)
+#define SVR4_TI_BIND (SVR4_TIMOD|142)
+#define SVR4_TI_UNBIND (SVR4_TIMOD|143)
+#define SVR4_TI_GETMYNAME (SVR4_TIMOD|144)
+#define SVR4_TI_GETPEERNAME (SVR4_TIMOD|145)
+#define SVR4_TI_SETMYNAME (SVR4_TIMOD|146)
+#define SVR4_TI_SETPEERNAME (SVR4_TIMOD|147)
+#define SVR4_TI_SYNC (SVR4_TIMOD|148)
+#define SVR4_TI_GETADDRS (SVR4_TIMOD|149)
+
+#define SVR4_TI_CONNECT_REQUEST 0x00
+#define SVR4_TI_CONNECT_RESPONSE 0x01
+#define SVR4_TI_DISCONNECT_REQUEST 0x02
+#define SVR4_TI_DATA_REQUEST 0x03
+#define SVR4_TI_EXPDATA_REQUEST 0x04
+#define SVR4_TI_INFO_REQUEST 0x05
+#define SVR4_TI_OLD_BIND_REQUEST 0x06
+#define SVR4_TI_UNBIND_REQUEST 0x07
+#define SVR4_TI_SENDTO_REQUEST 0x08
+#define SVR4_TI_OLD_OPTMGMT_REQUEST 0x09
+#define SVR4_TI_ORDREL_REQUEST 0x0a
+
+#define SVR4_TI_ACCEPT_REPLY 0x0b
+#define SVR4_TI_CONNECT_REPLY 0x0c
+#define SVR4_TI_DISCONNECT_IND 0x0d
+#define SVR4_TI_DATA_IND 0x0e
+#define SVR4_TI_EXPDATA_IND 0x0f
+#define SVR4_TI_INFO_REPLY 0x10
+#define SVR4_TI_BIND_REPLY 0x11
+#define SVR4_TI_ERROR_REPLY 0x12
+#define SVR4_TI_OK_REPLY 0x13
+#define SVR4_TI_RECVFROM_IND 0x14
+#define SVR4_TI_RECVFROM_ERROR_IND 0x15
+#define SVR4_TI_OPTMGMT_REPLY 0x16
+#define SVR4_TI_ORDREL_IND 0x17
+
+#define SVR4_TI_ADDRESS_REQUEST 0x18
+#define SVR4_TI_ADDRESS_REPLY 0x19
+
+#define SVR4_TI_BIND_REQUEST 0x20
+#define SVR4_TI_OPTMGMT_REQUEST 0x21
+
+#define SVR4_TI__ACCEPT_WAIT 0x10000001
+#define SVR4_TI__ACCEPT_OK 0x10000002
+
+struct svr4_netbuf {
+ u_int maxlen;
+ u_int len;
+ char *buf;
+};
+
+#endif /* !_SVR4_TIMOD_H_ */
diff --git a/sys/compat/svr4/svr4_ttold.c b/sys/compat/svr4/svr4_ttold.c
new file mode 100644
index 0000000..47a8135
--- /dev/null
+++ b/sys/compat/svr4/svr4_ttold.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl_compat.h>
+#include <sys/termios.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_util.h>
+#include <compat/svr4/svr4_ttold.h>
+#include <compat/svr4/svr4_ioctl.h>
+
+
+static void svr4_tchars_to_bsd_tchars(const struct svr4_tchars *st,
+ struct tchars *bt);
+static void bsd_tchars_to_svr4_tchars(const struct tchars *bt,
+ struct svr4_tchars *st);
+static void svr4_sgttyb_to_bsd_sgttyb(const struct svr4_sgttyb *ss,
+ struct sgttyb *bs);
+static void bsd_sgttyb_to_svr4_sgttyb(const struct sgttyb *bs,
+ struct svr4_sgttyb *ss);
+static void svr4_ltchars_to_bsd_ltchars(const struct svr4_ltchars *sl,
+ struct ltchars *bl);
+static void bsd_ltchars_to_svr4_ltchars(const struct ltchars *bl,
+ struct svr4_ltchars *sl);
+
+#ifdef DEBUG_SVR4
+static void print_svr4_sgttyb(const char *, struct svr4_sgttyb *);
+static void print_svr4_tchars(const char *, struct svr4_tchars *);
+static void print_svr4_ltchars(const char *, struct svr4_ltchars *);
+
+static void
+print_svr4_sgttyb(str, ss)
+ const char *str;
+ struct svr4_sgttyb *ss;
+{
+
+ uprintf("%s\nispeed=%o ospeed=%o ", str, ss->sg_ispeed, ss->sg_ospeed);
+ uprintf("erase=%o kill=%o flags=%o\n", ss->sg_erase, ss->sg_kill,
+ ss->sg_flags);
+}
+
+static void
+print_svr4_tchars(str, st)
+ const char *str;
+ struct svr4_tchars *st;
+{
+ uprintf("%s\nintrc=%o quitc=%o ", str, st->t_intrc, st->t_quitc);
+ uprintf("startc=%o stopc=%o eofc=%o brkc=%o\n", st->t_startc,
+ st->t_stopc, st->t_eofc, st->t_brkc);
+}
+
+static void
+print_svr4_ltchars(str, sl)
+ const char *str;
+ struct svr4_ltchars *sl;
+{
+ uprintf("%s\nsuspc=%o dsuspc=%o ", str, sl->t_suspc, sl->t_dsuspc);
+ uprintf("rprntc=%o flushc=%o werasc=%o lnextc=%o\n", sl->t_rprntc,
+ sl->t_flushc, sl->t_werasc, sl->t_lnextc);
+}
+#endif /* DEBUG_SVR4 */
+
+static void
+svr4_tchars_to_bsd_tchars(st, bt)
+ const struct svr4_tchars *st;
+ struct tchars *bt;
+{
+ bt->t_intrc = st->t_intrc;
+ bt->t_quitc = st->t_quitc;
+ bt->t_startc = st->t_startc;
+ bt->t_stopc = st->t_stopc;
+ bt->t_eofc = st->t_eofc;
+ bt->t_brkc = st->t_brkc;
+}
+
+
+static void
+bsd_tchars_to_svr4_tchars(bt, st)
+ const struct tchars *bt;
+ struct svr4_tchars *st;
+{
+ st->t_intrc = bt->t_intrc;
+ st->t_quitc = bt->t_quitc;
+ st->t_startc = bt->t_startc;
+ st->t_stopc = bt->t_stopc;
+ st->t_eofc = bt->t_eofc;
+ st->t_brkc = bt->t_brkc;
+}
+
+
+static void
+svr4_sgttyb_to_bsd_sgttyb(ss, bs)
+ const struct svr4_sgttyb *ss;
+ struct sgttyb *bs;
+{
+ bs->sg_ispeed = ss->sg_ispeed;
+ bs->sg_ospeed = ss->sg_ospeed;
+ bs->sg_erase = ss->sg_erase;
+ bs->sg_kill = ss->sg_kill;
+ bs->sg_flags = ss->sg_flags;
+};
+
+
+static void
+bsd_sgttyb_to_svr4_sgttyb(bs, ss)
+ const struct sgttyb *bs;
+ struct svr4_sgttyb *ss;
+{
+ ss->sg_ispeed = bs->sg_ispeed;
+ ss->sg_ospeed = bs->sg_ospeed;
+ ss->sg_erase = bs->sg_erase;
+ ss->sg_kill = bs->sg_kill;
+ ss->sg_flags = bs->sg_flags;
+}
+
+
+static void
+svr4_ltchars_to_bsd_ltchars(sl, bl)
+ const struct svr4_ltchars *sl;
+ struct ltchars *bl;
+{
+ bl->t_suspc = sl->t_suspc;
+ bl->t_dsuspc = sl->t_dsuspc;
+ bl->t_rprntc = sl->t_rprntc;
+ bl->t_flushc = sl->t_flushc;
+ bl->t_werasc = sl->t_werasc;
+ bl->t_lnextc = sl->t_lnextc;
+}
+
+
+static void
+bsd_ltchars_to_svr4_ltchars(bl, sl)
+ const struct ltchars *bl;
+ struct svr4_ltchars *sl;
+{
+ sl->t_suspc = bl->t_suspc;
+ sl->t_dsuspc = bl->t_dsuspc;
+ sl->t_rprntc = bl->t_rprntc;
+ sl->t_flushc = bl->t_flushc;
+ sl->t_werasc = bl->t_werasc;
+ sl->t_lnextc = bl->t_lnextc;
+}
+
+
+int
+svr4_ttold_ioctl(fp, td, retval, fd, cmd, data)
+ struct file *fp;
+ struct thread *td;
+ register_t *retval;
+ int fd;
+ u_long cmd;
+ caddr_t data;
+{
+ int error;
+
+ *retval = 0;
+
+ switch (cmd) {
+ case SVR4_TIOCGPGRP:
+ {
+ pid_t pid;
+
+ if ((error = fo_ioctl(fp, TIOCGPGRP, (caddr_t) &pid, td)) != 0)
+ return error;
+
+ DPRINTF(("TIOCGPGRP %d\n", pid));
+
+ if ((error = copyout(&pid, data, sizeof(pid))) != 0)
+ return error;
+
+ }
+
+ case SVR4_TIOCSPGRP:
+ {
+ pid_t pid;
+
+ if ((error = copyin(data, &pid, sizeof(pid))) != 0)
+ return error;
+
+ DPRINTF(("TIOCSPGRP %d\n", pid));
+
+ return fo_ioctl(fp, TIOCSPGRP, (caddr_t) &pid, td);
+ }
+
+ case SVR4_TIOCGSID:
+ {
+#if defined(TIOCGSID)
+ pid_t pid;
+ if ((error = fo_ioctl(fp, TIOCGSID, (caddr_t) &pid, td)) != 0)
+ return error;
+
+ DPRINTF(("TIOCGSID %d\n", pid));
+
+ return copyout(&pid, data, sizeof(pid));
+#else
+ uprintf("ioctl(TIOCGSID) for pid %d unsupported\n", td->td_proc->p_pid);
+ return EINVAL;
+#endif
+ }
+
+ case SVR4_TIOCGETP:
+ {
+ struct sgttyb bs;
+ struct svr4_sgttyb ss;
+
+ error = fo_ioctl(fp, TIOCGETP, (caddr_t) &bs, td);
+ if (error)
+ return error;
+
+ bsd_sgttyb_to_svr4_sgttyb(&bs, &ss);
+#ifdef DEBUG_SVR4
+ print_svr4_sgttyb("SVR4_TIOCGETP", &ss);
+#endif /* DEBUG_SVR4 */
+ return copyout(&ss, data, sizeof(ss));
+ }
+
+ case SVR4_TIOCSETP:
+ case SVR4_TIOCSETN:
+ {
+ struct sgttyb bs;
+ struct svr4_sgttyb ss;
+
+ if ((error = copyin(data, &ss, sizeof(ss))) != 0)
+ return error;
+
+ svr4_sgttyb_to_bsd_sgttyb(&ss, &bs);
+#ifdef DEBUG_SVR4
+ print_svr4_sgttyb("SVR4_TIOCSET{P,N}", &ss);
+#endif /* DEBUG_SVR4 */
+ cmd = (cmd == SVR4_TIOCSETP) ? TIOCSETP : TIOCSETN;
+ return fo_ioctl(fp, cmd, (caddr_t) &bs, td);
+ }
+
+ case SVR4_TIOCGETC:
+ {
+ struct tchars bt;
+ struct svr4_tchars st;
+
+ error = fo_ioctl(fp, TIOCGETC, (caddr_t) &bt, td);
+ if (error)
+ return error;
+
+ bsd_tchars_to_svr4_tchars(&bt, &st);
+#ifdef DEBUG_SVR4
+ print_svr4_tchars("SVR4_TIOCGETC", &st);
+#endif /* DEBUG_SVR4 */
+ return copyout(&st, data, sizeof(st));
+ }
+
+ case SVR4_TIOCSETC:
+ {
+ struct tchars bt;
+ struct svr4_tchars st;
+
+ if ((error = copyin(data, &st, sizeof(st))) != 0)
+ return error;
+
+ svr4_tchars_to_bsd_tchars(&st, &bt);
+#ifdef DEBUG_SVR4
+ print_svr4_tchars("SVR4_TIOCSETC", &st);
+#endif /* DEBUG_SVR4 */
+ return fo_ioctl(fp, TIOCSETC, (caddr_t) &bt, td);
+ }
+
+ case SVR4_TIOCGLTC:
+ {
+ struct ltchars bl;
+ struct svr4_ltchars sl;
+
+ error = fo_ioctl(fp, TIOCGLTC, (caddr_t) &bl, td);
+ if (error)
+ return error;
+
+ bsd_ltchars_to_svr4_ltchars(&bl, &sl);
+#ifdef DEBUG_SVR4
+ print_svr4_ltchars("SVR4_TIOCGLTC", &sl);
+#endif /* DEBUG_SVR4 */
+ return copyout(&sl, data, sizeof(sl));
+ }
+
+ case SVR4_TIOCSLTC:
+ {
+ struct ltchars bl;
+ struct svr4_ltchars sl;
+
+ if ((error = copyin(data, &sl, sizeof(sl))) != 0)
+ return error;
+
+ svr4_ltchars_to_bsd_ltchars(&sl, &bl);
+#ifdef DEBUG_SVR4
+ print_svr4_ltchars("SVR4_TIOCSLTC", &sl);
+#endif /* DEBUG_SVR4 */
+ return fo_ioctl(fp, TIOCSLTC, (caddr_t) &bl, td);
+ }
+
+ case SVR4_TIOCLGET:
+ {
+ int flags;
+ if ((error = fo_ioctl(fp, TIOCLGET, (caddr_t) &flags, td)) != 0)
+ return error;
+ DPRINTF(("SVR4_TIOCLGET %o\n", flags));
+ return copyout(&flags, data, sizeof(flags));
+ }
+
+ case SVR4_TIOCLSET:
+ case SVR4_TIOCLBIS:
+ case SVR4_TIOCLBIC:
+ {
+ int flags;
+
+ if ((error = copyin(data, &flags, sizeof(flags))) != 0)
+ return error;
+
+ switch (cmd) {
+ case SVR4_TIOCLSET:
+ cmd = TIOCLSET;
+ break;
+ case SVR4_TIOCLBIS:
+ cmd = TIOCLBIS;
+ break;
+ case SVR4_TIOCLBIC:
+ cmd = TIOCLBIC;
+ break;
+ }
+
+ DPRINTF(("SVR4_TIOCL{SET,BIS,BIC} %o\n", flags));
+ return fo_ioctl(fp, cmd, (caddr_t) &flags, td);
+ }
+
+ default:
+ DPRINTF(("Unknown svr4 ttold %lx\n", cmd));
+ return 0; /* ENOSYS really */
+ }
+}
diff --git a/sys/compat/svr4/svr4_ttold.h b/sys/compat/svr4/svr4_ttold.h
new file mode 100644
index 0000000..c578170
--- /dev/null
+++ b/sys/compat/svr4/svr4_ttold.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TTOLD_H_
+#define _SVR4_TTOLD_H_
+
+struct svr4_tchars {
+ char t_intrc;
+ char t_quitc;
+ char t_startc;
+ char t_stopc;
+ char t_eofc;
+ char t_brkc;
+};
+
+struct svr4_sgttyb {
+ u_char sg_ispeed;
+ u_char sg_ospeed;
+ u_char sg_erase;
+ u_char sg_kill;
+ int sg_flags;
+};
+
+struct svr4_ltchars {
+ char t_suspc;
+ char t_dsuspc;
+ char t_rprntc;
+ char t_flushc;
+ char t_werasc;
+ char t_lnextc;
+};
+
+#ifndef SVR4_tIOC
+#define SVR4_tIOC ('t' << 8)
+#endif
+
+#define SVR4_TIOCGETD (SVR4_tIOC | 0)
+#define SVR4_TIOCSETD (SVR4_tIOC | 1)
+#define SVR4_TIOCHPCL (SVR4_tIOC | 2)
+#define SVR4_TIOCGETP (SVR4_tIOC | 8)
+#define SVR4_TIOCSETP (SVR4_tIOC | 9)
+#define SVR4_TIOCSETN (SVR4_tIOC | 10)
+#define SVR4_TIOCEXCL (SVR4_tIOC | 13)
+#define SVR4_TIOCNXCL (SVR4_tIOC | 14)
+#define SVR4_TIOCFLUSH (SVR4_tIOC | 16)
+#define SVR4_TIOCSETC (SVR4_tIOC | 17)
+#define SVR4_TIOCGETC (SVR4_tIOC | 18)
+#define SVR4_TIOCGPGRP (SVR4_tIOC | 20)
+#define SVR4_TIOCSPGRP (SVR4_tIOC | 21)
+#define SVR4_TIOCGSID (SVR4_tIOC | 22)
+#define SVR4_TIOCSTI (SVR4_tIOC | 23)
+#define SVR4_TIOCSSID (SVR4_tIOC | 24)
+#define SVR4_TIOCMSET (SVR4_tIOC | 26)
+#define SVR4_TIOCMBIS (SVR4_tIOC | 27)
+#define SVR4_TIOCMBIC (SVR4_tIOC | 28)
+#define SVR4_TIOCMGET (SVR4_tIOC | 29)
+#define SVR4_TIOCREMOTE (SVR4_tIOC | 30)
+#define SVR4_TIOCSIGNAL (SVR4_tIOC | 31)
+
+#define SVR4_TIOCSTART (SVR4_tIOC | 110)
+#define SVR4_TIOCSTOP (SVR4_tIOC | 111)
+#define SVR4_TIOCNOTTY (SVR4_tIOC | 113)
+#define SVR4_TIOCOUTQ (SVR4_tIOC | 115)
+#define SVR4_TIOCGLTC (SVR4_tIOC | 116)
+#define SVR4_TIOCSLTC (SVR4_tIOC | 117)
+#define SVR4_TIOCCDTR (SVR4_tIOC | 120)
+#define SVR4_TIOCSDTR (SVR4_tIOC | 121)
+#define SVR4_TIOCCBRK (SVR4_tIOC | 122)
+#define SVR4_TIOCSBRK (SVR4_tIOC | 123)
+#define SVR4_TIOCLGET (SVR4_tIOC | 124)
+#define SVR4_TIOCLSET (SVR4_tIOC | 125)
+#define SVR4_TIOCLBIC (SVR4_tIOC | 126)
+#define SVR4_TIOCLBIS (SVR4_tIOC | 127)
+
+#define SVR4_TIOCM_LE 0001
+#define SVR4_TIOCM_DTR 0002
+#define SVR4_TIOCM_RTS 0004
+#define SVR4_TIOCM_ST 0010
+#define SVR4_TIOCM_SR 0020
+#define SVR4_TIOCM_CTS 0040
+#define SVR4_TIOCM_CAR 0100
+#define SVR4_TIOCM_CD SVR4_TIOCM_CAR
+#define SVR4_TIOCM_RNG 0200
+#define SVR4_TIOCM_RI SVR4_TIOCM_RNG
+#define SVR4_TIOCM_DSR 0400
+
+#define SVR4_OTTYDISC 0
+#define SVR4_NETLDISC 1
+#define SVR4_NTTYDISC 2
+#define SVR4_TABLDISC 3
+#define SVR4_NTABLDISC 4
+#define SVR4_MOUSELDISC 5
+#define SVR4_KBDLDISC 6
+
+#endif /* !_SVR4_TTOLD_H_ */
diff --git a/sys/compat/svr4/svr4_types.h b/sys/compat/svr4/svr4_types.h
new file mode 100644
index 0000000..410746b
--- /dev/null
+++ b/sys/compat/svr4/svr4_types.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_TYPES_H_
+#define _SVR4_TYPES_H_
+
+typedef u_quad_t svr4_ino64_t;
+typedef quad_t svr4_off64_t;
+typedef quad_t svr4_blkcnt64_t;
+typedef u_quad_t svr4_fsblkcnt64_t;
+
+typedef long svr4_off_t;
+typedef u_long svr4_dev_t;
+typedef u_long svr4_ino_t;
+typedef u_long svr4_mode_t;
+typedef u_long svr4_nlink_t;
+typedef long svr4_uid_t;
+typedef long svr4_gid_t;
+typedef long svr4_daddr_t;
+typedef long svr4_pid_t;
+typedef long svr4_time_t;
+typedef long svr4_blkcnt_t;
+typedef u_long svr4_fsblkcnt_t;
+typedef char *svr4_caddr_t;
+typedef u_int svr4_size_t;
+
+typedef short svr4_o_dev_t;
+typedef short svr4_o_pid_t;
+typedef u_short svr4_o_ino_t;
+typedef u_short svr4_o_mode_t;
+typedef short svr4_o_nlink_t;
+typedef u_short svr4_o_uid_t;
+typedef u_short svr4_o_gid_t;
+typedef long svr4_clock_t;
+typedef int svr4_key_t;
+
+typedef struct timespec svr4_timestruc_t;
+
+#define svr4_omajor(x) ((int32_t)((((x) & 0x7f00) >> 8)))
+#define svr4_ominor(x) ((int32_t)((((x) & 0x00ff) >> 0)))
+#define svr4_omakedev(x,y) ((svr4_o_dev_t)((((x) << 8) & 0x7f00) | \
+ (((y) << 0) & 0x00ff)))
+
+#define svr4_to_bsd_odev_t(d) makedev(svr4_omajor(d), svr4_ominor(d))
+#define bsd_to_svr4_odev_t(d) svr4_omakedev(umajor(d), uminor(d))
+
+#define svr4_major(x) ((int32_t)((((x) & 0xfffc0000) >> 18)))
+#define svr4_minor(x) ((int32_t)((((x) & 0x0003ffff) >> 0)))
+#define svr4_makedev(x,y) ((svr4_dev_t)((((x) << 18) & 0xfffc0000) | \
+ (((y) << 0) & 0x0003ffff)))
+#define svr4_to_bsd_dev_t(d) makedev(svr4_major(d), svr4_minor(d))
+#define bsd_to_svr4_dev_t(d) svr4_makedev(umajor(d), uminor(d))
+
+#endif /* !_SVR4_TYPES_H_ */
diff --git a/sys/compat/svr4/svr4_ucontext.h b/sys/compat/svr4/svr4_ucontext.h
new file mode 100644
index 0000000..04bebe6
--- /dev/null
+++ b/sys/compat/svr4/svr4_ucontext.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UCONTEXT_H_
+#define _SVR4_UCONTEXT_H_
+
+/*
+ * Machine context
+ */
+
+#define SVR4_UC_SIGMASK 0x01
+#define SVR4_UC_STACK 0x02
+
+#define SVR4_UC_CPU 0x04
+#define SVR4_UC_FPU 0x08
+#define SVR4_UC_WEITEK 0x10
+
+#define SVR4_UC_MCONTEXT (SVR4_UC_CPU|SVR4_UC_FPU|SVR4_UC_WEITEK)
+
+#define SVR4_UC_ALL (SVR4_UC_SIGMASK|SVR4_UC_STACK|SVR4_UC_MCONTEXT)
+
+typedef struct svr4_ucontext {
+ u_long uc_flags;
+ /* struct svr4_ucontext *uc_link;*/
+ void *uc_link;
+ svr4_sigset_t uc_sigmask;
+ struct svr4_sigaltstack uc_stack;
+ svr4_mcontext_t uc_mcontext;
+ long uc_pad[5];
+} svr4_ucontext_t;
+
+#define SVR4_UC_GETREGSET 0
+#define SVR4_UC_SETREGSET 1
+
+/*
+ * Signal frame
+ */
+struct svr4_sigframe {
+ int sf_signum;
+ union svr4_siginfo *sf_sip;
+ struct svr4_ucontext *sf_ucp;
+ sig_t sf_handler;
+ struct svr4_ucontext sf_uc;
+ union svr4_siginfo sf_si;
+};
+
+#endif /* !_SVR4_UCONTEXT_H_ */
diff --git a/sys/compat/svr4/svr4_ulimit.h b/sys/compat/svr4/svr4_ulimit.h
new file mode 100644
index 0000000..0735d42
--- /dev/null
+++ b/sys/compat/svr4/svr4_ulimit.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_ULIMIT_H_
+#define _SVR4_ULIMIT_H_
+
+#define SVR4_GFILLIM 1
+#define SVR4_SFILLIM 2
+#define SVR4_GMEMLIM 3
+#define SVR4_GDESLIM 4
+#define SVR4_GTXTOFF 64
+
+
+#endif /* !_SVR4_ULIMIT_H_ */
diff --git a/sys/compat/svr4/svr4_ustat.h b/sys/compat/svr4/svr4_ustat.h
new file mode 100644
index 0000000..e9ebffb
--- /dev/null
+++ b/sys/compat/svr4/svr4_ustat.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_USTAT_H_
+#define _SVR4_USTAT_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_ustat {
+ svr4_daddr_t f_tfree;
+ svr4_ino_t f_tinode;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+#endif /* !_SVR4_USTAT_H_ */
diff --git a/sys/compat/svr4/svr4_util.h b/sys/compat/svr4/svr4_util.h
new file mode 100644
index 0000000..9e5be7f
--- /dev/null
+++ b/sys/compat/svr4/svr4_util.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UTIL_H_
+#define _SVR4_UTIL_H_
+
+/*#include <compat/common/compat_util.h>*/
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+#ifdef DEBUG_SVR4
+#define DPRINTF(a) uprintf a;
+#else
+#define DPRINTF(a)
+#endif
+
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode))
+ return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+}
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+extern const char svr4_emul_path[];
+int svr4_emul_find(struct thread *, caddr_t *, const char *, char *,
+ char **, int);
+
+#define CHECKALT(p, sgp, path, i) \
+ do { \
+ int _error; \
+ \
+ _error = svr4_emul_find(p, sgp, svr4_emul_path, path, \
+ &path, i); \
+ if (_error == EFAULT) \
+ return (_error); \
+ } while (0)
+
+#define CHECKALTEXIST(p, sgp, path) CHECKALT(p, sgp, path, 0)
+#define CHECKALTCREAT(p, sgp, path) CHECKALT(p, sgp, path, 1)
+
+#endif /* !_SVR4_UTIL_H_ */
diff --git a/sys/compat/svr4/svr4_utsname.h b/sys/compat/svr4/svr4_utsname.h
new file mode 100644
index 0000000..0ff6dea
--- /dev/null
+++ b/sys/compat/svr4/svr4_utsname.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_UTSNAME_H_
+#define _SVR4_UTSNAME_H_
+
+#include <compat/svr4/svr4_types.h>
+
+struct svr4_utsname {
+ char sysname[257];
+ char nodename[257];
+ char release[257];
+ char version[257];
+ char machine[257];
+};
+
+#endif /* !_SVR4_UTSNAME_H_ */
diff --git a/sys/compat/svr4/svr4_wait.h b/sys/compat/svr4/svr4_wait.h
new file mode 100644
index 0000000..9a92c01
--- /dev/null
+++ b/sys/compat/svr4/svr4_wait.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998 Mark Newton
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVR4_WAIT_H_
+#define _SVR4_WAIT_H_
+
+
+#define SVR4_P_PID 0
+#define SVR4_P_PPID 1
+#define SVR4_P_PGID 2
+#define SVR4_P_SID 3
+#define SVR4_P_CID 4
+#define SVR4_P_UID 5
+#define SVR4_P_GID 6
+#define SVR4_P_ALL 7
+
+#define SVR4_WEXITED 0x01
+#define SVR4_WTRAPPED 0x02
+#define SVR4_WSTOPPED 0x04
+#define SVR4_WCONTINUED 0x08
+#define SVR4_WUNDEF1 0x10
+#define SVR4_WUNDEF2 0x20
+#define SVR4_WNOHANG 0x40
+#define SVR4_WNOWAIT 0x80
+
+#define SVR4_WOPTMASK (SVR4_WEXITED|SVR4_WTRAPPED|SVR4_WSTOPPED|\
+ SVR4_WCONTINUED|SVR4_WNOHANG|SVR4_WNOWAIT)
+
+#endif /* !_SVR4_WAIT_H_ */
diff --git a/sys/compat/svr4/syscalls.conf b/sys/compat/svr4/syscalls.conf
new file mode 100644
index 0000000..46f7bd3
--- /dev/null
+++ b/sys/compat/svr4/syscalls.conf
@@ -0,0 +1,12 @@
+# $FreeBSD$
+sysnames="svr4_syscallnames.c"
+sysproto="svr4_proto.h"
+sysproto_h=_SVR4_SYSPROTO_H_
+syshdr="svr4_syscall.h"
+syssw="svr4_sysent.c"
+sysmk="/dev/null"
+syshide="/dev/null"
+syscallprefix="SVR4_SYS_"
+switchname="svr4_sysent"
+namesname="svr4_syscallnames"
+sysvec="\n"
diff --git a/sys/compat/svr4/syscalls.master b/sys/compat/svr4/syscalls.master
new file mode 100644
index 0000000..f085587
--- /dev/null
+++ b/sys/compat/svr4/syscalls.master
@@ -0,0 +1,366 @@
+ $FreeBSD$
+; from: @(#)syscalls.master 8.1 (Berkeley) 7/19/93
+;
+; System call name/number master file (or rather, slave, from SVR4).
+; Processed to create svr4_sysent.c, svr4_syscalls.c and svr4_syscall.h.
+
+; Columns: number type nargs namespc name alt{name,tag,rtyp}/comments
+; number system call number, must be in order
+; type one of STD, OBSOL, UNIMPL, COMPAT
+; namespc one of POSIX, BSD, STD, NOHIDE (I dont care :-) -Peter
+; name psuedo-prototype of syscall routine
+; If one of the following alts is different, then all appear:
+; altname name of system call if different
+; alttag name of args struct tag if different from [o]`name'"_args"
+; altrtyp return type if not int (bogus - syscalls always return int)
+; for UNIMPL/OBSOL, name continues with comments
+
+; types:
+; STD always included
+; COMPAT included on COMPAT #ifdef
+; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h
+; OBSOL obsolete, not included in system, only specifies name
+; UNIMPL not implemented, placeholder only
+
+; #ifdef's, etc. may be included, and are copied to the output files.
+
+#include <sys/types.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <netinet/in.h>
+
+#include <compat/svr4/svr4.h>
+#include <compat/svr4/svr4_types.h>
+#include <compat/svr4/svr4_signal.h>
+#include <compat/svr4/svr4_proto.h>
+
+0 UNIMPL SVR4 unused
+1 NOPROTO POSIX { void sys_exit(int rval); } exit sys_exit_args void
+2 MNOPROTO POSIX { int fork(void); }
+3 NOPROTO POSIX { int read(int fd, char *buf, u_int nbyte); }
+4 NOPROTO SVR4 { int write(int fd, char *buf, u_int nbyte); }
+5 STD SVR4 { int svr4_sys_open(char *path, int flags, int mode); }
+6 NOPROTO SVR4 { int close(int fd); }
+7 STD SVR4 { int svr4_sys_wait(int *status); }
+8 STD SVR4 { int svr4_sys_creat(char *path, int mode); }
+9 NOPROTO SVR4 { int link(char *path, char *link); }
+10 NOPROTO SVR4 { int unlink(char *path); }
+11 STD SVR4 { int svr4_sys_execv(char *path, char **argp); }
+12 NOPROTO SVR4 { int chdir(char *path); }
+13 STD SVR4 { int svr4_sys_time(time_t *t); }
+14 STD SVR4 { int svr4_sys_mknod(char* path, int mode, int dev); }
+15 NOPROTO SVR4 { int chmod(char *path, int mode); }
+16 NOPROTO SVR4 { int chown(char *path, uid_t uid, gid_t gid); }
+17 STD SVR4 { int svr4_sys_break(caddr_t nsize); }
+18 STD SVR4 { int svr4_sys_stat(char* path, \
+ struct svr4_stat* ub); }
+19 NOPROTO SVR4 { int lseek(int filedes, off_t *offset, int whence); }
+20 NOPROTO SVR4 { pid_t getpid(void); }
+21 UNIMPL SVR4 old_mount
+22 UNIMPL SVR4 sysv_umount
+23 NOPROTO SVR4 { int setuid(uid_t uid); }
+24 NOPROTO SVR4 { uid_t getuid(void); }
+25 UNIMPL SVR4 stime
+26 UNIMPL SVR4 ptrace
+27 STD SVR4 { int svr4_sys_alarm(unsigned sec); }
+28 STD SVR4 { int svr4_sys_fstat(int fd, struct svr4_stat *sb); }
+29 STD SVR4 { int svr4_sys_pause(void); }
+30 STD SVR4 { int svr4_sys_utime(char *path, \
+ struct svr4_utimbuf *ubuf); }
+31 UNIMPL SVR4 stty
+32 UNIMPL SVR4 gtty
+33 STD SVR4 { int svr4_sys_access(char *path, int flags); }
+34 STD SVR4 { int svr4_sys_nice(int prio); }
+35 UNIMPL SVR4 statfs
+36 NOPROTO SVR4 { int sync(void); }
+37 STD SVR4 { int svr4_sys_kill(int pid, int signum); }
+38 UNIMPL SVR4 fstatfs
+39 STD SVR4 { int svr4_sys_pgrpsys(int cmd, int pid, int pgid); }
+40 UNIMPL SVR4 xenix
+41 NOPROTO SVR4 { int dup(u_int fd); }
+42 NOPROTO SVR4 { int pipe(void); }
+43 STD SVR4 { int svr4_sys_times(struct tms *tp); }
+44 UNIMPL SVR4 profil
+45 UNIMPL SVR4 plock
+46 NOPROTO SVR4 { int setgid(gid_t gid); }
+47 NOPROTO SVR4 { gid_t getgid(void); }
+48 STD SVR4 { int svr4_sys_signal(int signum, \
+ svr4_sig_t handler); }
+#if defined(NOTYET)
+49 STD SVR4 { int svr4_sys_msgsys(int what, int a2, int a3, \
+ int a4, int a5); }
+#else
+49 UNIMPL SVR4 msgsys
+#endif
+50 STD SVR4 { int svr4_sys_sysarch(int op, void *a1); }
+51 UNIMPL SVR4 acct
+52 UNIMPL SVR4 shmsys
+53 UNIMPL SVR4 semsys
+54 STD SVR4 { int svr4_sys_ioctl(int fd, u_long com, \
+ caddr_t data); }
+55 UNIMPL SVR4 uadmin
+56 UNIMPL SVR4 exch
+57 STD SVR4 { int svr4_sys_utssys(void *a1, void *a2, int sel, \
+ void *a3); }
+58 NOPROTO SVR4 { int fsync(int fd); }
+59 STD SVR4 { int svr4_sys_execve(char *path, char **argp, \
+ char **envp); }
+60 NOPROTO SVR4 { int umask(int newmask); }
+61 NOPROTO SVR4 { int chroot(char *path); }
+62 STD SVR4 { int svr4_sys_fcntl(int fd, int cmd, char *arg); }
+63 STD SVR4 { int svr4_sys_ulimit(int cmd, long newlimit); }
+64 UNIMPL SVR4 reserved
+65 UNIMPL SVR4 reserved
+66 UNIMPL SVR4 reserved
+67 UNIMPL SVR4 reserved
+68 UNIMPL SVR4 reserved
+69 UNIMPL SVR4 reserved
+70 UNIMPL SVR4 advfs
+71 UNIMPL SVR4 unadvfs
+72 UNIMPL SVR4 rmount
+73 UNIMPL SVR4 rumount
+74 UNIMPL SVR4 rfstart
+75 UNIMPL SVR4 sigret
+76 UNIMPL SVR4 rdebug
+77 UNIMPL SVR4 rfstop
+78 UNIMPL SVR4 rfsys
+79 NOPROTO SVR4 { int rmdir(char *path); }
+80 NOPROTO SVR4 { int mkdir(char *path, int mode); }
+81 STD SVR4 { int svr4_sys_getdents(int fd, char *buf, \
+ int nbytes); }
+82 UNIMPL SVR4 libattach
+83 UNIMPL SVR4 libdetach
+84 UNIMPL SVR4 sysfs
+85 STD SVR4 { int svr4_sys_getmsg(int fd, struct svr4_strbuf *ctl, \
+ struct svr4_strbuf *dat, int *flags); }
+86 STD SVR4 { int svr4_sys_putmsg(int fd, struct svr4_strbuf *ctl, \
+ struct svr4_strbuf *dat, int flags); }
+87 STD SVR4 { int svr4_sys_poll(struct pollfd *fds, unsigned int nfds, \
+ int timeout); }
+88 STD SVR4 { int svr4_sys_lstat(char *path, \
+ struct svr4_stat *ub); }
+89 NOPROTO SVR4 { int symlink(char *path, char *link); }
+90 NOPROTO SVR4 { int readlink(char *path, char *buf, int count); }
+91 NOPROTO SVR4 { int getgroups(u_int gidsetsize, gid_t *gidset); }
+92 NOPROTO SVR4 { int setgroups(u_int gidsetsize, gid_t *gidset); }
+93 NOPROTO SVR4 { int fchmod(int fd, int mode); }
+94 NOPROTO SVR4 { int fchown(int fd, int uid, int gid); }
+95 STD SVR4 { int svr4_sys_sigprocmask(int how, \
+ svr4_sigset_t *set, svr4_sigset_t *oset); }
+96 STD SVR4 { int svr4_sys_sigsuspend(svr4_sigset_t *ss); }
+97 STD SVR4 { int svr4_sys_sigaltstack( \
+ struct svr4_sigaltstack *nss, \
+ struct svr4_sigaltstack *oss); }
+98 STD SVR4 { int svr4_sys_sigaction(int signum, \
+ struct svr4_sigaction *nsa, \
+ struct svr4_sigaction *osa); }
+99 STD SVR4 { int svr4_sys_sigpending(int what, \
+ svr4_sigset_t *mask); }
+100 STD SVR4 { int svr4_sys_context(int func, \
+ struct svr4_ucontext *uc); }
+101 UNIMPL SVR4 evsys
+102 UNIMPL SVR4 evtrapret
+103 STD SVR4 { int svr4_sys_statvfs(char *path, \
+ struct svr4_statvfs *fs); }
+104 STD SVR4 { int svr4_sys_fstatvfs(int fd, \
+ struct svr4_statvfs *fs); }
+105 UNIMPL SVR4 whoknows
+106 UNIMPL SVR4 nfssvc
+107 STD SVR4 { int svr4_sys_waitsys(int grp, int id, \
+ union svr4_siginfo *info, int options); }
+108 UNIMPL SVR4 sigsendsys
+109 STD SVR4 { int svr4_sys_hrtsys(int cmd, int fun, int sub, \
+ void *rv1, void *rv2); }
+110 UNIMPL SVR4 acancel
+111 UNIMPL SVR4 async
+112 UNIMPL SVR4 priocntlsys
+113 STD SVR4 { int svr4_sys_pathconf(char *path, int name); }
+114 UNIMPL SVR4 mincore
+115 STD SVR4 { caddr_t svr4_sys_mmap( caddr_t addr, svr4_size_t len, \
+ int prot, int flags, int fd, svr4_off_t pos); }
+116 NOPROTO SVR4 { int mprotect(void *addr, int len, int prot); }
+117 NOPROTO SVR4 { int munmap(void *addr, int len); }
+118 STD SVR4 { int svr4_sys_fpathconf(int fd, int name); }
+119 MNOPROTO SVR4 { int vfork(void); }
+120 NOPROTO SVR4 { int fchdir(int fd); }
+121 NOPROTO SVR4 { int readv(int fd, struct iovec *iovp, \
+ u_int iovcnt); }
+122 NOPROTO SVR4 { int writev(int fd, struct iovec *iovp, \
+ u_int iovcnt); }
+123 STD SVR4 { int svr4_sys_xstat(int two, char *path, \
+ struct svr4_xstat *ub); }
+124 STD SVR4 { int svr4_sys_lxstat(int two, char *path, \
+ struct svr4_xstat *ub); }
+125 STD SVR4 { int svr4_sys_fxstat(int two, int fd, \
+ struct svr4_xstat *sb); }
+126 STD SVR4 { int svr4_sys_xmknod(int two, char *path, \
+ svr4_mode_t mode, svr4_dev_t dev); }
+127 UNIMPL SVR4 clocal
+128 STD SVR4 { int svr4_sys_setrlimit(int which, \
+ const struct svr4_rlimit *rlp); }
+129 STD SVR4 { int svr4_sys_getrlimit(int which, \
+ struct svr4_rlimit *rlp); }
+130 NOPROTO SVR4 { int lchown(char *path, uid_t uid, gid_t gid); }
+131 STD SVR4 { int svr4_sys_memcntl(void * addr, \
+ svr4_size_t len, int cmd, void * arg, \
+ int attr, int mask); }
+132 UNIMPL SVR4 getpmsg
+133 UNIMPL SVR4 putpmsg
+134 NOPROTO SVR4 { int rename(char *from, char *to); }
+135 STD SVR4 { int svr4_sys_uname(struct svr4_utsname* name, \
+ int dummy); }
+136 NOPROTO SVR4 { int setegid(gid_t egid); }
+137 STD SVR4 { int svr4_sys_sysconfig(int name); }
+138 MNOPROTO SVR4 { int adjtime(struct timeval *delta, \
+ struct timeval *olddelta); }
+139 STD SVR4 { long svr4_sys_systeminfo(int what, char *buf, \
+ long len); }
+140 UNIMPL SVR4 notused
+141 NOPROTO SVR4 { int seteuid(uid_t euid); }
+142 UNIMPL SVR4 vtrace
+; fork1
+143 MUNIMPL SVR4 { int fork(void); }
+144 UNIMPL SVR4 sigtimedwait
+145 UNIMPL SVR4 lwp_info
+146 UNIMPL SVR4 yield
+147 UNIMPL SVR4 lwp_sema_wait
+148 UNIMPL SVR4 lwp_sema_post
+149 UNIMPL SVR4 lwp_sema_trywait
+150 UNIMPL SVR4 notused
+151 UNIMPL SVR4 notused
+152 UNIMPL SVR4 modctl
+153 STD SVR4 { int svr4_sys_fchroot(int fd); }
+154 STD SVR4 { int svr4_sys_utimes(char *path, \
+ struct timeval *tptr); }
+155 STD SVR4 { int svr4_sys_vhangup(void); }
+156 STD SVR4 { int svr4_sys_gettimeofday(struct timeval *tp); }
+157 MNOPROTO SVR4 { int getitimer(u_int which, struct itimerval *itv); }
+158 MNOPROTO SVR4 { int setitimer(u_int which, struct itimerval *itv, \
+ struct itimerval *oitv); }
+159 UNIMPL SVR4 lwp_create
+160 UNIMPL SVR4 lwp_exit
+161 UNIMPL SVR4 lwp_suspend
+162 UNIMPL SVR4 lwp_continue
+163 UNIMPL SVR4 lwp_kill
+164 UNIMPL SVR4 lwp_self
+165 UNIMPL SVR4 lwp_getprivate
+166 UNIMPL SVR4 lwp_setprivate
+167 UNIMPL SVR4 lwp_wait
+168 UNIMPL SVR4 lwp_mutex_unlock
+169 UNIMPL SVR4 lwp_mutex_lock
+170 UNIMPL SVR4 lwp_cond_wait
+171 UNIMPL SVR4 lwp_cond_signal
+172 UNIMPL SVR4 lwp_cond_broadcast
+173 UNIMPL SVR4 { ssize_t svr4_sys_pread(int fd, void *buf, \
+ size_t nbyte, svr4_off_t off); }
+174 UNIMPL SVR4 { ssize_t svr4_sys_pwrite(int fd, const void *buf, \
+ size_t nbyte, svr4_off_t off); }
+175 STD SVR4 { svr4_off64_t svr4_sys_llseek(int fd, long offset1, \
+ long offset2, int whence); }
+176 UNIMPL SVR4 inst_sync
+177 UNIMPL SVR4 whoknows
+178 UNIMPL SVR4 kaio
+179 UNIMPL SVR4 whoknows
+180 UNIMPL SVR4 whoknows
+181 UNIMPL SVR4 whoknows
+182 UNIMPL SVR4 whoknows
+183 UNIMPL SVR4 whoknows
+184 UNIMPL SVR4 tsolsys
+185 STD SVR4 { int svr4_sys_acl(char *path, int cmd, int num, \
+ struct svr4_aclent *buf); }
+186 STD SVR4 { int svr4_sys_auditsys(int code, int a1, int a2, \
+ int a3, int a4, int a5); }
+187 UNIMPL SVR4 processor_bind
+188 UNIMPL SVR4 processor_info
+189 UNIMPL SVR4 p_online
+190 UNIMPL SVR4 sigqueue
+191 UNIMPL SVR4 clock_gettime
+192 UNIMPL SVR4 clock_settime
+193 UNIMPL SVR4 clock_getres
+194 UNIMPL SVR4 timer_create
+195 UNIMPL SVR4 timer_delete
+196 UNIMPL SVR4 timer_settime
+197 UNIMPL SVR4 timer_gettime
+198 UNIMPL SVR4 timer_overrun
+199 MNOPROTO SVR4 { int nanosleep(const struct timespec *rqtp, \
+ struct timespec *rmtp); }
+200 STD SVR4 { int svr4_sys_facl(int fd, int cmd, int num, \
+ struct svr4_aclent *buf); }
+201 UNIMPL SVR4 door
+202 NOPROTO SVR4 { int setreuid(int ruid, int euid); }
+203 NOPROTO SVR4 { int setregid(int rgid, int egid); }
+204 UNIMPL SVR4 install_utrap
+205 UNIMPL SVR4 signotify
+206 UNIMPL SVR4 schedctl
+207 UNIMPL SVR4 pset
+208 UNIMPL SVR4 whoknows
+209 STD SVR4 { int svr4_sys_resolvepath(const char *path, \
+ char *buf, size_t bufsiz); }
+210 UNIMPL SVR4 signotifywait
+211 UNIMPL SVR4 lwp_sigredirect
+212 UNIMPL SVR4 lwp_alarm
+213 STD SVR4 { int svr4_sys_getdents64(int fd, \
+ struct svr4_dirent64 *dp, \
+ int nbytes); }
+;213 UNIMPL SVR4 getdents64
+214 STD SVR4 { caddr_t svr4_sys_mmap64(void *addr, \
+ svr4_size_t len, int prot, int flags, int fd, \
+ svr4_off64_t pos); }
+215 STD SVR4 { int svr4_sys_stat64(char *path, \
+ struct svr4_stat64 *sb); }
+216 STD SVR4 { int svr4_sys_lstat64(char *path, \
+ struct svr4_stat64 *sb); }
+217 STD SVR4 { int svr4_sys_fstat64(int fd, \
+ struct svr4_stat64 *sb); }
+218 STD SVR4 { int svr4_sys_statvfs64(char *path, \
+ struct svr4_statvfs64 *fs); }
+219 STD SVR4 { int svr4_sys_fstatvfs64(int fd, \
+ struct svr4_statvfs64 *fs); }
+220 STD SVR4 { int svr4_sys_setrlimit64(int which, \
+ const struct svr4_rlimit64 *rlp); }
+221 STD SVR4 { int svr4_sys_getrlimit64(int which, \
+ struct svr4_rlimit64 *rlp); }
+222 UNIMPL SVR4 pread64
+223 UNIMPL SVR4 pwrite64
+224 STD SVR4 { int svr4_sys_creat64(char *path, int mode); }
+225 STD SVR4 { int svr4_sys_open64(char *path, int flags, \
+ int mode); }
+226 UNIMPL SVR4 rpcsys
+227 UNIMPL SVR4 whoknows
+228 UNIMPL SVR4 whoknows
+229 UNIMPL SVR4 whoknows
+230 STD SVR4 { int svr4_sys_socket(int domain, int type, \
+ int protocol); }
+231 NOPROTO SVR4 { int socketpair(int domain, int type, \
+ int protocol, int *rsv); }
+232 NOPROTO SVR4 { int bind(int s, const struct sockaddr *name, \
+ int namelen); }
+233 NOPROTO SVR4 { int listen(int s, int backlog); }
+234 NOPROTO SVR4 { int accept(int s, struct sockaddr *name, \
+ int *anamelen); }
+235 NOPROTO SVR4 { int connect(int s, const struct sockaddr *name, \
+ int namelen); }
+236 NOPROTO SVR4 { int shutdown(int s, int how); }
+237 STD SVR4 { int svr4_sys_recv(int s, caddr_t buf, int len, int flags); }
+238 NOPROTO SVR4 { ssize_t recvfrom(int s, void *buf, size_t len, \
+ int flags, struct sockaddr *from, \
+ int *fromlenaddr); }
+239 NOPROTO SVR4 { ssize_t recvmsg(int s, struct msghdr *msg, \
+ int flags); }
+240 STD SVR4 { int svr4_sys_send(int s, caddr_t buf, int len, int flags); }
+241 NOPROTO SVR4 { ssize_t sendmsg(int s, const struct msghdr *msg, \
+ int flags); }
+242 STD SVR4 { ssize_t svr4_sys_sendto(int s, void *buf, \
+ size_t len, int flags, \
+ struct sockaddr *to, int tolen); }
+243 NOPROTO SVR4 { int getpeername(int fdes, struct sockaddr *asa, \
+ int *alen); }
+244 NOPROTO SVR4 { int getsockname(int fdes, struct sockaddr *asa, \
+ int *alen); }
+245 NOPROTO SVR4 { int getsockopt(int s, int level, int name, \
+ void *val, int *avalsize); }
+246 NOPROTO SVR4 { int setsockopt(int s, int level, int name, \
+ const void *val, int valsize); }
+247 UNIMPL SVR4 sockconfig
+248 UNIMPL SVR4 { int ntp_gettime(struct ntptimeval *ntvp); }
+249 MUNIMPL SVR4 { int ntp_adjtime(struct timex *tp); }
OpenPOWER on IntegriCloud