summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>1995-10-18 08:37:01 +0000
committerderaadt <deraadt@openbsd.org>1995-10-18 08:37:01 +0000
commitdf930be708d50e9715f173caa26ffe1b7599b157 (patch)
treeaa317e49e28cb999c9cf3db7f00c20903fe6010a /sys/compat/linux
downloadwireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.tar.xz
wireguard-openbsd-df930be708d50e9715f173caa26ffe1b7599b157.zip
initial import of NetBSD tree
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/Makefile11
-rw-r--r--sys/compat/linux/files.linux18
-rw-r--r--sys/compat/linux/linux_dirent.h49
-rw-r--r--sys/compat/linux/linux_errno.h158
-rw-r--r--sys/compat/linux/linux_error.c177
-rw-r--r--sys/compat/linux/linux_exec.c502
-rw-r--r--sys/compat/linux/linux_exec.h74
-rw-r--r--sys/compat/linux/linux_fcntl.h90
-rw-r--r--sys/compat/linux/linux_file.c795
-rw-r--r--sys/compat/linux/linux_ioctl.c656
-rw-r--r--sys/compat/linux/linux_ioctl.h278
-rw-r--r--sys/compat/linux/linux_ipc.c707
-rw-r--r--sys/compat/linux/linux_ipc.h64
-rw-r--r--sys/compat/linux/linux_ipccall.h54
-rw-r--r--sys/compat/linux/linux_misc.c1105
-rw-r--r--sys/compat/linux/linux_mmap.h53
-rw-r--r--sys/compat/linux/linux_msg.h93
-rw-r--r--sys/compat/linux/linux_sem.h72
-rw-r--r--sys/compat/linux/linux_shm.h63
-rw-r--r--sys/compat/linux/linux_signal.c501
-rw-r--r--sys/compat/linux/linux_signal.h95
-rw-r--r--sys/compat/linux/linux_socket.c704
-rw-r--r--sys/compat/linux/linux_socket.h107
-rw-r--r--sys/compat/linux/linux_socketcall.h162
-rw-r--r--sys/compat/linux/linux_sockio.h40
-rw-r--r--sys/compat/linux/linux_syscall.h120
-rw-r--r--sys/compat/linux/linux_syscallargs.h433
-rw-r--r--sys/compat/linux/linux_syscalls.c165
-rw-r--r--sys/compat/linux/linux_sysent.c325
-rw-r--r--sys/compat/linux/linux_types.h151
-rw-r--r--sys/compat/linux/linux_util.h48
-rw-r--r--sys/compat/linux/syscalls.conf12
-rw-r--r--sys/compat/linux/syscalls.master235
33 files changed, 8117 insertions, 0 deletions
diff --git a/sys/compat/linux/Makefile b/sys/compat/linux/Makefile
new file mode 100644
index 00000000000..0627f6119a4
--- /dev/null
+++ b/sys/compat/linux/Makefile
@@ -0,0 +1,11 @@
+# $NetBSD: Makefile,v 1.1 1995/02/28 23:26:21 fvdl Exp $
+
+DEP= syscalls.conf syscalls.master ../../kern/makesyscalls.sh
+OBJS= linux_sysent.c linux_syscalls.c linux_syscall.h linux_syscallargs.h
+
+${OBJS}: ${DEP}
+ -mv -f linux_sysent.c linux_sysent.c.bak
+ -mv -f linux_syscalls.c linux_syscalls.c.bak
+ -mv -f linux_syscall.h linux_syscall.h.bak
+ -mv -f linux_syscallargs.h linux_syscallargs.h.bak
+ sh ../../kern/makesyscalls.sh syscalls.conf syscalls.master
diff --git a/sys/compat/linux/files.linux b/sys/compat/linux/files.linux
new file mode 100644
index 00000000000..c8aca4ae530
--- /dev/null
+++ b/sys/compat/linux/files.linux
@@ -0,0 +1,18 @@
+# $NetBSD: files.linux,v 1.3 1995/08/14 01:34:11 mycroft Exp $
+#
+# Config.new file description for machine-independent Linux compat code.
+# Included by ports that need it.
+
+# ports should define any machine-specific files they need in their
+# own file lists.
+
+file compat/linux/linux_error.c compat_linux
+file compat/linux/linux_exec.c compat_linux
+file compat/linux/linux_file.c compat_linux
+file compat/linux/linux_ioctl.c compat_linux
+file compat/linux/linux_ipc.c compat_linux
+file compat/linux/linux_misc.c compat_linux
+file compat/linux/linux_signal.c compat_linux
+file compat/linux/linux_socket.c compat_linux
+file compat/linux/linux_syscalls.c compat_linux
+file compat/linux/linux_sysent.c compat_linux
diff --git a/sys/compat/linux/linux_dirent.h b/sys/compat/linux/linux_dirent.h
new file mode 100644
index 00000000000..de63da00ca3
--- /dev/null
+++ b/sys/compat/linux/linux_dirent.h
@@ -0,0 +1,49 @@
+/* $NetBSD: linux_dirent.h,v 1.3 1995/10/07 06:26:59 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_DIRENT_H
+#define _LINUX_DIRENT_H
+
+#define LINUX_MAXNAMLEN 255
+
+struct linux_dirent {
+ linux_ino_t d_ino;
+ linux_off_t d_off;
+ u_short d_reclen;
+ char d_name[LINUX_MAXNAMLEN + 1];
+};
+
+#define LINUX_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
+#define LINUX_RECLEN(de,namlen) ALIGN((LINUX_NAMEOFF(de) + (namlen) + 1))
+
+#endif /* !_LINUX_DIRENT_H */
diff --git a/sys/compat/linux/linux_errno.h b/sys/compat/linux/linux_errno.h
new file mode 100644
index 00000000000..94530fd2eed
--- /dev/null
+++ b/sys/compat/linux/linux_errno.h
@@ -0,0 +1,158 @@
+/* $NetBSD: linux_errno.h,v 1.1 1995/02/28 23:25:34 fvdl Exp $ */
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_ERRNO_H
+#define _LINUX_ERRNO_H
+
+#define LINUX_EPERM 1
+#define LINUX_ENOENT 2
+#define LINUX_ESRCH 3
+#define LINUX_EINTR 4
+#define LINUX_EIO 5
+#define LINUX_ENXIO 6
+#define LINUX_E2BIG 7
+#define LINUX_ENOEXEC 8
+#define LINUX_EBADF 9
+#define LINUX_ECHILD 10
+#define LINUX_EAGAIN 11
+#define LINUX_ENOMEM 12
+#define LINUX_EACCES 13
+#define LINUX_EFAULT 14
+#define LINUX_ENOTBLK 15
+#define LINUX_EBUSY 16
+#define LINUX_EEXIST 17
+#define LINUX_EXDEV 18
+#define LINUX_ENODEV 19
+#define LINUX_ENOTDIR 20
+#define LINUX_EISDIR 21
+#define LINUX_EINVAL 22
+#define LINUX_ENFILE 23
+#define LINUX_EMFILE 24
+#define LINUX_ENOTTY 25
+#define LINUX_ETXTBSY 26
+#define LINUX_EFBIG 27
+#define LINUX_ENOSPC 28
+#define LINUX_ESPIPE 29
+#define LINUX_EROFS 30
+#define LINUX_EMLINK 31
+#define LINUX_EPIPE 32
+#define LINUX_EDOM 33
+#define LINUX_ERANGE 34
+#define LINUX_EDEADLK 35
+#define LINUX_ENAMETOOLONG 36
+#define LINUX_ENOLCK 37
+#define LINUX_ENOSYS 38
+#define LINUX_ENOTEMPTY 39
+#define LINUX_ELOOP 40
+#define LINUX_ENOMSG 42
+#define LINUX_EIDRM 43
+#define LINUX_ECHRNG 44
+#define LINUX_EL2NSYNC 45
+#define LINUX_EL3HLT 46
+#define LINUX_EL3RST 47
+#define LINUX_ELNRNG 48
+#define LINUX_EUNATCH 49
+#define LINUX_ENOCSI 50
+#define LINUX_EL2HLT 51
+#define LINUX_EBADE 52
+#define LINUX_EBADR 53
+#define LINUX_EXFULL 54
+#define LINUX_ENOANO 55
+#define LINUX_EBADRQC 56
+#define LINUX_EBADSLT 57
+#define LINUX_EDEADLOCK 58
+#define LINUX_EBFONT 59
+#define LINUX_ENOSTR 60
+#define LINUX_ENODATA 61
+#define LINUX_ETIME 62
+#define LINUX_ENOSR 63
+#define LINUX_ENONET 64
+#define LINUX_ENOPKG 65
+#define LINUX_EREMOTE 66
+#define LINUX_ENOLINK 67
+#define LINUX_EADV 68
+#define LINUX_ESRMNT 69
+#define LINUX_ECOMM 70
+#define LINUX_EPROTO 71
+#define LINUX_EMULTIHOP 72
+#define LINUX_EDOTDOT 73
+#define LINUX_EBADMSG 74
+#define LINUX_EOVERFLOW 75
+#define LINUX_ENOTUNIQ 76
+#define LINUX_EBADFD 77
+#define LINUX_EREMCHG 78
+#define LINUX_ELIBACC 79
+#define LINUX_ELIBBAD 80
+#define LINUX_ELIBSCN 81
+#define LINUX_ELIBMAX 82
+#define LINUX_ELIBEXEC 83
+#define LINUX_EILSEQ 84
+#define LINUX_ERESTART 85
+#define LINUX_ESTRPIPE 86
+#define LINUX_EUSERS 87
+#define LINUX_ENOTSOCK 88
+#define LINUX_EDESTADDRREQ 89
+#define LINUX_EMSGSIZE 90
+#define LINUX_EPROTOTYPE 91
+#define LINUX_ENOPROTOOPT 92
+#define LINUX_EPROTONOSUPPORT 93
+#define LINUX_ESOCKTNOSUPPORT 94
+#define LINUX_EOPNOTSUPP 95
+#define LINUX_EPFNOSUPPORT 96
+#define LINUX_EAFNOSUPPORT 97
+#define LINUX_EADDRINUSE 98
+#define LINUX_EADDRNOTAVAIL 99
+#define LINUX_ENETDOWN 100
+#define LINUX_ENETUNREACH 101
+#define LINUX_ENETRESET 102
+#define LINUX_ECONNABORTED 103
+#define LINUX_ECONNRESET 104
+#define LINUX_ENOBUFS 105
+#define LINUX_EISCONN 106
+#define LINUX_ENOTCONN 107
+#define LINUX_ESHUTDOWN 108
+#define LINUX_ETOOMANYREFS 109
+#define LINUX_ETIMEDOUT 110
+#define LINUX_ECONNREFUSED 111
+#define LINUX_EHOSTDOWN 112
+#define LINUX_EHOSTUNREACH 113
+#define LINUX_EALREADY 114
+#define LINUX_EINPROGRESS 115
+#define LINUX_ESTALE 116
+#define LINUX_EUCLEAN 117
+#define LINUX_ENOTNAM 118
+#define LINUX_ENAVAIL 119
+#define LINUX_EISNAM 120
+#define LINUX_EREMOTEIO 121
+#define LINUX_EDQUOT 122
+
+#endif /* !_LINUX_ERRNO_H */
diff --git a/sys/compat/linux/linux_error.c b/sys/compat/linux/linux_error.c
new file mode 100644
index 00000000000..1c42debe480
--- /dev/null
+++ b/sys/compat/linux/linux_error.c
@@ -0,0 +1,177 @@
+/* $NetBSD: linux_error.c,v 1.2 1995/04/22 19:48:32 christos Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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 <compat/linux/linux_errno.h>
+
+int linux_error[] = {
+ 0,
+ -LINUX_EPERM,
+ -LINUX_ENOENT,
+ -LINUX_ESRCH,
+ -LINUX_EINTR,
+ -LINUX_EIO,
+ -LINUX_ENXIO,
+ -LINUX_E2BIG,
+ -LINUX_ENOEXEC,
+ -LINUX_EBADF,
+ -LINUX_ECHILD,
+ -LINUX_EDEADLK,
+ -LINUX_ENOMEM,
+ -LINUX_EACCES,
+ -LINUX_EFAULT,
+ -LINUX_ENOTBLK,
+ -LINUX_EBUSY,
+ -LINUX_EEXIST,
+ -LINUX_EXDEV,
+ -LINUX_ENODEV,
+ -LINUX_ENOTDIR,
+ -LINUX_EISDIR,
+ -LINUX_EINVAL,
+ -LINUX_ENFILE,
+ -LINUX_EMFILE,
+ -LINUX_ENOTTY,
+ -LINUX_ETXTBSY,
+ -LINUX_EFBIG,
+ -LINUX_ENOSPC,
+ -LINUX_ESPIPE,
+ -LINUX_EROFS,
+ -LINUX_EMLINK,
+ -LINUX_EPIPE,
+ -LINUX_EDOM,
+ -LINUX_ERANGE,
+ -LINUX_EAGAIN,
+ -LINUX_EINPROGRESS,
+ -LINUX_EALREADY,
+ -LINUX_ENOTSOCK,
+ -LINUX_EDESTADDRREQ,
+ -LINUX_EMSGSIZE,
+ -LINUX_EPROTOTYPE,
+ -LINUX_ENOPROTOOPT,
+ -LINUX_EPROTONOSUPPORT,
+ -LINUX_ESOCKTNOSUPPORT,
+ -LINUX_EOPNOTSUPP,
+ -LINUX_EPFNOSUPPORT,
+ -LINUX_EAFNOSUPPORT,
+ -LINUX_EADDRINUSE,
+ -LINUX_EADDRNOTAVAIL,
+ -LINUX_ENETDOWN,
+ -LINUX_ENETUNREACH,
+ -LINUX_ENETRESET,
+ -LINUX_ECONNABORTED,
+ -LINUX_ECONNRESET,
+ -LINUX_ENOBUFS,
+ -LINUX_EISCONN,
+ -LINUX_ENOTCONN,
+ -LINUX_ESHUTDOWN,
+ -LINUX_ETOOMANYREFS,
+ -LINUX_ETIMEDOUT,
+ -LINUX_ECONNREFUSED,
+ -LINUX_ELOOP,
+ -LINUX_ENAMETOOLONG,
+ -LINUX_EHOSTDOWN,
+ -LINUX_EHOSTUNREACH,
+ -LINUX_ENOTEMPTY,
+ -LINUX_ENOSYS, /* not mapped (EPROCLIM) */
+ -LINUX_EUSERS,
+ -LINUX_EDQUOT,
+ -LINUX_ESTALE,
+ -LINUX_EREMOTE,
+ -LINUX_ENOSYS, /* not mapped (EBADRPC) */
+ -LINUX_ENOSYS, /* not mapped (ERPCMISMATCH) */
+ -LINUX_ENOSYS, /* not mapped (EPROGUNAVAIL) */
+ -LINUX_ENOSYS, /* not mapped (EPROGMISMATCH) */
+ -LINUX_ENOSYS, /* not mapped (EPROCUNAVAIL) */
+ -LINUX_ENOLCK,
+ -LINUX_ENOSYS,
+ -LINUX_ENOSYS, /* not mapped (EFTYPE) */
+ -LINUX_ENOSYS, /* not mapped (EAUTH) */
+ -LINUX_ENOSYS, /* not mapped (ENEEDAUTH) */
+ -LINUX_ENOSYS, /* not mapped (ELAST) */
+
+ /*
+ * The rest of the list consists of errors that only
+ * Linux has. They can be used to map them on to
+ * themselves, so Linux emulating syscalls can return
+ * these values.
+ */
+
+ -LINUX_ENOMSG,
+ -LINUX_EIDRM,
+ -LINUX_ECHRNG,
+ -LINUX_EL2NSYNC,
+ -LINUX_EL3HLT,
+ -LINUX_EL3RST,
+ -LINUX_ELNRNG,
+ -LINUX_EUNATCH,
+ -LINUX_ENOCSI,
+ -LINUX_EL2HLT,
+ -LINUX_EBADE,
+ -LINUX_EBADR,
+ -LINUX_EXFULL,
+ -LINUX_ENOANO,
+ -LINUX_EBADRQC,
+ -LINUX_EBADSLT,
+ -LINUX_EDEADLOCK,
+ -LINUX_EBFONT,
+ -LINUX_ENOSTR,
+ -LINUX_ENODATA,
+ -LINUX_ETIME,
+ -LINUX_ENOSR,
+ -LINUX_ENONET,
+ -LINUX_ENOPKG,
+ -LINUX_ENOLINK,
+ -LINUX_EADV,
+ -LINUX_ESRMNT,
+ -LINUX_ECOMM,
+ -LINUX_EPROTO,
+ -LINUX_EMULTIHOP,
+ -LINUX_EDOTDOT,
+ -LINUX_EBADMSG,
+ -LINUX_EOVERFLOW,
+ -LINUX_ENOTUNIQ,
+ -LINUX_EBADFD,
+ -LINUX_EREMCHG,
+ -LINUX_ELIBACC,
+ -LINUX_ELIBBAD,
+ -LINUX_ELIBSCN,
+ -LINUX_ELIBMAX,
+ -LINUX_ELIBEXEC,
+ -LINUX_EILSEQ,
+ -LINUX_ERESTART,
+ -LINUX_ESTRPIPE,
+ -LINUX_EUCLEAN,
+ -LINUX_ENOTNAM,
+ -LINUX_ENAVAIL,
+ -LINUX_EISNAM,
+ -LINUX_EREMOTEIO
+};
diff --git a/sys/compat/linux/linux_exec.c b/sys/compat/linux/linux_exec.c
new file mode 100644
index 00000000000..cc266db42bd
--- /dev/null
+++ b/sys/compat/linux/linux_exec.c
@@ -0,0 +1,502 @@
+/* $NetBSD: linux_exec.c,v 1.12 1995/10/07 06:27:00 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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.
+ *
+ * based on exec_aout.c, sunos_exec.c and svr4_exec.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/exec_elf.h>
+
+#include <sys/mman.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_map.h>
+
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/exec.h>
+#include <machine/linux_machdep.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_syscall.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_exec.h>
+
+static void *linux_aout_copyargs __P((struct exec_package *,
+ struct ps_strings *, void *, void *));
+
+#define LINUX_AOUT_AUX_ARGSIZ 2
+#define LINUX_ELF_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
+
+
+const char linux_emul_path[] = "/emul/linux";
+extern int linux_error[];
+extern char linux_sigcode[], linux_esigcode[];
+extern struct sysent linux_sysent[];
+extern char *linux_syscallnames[];
+
+struct emul emul_linux_aout = {
+ "linux",
+ linux_error,
+ linux_sendsig,
+ LINUX_SYS_syscall,
+ LINUX_SYS_MAXSYSCALL,
+ linux_sysent,
+ linux_syscallnames,
+ LINUX_AOUT_AUX_ARGSIZ,
+ linux_aout_copyargs,
+ setregs,
+ linux_sigcode,
+ linux_esigcode,
+};
+
+struct emul emul_linux_elf = {
+ "linux",
+ linux_error,
+ linux_sendsig,
+ LINUX_SYS_syscall,
+ LINUX_SYS_MAXSYSCALL,
+ linux_sysent,
+ linux_syscallnames,
+ LINUX_ELF_AUX_ARGSIZ,
+ elf_copyargs,
+ setregs,
+ linux_sigcode,
+ linux_esigcode,
+};
+
+
+static void *
+linux_aout_copyargs(pack, arginfo, stack, argp)
+ struct exec_package *pack;
+ struct ps_strings *arginfo;
+ void *stack;
+ void *argp;
+{
+ char **cpp = stack;
+ char **stk = stack;
+ char *dp, *sp;
+ size_t len;
+ void *nullp = NULL;
+ int argc = arginfo->ps_nargvstr;
+ int envc = arginfo->ps_nenvstr;
+
+ if (copyout(&argc, cpp++, sizeof(argc)))
+ return NULL;
+
+ /* leave room for envp and argv */
+ cpp += 2;
+ if (copyout(&cpp, &stk[1], sizeof (cpp)))
+ return NULL;
+
+ dp = (char *) (cpp + argc + envc + 2);
+ sp = argp;
+
+ /* XXX don't copy them out, remap them! */
+ arginfo->ps_argvstr = cpp; /* remember location of argv for later */
+
+ for (; --argc >= 0; sp += len, dp += len)
+ if (copyout(&dp, cpp++, sizeof(dp)) ||
+ copyoutstr(sp, dp, ARG_MAX, &len))
+ return NULL;
+
+ if (copyout(&nullp, cpp++, sizeof(nullp)))
+ return NULL;
+
+ if (copyout(&cpp, &stk[2], sizeof (cpp)))
+ return NULL;
+
+ arginfo->ps_envstr = cpp; /* remember location of envp for later */
+
+ for (; --envc >= 0; sp += len, dp += len)
+ if (copyout(&dp, cpp++, sizeof(dp)) ||
+ copyoutstr(sp, dp, ARG_MAX, &len))
+ return NULL;
+
+ if (copyout(&nullp, cpp++, sizeof(nullp)))
+ return NULL;
+
+ return cpp;
+}
+
+int
+exec_linux_aout_makecmds(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ struct exec *linux_ep = epp->ep_hdr;
+ int machtype, magic;
+ int error = ENOEXEC;
+
+ magic = LINUX_N_MAGIC(linux_ep);
+ machtype = LINUX_N_MACHTYPE(linux_ep);
+
+
+ if (machtype != LINUX_MID_MACHINE)
+ return (ENOEXEC);
+
+ switch (magic) {
+ case QMAGIC:
+ error = exec_linux_aout_prep_qmagic(p, epp);
+ break;
+ case ZMAGIC:
+ error = exec_linux_aout_prep_zmagic(p, epp);
+ break;
+ case NMAGIC:
+ error = exec_linux_aout_prep_nmagic(p, epp);
+ break;
+ case OMAGIC:
+ error = exec_linux_aout_prep_omagic(p, epp);
+ break;
+ }
+ if (error == 0)
+ epp->ep_emul = &emul_linux_aout;
+ return error;
+}
+
+/*
+ * Since text starts at 0x400 in Linux ZMAGIC executables, and 0x400
+ * is very likely not page aligned on most architectures, it is treated
+ * as an NMAGIC here. XXX
+ */
+
+int
+exec_linux_aout_prep_zmagic(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ struct exec *execp = epp->ep_hdr;
+
+ epp->ep_taddr = LINUX_N_TXTADDR(*execp, ZMAGIC);
+ epp->ep_tsize = execp->a_text;
+ epp->ep_daddr = LINUX_N_DATADDR(*execp, ZMAGIC);
+ epp->ep_dsize = execp->a_data + execp->a_bss;
+ epp->ep_entry = execp->a_entry;
+
+ /* set up command for text segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
+ epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, ZMAGIC),
+ VM_PROT_READ|VM_PROT_EXECUTE);
+
+ /* set up command for data segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
+ epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, ZMAGIC),
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /* set up command for bss segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
+ epp->ep_daddr + execp->a_data, NULLVP, 0,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ return exec_aout_setup_stack(p, epp);
+}
+
+/*
+ * exec_aout_prep_nmagic(): Prepare Linux NMAGIC package.
+ * Not different from the normal stuff.
+ */
+
+int
+exec_linux_aout_prep_nmagic(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ struct exec *execp = epp->ep_hdr;
+ long bsize, baddr;
+
+ epp->ep_taddr = LINUX_N_TXTADDR(*execp, NMAGIC);
+ epp->ep_tsize = execp->a_text;
+ epp->ep_daddr = LINUX_N_DATADDR(*execp, NMAGIC);
+ epp->ep_dsize = execp->a_data + execp->a_bss;
+ epp->ep_entry = execp->a_entry;
+
+ /* set up command for text segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_text,
+ epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, NMAGIC),
+ VM_PROT_READ|VM_PROT_EXECUTE);
+
+ /* set up command for data segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, execp->a_data,
+ epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, NMAGIC),
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /* set up command for bss segment */
+ baddr = roundup(epp->ep_daddr + execp->a_data, NBPG);
+ bsize = epp->ep_daddr + epp->ep_dsize - baddr;
+ if (bsize > 0)
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
+ NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ return exec_aout_setup_stack(p, epp);
+}
+
+/*
+ * exec_aout_prep_omagic(): Prepare Linux OMAGIC package.
+ * Business as usual.
+ */
+
+int
+exec_linux_aout_prep_omagic(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ struct exec *execp = epp->ep_hdr;
+ long dsize, bsize, baddr;
+
+ epp->ep_taddr = LINUX_N_TXTADDR(*execp, OMAGIC);
+ epp->ep_tsize = execp->a_text;
+ epp->ep_daddr = LINUX_N_DATADDR(*execp, OMAGIC);
+ epp->ep_dsize = execp->a_data + execp->a_bss;
+ epp->ep_entry = execp->a_entry;
+
+ /* set up command for text and data segments */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn,
+ execp->a_text + execp->a_data, epp->ep_taddr, epp->ep_vp,
+ LINUX_N_TXTOFF(*execp, OMAGIC), VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /* set up command for bss segment */
+ baddr = roundup(epp->ep_daddr + execp->a_data, NBPG);
+ bsize = epp->ep_daddr + epp->ep_dsize - baddr;
+ if (bsize > 0)
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, bsize, baddr,
+ NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /*
+ * Make sure (# of pages) mapped above equals (vm_tsize + vm_dsize);
+ * obreak(2) relies on this fact. Both `vm_tsize' and `vm_dsize' are
+ * computed (in execve(2)) by rounding *up* `ep_tsize' and `ep_dsize'
+ * respectively to page boundaries.
+ * Compensate `ep_dsize' for the amount of data covered by the last
+ * text page.
+ */
+ dsize = epp->ep_dsize + execp->a_text - roundup(execp->a_text, NBPG);
+ epp->ep_dsize = (dsize > 0) ? dsize : 0;
+ return exec_aout_setup_stack(p, epp);
+}
+
+int
+exec_linux_aout_prep_qmagic(p, epp)
+ struct proc *p;
+ struct exec_package *epp;
+{
+ struct exec *execp = epp->ep_hdr;
+
+ epp->ep_taddr = LINUX_N_TXTADDR(*execp, QMAGIC);
+ epp->ep_tsize = execp->a_text;
+ epp->ep_daddr = LINUX_N_DATADDR(*execp, QMAGIC);
+ epp->ep_dsize = execp->a_data + execp->a_bss;
+ epp->ep_entry = execp->a_entry;
+
+ /*
+ * check if vnode is in open for writing, because we want to
+ * demand-page out of it. if it is, don't do it, for various
+ * reasons
+ */
+ if ((execp->a_text != 0 || execp->a_data != 0) &&
+ epp->ep_vp->v_writecount != 0) {
+#ifdef DIAGNOSTIC
+ if (epp->ep_vp->v_flag & VTEXT)
+ panic("exec: a VTEXT vnode has writecount != 0\n");
+#endif
+ return ETXTBSY;
+ }
+ epp->ep_vp->v_flag |= VTEXT;
+
+ /* set up command for text segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_text,
+ epp->ep_taddr, epp->ep_vp, LINUX_N_TXTOFF(*execp, QMAGIC),
+ VM_PROT_READ|VM_PROT_EXECUTE);
+
+ /* set up command for data segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_pagedvn, execp->a_data,
+ epp->ep_daddr, epp->ep_vp, LINUX_N_DATOFF(*execp, QMAGIC),
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ /* set up command for bss segment */
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, execp->a_bss,
+ epp->ep_daddr + execp->a_data, NULLVP, 0,
+ VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+
+ return exec_aout_setup_stack(p, epp);
+}
+
+int
+linux_elf_probe(p, epp, itp, pos)
+ struct proc *p;
+ struct exec_package *epp;
+ char *itp;
+ u_long *pos;
+{
+ char *bp;
+ int error;
+ size_t len;
+
+ if (itp[0]) {
+ if ((error = emul_find(p, NULL, linux_emul_path, itp, &bp, 0)))
+ return error;
+ if ((error = copystr(bp, itp, MAXPATHLEN, &len)))
+ return error;
+ free(bp, M_TEMP);
+ }
+ epp->ep_emul = &emul_linux_elf;
+ *pos = ELF32_NO_ADDR;
+ return 0;
+}
+
+/*
+ * The Linux system call to load shared libraries, a.out version. The
+ * a.out shared libs are just files that are mapped onto a fixed
+ * address in the process' address space. The address is given in
+ * a_entry. Read in the header, set up some VM commands and run them.
+ *
+ * Yes, both text and data are mapped at once, so we're left with
+ * writeable text for the shared libs. The Linux crt0 seemed to break
+ * sometimes when data was mapped seperately. It munmapped a uselib()
+ * of ld.so by hand, which failed with shared text and data for ld.so
+ * Yuck.
+ *
+ * Because of the problem with ZMAGIC executables (text starts
+ * at 0x400 in the file, but needs to be mapped at 0), ZMAGIC
+ * shared libs are not handled very efficiently :-(
+ */
+
+int
+linux_sys_uselib(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_uselib_args /* {
+ syscallarg(char *) path;
+ } */ *uap = v;
+ caddr_t sg;
+ long bsize, dsize, tsize, taddr, baddr, daddr;
+ struct nameidata ni;
+ struct vnode *vp;
+ struct exec hdr;
+ struct exec_vmcmd_set vcset;
+ int rem, i, magic, error;
+
+ sg = stackgap_init(p->p_emul);
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ NDINIT(&ni, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
+
+ if ((error = namei(&ni)))
+ return error;
+
+ vp = ni.ni_vp;
+
+ if ((error = vn_rdwr(UIO_READ, vp, (caddr_t) &hdr, LINUX_AOUT_HDR_SIZE,
+ 0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
+ &rem, p))) {
+ vrele(vp);
+ return error;
+ }
+
+ if (rem != 0) {
+ vrele(vp);
+ return ENOEXEC;
+ }
+
+ if (LINUX_N_MACHTYPE(&hdr) != LINUX_MID_MACHINE)
+ return ENOEXEC;
+
+ magic = LINUX_N_MAGIC(&hdr);
+ taddr = hdr.a_entry & (~(NBPG - 1));
+ tsize = hdr.a_text;
+ daddr = taddr + tsize;
+ dsize = hdr.a_data + hdr.a_bss;
+
+ if ((hdr.a_text != 0 || hdr.a_data != 0) && vp->v_writecount != 0) {
+ vrele(vp);
+ return ETXTBSY;
+ }
+ vp->v_flag |= VTEXT;
+
+ vcset.evs_cnt = 0;
+ vcset.evs_used = 0;
+
+ NEW_VMCMD(&vcset,
+ magic == ZMAGIC ? vmcmd_map_readvn : vmcmd_map_pagedvn,
+ hdr.a_text + hdr.a_data, taddr,
+ vp, LINUX_N_TXTOFF(hdr, magic),
+ VM_PROT_READ|VM_PROT_EXECUTE|VM_PROT_WRITE);
+
+ baddr = roundup(daddr + hdr.a_data, NBPG);
+ bsize = daddr + dsize - baddr;
+ if (bsize > 0) {
+ NEW_VMCMD(&vcset, vmcmd_map_zero, bsize, baddr,
+ NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+ }
+
+ for (i = 0; i < vcset.evs_used && !error; i++) {
+ struct exec_vmcmd *vcp;
+
+ vcp = &vcset.evs_cmds[i];
+ error = (*vcp->ev_proc)(p, vcp);
+ }
+
+ kill_vmcmds(&vcset);
+
+ vrele(vp);
+
+ return error;
+}
+
+/*
+ * Execve(2). Just check the alternate emulation path, and pass it on
+ * to the NetBSD execve().
+ */
+int
+linux_sys_execve(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_execve_args /* {
+ syscallarg(char *) path;
+ syscallarg(char **) argv;
+ syscallarg(char **) envp;
+ } */ *uap = v;
+ caddr_t sg;
+
+ sg = stackgap_init(p->p_emul);
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_execve(p, uap, retval);
+}
diff --git a/sys/compat/linux/linux_exec.h b/sys/compat/linux/linux_exec.h
new file mode 100644
index 00000000000..fe26bac4f31
--- /dev/null
+++ b/sys/compat/linux/linux_exec.h
@@ -0,0 +1,74 @@
+/* $NetBSD: linux_exec.h,v 1.5 1995/10/07 06:27:01 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_EXEC_H
+#define _LINUX_EXEC_H
+
+#define LINUX_M_I386 100
+/* Sparc? Alpha? */
+
+/* XXX linux_machdep.h ? */
+#ifdef i386
+#define LINUX_MID_MACHINE LINUX_M_I386
+#endif
+
+#define LINUX_AOUT_HDR_SIZE (sizeof (struct exec))
+
+#define LINUX_N_MAGIC(ep) ((ep)->a_midmag & 0xffff)
+#define LINUX_N_MACHTYPE(ep) (((ep)->a_midmag >> 16) & 0xff)
+
+#define LINUX_N_TXTOFF(x,m) \
+ ((m) == ZMAGIC ? 1024 : ((m) == QMAGIC ? 0 : sizeof (struct exec)))
+
+#define LINUX_N_DATOFF(x,m) (LINUX_N_TXTOFF(x,m) + (x).a_text)
+
+#define LINUX_N_TXTADDR(x,m) ((m) == QMAGIC ? PAGE_SIZE : 0)
+
+#define LINUX__N_SEGMENT_ROUND(x) (((x) + NBPG - 1) & ~(NBPG - 1))
+
+#define LINUX__N_TXTENDADDR(x,m) (LINUX_N_TXTADDR(x,m)+(x).a_text)
+
+#define LINUX_N_DATADDR(x,m) \
+ ((m)==OMAGIC? (LINUX__N_TXTENDADDR(x,m)) \
+ : (LINUX__N_SEGMENT_ROUND (LINUX__N_TXTENDADDR(x,m))))
+
+#define LINUX_N_BSSADDR(x,m) (LINUX_N_DATADDR(x,m) + (x).a_data)
+
+int exec_linux_aout_makecmds __P((struct proc *, struct exec_package *));
+int exec_linux_elf_makecmds __P((struct proc *, struct exec_package *));
+
+int linux_elf_probe __P((struct proc *p, struct exec_package *epp, char *itp,
+ u_long *pos));
+
+#endif /* !_LINUX_EXEC_H */
diff --git a/sys/compat/linux/linux_fcntl.h b/sys/compat/linux/linux_fcntl.h
new file mode 100644
index 00000000000..4c34e7d3f45
--- /dev/null
+++ b/sys/compat/linux/linux_fcntl.h
@@ -0,0 +1,90 @@
+/* $NetBSD: linux_fcntl.h,v 1.1 1995/02/28 23:25:40 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+/*
+ * Various flag values used in Linux for open(2) and fcntl(2).
+ */
+
+#ifndef _LINUX_FCNTL_H
+#define _LINUX_FCNTL_H
+
+/* read/write mode for open(2) (as usual) */
+#define LINUX_O_RDONLY 0x0000
+#define LINUX_O_WRONLY 0x0001
+#define LINUX_O_RDWR 0x0002
+#define LINUX_O_ACCMODE 0x0003
+
+/* flags used in open(2) */
+#define LINUX_O_CREAT 0x0040
+#define LINUX_O_EXCL 0x0080
+#define LINUX_O_NOCTTY 0x0100
+#define LINUX_O_TRUNC 0x0200
+#define LINUX_O_APPEND 0x0400
+#define LINUX_O_NDELAY 0x0800
+#define LINUX_O_SYNC 0x1000
+
+#define LINUX_FASYNC 0x2000
+
+/* fcntl(2) operations */
+#define LINUX_F_DUPFD 0
+#define LINUX_F_GETFD 1
+#define LINUX_F_SETFD 2
+#define LINUX_F_GETFL 3
+#define LINUX_F_SETFL 4
+#define LINUX_F_GETLK 5
+#define LINUX_F_SETLK 6
+#define LINUX_F_SETLKW 7
+#define LINUX_F_SETOWN 8
+#define LINUX_F_GETOWN 9
+
+#define LINUX_F_RDLCK 0
+#define LINUX_F_WRLCK 1
+#define LINUX_F_UNLCK 2
+
+#define LINUX_LOCK_EX 4
+#define LINUX_LOCK_SH 8
+
+/*
+ * The arguments in the flock structure have a different order from the
+ * BSD structure.
+ */
+
+struct linux_flock {
+ short l_type;
+ short l_whence;
+ linux_off_t l_start;
+ linux_off_t l_len;
+ linux_pid_t l_pid;
+};
+
+#endif /* _LINUX_FCNTL_H */
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
new file mode 100644
index 00000000000..c05a89916f2
--- /dev/null
+++ b/sys/compat/linux/linux_file.c
@@ -0,0 +1,795 @@
+/* $NetBSD: linux_file.c,v 1.13 1995/10/08 22:53:43 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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/namei.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/mount.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/tty.h>
+#include <sys/conf.h>
+
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_fcntl.h>
+#include <compat/linux/linux_util.h>
+
+/*
+ * Some file-related calls are handled here. The usual flag conversion
+ * an structure conversion is done, and alternate emul path searching.
+ */
+
+/*
+ * The next two functions convert between the Linux and NetBSD values
+ * of the flags used in open(2) and fcntl(2).
+ */
+static int
+linux_to_bsd_ioflags(int lflags)
+{
+ int res = 0;
+
+ res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC);
+ res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
+ res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
+
+ return res;
+}
+
+static int
+bsd_to_linux_ioflags(int bflags)
+{
+ int res = 0;
+
+ res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
+ res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
+ res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
+ res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
+ res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
+ res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
+ res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
+ res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
+ res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC);
+ res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
+ res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
+
+ return res;
+}
+
+/*
+ * creat(2) is an obsolete function, but it's present as a Linux
+ * system call, so let's deal with it.
+ *
+ * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
+ */
+int
+linux_sys_creat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_creat_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap = v;
+ struct sys_open_args oa;
+ caddr_t sg;
+
+ sg = stackgap_init(p->p_emul);
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
+
+ SCARG(&oa, path) = SCARG(uap, path);
+ SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
+ SCARG(&oa, mode) = SCARG(uap, mode);
+
+ return sys_open(p, &oa, retval);
+}
+
+/*
+ * open(2). Take care of the different flag values, and let the
+ * NetBSD syscall do the real work. See if this operation
+ * gives the current process a controlling terminal.
+ * (XXX is this necessary?)
+ */
+int
+linux_sys_open(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_open_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+ } */ *uap = v;
+ int error, fl;
+ struct sys_open_args boa;
+ caddr_t sg;
+
+ sg = stackgap_init(p->p_emul);
+
+ fl = linux_to_bsd_ioflags(SCARG(uap, flags));
+
+ if (fl & O_CREAT)
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
+ else
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ SCARG(&boa, path) = SCARG(uap, path);
+ SCARG(&boa, flags) = fl;
+ SCARG(&boa, mode) = SCARG(uap, mode);
+
+ if ((error = sys_open(p, &boa, retval)))
+ return error;
+
+ /*
+ * this bit from sunos_misc.c (and svr4_fcntl.c).
+ * If we are a session leader, and we don't have a controlling
+ * terminal yet, and the O_NOCTTY flag is not set, try to make
+ * this the controlling terminal.
+ */
+ if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp = fdp->fd_ofiles[*retval];
+
+ /* ignore any error, just give it a try */
+ if (fp->f_type == DTYPE_VNODE)
+ (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
+ }
+ return 0;
+}
+
+/*
+ * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
+ */
+int
+linux_sys_llseek(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_llseek_args /* {
+ syscallarg(int) fd;
+ syscallarg(uint32_t) ohigh;
+ syscallarg(uint32_t) olow;
+ syscallarg(caddr_t) res;
+ syscallarg(int) whence;
+ } */ *uap = v;
+ struct sys_lseek_args bla;
+ int error;
+ off_t off;
+
+ off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
+
+ SCARG(&bla, fd) = SCARG(uap, fd);
+ SCARG(&bla, offset) = off;
+ SCARG(&bla, whence) = SCARG(uap, whence);
+
+ if ((error = sys_lseek(p, &bla, retval)))
+ return error;
+
+ if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
+ return error;
+
+ retval[0] = 0;
+ return 0;
+}
+
+/*
+ * The next two functions take care of converting the flock
+ * structure back and forth between Linux and NetBSD format.
+ * The only difference in the structures is the order of
+ * the fields, and the 'whence' value.
+ */
+static void
+bsd_to_linux_flock(bfp, lfp)
+ struct flock *bfp;
+ struct linux_flock *lfp;
+{
+
+ lfp->l_start = bfp->l_start;
+ lfp->l_len = bfp->l_len;
+ lfp->l_pid = bfp->l_pid;
+ lfp->l_whence = bfp->l_whence;
+ switch (bfp->l_type) {
+ case F_RDLCK:
+ lfp->l_type = LINUX_F_RDLCK;
+ break;
+ case F_UNLCK:
+ lfp->l_type = LINUX_F_UNLCK;
+ break;
+ case F_WRLCK:
+ lfp->l_type = LINUX_F_WRLCK;
+ break;
+ }
+}
+
+static void
+linux_to_bsd_flock(lfp, bfp)
+ struct linux_flock *lfp;
+ struct flock *bfp;
+{
+
+ bfp->l_start = lfp->l_start;
+ bfp->l_len = lfp->l_len;
+ bfp->l_pid = lfp->l_pid;
+ bfp->l_whence = lfp->l_whence;
+ switch (lfp->l_type) {
+ case LINUX_F_RDLCK:
+ bfp->l_type = F_RDLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bfp->l_type = F_UNLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bfp->l_type = F_WRLCK;
+ break;
+ }
+}
+
+/*
+ * Most actions in the fcntl() call are straightforward; simply
+ * pass control to the NetBSD system call. A few commands need
+ * conversions after the actual system call has done its work,
+ * because the flag values and lock structure are different.
+ */
+int
+linux_sys_fcntl(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_fcntl_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) cmd;
+ syscallarg(void *) arg;
+ } */ *uap = v;
+ int fd, cmd, error, val;
+ caddr_t arg, sg;
+ struct linux_flock lfl;
+ struct flock *bfp, bfl;
+ struct sys_fcntl_args fca;
+ struct filedesc *fdp;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr va;
+ long pgid;
+ struct pgrp *pgrp;
+ struct tty *tp, *(*d_tty) __P((dev_t));
+
+ fd = SCARG(uap, fd);
+ cmd = SCARG(uap, cmd);
+ arg = (caddr_t) SCARG(uap, arg);
+
+ switch (cmd) {
+ case LINUX_F_DUPFD:
+ cmd = F_DUPFD;
+ break;
+ case LINUX_F_GETFD:
+ cmd = F_GETFD;
+ break;
+ case LINUX_F_SETFD:
+ cmd = F_SETFD;
+ break;
+ case LINUX_F_GETFL:
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = F_GETFL;
+ SCARG(&fca, arg) = arg;
+ if ((error = sys_fcntl(p, &fca, retval)))
+ return error;
+ retval[0] = bsd_to_linux_ioflags(retval[0]);
+ return 0;
+ case LINUX_F_SETFL:
+ val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = F_SETFL;
+ SCARG(&fca, arg) = (caddr_t) val;
+ return sys_fcntl(p, &fca, retval);
+ case LINUX_F_GETLK:
+ sg = stackgap_init(p->p_emul);
+ bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = F_GETLK;
+ SCARG(&fca, arg) = bfp;
+ if ((error = sys_fcntl(p, &fca, retval)))
+ return error;
+ if ((error = copyin(bfp, &bfl, sizeof bfl)))
+ return error;
+ bsd_to_linux_flock(&bfl, &lfl);
+ return copyout(&lfl, arg, sizeof lfl);
+ break;
+ case LINUX_F_SETLK:
+ case LINUX_F_SETLKW:
+ cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
+ if ((error = copyin(arg, &lfl, sizeof lfl)))
+ return error;
+ linux_to_bsd_flock(&lfl, &bfl);
+ sg = stackgap_init(p->p_emul);
+ bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
+ if ((error = copyout(&bfl, bfp, sizeof bfl)))
+ return error;
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = cmd;
+ SCARG(&fca, arg) = bfp;
+ return sys_fcntl(p, &fca, retval);
+ break;
+ case LINUX_F_SETOWN:
+ case LINUX_F_GETOWN:
+ /*
+ * We need to route around the normal fcntl() for these calls,
+ * since it uses TIOC{G,S}PGRP, which is too restrictive for
+ * Linux F_{G,S}ETOWN semantics. For sockets, this problem
+ * does not exist.
+ */
+ fdp = p->p_fd;
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL)
+ return EBADF;
+ if (fp->f_type == DTYPE_SOCKET) {
+ cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
+ break;
+ }
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VCHR)
+ return EINVAL;
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+ d_tty = cdevsw[major(va.va_rdev)].d_tty;
+ if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
+ return EINVAL;
+ if (cmd == LINUX_F_GETOWN) {
+ retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
+ return 0;
+ }
+ if ((long)arg <= 0) {
+ pgid = -(long)arg;
+ } else {
+ struct proc *p1 = pfind((long)arg);
+ if (p1 == 0)
+ return (ESRCH);
+ pgid = (long)p1->p_pgrp->pg_id;
+ }
+ pgrp = pgfind(pgid);
+ if (pgrp == NULL || pgrp->pg_session != p->p_session)
+ return EPERM;
+ tp->t_pgrp = pgrp;
+ return 0;
+ default:
+ return EOPNOTSUPP;
+ }
+
+ SCARG(&fca, fd) = fd;
+ SCARG(&fca, cmd) = cmd;
+ SCARG(&fca, arg) = arg;
+
+ return sys_fcntl(p, &fca, retval);
+}
+
+/*
+ * Convert a NetBSD stat structure to a Linux stat structure.
+ * Only the order of the fields and the padding in the structure
+ * is different. linux_fakedev is a machine-dependent function
+ * which optionally converts device driver major/minor numbers
+ * (XXX horrible, but what can you do against code that compares
+ * things against constant major device numbers? sigh)
+ */
+static void
+bsd_to_linux_stat(bsp, lsp)
+ struct stat *bsp;
+ struct linux_stat *lsp;
+{
+
+ lsp->lst_dev = bsp->st_dev;
+ lsp->lst_ino = bsp->st_ino;
+ lsp->lst_mode = bsp->st_mode;
+ lsp->lst_nlink = bsp->st_nlink;
+ lsp->lst_uid = bsp->st_uid;
+ lsp->lst_gid = bsp->st_gid;
+ lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
+ lsp->lst_size = bsp->st_size;
+ lsp->lst_blksize = bsp->st_blksize;
+ lsp->lst_blocks = bsp->st_blocks;
+ lsp->lst_atime = bsp->st_atime;
+ lsp->lst_mtime = bsp->st_mtime;
+ lsp->lst_ctime = bsp->st_ctime;
+}
+
+/*
+ * The stat functions below are plain sailing. stat and lstat are handled
+ * by one function to avoid code duplication.
+ */
+int
+linux_sys_fstat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_fstat_args /* {
+ syscallarg(int) fd;
+ syscallarg(linux_stat *) sp;
+ } */ *uap = v;
+ struct sys_fstat_args fsa;
+ struct linux_stat tmplst;
+ struct stat *st,tmpst;
+ caddr_t sg;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+
+ st = stackgap_alloc(&sg, sizeof (struct stat));
+
+ SCARG(&fsa, fd) = SCARG(uap, fd);
+ SCARG(&fsa, sb) = st;
+
+ if ((error = sys_fstat(p, &fsa, retval)))
+ return error;
+
+ if ((error = copyin(st, &tmpst, sizeof tmpst)))
+ return error;
+
+ bsd_to_linux_stat(&tmpst, &tmplst);
+
+ if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
+ return error;
+
+ return 0;
+}
+
+static int
+linux_stat1(p, uap, retval, dolstat)
+ struct proc *p;
+ struct linux_sys_stat_args *uap;
+ register_t *retval;
+ int dolstat;
+{
+ struct sys_stat_args sa;
+ struct linux_stat tmplst;
+ struct stat *st, tmpst;
+ caddr_t sg;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ st = stackgap_alloc(&sg, sizeof (struct stat));
+ SCARG(&sa, ub) = st;
+ SCARG(&sa, path) = SCARG(uap, path);
+
+ if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
+ sys_stat(p, &sa, retval))))
+ return error;
+
+ if ((error = copyin(st, &tmpst, sizeof tmpst)))
+ return error;
+
+ bsd_to_linux_stat(&tmpst, &tmplst);
+
+ if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
+ return error;
+
+ return 0;
+}
+
+int
+linux_sys_stat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_stat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct linux_stat *) sp;
+ } */ *uap = v;
+
+ return linux_stat1(p, uap, retval, 0);
+}
+
+int
+linux_sys_lstat(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_lstat_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct linux_stat *) sp;
+ } */ *uap = v;
+
+ return linux_stat1(p, uap, retval, 1);
+}
+
+/*
+ * The following syscalls are mostly here because of the alternate path check.
+ */
+int
+linux_sys_access(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_access_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_access(p, uap, retval);
+}
+
+int
+linux_sys_unlink(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+
+{
+ struct linux_sys_unlink_args /* {
+ syscallarg(char *) path;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_unlink(p, uap, retval);
+}
+
+int
+linux_sys_chdir(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_chdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_chdir(p, uap, retval);
+}
+
+int
+linux_sys_mknod(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_mknod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ syscallarg(int) dev;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+ struct sys_mkfifo_args bma;
+
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
+
+ /*
+ * BSD handles FIFOs seperately
+ */
+ if (SCARG(uap, mode) & S_IFIFO) {
+ SCARG(&bma, path) = SCARG(uap, path);
+ SCARG(&bma, mode) = SCARG(uap, mode);
+ return sys_mkfifo(p, uap, retval);
+ } else
+ return sys_mknod(p, uap, retval);
+}
+
+int
+linux_sys_chmod(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_chmod_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_chmod(p, uap, retval);
+}
+
+int
+linux_sys_chown(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_chown_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap = v;
+ struct sys_chown_args bca;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ SCARG(&bca, path) = SCARG(uap, path);
+ SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, uid);
+ SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
+ (gid_t)-1 : SCARG(uap, gid);
+
+ return sys_chown(p, &bca, retval);
+}
+
+int
+linux_sys_fchown(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_fchown_args /* {
+ syscallarg(int) fd;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+ } */ *uap = v;
+ struct sys_fchown_args bfa;
+
+ SCARG(&bfa, fd) = SCARG(uap, fd);
+ SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, uid);
+ SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
+ (gid_t)-1 : SCARG(uap, gid);
+
+ return sys_fchown(p, &bfa, retval);
+}
+
+int
+linux_sys_rename(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_rename_args /* {
+ syscallarg(char *) from;
+ syscallarg(char *) to;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
+
+ return sys_rename(p, uap, retval);
+}
+
+int
+linux_sys_mkdir(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_mkdir_args /* {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
+
+ return sys_mkdir(p, uap, retval);
+}
+
+int
+linux_sys_rmdir(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_rmdir_args /* {
+ syscallarg(char *) path;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return sys_rmdir(p, uap, retval);
+}
+
+int
+linux_sys_symlink(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_symlink_args /* {
+ syscallarg(char *) path;
+ syscallarg(char *) to;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+ LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
+
+ return sys_symlink(p, uap, retval);
+}
+
+int
+linux_sys_readlink(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_readlink_args /* {
+ syscallarg(char *) name;
+ syscallarg(char *) buf;
+ syscallarg(int) count;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
+
+ return sys_readlink(p, uap, retval);
+}
+
+int
+linux_sys_truncate(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_truncate_args /* {
+ syscallarg(char *) path;
+ syscallarg(long) length;
+ } */ *uap = v;
+ caddr_t sg = stackgap_init(p->p_emul);
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ return compat_43_sys_truncate(p, uap, retval);
+}
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
new file mode 100644
index 00000000000..15967402545
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.c
@@ -0,0 +1,656 @@
+/* $NetBSD: linux_ioctl.c,v 1.8 1995/10/07 06:27:07 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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/proc.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+#include <sys/tty.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <net/if.h>
+#include <sys/sockio.h>
+
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_sockio.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+
+static speed_t linux_speeds[] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200
+};
+
+static int linux_spmasks[] = {
+ LINUX_B0, LINUX_B50, LINUX_B75, LINUX_B110, LINUX_B134, LINUX_B150,
+ LINUX_B200, LINUX_B300, LINUX_B600, LINUX_B1200, LINUX_B1800,
+ LINUX_B2400, LINUX_B4800, LINUX_B9600, LINUX_B19200, LINUX_B38400,
+ LINUX_B57600, LINUX_B115200, LINUX_B230400
+};
+
+/*
+ * Deal with termio ioctl cruft. This doesn't look very good..
+ * XXX too much code duplication, obviously..
+ *
+ * The conversion routines between Linux and BSD structures assume
+ * that the fields are already filled with the current values,
+ * so that fields present in BSD but not in Linux keep their current
+ * values.
+ */
+
+static int
+linux_termio_to_bsd_termios(lt, bts)
+ register struct linux_termio *lt;
+ register struct termios *bts;
+{
+ int index;
+
+ bts->c_iflag = 0;
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNBRK, IGNBRK);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_BRKINT, BRKINT);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNPAR, IGNPAR);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INPCK, INPCK);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ISTRIP, ISTRIP);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INLCR, INLCR);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNCR, IGNCR);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ICRNL, ICRNL);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXON, IXON);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXANY, IXANY);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXOFF, IXOFF);
+ bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IMAXBEL, IMAXBEL);
+
+ bts->c_oflag = 0;
+ bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_OPOST, OPOST);
+ bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_ONLCR, ONLCR);
+ bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_XTABS, OXTABS);
+
+ /*
+ * This could have been:
+ * bts->c_cflag = (lt->c_flag & LINUX_CSIZE) << 4
+ * But who knows, those values might perhaps change one day.
+ */
+ switch (lt->c_cflag & LINUX_CSIZE) {
+ case LINUX_CS5:
+ bts->c_cflag = CS5;
+ break;
+ case LINUX_CS6:
+ bts->c_cflag = CS6;
+ break;
+ case LINUX_CS7:
+ bts->c_cflag = CS7;
+ break;
+ case LINUX_CS8:
+ bts->c_cflag = CS8;
+ break;
+ }
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CSTOPB, CSTOPB);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CREAD, CREAD);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARENB, PARENB);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARODD, PARODD);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_HUPCL, HUPCL);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CLOCAL, CLOCAL);
+ bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CRTSCTS, CRTSCTS);
+
+ bts->c_lflag = 0;
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ISIG, ISIG);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ICANON, ICANON);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHO, ECHO);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOE, ECHOE);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOK, ECHOK);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHONL, ECHONL);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_NOFLSH, NOFLSH);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_TOSTOP, TOSTOP);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOCTL, ECHOCTL);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOPRT, ECHOPRT);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOKE, ECHOKE);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_FLUSHO, FLUSHO);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_PENDIN, PENDIN);
+ bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_IEXTEN, IEXTEN);
+
+ index = lt->c_cflag & LINUX_CBAUD;
+ if (index & LINUX_CBAUDEX)
+ index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1;
+ bts->c_ispeed = bts->c_ospeed = linux_speeds[index];
+
+ bts->c_cc[VINTR] = lt->c_cc[LINUX_VINTR];
+ bts->c_cc[VQUIT] = lt->c_cc[LINUX_VQUIT];
+ bts->c_cc[VERASE] = lt->c_cc[LINUX_VERASE];
+ bts->c_cc[VKILL] = lt->c_cc[LINUX_VKILL];
+ bts->c_cc[VEOF] = lt->c_cc[LINUX_VEOF];
+ bts->c_cc[VTIME] = lt->c_cc[LINUX_VTIME];
+ bts->c_cc[VMIN] = lt->c_cc[LINUX_VMIN];
+}
+
+static int
+bsd_termios_to_linux_termio(bts, lt)
+ register struct termios *bts;
+ register struct linux_termio *lt;
+{
+ int i, mask;
+
+ lt->c_iflag = 0;
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF);
+ lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL);
+
+ lt->c_oflag = 0;
+ lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST);
+ lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR);
+ lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS);
+
+ switch (bts->c_cflag & CSIZE) {
+ case CS5:
+ lt->c_cflag = LINUX_CS5;
+ break;
+ case CS6:
+ lt->c_cflag = LINUX_CS6;
+ break;
+ case CS7:
+ lt->c_cflag = LINUX_CS7;
+ break;
+ case CS8:
+ lt->c_cflag = LINUX_CS8;
+ break;
+ }
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL);
+ lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS);
+
+ lt->c_lflag = 0;
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN);
+ lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN);
+
+ mask = LINUX_B9600; /* XXX default value should this be 0? */
+ for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) {
+ if (bts->c_ospeed == linux_speeds[i]) {
+ mask = linux_spmasks[i];
+ break;
+ }
+ }
+ lt->c_cflag |= mask;
+
+ lt->c_cc[LINUX_VINTR] = bts->c_cc[VINTR];
+ lt->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT];
+ lt->c_cc[LINUX_VERASE] = bts->c_cc[VERASE];
+ lt->c_cc[LINUX_VKILL] = bts->c_cc[VKILL];
+ lt->c_cc[LINUX_VEOF] = bts->c_cc[VEOF];
+ lt->c_cc[LINUX_VTIME] = bts->c_cc[VTIME];
+ lt->c_cc[LINUX_VMIN] = bts->c_cc[VMIN];
+ lt->c_cc[LINUX_VSWTC] = 0;
+
+ /* XXX should be fixed someday */
+ lt->c_line = 0;
+}
+
+static int
+linux_termios_to_bsd_termios(lts, bts)
+ register struct linux_termios *lts;
+ register struct termios *bts;
+{
+ int index;
+
+ bts->c_iflag = 0;
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNBRK, IGNBRK);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_BRKINT, BRKINT);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNPAR, IGNPAR);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INPCK, INPCK);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ISTRIP, ISTRIP);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INLCR, INLCR);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNCR, IGNCR);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ICRNL, ICRNL);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXON, IXON);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXANY, IXANY);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXOFF, IXOFF);
+ bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IMAXBEL, IMAXBEL);
+
+ bts->c_oflag = 0;
+ bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_OPOST, OPOST);
+ bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_ONLCR, ONLCR);
+ bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_XTABS, OXTABS);
+
+ bts->c_cflag = 0;
+ switch (lts->c_cflag & LINUX_CSIZE) {
+ case LINUX_CS5:
+ bts->c_cflag = CS5;
+ break;
+ case LINUX_CS6:
+ bts->c_cflag = CS6;
+ break;
+ case LINUX_CS7:
+ bts->c_cflag = CS7;
+ break;
+ case LINUX_CS8:
+ bts->c_cflag = CS8;
+ break;
+ }
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CSTOPB, CSTOPB);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CREAD, CREAD);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARENB, PARENB);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARODD, PARODD);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_HUPCL, HUPCL);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CLOCAL, CLOCAL);
+ bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CRTSCTS, CRTSCTS);
+
+ bts->c_lflag = 0;
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ISIG, ISIG);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ICANON, ICANON);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHO, ECHO);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOE, ECHOE);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOK, ECHOK);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHONL, ECHONL);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_NOFLSH, NOFLSH);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_TOSTOP, TOSTOP);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOCTL, ECHOCTL);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOPRT, ECHOPRT);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOKE, ECHOKE);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_FLUSHO, FLUSHO);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_PENDIN, PENDIN);
+ bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_IEXTEN, IEXTEN);
+
+ index = lts->c_cflag & LINUX_CBAUD;
+ if (index & LINUX_CBAUDEX)
+ index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1;
+ bts->c_ispeed = bts->c_ospeed = linux_speeds[index];
+
+ bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR];
+ bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT];
+ bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE];
+ bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL];
+ bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF];
+ bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME];
+ bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN];
+ bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL];
+ bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2];
+ bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE];
+ bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP];
+ bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART];
+ bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP];
+ bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT];
+ bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD];
+ bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT];
+}
+
+static int
+bsd_termios_to_linux_termios(bts, lts)
+ register struct termios *bts;
+ register struct linux_termios *lts;
+{
+ int i, mask;
+
+ lts->c_iflag = 0;
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF);
+ lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL);
+
+ lts->c_oflag = 0;
+ lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST);
+ lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR);
+ lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS);
+
+ switch (bts->c_cflag & CSIZE) {
+ case CS5:
+ lts->c_cflag = LINUX_CS5;
+ break;
+ case CS6:
+ lts->c_cflag = LINUX_CS6;
+ break;
+ case CS7:
+ lts->c_cflag = LINUX_CS7;
+ break;
+ case CS8:
+ lts->c_cflag = LINUX_CS8;
+ break;
+ }
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL);
+ lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS);
+
+ lts->c_lflag = 0;
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN);
+ lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN);
+
+ mask = LINUX_B9600; /* XXX default value */
+ for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) {
+ if (bts->c_ospeed == linux_speeds[i]) {
+ mask = linux_spmasks[i];
+ break;
+ }
+ }
+ lts->c_cflag |= mask;
+
+ lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR];
+ lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT];
+ lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE];
+ lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL];
+ lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF];
+ lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME];
+ lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN];
+ lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL];
+ lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2];
+ lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE];
+ lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP];
+ lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART];
+ lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP];
+ lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT];
+ lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD];
+ lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT];
+ lts->c_cc[LINUX_VSWTC] = 0;
+
+ /* XXX should be fixed someday */
+ lts->c_line = 0;
+}
+
+/*
+ * Most ioctl command are just converted to their NetBSD values,
+ * and passed on. The ones that take structure pointers and (flag)
+ * values need some massaging. This is done the usual way by
+ * allocating stackgap memory, letting the actual ioctl call do its
+ * work their and converting back the data afterwards.
+ */
+int
+linux_sys_ioctl(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct linux_sys_ioctl_args /* {
+ syscallarg(int) fd;
+ syscallarg(u_long) com;
+ syscallarg(caddr_t) data;
+ } */ *uap = v;
+ int fd;
+ unsigned long com;
+ caddr_t data, sg;
+ struct file *fp;
+ struct filedesc *fdp;
+ struct linux_termio tmplt, *alt;
+ struct linux_termios tmplts, *alts;
+ struct termios tmpbts, *abts;
+ struct sys_ioctl_args ia;
+ int error, idat, *idatp;
+
+ fd = SCARG(&ia, fd) = SCARG(uap, fd);
+ com = SCARG(uap, com);
+ data = SCARG(&ia, data) = SCARG(uap, data);
+ retval[0] = 0;
+
+ fdp = p->p_fd;
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL)
+ return (EBADF);
+
+ if ((fp->f_flag & (FREAD | FWRITE)) == 0)
+ return (EBADF);
+
+ sg = stackgap_init(p->p_emul);
+
+ switch (com) {
+ case LINUX_TCGETS:
+ SCARG(&ia, com) = TIOCGETA;
+ abts = stackgap_alloc(&sg, sizeof (*abts));
+ SCARG(&ia, data) = (caddr_t) abts;
+ if ((error = sys_ioctl(p, &ia, retval)) != 0)
+ return error;
+ if ((error = copyin(abts, &tmpbts, sizeof tmpbts)))
+ return error;
+ bsd_termios_to_linux_termios(&tmpbts, &tmplts);
+ return copyout(&tmplts, data, sizeof tmplts);
+ case LINUX_TCSETS:
+ case LINUX_TCSETSW:
+ case LINUX_TCSETSF:
+ switch (com) {
+ case LINUX_TCSETS:
+ SCARG(&ia, com) = TIOCSETA;
+ break;
+ case LINUX_TCSETSW:
+ SCARG(&ia, com) = TIOCSETAW;
+ break;
+ case LINUX_TCSETSF:
+ SCARG(&ia, com) = TIOCSETAF;
+ break;
+ }
+ if ((error = copyin(data, &tmplts, sizeof tmplts)))
+ return error;
+ abts = stackgap_alloc(&sg, sizeof tmpbts);
+ /*
+ * First fill in all fields, so that we keep the current
+ * values for fields that Linux doesn't know about.
+ */
+ if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA,
+ (caddr_t) &tmpbts, p)))
+ return error;
+ linux_termios_to_bsd_termios(&tmplts, &tmpbts);
+ if ((error = copyout(&tmpbts, abts, sizeof tmpbts)))
+ return error;
+ SCARG(&ia, data) = (caddr_t) abts;
+ return sys_ioctl(p, &ia, retval);
+ case LINUX_TCGETA:
+ SCARG(&ia, com) = TIOCGETA;
+ abts = stackgap_alloc(&sg, sizeof (*abts));
+ SCARG(&ia, data) = (caddr_t) abts;
+ if ((error = sys_ioctl(p, &ia, retval)) != 0)
+ return error;
+ if ((error = copyin(abts, &tmpbts, sizeof tmpbts)))
+ return error;
+ bsd_termios_to_linux_termio(&tmpbts, &tmplt);
+ return copyout(&tmplt, data, sizeof tmplt);
+ case LINUX_TCSETA:
+ case LINUX_TCSETAW:
+ case LINUX_TCSETAF:
+ switch (com) {
+ case LINUX_TCSETA:
+ SCARG(&ia, com) = TIOCSETA;
+ break;
+ case LINUX_TCSETAW:
+ SCARG(&ia, com) = TIOCSETAW;
+ break;
+ case LINUX_TCSETAF:
+ SCARG(&ia, com) = TIOCSETAF;
+ break;
+ }
+ if ((error = copyin(&tmplt, data, sizeof tmplt)))
+ return error;
+ abts = stackgap_alloc(&sg, sizeof tmpbts);
+ /*
+ * First fill in all fields, so that we keep the current
+ * values for fields that Linux doesn't know about.
+ */
+ if ((error = (*fp->f_ops->fo_ioctl)(fp, TIOCGETA,
+ (caddr_t) &tmpbts, p)))
+ return error;
+ linux_termio_to_bsd_termios(&tmplt, &tmpbts);
+ if ((error = copyout(&tmpbts, abts, sizeof tmpbts)))
+ return error;
+ SCARG(&ia, data) = (caddr_t) abts;
+ return sys_ioctl(p, &ia, retval);
+ case LINUX_TIOCSETD:
+ if ((error = copyin(data, (caddr_t) &idat, sizeof idat)))
+ return error;
+ switch (idat) {
+ case LINUX_N_TTY:
+ idat = TTYDISC;
+ break;
+ case LINUX_N_SLIP:
+ idat = SLIPDISC;
+ break;
+ case LINUX_N_PPP:
+ idat = PPPDISC;
+ break;
+ /*
+ * We can't handle the mouse line discipline Linux has.
+ */
+ case LINUX_N_MOUSE:
+ default:
+ return EINVAL;
+ }
+
+ idatp = (int *) stackgap_alloc(&sg, sizeof (int));
+ if ((error = copyout(&idat, idatp, sizeof (int))))
+ return error;
+ SCARG(&ia, com) = TIOCSETD;
+ SCARG(&ia, data) = (caddr_t) idatp;
+ break;
+ case LINUX_TIOCGETD:
+ idatp = (int *) stackgap_alloc(&sg, sizeof (int));
+ SCARG(&ia, com) = TIOCGETD;
+ SCARG(&ia, data) = (caddr_t) idatp;
+ if ((error = sys_ioctl(p, &ia, retval)))
+ return error;
+ if ((error = copyin(idatp, (caddr_t) &idat, sizeof (int))))
+ return error;
+ switch (idat) {
+ case TTYDISC:
+ idat = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ idat = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ idat = LINUX_N_PPP;
+ break;
+ /*
+ * Linux does not have the tablet line discipline.
+ */
+ case TABLDISC:
+ default:
+ idat = -1; /* XXX What should this be? */
+ break;
+ }
+ return copyout(&idat, data, sizeof (int));
+ case LINUX_TIOCGWINSZ:
+ SCARG(&ia, com) = TIOCGWINSZ;
+ break;
+ case LINUX_TIOCSWINSZ:
+ SCARG(&ia, com) = TIOCSWINSZ;
+ break;
+ case LINUX_TIOCGPGRP:
+ SCARG(&ia, com) = TIOCGPGRP;
+ break;
+ case LINUX_TIOCSPGRP:
+ SCARG(&ia, com) = TIOCSPGRP;
+ break;
+ case LINUX_FIONREAD:
+ SCARG(&ia, com) = FIONREAD;
+ break;
+ case LINUX_FIONBIO:
+ SCARG(&ia, com) = FIONBIO;
+ break;
+ case LINUX_FIOASYNC:
+ SCARG(&ia, com) = FIOASYNC;
+ break;
+ case LINUX_TIOCEXCL:
+ SCARG(&ia, com) = TIOCEXCL;
+ break;
+ case LINUX_TIOCNXCL:
+ SCARG(&ia, com) = TIOCNXCL;
+ break;
+ case LINUX_TIOCCONS:
+ SCARG(&ia, com) = TIOCCONS;
+ break;
+ case LINUX_TIOCNOTTY:
+ SCARG(&ia, com) = TIOCNOTTY;
+ break;
+ case LINUX_SIOCADDMULTI:
+ SCARG(&ia, com) = SIOCADDMULTI;
+ break;
+ case LINUX_SIOCDELMULTI:
+ SCARG(&ia, com) = SIOCDELMULTI;
+ break;
+ default:
+ return linux_machdepioctl(p, uap, retval);
+ }
+
+ return sys_ioctl(p, &ia, retval);
+}
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
new file mode 100644
index 00000000000..0acc5da9f02
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.h
@@ -0,0 +1,278 @@
+/* $NetBSD: linux_ioctl.h,v 1.2 1995/08/16 04:14:58 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_IOCTL_H
+#define _LINUX_IOCTL_H
+
+#define _LINUX_IO(c,n) (((c)<< 8) | (n))
+
+#define LINUX_TCGETS _LINUX_IO('T',1)
+#define LINUX_TCSETS _LINUX_IO('T',2)
+#define LINUX_TCSETSW _LINUX_IO('T',3)
+#define LINUX_TCSETSF _LINUX_IO('T',4)
+#define LINUX_TCGETA _LINUX_IO('T',5)
+#define LINUX_TCSETA _LINUX_IO('T',6)
+#define LINUX_TCSETAW _LINUX_IO('T',7)
+#define LINUX_TCSETAF _LINUX_IO('T',8)
+#define LINUX_TCSBRK _LINUX_IO('T',9)
+#define LINUX_TCXONC _LINUX_IO('T',10)
+#define LINUX_TCFLSH _LINUX_IO('T',11)
+#define LINUX_TIOCEXCL _LINUX_IO('T',12)
+#define LINUX_TIOCNXCL _LINUX_IO('T',13)
+#define LINUX_TIOCSCTTY _LINUX_IO('T',14)
+#define LINUX_TIOCGPGRP _LINUX_IO('T',15)
+#define LINUX_TIOCSPGRP _LINUX_IO('T',16)
+#define LINUX_TIOCOUTQ _LINUX_IO('T',17)
+#define LINUX_TIOCSTI _LINUX_IO('T',18)
+#define LINUX_TIOCGWINSZ _LINUX_IO('T',19)
+#define LINUX_TIOCSWINSZ _LINUX_IO('T',20)
+#define LINUX_TIOCMGET _LINUX_IO('T',21)
+#define LINUX_TIOCMBIS _LINUX_IO('T',22)
+#define LINUX_TIOCMBIC _LINUX_IO('T',23)
+#define LINUX_TIOCMSET _LINUX_IO('T',24)
+#define LINUX_TIOCGSOFTCAR _LINUX_IO('T',25)
+#define LINUX_TIOCSSOFTCAR _LINUX_IO('T',26)
+#define LINUX_FIONREAD _LINUX_IO('T',27)
+#define LINUX_TIOCINQ LINUX_FIONREAD
+#define LINUX_TIOCLINUX _LINUX_IO('T',28)
+#define LINUX_TIOCCONS _LINUX_IO('T',29)
+#define LINUX_TIOCGSERIAL _LINUX_IO('T',30)
+#define LINUX_TIOCSSERIAL _LINUX_IO('T',31)
+#define LINUX_TIOCPKT _LINUX_IO('T',32)
+#define LINUX_FIONBIO _LINUX_IO('T',33)
+#define LINUX_TIOCNOTTY _LINUX_IO('T',34)
+#define LINUX_TIOCSETD _LINUX_IO('T',35)
+#define LINUX_TIOCGETD _LINUX_IO('T',36)
+#define LINUX_TCSBRKP _LINUX_IO('T',37)
+#define LINUX_TIOCTTYGSTRUCT _LINUX_IO('T',38)
+
+#define LINUX_FIONCLEX _LINUX_IO('T',80)
+#define LINUX_FIOCLEX _LINUX_IO('T',81)
+#define LINUX_FIOASYNC _LINUX_IO('T',82)
+#define LINUX_TIOCSERCONFIG _LINUX_IO('T',83)
+#define LINUX_TIOCSERGWILD _LINUX_IO('T',84)
+#define LINUX_TIOCSERSWILD _LINUX_IO('T',85)
+#define LINUX_TIOCGLCKTRMIOS _LINUX_IO('T',86)
+#define LINUX_TIOCSLCKTRMIOS _LINUX_IO('T',87)
+#define LINUX_TIOCSERGSTRUCT _LINUX_IO('T',88)
+#define LINUX_TIOCSERGETLSR _LINUX_IO('T',89)
+
+
+#define LINUX_NCC 8
+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];
+};
+
+typedef unsigned char linux_cc_t;
+typedef unsigned long linux_tcflag_t;
+
+#define LINUX_NCCS 19
+struct linux_termios {
+ linux_tcflag_t c_iflag;
+ linux_tcflag_t c_oflag;
+ linux_tcflag_t c_cflag;
+ linux_tcflag_t c_lflag;
+ linux_cc_t c_line;
+ linux_cc_t c_cc[LINUX_NCCS];
+};
+
+/* Just in old style linux_termio struct */
+#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
+
+/* In the termios struct too */
+#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
+
+/* 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
+#define LINUX_IUCLC 0x0000200
+#define LINUX_IXON 0x0000400
+#define LINUX_IXANY 0x0000800
+#define LINUX_IXOFF 0x0001000
+#define LINUX_IMAXBEL 0x0002000
+
+/* Linux c_oflag masks */
+#define LINUX_OPOST 0x0000001
+#define LINUX_OLCUC 0x0000002
+#define LINUX_ONLCR 0x0000004
+#define LINUX_OCRNL 0x0000008
+#define LINUX_ONOCR 0x0000010
+#define LINUX_ONLRET 0x0000020
+#define LINUX_OFILL 0x0000040
+#define LINUX_OFDEL 0x0000080
+#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
+
+/* Linux c_cflag bit masks */
+
+#define LINUX_NSPEEDS 16
+#define LINUX_NXSPEEDS 2
+
+#define LINUX_CBAUD 0x0000100f
+
+#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
+#define LINUX_CBAUDEX 0x00001000
+#define LINUX_B57600 0x00001001
+#define LINUX_B115200 0x00001002
+#define LINUX_B230400 0x00001003
+
+#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
+
+#define LINUX_CRTSCTS 0x80000000
+
+/* Linux c_lflag masks */
+#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
+
+/* Linux modem line defines.. not sure if they'll be used */
+#define LINUX_TIOCM_LE 0x0001
+#define LINUX_TIOCM_DTR 0x0002
+#define LINUX_TIOCM_RTS 0x0004
+#define LINUX_TIOCM_ST 0x0008
+#define LINUX_TIOCM_SR 0x0010
+#define LINUX_TIOCM_CTS 0x0020
+#define LINUX_TIOCM_CAR 0x0040
+#define LINUX_TIOCM_RNG 0x0080
+#define LINUX_TIOCM_DSR 0x0100
+#define LINUX_TIOCM_CD LINUX_TIOCM_CAR
+#define LINUX_TIOCM_RI LINUX_TIOCM_RNG
+
+#define LINUX_TCIFLUSH 0
+#define LINUX_TCOFLUSH 1
+#define LINUX_TCIOFLUSH 2
+
+#define LINUX_TCOOFF 0
+#define LINUX_TCOON 1
+#define LINUX_TCIOFF 2
+#define LINUX_TCION 3
+
+#define LINUX_TCSANOW 0
+#define LINUX_TCSADRAIN 1
+#define LINUX_TCSAFLUSH 2
+
+/* Linux line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+#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 00000000000..407a075eb7e
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.c
@@ -0,0 +1,707 @@
+/* $NetBSD: linux_ipc.c,v 1.9 1995/10/08 22:49:29 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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/types.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#include <sys/msg.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/systm.h>
+#include <sys/stat.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_msg.h>
+#include <compat/linux/linux_shm.h>
+#include <compat/linux/linux_sem.h>
+#include <compat/linux/linux_ipccall.h>
+
+/*
+ * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
+ * The main difference is, that Linux handles it all via one
+ * system call, which has the usual maximum amount of 5 arguments.
+ * This results in a kludge for calls that take 6 of them.
+ *
+ * The SYSVXXXX options have to be enabled to get the appropriate
+ * functions to work.
+ */
+
+#ifdef SYSVSEM
+static int linux_semop __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_semget __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_semctl __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+#endif
+
+#ifdef SYSVMSG
+static int linux_msgsnd __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_msgrcv __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_msgop __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_msgctl __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+#endif
+
+#ifdef SYSVSHM
+static int linux_shmat __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_shmdt __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_shmget __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+static int linux_shmctl __P((struct proc *, struct linux_sys_ipc_args *,
+ register_t *));
+#endif
+
+
+int
+linux_sys_ipc(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap = v;
+ int what, error;
+
+ switch (SCARG(uap, what)) {
+#ifdef SYSVSEM
+ case LINUX_SYS_semop:
+ return linux_semop(p, uap, retval);
+ case LINUX_SYS_semget:
+ return linux_semget(p, uap, retval);
+ case LINUX_SYS_semctl:
+ return linux_semctl(p, uap, retval);
+#endif
+#ifdef SYSVMSG
+ case LINUX_SYS_msgsnd:
+ return linux_msgsnd(p, uap, retval);
+ case LINUX_SYS_msgrcv:
+ return linux_msgrcv(p, uap, retval);
+ case LINUX_SYS_msgget:
+ return linux_msgget(p, uap, retval);
+ case LINUX_SYS_msgctl:
+ return linux_msgctl(p, uap, retval);
+#endif
+#ifdef SYSVSHM
+ case LINUX_SYS_shmat:
+ return linux_shmat(p, uap, retval);
+ case LINUX_SYS_shmdt:
+ return linux_shmdt(p, uap, retval);
+ case LINUX_SYS_shmget:
+ return linux_shmget(p, uap, retval);
+ case LINUX_SYS_shmctl:
+ return linux_shmctl(p, uap, retval);
+#endif
+ default:
+ return ENOSYS;
+ }
+}
+
+/*
+ * Convert between Linux and NetBSD ipc_perm structures. Only the
+ * order of the fields is different.
+ */
+static void
+linux_to_bsd_ipc_perm(lpp, bpp)
+ struct linux_ipc_perm *lpp;
+ struct ipc_perm *bpp;
+{
+
+ bpp->key = lpp->l_key;
+ bpp->uid = lpp->l_uid;
+ bpp->gid = lpp->l_gid;
+ bpp->cuid = lpp->l_cuid;
+ bpp->cgid = lpp->l_cgid;
+ bpp->mode = lpp->l_mode;
+ bpp->seq = lpp->l_seq;
+}
+
+static void
+bsd_to_linux_ipc_perm(bpp, lpp)
+ struct ipc_perm *bpp;
+ struct linux_ipc_perm *lpp;
+{
+
+ lpp->l_key = bpp->key;
+ lpp->l_uid = bpp->uid;
+ lpp->l_gid = bpp->gid;
+ lpp->l_cuid = bpp->cuid;
+ lpp->l_cgid = bpp->cgid;
+ lpp->l_mode = bpp->mode;
+ lpp->l_seq = bpp->seq;
+}
+
+#ifdef SYSVSEM
+/*
+ * Semaphore operations. Most constants and structures are the same on
+ * both systems. Only semctl() needs some extra work.
+ */
+
+/*
+ * Convert between Linux and NetBSD semid_ds structures.
+ */
+static void
+bsd_to_linux_semid_ds(bs, ls)
+ struct semid_ds *bs;
+ struct linux_semid_ds *ls;
+{
+
+ bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
+ ls->l_sem_otime = bs->sem_otime;
+ ls->l_sem_ctime = bs->sem_ctime;
+ ls->l_sem_nsems = bs->sem_nsems;
+ ls->l_sem_base = bs->sem_base;
+}
+
+static void
+linux_to_bsd_semid_ds(ls, bs)
+ struct linux_semid_ds *ls;
+ struct semid_ds *bs;
+{
+
+ linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
+ bs->sem_otime = ls->l_sem_otime;
+ bs->sem_ctime = ls->l_sem_ctime;
+ bs->sem_nsems = ls->l_sem_nsems;
+ bs->sem_base = ls->l_sem_base;
+}
+
+int
+linux_semop(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_semop_args bsa;
+
+ SCARG(&bsa, semid) = SCARG(uap, a1);
+ SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
+ SCARG(&bsa, nsops) = SCARG(uap, a2);
+
+ return sys_semop(p, &bsa, retval);
+}
+
+int
+linux_semget(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_semget_args bsa;
+
+ SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
+ SCARG(&bsa, nsems) = SCARG(uap, a2);
+ SCARG(&bsa, semflg) = SCARG(uap, a3);
+
+ return sys_semget(p, &bsa, retval);
+}
+
+/*
+ * Most of this can be handled by directly passing the arguments on,
+ * buf IPC_* require a lot of copy{in,out} because of the extra indirection
+ * (we are passed a pointer to a union cointaining a pointer to a semid_ds
+ * structure.
+ */
+int
+linux_semctl(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ caddr_t sg, unptr, dsp, ldsp;
+ int error, cmd;
+ struct sys___semctl_args bsa;
+ struct linux_semid_ds lm;
+ struct semid_ds bm;
+
+ SCARG(&bsa, semid) = SCARG(uap, a1);
+ SCARG(&bsa, semnum) = SCARG(uap, a2);
+ SCARG(&bsa, cmd) = SCARG(uap, a3);
+ SCARG(&bsa, arg) = (union semun *)SCARG(uap, ptr);
+ switch(SCARG(uap, a3)) {
+ case LINUX_GETVAL:
+ cmd = GETVAL;
+ break;
+ case LINUX_GETPID:
+ cmd = GETPID;
+ break;
+ case LINUX_GETNCNT:
+ cmd = GETNCNT;
+ break;
+ case LINUX_GETZCNT:
+ cmd = GETZCNT;
+ break;
+ case LINUX_SETVAL:
+ cmd = SETVAL;
+ break;
+ case LINUX_IPC_RMID:
+ cmd = IPC_RMID;
+ break;
+ case LINUX_IPC_SET:
+ if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
+ return error;
+ if ((error = copyin(ldsp, (caddr_t)&lm, sizeof lm)))
+ return error;
+ linux_to_bsd_semid_ds(&lm, &bm);
+ sg = stackgap_init(p->p_emul);
+ unptr = stackgap_alloc(&sg, sizeof (union semun));
+ dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
+ if ((error = copyout((caddr_t)&bm, dsp, sizeof bm)))
+ return error;
+ if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
+ return error;
+ SCARG(&bsa, arg) = (union semun *)unptr;
+ return sys___semctl(p, &bsa, retval);
+ case LINUX_IPC_STAT:
+ sg = stackgap_init(p->p_emul);
+ unptr = stackgap_alloc(&sg, sizeof (union semun *));
+ dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
+ if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
+ return error;
+ SCARG(&bsa, arg) = (union semun *)unptr;
+ if ((error = sys___semctl(p, &bsa, retval)))
+ return error;
+ if ((error = copyin(dsp, (caddr_t)&bm, sizeof bm)))
+ return error;
+ bsd_to_linux_semid_ds(&bm, &lm);
+ if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
+ return error;
+ return copyout((caddr_t)&lm, ldsp, sizeof lm);
+ default:
+ return EINVAL;
+ }
+ SCARG(&bsa, cmd) = cmd;
+
+ return sys___semctl(p, &bsa, retval);
+}
+#endif /* SYSVSEM */
+
+#ifdef SYSVMSG
+
+static void
+linux_to_bsd_msqid_ds(lmp, bmp)
+ struct linux_msqid_ds *lmp;
+ struct msqid_ds *bmp;
+{
+
+ linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
+ bmp->msg_first = lmp->l_msg_first;
+ bmp->msg_last = lmp->l_msg_last;
+ bmp->msg_cbytes = lmp->l_msg_cbytes;
+ bmp->msg_qnum = lmp->l_msg_qnum;
+ bmp->msg_qbytes = lmp->l_msg_qbytes;
+ bmp->msg_lspid = lmp->l_msg_lspid;
+ bmp->msg_lrpid = lmp->l_msg_lrpid;
+ bmp->msg_stime = lmp->l_msg_stime;
+ bmp->msg_rtime = lmp->l_msg_rtime;
+ bmp->msg_ctime = lmp->l_msg_ctime;
+}
+
+static void
+bsd_to_linux_msqid_ds(bmp, lmp)
+ struct msqid_ds *bmp;
+ struct linux_msqid_ds *lmp;
+{
+
+ bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
+ lmp->l_msg_first = bmp->msg_first;
+ lmp->l_msg_last = bmp->msg_last;
+ lmp->l_msg_cbytes = bmp->msg_cbytes;
+ lmp->l_msg_qnum = bmp->msg_qnum;
+ lmp->l_msg_qbytes = bmp->msg_qbytes;
+ lmp->l_msg_lspid = bmp->msg_lspid;
+ lmp->l_msg_lrpid = bmp->msg_lrpid;
+ lmp->l_msg_stime = bmp->msg_stime;
+ lmp->l_msg_rtime = bmp->msg_rtime;
+ lmp->l_msg_ctime = bmp->msg_ctime;
+}
+
+int
+linux_msgsnd(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_msgsnd_args bma;
+
+ SCARG(&bma, msqid) = SCARG(uap, a1);
+ SCARG(&bma, msgp) = SCARG(uap, ptr);
+ SCARG(&bma, msgsz) = SCARG(uap, a2);
+ SCARG(&bma, msgflg) = SCARG(uap, a3);
+
+ return sys_msgsnd(p, &bma, retval);
+}
+
+int
+linux_msgrcv(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_msgrcv_args bma;
+ struct linux_msgrcv_msgarg kluge;
+ int error;
+
+ if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
+ return error;
+
+ SCARG(&bma, msqid) = SCARG(uap, a1);
+ SCARG(&bma, msgp) = kluge.msg;
+ SCARG(&bma, msgsz) = SCARG(uap, a2);
+ SCARG(&bma, msgtyp) = kluge.type;
+ SCARG(&bma, msgflg) = SCARG(uap, a3);
+
+ return sys_msgrcv(p, &bma, retval);
+}
+
+int
+linux_msgget(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_msgget_args bma;
+
+ SCARG(&bma, key) = (key_t)SCARG(uap, a1);
+ SCARG(&bma, msgflg) = SCARG(uap, a2);
+
+ return sys_msgget(p, &bma, retval);
+}
+
+int
+linux_msgctl(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_msgctl_args bma;
+ caddr_t umsgptr, sg;
+ struct linux_msqid_ds lm;
+ struct msqid_ds bm;
+ int error;
+
+ SCARG(&bma, msqid) = SCARG(uap, a1);
+ SCARG(&bma, cmd) = SCARG(uap, a2);
+ switch (SCARG(uap, a2)) {
+ case LINUX_IPC_RMID:
+ return sys_msgctl(p, &bma, retval);
+ case LINUX_IPC_SET:
+ if ((error = copyin(SCARG(uap, ptr), (caddr_t)&lm, sizeof lm)))
+ return error;
+ linux_to_bsd_msqid_ds(&lm, &bm);
+ sg = stackgap_init(p->p_emul);
+ umsgptr = stackgap_alloc(&sg, sizeof bm);
+ if ((error = copyout((caddr_t)&bm, umsgptr, sizeof bm)))
+ return error;
+ SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
+ return sys_msgctl(p, &bma, retval);
+ case LINUX_IPC_STAT:
+ sg = stackgap_init(p->p_emul);
+ umsgptr = stackgap_alloc(&sg, sizeof (struct msqid_ds));
+ SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
+ if ((error = sys_msgctl(p, &bma, retval)))
+ return error;
+ if ((error = copyin(umsgptr, (caddr_t)&bm, sizeof bm)))
+ return error;
+ bsd_to_linux_msqid_ds(&bm, &lm);
+ return copyout((caddr_t)&lm, SCARG(uap, ptr), sizeof lm);
+ }
+ return EINVAL;
+}
+#endif /* SYSVMSG */
+
+#ifdef SYSVSHM
+/*
+ * shmat(2). Very straightforward, except that Linux passes a pointer
+ * in which the return value is to be passed. This is subsequently
+ * handled by libc, apparently.
+ */
+int
+linux_shmat(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_shmat_args bsa;
+ int error;
+
+ SCARG(&bsa, shmid) = SCARG(uap, a1);
+ SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
+ SCARG(&bsa, shmflg) = SCARG(uap, a2);
+
+ if ((error = sys_shmat(p, &bsa, retval)))
+ return error;
+
+ if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3),
+ sizeof retval[0])))
+ return error;
+
+ retval[0] = 0;
+ return 0;
+}
+
+/*
+ * shmdt(): this could have been mapped directly, if it wasn't for
+ * the extra indirection by the linux_ipc system call.
+ */
+int
+linux_shmdt(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_shmdt_args bsa;
+
+ SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
+
+ return sys_shmdt(p, &bsa, retval);
+}
+
+/*
+ * Same story as shmdt.
+ */
+int
+linux_shmget(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ struct sys_shmget_args bsa;
+
+ SCARG(&bsa, key) = SCARG(uap, a1);
+ SCARG(&bsa, size) = SCARG(uap, a2);
+ SCARG(&bsa, shmflg) = SCARG(uap, a3);
+
+ return sys_shmget(p, &bsa, retval);
+}
+
+/*
+ * Convert between Linux and NetBSD shmid_ds structures.
+ * The order of the fields is once again the difference, and
+ * we also need a place to store the internal data pointer
+ * in, which is unfortunately stored in this structure.
+ *
+ * We abuse a Linux internal field for that.
+ */
+static void
+linux_to_bsd_shmid_ds(lsp, bsp)
+ struct linux_shmid_ds *lsp;
+ struct shmid_ds *bsp;
+{
+
+ linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->l_shm_segsz;
+ bsp->shm_lpid = lsp->l_shm_lpid;
+ bsp->shm_cpid = lsp->l_shm_cpid;
+ bsp->shm_nattch = lsp->l_shm_nattch;
+ bsp->shm_atime = lsp->l_shm_atime;
+ bsp->shm_dtime = lsp->l_shm_dtime;
+ bsp->shm_ctime = lsp->l_shm_ctime;
+ bsp->shm_internal = lsp->l_private2; /* XXX Oh well. */
+}
+
+static void
+bsd_to_linux_shmid_ds(bsp, lsp)
+ struct shmid_ds *bsp;
+ struct linux_shmid_ds *lsp;
+{
+
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
+ lsp->l_shm_segsz = bsp->shm_segsz;
+ lsp->l_shm_lpid = bsp->shm_lpid;
+ lsp->l_shm_cpid = bsp->shm_cpid;
+ lsp->l_shm_nattch = bsp->shm_nattch;
+ lsp->l_shm_atime = bsp->shm_atime;
+ lsp->l_shm_dtime = bsp->shm_dtime;
+ lsp->l_shm_ctime = bsp->shm_ctime;
+ lsp->l_private2 = bsp->shm_internal; /* XXX */
+}
+
+/*
+ * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT
+ * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented
+ * by NetBSD itself.
+ *
+ * The usual structure conversion and massaging is done.
+ */
+int
+linux_shmctl(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ipc_args /* {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+ } */ *uap;
+ register_t *retval;
+{
+ int error;
+ caddr_t sg;
+ struct sys_shmctl_args bsa;
+ struct shmid_ds *bsp, bs;
+ struct linux_shmid_ds lseg;
+
+ switch (SCARG(uap, a2)) {
+ case LINUX_IPC_STAT:
+ sg = stackgap_init(p->p_emul);
+ bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
+ SCARG(&bsa, shmid) = SCARG(uap, a1);
+ SCARG(&bsa, cmd) = IPC_STAT;
+ SCARG(&bsa, buf) = bsp;
+ if ((error = sys_shmctl(p, &bsa, retval)))
+ return error;
+ if ((error = copyin((caddr_t) &bs, (caddr_t) bsp, sizeof bs)))
+ return error;
+ bsd_to_linux_shmid_ds(&bs, &lseg);
+ return copyout((caddr_t) &lseg, SCARG(uap, ptr), sizeof lseg);
+ case LINUX_IPC_SET:
+ if ((error = copyin(SCARG(uap, ptr), (caddr_t) &lseg,
+ sizeof lseg)))
+ return error;
+ linux_to_bsd_shmid_ds(&lseg, &bs);
+ sg = stackgap_init(p->p_emul);
+ bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
+ if ((error = copyout((caddr_t) &bs, (caddr_t) bsp, sizeof bs)))
+ return error;
+ SCARG(&bsa, shmid) = SCARG(uap, a1);
+ SCARG(&bsa, cmd) = IPC_SET;
+ SCARG(&bsa, buf) = bsp;
+ return sys_shmctl(p, &bsa, retval);
+ case LINUX_IPC_RMID:
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ SCARG(&bsa, shmid) = SCARG(uap, a1);
+ switch (SCARG(uap, a2)) {
+ case LINUX_IPC_RMID:
+ SCARG(&bsa, cmd) = IPC_RMID;
+ break;
+ case LINUX_SHM_LOCK:
+ SCARG(&bsa, cmd) = SHM_LOCK;
+ break;
+ case LINUX_SHM_UNLOCK:
+ SCARG(&bsa, cmd) = SHM_UNLOCK;
+ break;
+ }
+ SCARG(&bsa, buf) = NULL;
+ return sys_shmctl(p, &bsa, retval);
+ case LINUX_IPC_INFO:
+ case LINUX_SHM_STAT:
+ case LINUX_SHM_INFO:
+ default:
+ return EINVAL;
+ }
+}
+#endif /* SYSVSHM */
diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h
new file mode 100644
index 00000000000..1f9245f6ed8
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.h
@@ -0,0 +1,64 @@
+/* $NetBSD: linux_ipc.h,v 1.1 1995/02/28 23:25:47 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_IPC_H
+#define _LINUX_IPC_H
+
+/*
+ * Structs and values to handle the SYSV ipc/shm/msg calls implemented
+ * in Linux. Most values match the NetBSD values (as they are both derived
+ * from SysV values). Values that are the same may not be defined here.
+ */
+
+typedef int linux_key_t;
+
+/*
+ * The only thing different about the Linux ipc_perm structure is the
+ * order of the fields.
+ */
+struct linux_ipc_perm {
+ linux_key_t l_key;
+ ushort l_uid;
+ ushort l_gid;
+ ushort l_cuid;
+ ushort l_cgid;
+ ushort l_mode;
+ ushort l_seq;
+};
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#endif /* _LINUX_IPC_H */
diff --git a/sys/compat/linux/linux_ipccall.h b/sys/compat/linux/linux_ipccall.h
new file mode 100644
index 00000000000..854b641dac2
--- /dev/null
+++ b/sys/compat/linux/linux_ipccall.h
@@ -0,0 +1,54 @@
+/* $NetBSD: linux_ipccall.h,v 1.2 1995/08/15 21:14:33 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_IPC_CALL_H
+#define _LINUX_IPC_CALL_H
+
+/*
+ * Defines for the numbers passes as the first argument to the
+ * linux_ipc() call, and based on which the actual system calls
+ * are made.
+ */
+#define LINUX_SYS_semop 1
+#define LINUX_SYS_semget 2
+#define LINUX_SYS_semctl 3
+#define LINUX_SYS_msgsnd 11
+#define LINUX_SYS_msgrcv 12
+#define LINUX_SYS_msgget 13
+#define LINUX_SYS_msgctl 14
+#define LINUX_SYS_shmat 21
+#define LINUX_SYS_shmdt 22
+#define LINUX_SYS_shmget 23
+#define LINUX_SYS_shmctl 24
+
+#endif /* _LINUX_IPC_CALL_H */
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
new file mode 100644
index 00000000000..a244225896a
--- /dev/null
+++ b/sys/compat/linux/linux_misc.c
@@ -0,0 +1,1105 @@
+/* $NetBSD: linux_misc.c,v 1.22 1995/10/09 11:24:05 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+/*
+ * Linux compatibility module. Try to deal with various Linux system calls.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/vnode.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#include <sys/unistd.h>
+
+#include <sys/syscallargs.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_fcntl.h>
+#include <compat/linux/linux_mmap.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_dirent.h>
+
+/*
+ * The information on a terminated (or stopped) process needs
+ * to be converted in order for Linux binaries to get a valid signal
+ * number out of it.
+ */
+static int
+bsd_to_linux_wstat(status)
+ int *status;
+{
+
+ if (WIFSIGNALED(*status))
+ *status = (*status & ~0177) |
+ bsd_to_linux_sig[WTERMSIG(*status)];
+ else if (WIFSTOPPED(*status))
+ *status = (*status & ~0xff00) |
+ (bsd_to_linux_sig[WSTOPSIG(*status)] << 8);
+}
+
+/*
+ * waitpid(2). Passed on to the NetBSD call, surrounded by code to
+ * reserve some space for a NetBSD-style wait status, and converting
+ * it to what Linux wants.
+ */
+int
+linux_sys_waitpid(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_waitpid_args /* {
+ syscallarg(int) pid;
+ syscallarg(int *) status;
+ syscallarg(int) options;
+ } */ *uap = v;
+ struct sys_wait4_args w4a;
+ int error, *status, tstat;
+ caddr_t sg;
+
+ if (SCARG(uap, status) != NULL) {
+ sg = stackgap_init(p->p_emul);
+ status = (int *) stackgap_alloc(&sg, sizeof status);
+ } else
+ status = NULL;
+
+ SCARG(&w4a, pid) = SCARG(uap, pid);
+ SCARG(&w4a, status) = status;
+ SCARG(&w4a, options) = SCARG(uap, options);
+ SCARG(&w4a, rusage) = NULL;
+
+ if ((error = sys_wait4(p, &w4a, retval)))
+ return error;
+
+ p->p_siglist &= ~sigmask(SIGCHLD);
+
+ if (status != NULL) {
+ if ((error = copyin(status, &tstat, sizeof tstat)))
+ return error;
+
+ bsd_to_linux_wstat(&tstat);
+ return copyout(&tstat, SCARG(uap, status), sizeof tstat);
+ }
+
+ return 0;
+}
+
+/*
+ * This is very much the same as waitpid()
+ */
+int
+linux_sys_wait4(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_wait4_args /* {
+ syscallarg(int) pid;
+ syscallarg(int *) status;
+ syscallarg(int) options;
+ syscallarg(struct rusage *) rusage;
+ } */ *uap = v;
+ struct sys_wait4_args w4a;
+ int error, *status, tstat;
+ caddr_t sg;
+
+ if (SCARG(uap, status) != NULL) {
+ sg = stackgap_init(p->p_emul);
+ status = (int *) stackgap_alloc(&sg, sizeof status);
+ } else
+ status = NULL;
+
+ SCARG(&w4a, pid) = SCARG(uap, pid);
+ SCARG(&w4a, status) = status;
+ SCARG(&w4a, options) = SCARG(uap, options);
+ SCARG(&w4a, rusage) = SCARG(uap, rusage);
+
+ if ((error = sys_wait4(p, &w4a, retval)))
+ return error;
+
+ p->p_siglist &= ~sigmask(SIGCHLD);
+
+ if (status != NULL) {
+ if ((error = copyin(status, &tstat, sizeof tstat)))
+ return error;
+
+ bsd_to_linux_wstat(&tstat);
+
+ return copyout(&tstat, SCARG(uap, status), sizeof tstat);
+ }
+
+ return 0;
+}
+
+/*
+ * This is the old brk(2) call. I don't think anything in the Linux
+ * world uses this anymore
+ */
+int
+linux_sys_break(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_brk_args /* {
+ syscallarg(char *) nsize;
+ } */ *uap = v;
+
+ return ENOSYS;
+}
+
+/*
+ * Linux brk(2). The check if the new address is >= the old one is
+ * done in the kernel in Linux. NetBSD does it in the library.
+ */
+int
+linux_sys_brk(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_brk_args /* {
+ syscallarg(char *) nsize;
+ } */ *uap = v;
+ char *nbrk = SCARG(uap, nsize);
+ struct sys_obreak_args oba;
+ struct vmspace *vm = p->p_vmspace;
+ int error = 0;
+ caddr_t oldbrk, newbrk;
+
+ oldbrk = vm->vm_daddr + ctob(vm->vm_dsize);
+ /*
+ * XXX inconsistent.. Linux always returns at least the old
+ * brk value, but it will be page-aligned if this fails,
+ * and possibly not page aligned if it succeeds (the user
+ * supplied pointer is returned).
+ */
+ SCARG(&oba, nsize) = nbrk;
+
+ if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(p, &oba, retval) == 0)
+ retval[0] = (register_t)nbrk;
+ else
+ retval[0] = (register_t)oldbrk;
+
+ return 0;
+}
+
+/*
+ * I wonder why Linux has gettimeofday() _and_ time().. Still, we
+ * need to deal with it.
+ */
+int
+linux_sys_time(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_time_args /* {
+ linux_time_t *t;
+ } */ *uap = v;
+ struct timeval atv;
+ linux_time_t tt;
+ int error;
+
+ microtime(&atv);
+
+ tt = atv.tv_sec;
+ if (SCARG(uap, t) && (error = copyout(&tt, SCARG(uap, t), sizeof tt)))
+ return error;
+
+ retval[0] = tt;
+ return 0;
+}
+
+/*
+ * Convert BSD statfs structure to Linux statfs structure.
+ * The Linux structure has less fields, and it also wants
+ * the length of a name in a dir entry in a field, which
+ * we fake (probably the wrong way).
+ */
+static void
+bsd_to_linux_statfs(bsp, lsp)
+ struct statfs *bsp;
+ struct linux_statfs *lsp;
+{
+
+ lsp->l_ftype = bsp->f_type;
+ lsp->l_fbsize = bsp->f_bsize;
+ lsp->l_fblocks = bsp->f_blocks;
+ lsp->l_fbfree = bsp->f_bfree;
+ lsp->l_fbavail = bsp->f_bavail;
+ lsp->l_ffiles = bsp->f_files;
+ lsp->l_fffree = bsp->f_ffree;
+ lsp->l_ffsid.val[0] = bsp->f_fsid.val[0];
+ lsp->l_ffsid.val[1] = bsp->f_fsid.val[1];
+ lsp->l_fnamelen = MAXNAMLEN; /* XXX */
+}
+
+/*
+ * Implement the fs stat functions. Straightforward.
+ */
+int
+linux_sys_statfs(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_statfs_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct linux_statfs *) sp;
+ } */ *uap = v;
+ struct statfs btmp, *bsp;
+ struct linux_statfs ltmp;
+ struct sys_statfs_args bsa;
+ caddr_t sg;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+ bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
+
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ SCARG(&bsa, path) = SCARG(uap, path);
+ SCARG(&bsa, buf) = bsp;
+
+ if ((error = sys_statfs(p, &bsa, retval)))
+ return error;
+
+ if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
+ return error;
+
+ bsd_to_linux_statfs(&btmp, &ltmp);
+
+ return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
+}
+
+int
+linux_sys_fstatfs(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_fstatfs_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct linux_statfs *) sp;
+ } */ *uap = v;
+ struct statfs btmp, *bsp;
+ struct linux_statfs ltmp;
+ struct sys_fstatfs_args bsa;
+ caddr_t sg;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+ bsp = (struct statfs *) stackgap_alloc(&sg, sizeof (struct statfs));
+
+ SCARG(&bsa, fd) = SCARG(uap, fd);
+ SCARG(&bsa, buf) = bsp;
+
+ if ((error = sys_fstatfs(p, &bsa, retval)))
+ return error;
+
+ if ((error = copyin((caddr_t) bsp, (caddr_t) &btmp, sizeof btmp)))
+ return error;
+
+ bsd_to_linux_statfs(&btmp, &ltmp);
+
+ return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
+}
+
+/*
+ * uname(). Just copy the info from the various strings stored in the
+ * kernel, and put it in the Linux utsname structure. That structure
+ * is almost the same as the NetBSD one, only it has fields 65 characters
+ * long, and an extra domainname field.
+ */
+int
+linux_sys_uname(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_uname_args /* {
+ syscallarg(struct linux_utsname *) up;
+ } */ *uap = v;
+ extern char ostype[], hostname[], osrelease[], version[], machine[],
+ domainname[];
+ struct linux_utsname luts;
+ int len;
+ char *cp;
+
+ strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
+ strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
+ strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
+ strncpy(luts.l_version, version, sizeof(luts.l_version));
+ strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
+ strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
+
+ /* This part taken from the the uname() in libc */
+ len = sizeof(luts.l_version);
+ for (cp = luts.l_version; len--; ++cp)
+ if (*cp == '\n' || *cp == '\t')
+ if (len > 1)
+ *cp = ' ';
+ else
+ *cp = '\0';
+
+ return copyout(&luts, SCARG(uap, up), sizeof(luts));
+}
+
+int
+linux_sys_olduname(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_uname_args /* {
+ syscallarg(struct linux_oldutsname *) up;
+ } */ *uap = v;
+ extern char ostype[], hostname[], osrelease[], version[], machine[];
+ struct linux_oldutsname luts;
+ int len;
+ char *cp;
+
+ strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
+ strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
+ strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
+ strncpy(luts.l_version, version, sizeof(luts.l_version));
+ strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
+
+ /* This part taken from the the uname() in libc */
+ len = sizeof(luts.l_version);
+ for (cp = luts.l_version; len--; ++cp)
+ if (*cp == '\n' || *cp == '\t')
+ if (len > 1)
+ *cp = ' ';
+ else
+ *cp = '\0';
+
+ return copyout(&luts, SCARG(uap, up), sizeof(luts));
+}
+
+int
+linux_sys_oldolduname(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_uname_args /* {
+ syscallarg(struct linux_oldoldutsname *) up;
+ } */ *uap = v;
+ extern char ostype[], hostname[], osrelease[], version[], machine[];
+ struct linux_oldoldutsname luts;
+ int len;
+ char *cp;
+
+ strncpy(luts.l_sysname, ostype, sizeof(luts.l_sysname));
+ strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
+ strncpy(luts.l_release, osrelease, sizeof(luts.l_release));
+ strncpy(luts.l_version, version, sizeof(luts.l_version));
+ strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
+
+ /* This part taken from the the uname() in libc */
+ len = sizeof(luts.l_version);
+ for (cp = luts.l_version; len--; ++cp)
+ if (*cp == '\n' || *cp == '\t')
+ if (len > 1)
+ *cp = ' ';
+ else
+ *cp = '\0';
+
+ return copyout(&luts, SCARG(uap, up), sizeof(luts));
+}
+
+/*
+ * Linux wants to pass everything to a syscall in registers. However,
+ * mmap() has 6 of them. Oops: out of register error. They just pass
+ * everything in a structure.
+ */
+int
+linux_sys_mmap(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_mmap_args /* {
+ syscallarg(struct linux_mmap *) lmp;
+ } */ *uap = v;
+ struct linux_mmap lmap;
+ struct sys_mmap_args cma;
+ int error, flags;
+
+ if ((error = copyin(SCARG(uap, lmp), &lmap, sizeof lmap)))
+ return error;
+
+ flags = 0;
+ flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_SHARED, MAP_SHARED);
+ flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_PRIVATE, MAP_PRIVATE);
+ flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_FIXED, MAP_FIXED);
+ flags |= cvtto_bsd_mask(lmap.lm_flags, LINUX_MAP_ANON, MAP_ANON);
+
+ SCARG(&cma,addr) = lmap.lm_addr;
+ SCARG(&cma,len) = lmap.lm_len;
+ SCARG(&cma,prot) = lmap.lm_prot;
+ SCARG(&cma,flags) = flags;
+ SCARG(&cma,fd) = lmap.lm_fd;
+ SCARG(&cma,pad) = 0;
+ SCARG(&cma,pos) = lmap.lm_pos;
+
+ return sys_mmap(p, &cma, retval);
+}
+
+/*
+ * Linux doesn't use the retval[1] value to determine whether
+ * we are the child or parent.
+ */
+int
+linux_sys_fork(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ int error;
+
+ if ((error = sys_fork(p, v, retval)))
+ return error;
+
+ if (retval[1] == 1)
+ retval[0] = 0;
+
+ return 0;
+}
+
+/*
+ * This code is partly stolen from src/lib/libc/compat-43/times.c
+ * XXX - CLK_TCK isn't declared in /sys, just in <time.h>, done here
+ */
+
+#define CLK_TCK 100
+#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
+
+int
+linux_sys_times(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_times_args /* {
+ syscallarg(struct times *) tms;
+ } */ *uap = v;
+ struct timeval t;
+ struct linux_tms ltms;
+ struct rusage ru;
+ int error, s;
+
+ calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
+ ltms.ltms_utime = CONVTCK(ru.ru_utime);
+ ltms.ltms_stime = CONVTCK(ru.ru_stime);
+
+ ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
+ ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
+
+ if ((error = copyout(&ltms, SCARG(uap, tms), sizeof ltms)))
+ return error;
+
+ s = splclock();
+ timersub(&time, &boottime, &t);
+ splx(s);
+
+ retval[0] = ((linux_clock_t)(CONVTCK(t)));
+ return 0;
+}
+
+/*
+ * NetBSD passes fd[0] in retval[0], and fd[1] in retval[1].
+ * Linux directly passes the pointer.
+ */
+int
+linux_sys_pipe(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_pipe_args /* {
+ syscallarg(int *) pfds;
+ } */ *uap = v;
+ int error;
+
+ if ((error = sys_pipe(p, 0, retval)))
+ return error;
+
+ /* Assumes register_t is an int */
+
+ if ((error = copyout(retval, SCARG(uap, pfds), 2 * sizeof (int))))
+ return error;
+
+ retval[0] = 0;
+ return 0;
+}
+
+/*
+ * Alarm. This is a libc call which uses setitimer(2) in NetBSD.
+ * Fiddle with the timers to make it work.
+ */
+int
+linux_sys_alarm(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_alarm_args /* {
+ syscallarg(unsigned int) secs;
+ } */ *uap = v;
+ int error, s;
+ struct itimerval *itp, it;
+
+ itp = &p->p_realtimer;
+ s = splclock();
+ /*
+ * Clear any pending timer alarms.
+ */
+ untimeout(realitexpire, p);
+ timerclear(&itp->it_interval);
+ if (timerisset(&itp->it_value) &&
+ timercmp(&itp->it_value, &time, >))
+ timersub(&itp->it_value, &time, &itp->it_value);
+ /*
+ * Return how many seconds were left (rounded up)
+ */
+ retval[0] = itp->it_value.tv_sec;
+ if (itp->it_value.tv_usec)
+ retval[0]++;
+
+ /*
+ * alarm(0) just resets the timer.
+ */
+ if (SCARG(uap, secs) == 0) {
+ timerclear(&itp->it_value);
+ splx(s);
+ return 0;
+ }
+
+ /*
+ * Check the new alarm time for sanity, and set it.
+ */
+ timerclear(&it.it_interval);
+ it.it_value.tv_sec = SCARG(uap, secs);
+ it.it_value.tv_usec = 0;
+ if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) {
+ splx(s);
+ return (EINVAL);
+ }
+
+ if (timerisset(&it.it_value)) {
+ timeradd(&it.it_value, &time, &it.it_value);
+ timeout(realitexpire, p, hzto(&it.it_value));
+ }
+ p->p_realtimer = it;
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * utime(). Do conversion to things that utimes() understands,
+ * and pass it on.
+ */
+int
+linux_sys_utime(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_utime_args /* {
+ syscallarg(char *) path;
+ syscallarg(struct linux_utimbuf *)times;
+ } */ *uap = v;
+ caddr_t sg;
+ int error;
+ struct sys_utimes_args ua;
+ struct timeval tv[2], *tvp;
+ struct linux_utimbuf lut;
+
+ sg = stackgap_init(p->p_emul);
+ LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
+
+ SCARG(&ua, path) = SCARG(uap, path);
+
+ if (SCARG(uap, times) != NULL) {
+ if ((error = copyin(SCARG(uap, times), &lut, sizeof lut)))
+ return error;
+ tv[0].tv_usec = tv[1].tv_usec = 0;
+ tv[0].tv_sec = lut.l_actime;
+ tv[1].tv_sec = lut.l_modtime;
+ tvp = (struct timeval *) stackgap_alloc(&sg, sizeof(tv));
+ if ((error = copyout(tv, tvp, sizeof tv)))
+ return error;
+ SCARG(&ua, tptr) = tvp;
+ }
+ else
+ SCARG(&ua, tptr) = NULL;
+
+ return sys_utimes(p, uap, retval);
+}
+
+/*
+ * The old Linux readdir was only able to read one entry at a time,
+ * even though it had a 'count' argument. In fact, the emulation
+ * of the old call was better than the original, because it did handle
+ * the count arg properly. Don't bother with it anymore now, and use
+ * it to distinguish between old and new. The difference is that the
+ * newer one actually does multiple entries, and the reclen field
+ * really is the reclen, not the namelength.
+ */
+int
+linux_sys_readdir(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_readdir_args /* {
+ syscallarg(int) fd;
+ syscallarg(struct linux_dirent *) dent;
+ syscallarg(unsigned int) count;
+ } */ *uap = v;
+
+ SCARG(uap, count) = 1;
+ return linux_sys_getdents(p, uap, retval);
+}
+
+/*
+ * Linux 'readdir' call. This code is mostly taken from the
+ * SunOS getdents call (see compat/sunos/sunos_misc.c), though
+ * an attempt has been made to keep it a little cleaner (failing
+ * miserably, because of the cruft needed if count 1 is passed).
+ *
+ * The d_off field should contain the offset of the next valid entry,
+ * but in Linux it has the offset of the entry itself. We emulate
+ * that bug here.
+ *
+ * Read in BSD-style entries, convert them, and copy them out.
+ *
+ * Note that this doesn't handle union-mounted filesystems.
+ */
+int
+linux_sys_getdents(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_readdir_args /* {
+ syscallarg(int) fd;
+ syscallarg(caddr_t) dent;
+ syscallarg(unsigned int) count;
+ } */ *uap = v;
+ 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, linux_reclen;/* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct linux_dirent idb;
+ off_t off; /* true file offset */
+ int buflen, error, eofflag, nbytes, oldcall;
+ struct vattr va;
+ u_long *cookiebuf, *cookie;
+ int ncookies;
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+ vp = (struct vnode *)fp->f_data;
+
+ if (vp->v_type != VDIR) /* XXX vnode readdir op should do this */
+ return (EINVAL);
+
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ nbytes = SCARG(uap, count);
+ if (nbytes == 1) { /* emulating old, broken behaviour */
+ nbytes = sizeof (struct linux_dirent);
+ buflen = max(va.va_blocksize, nbytes);
+ oldcall = 1;
+ } else {
+ buflen = min(MAXBSIZE, nbytes);
+ oldcall = 0;
+ }
+ buf = malloc(buflen, M_TEMP, M_WAITOK);
+ ncookies = buflen / 16;
+ cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);
+ VOP_LOCK(vp);
+ 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_procp = p;
+ 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, cookiebuf,
+ ncookies);
+ if (error)
+ goto out;
+
+ inp = buf;
+ outp = SCARG(uap, dent);
+ resid = 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("linux_readdir");
+ if (bdp->d_fileno == 0) {
+ inp += reclen; /* it is a hole; squish it out */
+ off = *cookie++;
+ continue;
+ }
+ linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
+ if (reclen > len || resid < linux_reclen) {
+ /* entry too big for buffer, so just stop */
+ outp++;
+ off = *cookie++;
+ break;
+ }
+ /*
+ * Massage in place to make a Linux-shaped dirent (otherwise
+ * we have to worry about touching user memory outside of
+ * the copyout() call).
+ */
+ idb.d_ino = (linux_ino_t)bdp->d_fileno;
+ /*
+ * The old readdir() call misuses the offset and reclen fields.
+ */
+ if (oldcall) {
+ idb.d_off = (linux_off_t)linux_reclen;
+ idb.d_reclen = (u_short)bdp->d_namlen;
+ } else {
+ idb.d_off = (linux_off_t)off;
+ idb.d_reclen = (u_short)linux_reclen;
+ }
+ strcpy(idb.d_name, bdp->d_name);
+ if ((error = copyout((caddr_t)&idb, outp, linux_reclen)))
+ goto out;
+ /* advance past this real entry */
+ inp += reclen;
+ off = *cookie++; /* each entry points to itself */
+ /* advance output past Linux-shaped entry */
+ outp += linux_reclen;
+ resid -= linux_reclen;
+ if (oldcall)
+ break;
+ }
+
+ /* if we squished out the whole block, try again */
+ if (outp == SCARG(uap, dent))
+ goto again;
+ fp->f_offset = off; /* update the vnode offset */
+
+ if (oldcall)
+ nbytes = resid + linux_reclen;
+
+eof:
+ *retval = nbytes - resid;
+out:
+ VOP_UNLOCK(vp);
+ free(cookiebuf, M_TEMP);
+ free(buf, M_TEMP);
+ return error;
+}
+
+/*
+ * Not sure why the arguments to this older version of select() were put
+ * into a structure, because there are 5, and that can all be handled
+ * in registers on the i386 like Linux wants to.
+ */
+int
+linux_sys_oldselect(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_oldselect_args /* {
+ syscallarg(struct linux_select *) lsp;
+ } */ *uap = v;
+ struct linux_select ls;
+ int error;
+
+ if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
+ return error;
+
+ return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
+ ls.exceptfds, ls.timeout);
+}
+
+/*
+ * Even when just using registers to pass arguments to syscalls you can
+ * have 5 of them on the i386. So this newer version of select() does
+ * this.
+ */
+int
+linux_sys_select(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_select_args /* {
+ syscallarg(int) nfds;
+ syscallarg(fd_set *) readfds;
+ syscallarg(fd_set *) writefds;
+ syscallarg(fd_set *) exceptfds;
+ syscallarg(struct timeval *) timeout;
+ } */ *uap = v;
+
+ return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
+ SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
+}
+
+/*
+ * Common code for the old and new versions of select(). A couple of
+ * things are important:
+ * 1) return the amount of time left in the 'timeout' parameter
+ * 2) select never returns ERESTART on Linux, always return EINTR
+ */
+int
+linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
+ struct proc *p;
+ register_t *retval;
+ int nfds;
+ fd_set *readfds, *writefds, *exceptfds;
+ struct timeval *timeout;
+{
+ struct sys_select_args bsa;
+ struct timeval tv0, tv1, utv, *tvp;
+ caddr_t sg;
+ int error;
+
+ SCARG(&bsa, nd) = nfds;
+ SCARG(&bsa, in) = readfds;
+ SCARG(&bsa, ou) = writefds;
+ SCARG(&bsa, ex) = exceptfds;
+ SCARG(&bsa, tv) = timeout;
+
+ /*
+ * Store current time for computation of the amount of
+ * time left.
+ */
+ if (timeout) {
+ if ((error = copyin(timeout, &utv, sizeof(utv))))
+ return error;
+ if (itimerfix(&utv)) {
+ /*
+ * The timeval was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ sg = stackgap_init(p->p_emul);
+ 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)
+ timerclear(&utv);
+ if ((error = copyout(&utv, tvp, sizeof(utv))))
+ return error;
+ SCARG(&bsa, tv) = tvp;
+ }
+ microtime(&tv0);
+ }
+
+ error = sys_select(p, &bsa, retval);
+ if (error) {
+ /*
+ * See fs/select.c in the Linux kernel. Without this,
+ * Maelstrom doesn't work.
+ */
+ if (error == ERESTART)
+ error = EINTR;
+ return error;
+ }
+
+ if (timeout) {
+ if (*retval) {
+ /*
+ * 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);
+ timersub(&tv1, &tv0, &tv1);
+ timersub(&utv, &tv1, &utv);
+ if (utv.tv_sec < 0)
+ timerclear(&utv);
+ } else
+ timerclear(&utv);
+ if ((error = copyout(&utv, timeout, sizeof(utv))))
+ return error;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the process group of a certain process. Look it up
+ * and return the value.
+ */
+int
+linux_sys_getpgid(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_getpgid_args /* {
+ syscallarg(int) pid;
+ } */ *uap = v;
+ struct proc *targp;
+
+ if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid)
+ if ((targp = pfind(SCARG(uap, pid))) == 0)
+ return ESRCH;
+ else
+ targp = p;
+
+ retval[0] = targp->p_pgid;
+ return 0;
+}
+
+/*
+ * Set the 'personality' (emulation mode) for the current process. Only
+ * accept the Linux personality here (0). This call is needed because
+ * the Linux ELF crt0 issues it in an ugly kludge to make sure that
+ * ELF binaries run in Linux mode, not SVR4 mode.
+ */
+int
+linux_sys_personality(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_personality_args /* {
+ syscallarg(int) per;
+ } */ *uap = v;
+
+ if (SCARG(uap, per) != 0)
+ return EINVAL;
+ retval[0] = 0;
+ return 0;
+}
+
+/*
+ * The calls are here because of type conversions.
+ */
+int
+linux_sys_setreuid(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_setreuid_args /* {
+ syscallarg(int) ruid;
+ syscallarg(int) euid;
+ } */ *uap = v;
+ struct compat_43_sys_setreuid_args bsa;
+
+ SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, ruid);
+ SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, euid);
+
+ return compat_43_sys_setreuid(p, &bsa, retval);
+}
+
+int
+linux_sys_setregid(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_setregid_args /* {
+ syscallarg(int) rgid;
+ syscallarg(int) egid;
+ } */ *uap = v;
+ struct compat_43_sys_setregid_args bsa;
+
+ SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, rgid);
+ SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
+ (uid_t)-1 : SCARG(uap, egid);
+
+ return compat_43_sys_setregid(p, &bsa, retval);
+}
diff --git a/sys/compat/linux/linux_mmap.h b/sys/compat/linux/linux_mmap.h
new file mode 100644
index 00000000000..3b13dcc0c46
--- /dev/null
+++ b/sys/compat/linux/linux_mmap.h
@@ -0,0 +1,53 @@
+/* $NetBSD: linux_mmap.h,v 1.1 1995/02/28 23:25:52 fvdl Exp $ */
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_MMAP_H
+#define _LINUX_MMAP_H
+
+#define LINUX_PROT_NONE 0x00
+#define LINUX_PROT_READ 0x01
+#define LINUX_PROT_WRITE 0x02
+#define LINUX_PROT_EXEC 0x04
+
+#define LINUX_MAP_SHARED 0x0001
+#define LINUX_MAP_PRIVATE 0x0002
+
+#define LINUX_MAP_FIXED 0x0010
+#define LINUX_MAP_ANON 0x0020
+
+/* the following flags are silently ignored */
+
+#define LINUX_MAP_GROWSDOWN 0x0400
+#define LINUX_MAP_DENYWRITE 0x0800
+#define LINUX_MAP_EXECUTABLE 0x1000
+
+#endif /* !_LINUX_MMAP_H */
diff --git a/sys/compat/linux/linux_msg.h b/sys/compat/linux/linux_msg.h
new file mode 100644
index 00000000000..b7858236dbb
--- /dev/null
+++ b/sys/compat/linux/linux_msg.h
@@ -0,0 +1,93 @@
+/* $NetBSD: linux_msg.h,v 1.2 1995/08/15 21:14:34 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_MSG_H
+#define _LINUX_MSG_H
+
+/*
+ * msq_id_ds structure. Mostly the same fields, except for some internal
+ * ones.
+ */
+struct linux_msqid_ds {
+ struct linux_ipc_perm l_msg_perm;
+ void *l_msg_first;
+ void *l_msg_last;
+ linux_time_t l_msg_stime;
+ linux_time_t l_msg_rtime;
+ linux_time_t l_msg_ctime;
+ void *l_wwait; /* Linux internal */
+ void *l_rwait; /* Linux internal */
+ ushort l_msg_cbytes;
+ ushort l_msg_qnum;
+ ushort l_msg_qbytes;
+ ushort l_msg_lspid;
+ ushort l_msg_lrpid;
+};
+
+#define LINUX_MSG_NOERROR 0x1000
+#define LINUX_MSG_EXCEPT 0x2000
+
+/*
+ * The notorious anonymous message structure.
+ */
+struct linux_mymsg {
+ long l_mtype;
+ char l_mtext[1];
+};
+
+/*
+ * This kludge is used for the 6th argument to the msgrcv system
+ * call, to get around the maximum of 5 arguments to a syscall in Linux.
+ */
+struct linux_msgrcv_msgarg {
+ struct linux_mymsg *msg;
+ int type;
+};
+/*
+ * For msgctl calls.
+ */
+struct linux_msginfo {
+ int l_msgpool;
+ int l_msgmap;
+ int l_msgmax;
+ int l_msgmnb;
+ int l_msgmni;
+ int l_msgssz;
+ int l_msgtql;
+ ushort l_msgseg;
+};
+
+#define LINUX_MSG_STAT 11
+#define LINUX_MSG_INFO 12
+
+#endif /* _LINUX_MSG_H */
diff --git a/sys/compat/linux/linux_sem.h b/sys/compat/linux/linux_sem.h
new file mode 100644
index 00000000000..8cfbdab7f9a
--- /dev/null
+++ b/sys/compat/linux/linux_sem.h
@@ -0,0 +1,72 @@
+/* $NetBSD: linux_sem.h,v 1.1 1995/08/15 21:14:35 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SEM_H
+#define _LINUX_SEM_H
+
+/*
+ * Operations for semctl(2), in addition to IPC_STAT and IPC_SET
+ */
+#define LINUX_GETPID 11
+#define LINUX_GETVAL 12
+#define LINUX_GETALL 13
+#define LINUX_GETNCNT 14
+#define LINUX_GETZCNT 15
+#define LINUX_SETVAL 16
+#define LINUX_SETALL 17
+
+/*
+ * Linux semid_ds structure. Internally used pointer fields are not
+ * important to us and have been changed to void *
+ */
+
+struct linux_semid_ds {
+ struct linux_ipc_perm l_sem_perm;
+ linux_time_t l_sem_otime;
+ linux_time_t l_sem_ctime;
+ void *l_sem_base;
+ void *l_eventn;
+ void *l_eventz;
+ void *l_undo;
+ ushort l_sem_nsems;
+};
+
+union linux_semun {
+ int l_val;
+ struct linux_semid_ds *l_buf;
+ ushort *l_array;
+ void *l___buf; /* For unsupported IPC_INFO */
+ void *l___pad;
+};
+
+#endif /* _LINUX_SEM_H */
diff --git a/sys/compat/linux/linux_shm.h b/sys/compat/linux/linux_shm.h
new file mode 100644
index 00000000000..098595062d1
--- /dev/null
+++ b/sys/compat/linux/linux_shm.h
@@ -0,0 +1,63 @@
+/* $NetBSD: linux_shm.h,v 1.1 1995/02/28 23:25:57 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SHM_H
+#define _LINUX_SHM_H
+
+/*
+ * shm segment control structure
+ */
+struct linux_shmid_ds {
+ struct linux_ipc_perm l_shm_perm;
+ int l_shm_segsz;
+ linux_time_t l_shm_atime;
+ linux_time_t l_shm_dtime;
+ linux_time_t l_shm_ctime;
+ ushort l_shm_cpid;
+ ushort l_shm_lpid;
+ short l_shm_nattch;
+ ushort l_private1;
+ void *l_private2;
+ void *l_private3;
+};
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#endif /* _LINUX_SHM_H */
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
new file mode 100644
index 00000000000..212a0f254ee
--- /dev/null
+++ b/sys/compat/linux/linux_signal.c
@@ -0,0 +1,501 @@
+/* $NetBSD: linux_signal.c,v 1.9 1995/10/07 06:27:12 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ *
+ * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/malloc.h>
+
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_util.h>
+
+#define sigemptyset(s) bzero((s), sizeof(*(s)))
+#define sigismember(s, n) (*(s) & sigmask(n))
+#define sigaddset(s, n) (*(s) |= sigmask(n))
+
+#define linux_sigmask(n) (1 << ((n) - 1))
+#define linux_sigemptyset(s) bzero((s), sizeof(*(s)))
+#define linux_sigismember(s, n) (*(s) & linux_sigmask(n))
+#define linux_sigaddset(s, n) (*(s) |= linux_sigmask(n))
+
+int bsd_to_linux_sig[] = {
+ 0,
+ LINUX_SIGHUP,
+ LINUX_SIGINT,
+ LINUX_SIGQUIT,
+ LINUX_SIGILL,
+ LINUX_SIGTRAP,
+ LINUX_SIGABRT,
+ 0,
+ LINUX_SIGFPE,
+ LINUX_SIGKILL,
+ LINUX_SIGBUS,
+ LINUX_SIGSEGV,
+ 0,
+ LINUX_SIGPIPE,
+ LINUX_SIGALRM,
+ LINUX_SIGTERM,
+ LINUX_SIGURG,
+ LINUX_SIGSTOP,
+ LINUX_SIGTSTP,
+ LINUX_SIGCONT,
+ LINUX_SIGCHLD,
+ LINUX_SIGTTIN,
+ LINUX_SIGTTOU,
+ LINUX_SIGIO,
+ LINUX_SIGXCPU,
+ LINUX_SIGXFSZ,
+ LINUX_SIGVTALRM,
+ LINUX_SIGPROF,
+ LINUX_SIGWINCH,
+ 0,
+ LINUX_SIGUSR1,
+ LINUX_SIGUSR2,
+};
+
+int linux_to_bsd_sig[] = {
+ 0,
+ SIGHUP,
+ SIGINT,
+ SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGBUS,
+ SIGFPE,
+ SIGKILL,
+ SIGUSR1,
+ SIGSEGV,
+ SIGUSR2,
+ SIGPIPE,
+ SIGALRM,
+ SIGTERM,
+ 0,
+ SIGCHLD,
+ SIGCONT,
+ SIGSTOP,
+ SIGTSTP,
+ SIGTTIN,
+ SIGTTOU,
+ SIGURG,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGIO,
+ 0,
+ 0,
+};
+
+/*
+ * Ok, we know that Linux and BSD signals both are just an unsigned int.
+ * Don't bother to use the sigismember() stuff for now.
+ */
+void
+linux_to_bsd_sigset(lss, bss)
+ const linux_sigset_t *lss;
+ sigset_t *bss;
+{
+ int i, newsig;
+
+ sigemptyset(bss);
+ for (i = 1; i < LINUX_NSIG; i++) {
+ if (linux_sigismember(lss, i)) {
+ newsig = linux_to_bsd_sig[i];
+ if (newsig)
+ sigaddset(bss, newsig);
+ }
+ }
+}
+
+void
+bsd_to_linux_sigset(bss, lss)
+ const sigset_t *bss;
+ linux_sigset_t *lss;
+{
+ int i, newsig;
+
+ linux_sigemptyset(lss);
+ for (i = 1; i < NSIG; i++) {
+ if (sigismember(bss, i)) {
+ newsig = bsd_to_linux_sig[i];
+ if (newsig)
+ linux_sigaddset(lss, newsig);
+ }
+ }
+}
+
+/*
+ * Convert between Linux and BSD sigaction structures. Linux has
+ * one extra field (sa_restorer) which we don't support.
+ */
+void
+linux_to_bsd_sigaction(lsa, bsa)
+ struct linux_sigaction *lsa;
+ struct sigaction *bsa;
+{
+
+ bsa->sa_handler = lsa->sa_handler;
+ linux_to_bsd_sigset(&bsa->sa_mask, &lsa->sa_mask);
+ bsa->sa_flags = 0;
+ if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
+ bsa->sa_flags |= SA_ONSTACK;
+ if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
+ bsa->sa_flags |= SA_RESTART;
+ if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
+ bsa->sa_flags |= SA_RESETHAND;
+ if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
+ bsa->sa_flags |= SA_NODEFER;
+}
+
+void
+bsd_to_linux_sigaction(bsa, lsa)
+ struct sigaction *bsa;
+ struct linux_sigaction *lsa;
+{
+
+ lsa->sa_handler = bsa->sa_handler;
+ bsd_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask);
+ lsa->sa_flags = 0;
+ if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
+ lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
+ if ((bsa->sa_flags & SA_ONSTACK) != 0)
+ lsa->sa_flags |= LINUX_SA_ONSTACK;
+ if ((bsa->sa_flags & SA_RESTART) != 0)
+ lsa->sa_flags |= LINUX_SA_RESTART;
+ if ((bsa->sa_flags & SA_NODEFER) != 0)
+ lsa->sa_flags |= LINUX_SA_NOMASK;
+ if ((bsa->sa_flags & SA_RESETHAND) != 0)
+ lsa->sa_flags |= LINUX_SA_ONESHOT;
+ lsa->sa_restorer = NULL;
+}
+
+
+/*
+ * The Linux sigaction() system call. Do the usual conversions,
+ * and just call sigaction(). Some flags and values are silently
+ * ignored (see above).
+ */
+int
+linux_sys_sigaction(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sigaction_args /* {
+ syscallarg(int) signum;
+ syscallarg(struct linux_sigaction *) nsa;
+ syscallarg(struct linux_sigaction *) osa;
+ } */ *uap = v;
+ struct linux_sigaction *nlsa, *olsa, tmplsa;
+ struct sigaction *nbsa, *obsa, tmpbsa;
+ struct sys_sigaction_args sa;
+ caddr_t sg;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+ nlsa = SCARG(uap, nsa);
+ olsa = SCARG(uap, osa);
+
+ if (olsa != NULL)
+ obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ else
+ obsa = NULL;
+
+ if (nlsa != NULL) {
+ nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
+ if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
+ return error;
+ linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
+ if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
+ return error;
+ } else
+ nbsa = NULL;
+
+ SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
+ SCARG(&sa, nsa) = nbsa;
+ SCARG(&sa, osa) = obsa;
+
+ if ((error = sys_sigaction(p, &sa, retval)) != 0)
+ return error;
+
+ if (olsa != NULL) {
+ if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
+ return error;
+ bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
+ if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
+ return error;
+ }
+
+ return 0;
+}
+
+/*
+ * The Linux signal() system call. I think that the signal() in the C
+ * library actually calls sigaction, so I doubt this one is ever used.
+ * But hey, it can't hurt having it here. The same restrictions as for
+ * sigaction() apply.
+ */
+int
+linux_sys_signal(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_signal_args /* {
+ syscallarg(int) sig;
+ syscallarg(linux_handler_t) handler;
+ } */ *uap = v;
+ caddr_t sg;
+ struct sys_sigaction_args sa_args;
+ struct sigaction *osa, *nsa, tmpsa;
+ int error;
+
+ sg = stackgap_init(p->p_emul);
+ nsa = stackgap_alloc(&sg, sizeof *nsa);
+ osa = stackgap_alloc(&sg, sizeof *osa);
+
+ tmpsa.sa_handler = SCARG(uap, handler);
+ tmpsa.sa_mask = (sigset_t) 0;
+ tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
+ if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
+ return error;
+
+ SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
+ SCARG(&sa_args, osa) = osa;
+ SCARG(&sa_args, nsa) = nsa;
+ if ((error = sys_sigaction(p, &sa_args, retval)))
+ return error;
+
+ if ((error = copyin(osa, &tmpsa, sizeof *osa)))
+ return error;
+ retval[0] = (register_t) tmpsa.sa_handler;
+
+ return 0;
+}
+
+/*
+ * This is just a copy of the svr4 compat one. I feel so creative now.
+ */
+int
+linux_sys_sigprocmask(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sigprocmask_args /* {
+ syscallarg(int) how;
+ syscallarg(linux_sigset_t *) set;
+ syscallarg(linux_sigset_t *) oset;
+ } */ *uap = v;
+ linux_sigset_t ss;
+ sigset_t bs;
+ int error = 0;
+
+ *retval = 0;
+
+ if (SCARG(uap, oset) != NULL) {
+ /* Fix the return value first if needed */
+ bsd_to_linux_sigset(&p->p_sigmask, &ss);
+ if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
+ return error;
+ }
+
+ if (SCARG(uap, set) == NULL)
+ /* Just examine */
+ return 0;
+
+ if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
+ return error;
+
+ linux_to_bsd_sigset(&ss, &bs);
+
+ (void) splhigh();
+
+ switch (SCARG(uap, how)) {
+ case LINUX_SIG_BLOCK:
+ p->p_sigmask |= bs & ~sigcantmask;
+ break;
+
+ case LINUX_SIG_UNBLOCK:
+ p->p_sigmask &= ~bs;
+ break;
+
+ case LINUX_SIG_SETMASK:
+ p->p_sigmask = bs & ~sigcantmask;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ (void) spl0();
+
+ return error;
+}
+
+/*
+ * The functions below really make no distinction between an int
+ * and [linux_]sigset_t. This is ok for now, but it might break
+ * sometime. Then again, sigset_t is trusted to be an int everywhere
+ * else in the kernel too.
+ */
+/* ARGSUSED */
+int
+linux_sys_siggetmask(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+
+ bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
+ return 0;
+}
+
+/*
+ * The following three functions fiddle with a process' signal mask.
+ * Convert the signal masks because of the different signal
+ * values for Linux. The need for this is the reason why
+ * they are here, and have not been mapped directly.
+ */
+int
+linux_sys_sigsetmask(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sigsetmask_args /* {
+ syscallarg(linux_sigset_t) mask;
+ } */ *uap = v;
+ linux_sigset_t mask;
+ sigset_t bsdsig;
+
+ bsd_to_linux_sigset(&p->p_sigmask, (linux_sigset_t *)retval);
+
+ mask = SCARG(uap, mask);
+ bsd_to_linux_sigset(&mask, &bsdsig);
+
+ splhigh();
+ p->p_sigmask = bsdsig & ~sigcantmask;
+ spl0();
+
+ return 0;
+}
+
+int
+linux_sys_sigpending(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sigpending_args /* {
+ syscallarg(linux_sigset_t *) mask;
+ } */ *uap = v;
+ sigset_t bs;
+ linux_sigset_t ls;
+
+ bs = p->p_siglist & p->p_sigmask;
+ bsd_to_linux_sigset(&bs, &ls);
+
+ return copyout(&ls, SCARG(uap, mask), sizeof(ls));
+}
+
+int
+linux_sys_sigsuspend(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_sigsuspend_args /* {
+ syscallarg(caddr_t) restart;
+ syscallarg(int) oldmask;
+ syscallarg(int) mask;
+ } */ *uap = v;
+ struct sys_sigsuspend_args sa;
+
+ linux_to_bsd_sigset(&SCARG(uap, mask), &SCARG(&sa, mask));
+ return sys_sigsuspend(p, &sa, retval);
+}
+
+/*
+ * The deprecated pause(2), which is really just an instance
+ * of sigsuspend(2).
+ */
+int
+linux_sys_pause(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_sigsuspend_args bsa;
+
+ SCARG(&bsa, mask) = p->p_sigmask;
+ return sys_sigsuspend(p, &bsa, retval);
+}
+
+/*
+ * Once more: only a signal conversion is needed.
+ */
+int
+linux_sys_kill(p, v, retval)
+ register struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_kill_args /* {
+ syscallarg(int) pid;
+ syscallarg(int) signum;
+ } */ *uap = v;
+ struct sys_kill_args ka;
+
+ SCARG(&ka, pid) = SCARG(uap, pid);
+ SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
+ return sys_kill(p, &ka, retval);
+}
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
new file mode 100644
index 00000000000..e002dbf7c3d
--- /dev/null
+++ b/sys/compat/linux/linux_signal.h
@@ -0,0 +1,95 @@
+/* $NetBSD: linux_signal.h,v 1.4 1995/08/27 20:51:51 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SIGNAL_H
+#define _LINUX_SIGNAL_H
+
+#define LINUX_SIGHUP 1
+#define LINUX_SIGINT 2
+#define LINUX_SIGQUIT 3
+#define LINUX_SIGILL 4
+#define LINUX_SIGTRAP 5
+#define LINUX_SIGABRT 6
+#define LINUX_SIGIOT 6
+#define LINUX_SIGBUS 7
+#define LINUX_SIGFPE 8
+#define LINUX_SIGKILL 9
+#define LINUX_SIGUSR1 10
+#define LINUX_SIGSEGV 11
+#define LINUX_SIGUSR2 12
+#define LINUX_SIGPIPE 13
+#define LINUX_SIGALRM 14
+#define LINUX_SIGTERM 15
+#define LINUX_SIGSTKFLT 16
+#define LINUX_SIGCHLD 17
+#define LINUX_SIGCONT 18
+#define LINUX_SIGSTOP 19
+#define LINUX_SIGTSTP 20
+#define LINUX_SIGTTIN 21
+#define LINUX_SIGTTOU 22
+#define LINUX_SIGURG 23
+#define LINUX_SIGXCPU 24
+#define LINUX_SIGXFSZ 25
+#define LINUX_SIGVTALRM 26
+#define LINUX_SIGPROF 27
+#define LINUX_SIGWINCH 28
+#define LINUX_SIGIO 29
+#define LINUX_SIGPWR 30
+#define LINUX_NSIG 32
+
+#define LINUX_SIG_BLOCK 0
+#define LINUX_SIG_UNBLOCK 1
+#define LINUX_SIG_SETMASK 2
+
+typedef u_long linux_sigset_t;
+typedef void (*linux_handler_t) __P((int));
+
+struct linux_sigaction {
+ linux_handler_t sa_handler;
+ linux_sigset_t sa_mask;
+ u_long sa_flags;
+ void (*sa_restorer) __P((void));
+};
+
+/* sa_flags */
+#define LINUX_SA_NOCLDSTOP 0x00000001
+#define LINUX_SA_ONSTACK 0x08000000
+#define LINUX_SA_RESTART 0x10000000
+#define LINUX_SA_INTERRUPT 0x20000000
+#define LINUX_SA_NOMASK 0x40000000
+#define LINUX_SA_ONESHOT 0x80000000
+
+extern int bsd_to_linux_sig[];
+extern int linux_to_bsd_sig[];
+
+#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 00000000000..664a246f99e
--- /dev/null
+++ b/sys/compat/linux/linux_socket.c
@@ -0,0 +1,704 @@
+/* $NetBSD: linux_socket.c,v 1.12 1995/10/07 06:27:13 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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/kernel.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/device.h>
+
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_socket.h>
+#include <compat/linux/linux_socketcall.h>
+#include <compat/linux/linux_sockio.h>
+
+/*
+ * All the calls in this file are entered via one common system
+ * call in Linux, represented here by linux_socketcall()
+ * Arguments for the various calls are on the user stack. A pointer
+ * to them is the only thing that is passed. It is up to the various
+ * calls to copy them in themselves. To make it look better, they
+ * are copied to structures.
+ */
+
+/*
+ * Convert between Linux and BSD socket domain values
+ */
+int
+linux_to_bsd_domain(ldom)
+ int ldom;
+{
+
+ switch (ldom) {
+ 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;
+ default:
+ return -1;
+ }
+}
+
+int
+linux_socket(p, uap, retval)
+ struct proc *p;
+ struct linux_socket_args /* {
+ syscallarg(int) domain;
+ syscallarg(int) type;
+ syscallarg(int) protocol;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_socket_args lsa;
+ struct sys_socket_args bsa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, protocol) = lsa.protocol;
+ SCARG(&bsa, type) = lsa.type;
+ SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
+ if (SCARG(&bsa, domain) == -1)
+ return EINVAL;
+ return sys_socket(p, &bsa, retval);
+}
+
+int
+linux_bind(p, uap, retval)
+ struct proc *p;
+ struct linux_bind_args /* {
+ syscallarg(int) s;
+ syscallarg(struct sockaddr *) name;
+ syscallarg(int) namelen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_bind_args lba;
+ struct sys_bind_args bba;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba)))
+ return error;
+
+ SCARG(&bba, s) = lba.s;
+ SCARG(&bba, name) = (caddr_t) lba.name;
+ SCARG(&bba, namelen) = lba.namelen;
+
+ return sys_bind(p, &bba, retval);
+}
+
+int
+linux_connect(p, uap, retval)
+ struct proc *p;
+ struct linux_connect_args /* {
+ syscallarg(int) s;
+ syscallarg(struct sockaddr *) name;
+ syscallarg(int) namelen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_connect_args lca;
+ struct sys_connect_args bca;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca)))
+ return error;
+
+ SCARG(&bca, s) = lca.s;
+ SCARG(&bca, name) = (caddr_t) lca.name;
+ SCARG(&bca, namelen) = lca.namelen;
+
+ return sys_connect(p, &bca, retval);
+}
+
+int
+linux_listen(p, uap, retval)
+ struct proc *p;
+ struct linux_listen_args /* {
+ syscallarg(int) s;
+ syscallarg(int) backlog;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_listen_args lla;
+ struct sys_listen_args bla;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
+ return error;
+
+ SCARG(&bla, s) = lla.s;
+ SCARG(&bla, backlog) = lla.backlog;
+
+ return sys_listen(p, &bla, retval);
+}
+
+int
+linux_accept(p, uap, retval)
+ struct proc *p;
+ struct linux_accept_args /* {
+ syscallarg(int) s;
+ syscallarg(struct sockaddr *) addr;
+ syscallarg(int *) namelen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_accept_args laa;
+ struct compat_43_sys_accept_args baa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa)))
+ return error;
+
+ SCARG(&baa, s) = laa.s;
+ SCARG(&baa, name) = (caddr_t) laa.addr;
+ SCARG(&baa, anamelen) = laa.namelen;
+
+ return compat_43_sys_accept(p, &baa, retval);
+}
+
+int
+linux_getsockname(p, uap, retval)
+ struct proc *p;
+ struct linux_getsockname_args /* {
+ syscallarg(int) s;
+ syscallarg(struct sockaddr *) addr;
+ syscallarg(int *) namelen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_getsockname_args lga;
+ struct compat_43_sys_getsockname_args bga;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
+ return error;
+
+ SCARG(&bga, fdec) = lga.s;
+ SCARG(&bga, asa) = (caddr_t) lga.addr;
+ SCARG(&bga, alen) = lga.namelen;
+
+ return compat_43_sys_getsockname(p, &bga, retval);
+}
+
+int
+linux_getpeername(p, uap, retval)
+ struct proc *p;
+ struct linux_getpeername_args /* {
+ syscallarg(int) s;
+ syscallarg(struct sockaddr *) addr;
+ syscallarg(int *) namelen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_getpeername_args lga;
+ struct compat_43_sys_getpeername_args bga;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
+ return error;
+
+ SCARG(&bga, fdes) = lga.s;
+ SCARG(&bga, asa) = (caddr_t) lga.addr;
+ SCARG(&bga, alen) = lga.namelen;
+
+ return compat_43_sys_getpeername(p, &bga, retval);
+}
+
+int
+linux_socketpair(p, uap, retval)
+ struct proc *p;
+ struct linux_socketpair_args /* {
+ syscallarg(int) domain;
+ syscallarg(int) type;
+ syscallarg(int) protocol;
+ syscallarg(int *) rsv;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_socketpair_args lsa;
+ struct sys_socketpair_args bsa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
+ if (SCARG(&bsa, domain) == -1)
+ return EINVAL;
+ SCARG(&bsa, type) = lsa.type;
+ SCARG(&bsa, protocol) = lsa.protocol;
+ SCARG(&bsa, rsv) = lsa.rsv;
+
+ return sys_socketpair(p, &bsa, retval);
+}
+
+int
+linux_send(p, uap, retval)
+ struct proc *p;
+ struct linux_send_args /* {
+ syscallarg(int) s;
+ syscallarg(void *) msg;
+ syscallarg(int) len;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_send_args lsa;
+ struct compat_43_sys_send_args bsa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, s) = lsa.s;
+ SCARG(&bsa, buf) = lsa.msg;
+ SCARG(&bsa, len) = lsa.len;
+ SCARG(&bsa, flags) = lsa.flags;
+
+ return compat_43_sys_send(p, &bsa, retval);
+}
+
+int
+linux_recv(p, uap, retval)
+ struct proc *p;
+ struct linux_recv_args /* {
+ syscallarg(int) s;
+ syscallarg(void *) msg;
+ syscallarg(int) len;
+ syscallarg(int) flags;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_recv_args lra;
+ struct compat_43_sys_recv_args bra;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
+ return error;
+
+ SCARG(&bra, s) = lra.s;
+ SCARG(&bra, buf) = lra.msg;
+ SCARG(&bra, len) = lra.len;
+ SCARG(&bra, flags) = lra.flags;
+
+ return compat_43_sys_recv(p, &bra, retval);
+}
+
+int
+linux_sendto(p, uap, retval)
+ struct proc *p;
+ struct linux_sendto_args /* {
+ syscallarg(int) s;
+ syscallarg(void *) msg;
+ syscallarg(int) len;
+ syscallarg(int) flags;
+ syscallarg(sockaddr *) to;
+ syscallarg(int) tolen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_sendto_args lsa;
+ struct sys_sendto_args bsa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, s) = lsa.s;
+ SCARG(&bsa, buf) = lsa.msg;
+ SCARG(&bsa, len) = lsa.len;
+ SCARG(&bsa, flags) = lsa.flags;
+ SCARG(&bsa, to) = (caddr_t) lsa.to;
+ SCARG(&bsa, tolen) = lsa.tolen;
+
+ return sys_sendto(p, &bsa, retval);
+}
+
+int
+linux_recvfrom(p, uap, retval)
+ struct proc *p;
+ struct linux_recvfrom_args /* {
+ syscallarg(int) s;
+ syscallarg(void *) buf;
+ syscallarg(int) len;
+ syscallarg(int) flags;
+ syscallarg(struct sockaddr *) from;
+ syscallarg(int *) fromlen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_recvfrom_args lra;
+ struct compat_43_sys_recvfrom_args bra;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
+ return error;
+
+ SCARG(&bra, s) = lra.s;
+ SCARG(&bra, buf) = lra.buf;
+ SCARG(&bra, len) = lra.len;
+ SCARG(&bra, flags) = lra.flags;
+ SCARG(&bra, from) = (caddr_t) lra.from;
+ SCARG(&bra, fromlenaddr) = lra.fromlen;
+
+ return compat_43_sys_recvfrom(p, &bra, retval);
+}
+
+int
+linux_shutdown(p, uap, retval)
+ struct proc *p;
+ struct linux_shutdown_args /* {
+ syscallarg(int) s;
+ syscallarg(int) how;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_shutdown_args lsa;
+ struct sys_shutdown_args bsa;
+ int error;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, s) = lsa.s;
+ SCARG(&bsa, how) = lsa.how;
+
+ return sys_shutdown(p, &bsa, retval);
+}
+
+/*
+ * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
+ * is different, the rest matches IPPROTO_* on both systems.
+ */
+int
+linux_to_bsd_sopt_level(llevel)
+ int llevel;
+{
+
+ switch (llevel) {
+ case LINUX_SOL_SOCKET:
+ return SOL_SOCKET;
+ case LINUX_SOL_IP:
+ return IPPROTO_IP;
+ case LINUX_SOL_TCP:
+ return IPPROTO_TCP;
+ case LINUX_SOL_UDP:
+ return IPPROTO_UDP;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Convert Linux socket level socket option numbers to NetBSD values.
+ */
+int
+linux_to_bsd_so_sockopt(lopt)
+ int lopt;
+{
+
+ switch (lopt) {
+ 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;
+ case LINUX_SO_PRIORITY:
+ case LINUX_SO_NO_CHECK:
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Convert Linux IP level socket option number to NetBSD values.
+ */
+int
+linux_to_bsd_ip_sockopt(lopt)
+ int lopt;
+{
+
+ switch (lopt) {
+ case LINUX_IP_TOS:
+ return IP_TOS;
+ case LINUX_IP_TTL:
+ return IP_TTL;
+ case LINUX_IP_MULTICAST_TTL:
+ return IP_MULTICAST_TTL;
+ case LINUX_IP_MULTICAST_LOOP:
+ return IP_MULTICAST_LOOP;
+ case LINUX_IP_MULTICAST_IF:
+ return IP_MULTICAST_IF;
+ case LINUX_IP_ADD_MEMBERSHIP:
+ return IP_ADD_MEMBERSHIP;
+ case LINUX_IP_DROP_MEMBERSHIP:
+ return IP_DROP_MEMBERSHIP;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Convert Linux TCP level socket option number to NetBSD values.
+ */
+int
+linux_to_bsd_tcp_sockopt(lopt)
+ int lopt;
+{
+
+ switch (lopt) {
+ case LINUX_TCP_NODELAY:
+ return TCP_NODELAY;
+ case LINUX_TCP_MAXSEG:
+ return TCP_MAXSEG;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Convert Linux UDP level socket option number to NetBSD values.
+ */
+int
+linux_to_bsd_udp_sockopt(lopt)
+ int lopt;
+{
+
+ switch (lopt) {
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Another reasonably straightforward function: setsockopt(2).
+ * The level and option numbers are converted; the values passed
+ * are not (yet) converted, the ones currently implemented don't
+ * need conversion, as they are the same on both systems.
+ */
+int
+linux_setsockopt(p, uap, retval)
+ struct proc *p;
+ struct linux_setsockopt_args /* {
+ syscallarg(int) s;
+ syscallarg(int) level;
+ syscallarg(int) optname;
+ syscallarg(void *) optval;
+ syscallarg(int) optlen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_setsockopt_args lsa;
+ struct sys_setsockopt_args bsa;
+ int error, name;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
+ return error;
+
+ SCARG(&bsa, s) = lsa.s;
+ SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
+ SCARG(&bsa, val) = lsa.optval;
+ SCARG(&bsa, valsize) = lsa.optlen;
+
+ switch (SCARG(&bsa, level)) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(lsa.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(lsa.optname);
+ break;
+ case IPPROTO_TCP:
+ name = linux_to_bsd_tcp_sockopt(lsa.optname);
+ break;
+ case IPPROTO_UDP:
+ name = linux_to_bsd_udp_sockopt(lsa.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (name == -1)
+ return EINVAL;
+ SCARG(&bsa, name) = name;
+
+ return sys_setsockopt(p, &bsa, retval);
+}
+
+/*
+ * getsockopt(2) is very much the same as setsockopt(2) (see above)
+ */
+int
+linux_getsockopt(p, uap, retval)
+ struct proc *p;
+ struct linux_getsockopt_args /* {
+ syscallarg(int) s;
+ syscallarg(int) level;
+ syscallarg(int) optname;
+ syscallarg(void *) optval;
+ syscallarg(int) *optlen;
+ } */ *uap;
+ register_t *retval;
+{
+ struct linux_getsockopt_args lga;
+ struct sys_getsockopt_args bga;
+ int error, name;
+
+ if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
+ return error;
+
+ SCARG(&bga, s) = lga.s;
+ SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
+ SCARG(&bga, val) = lga.optval;
+ SCARG(&bga, avalsize) = lga.optlen;
+
+ switch (SCARG(&bga, level)) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(lga.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(lga.optname);
+ break;
+ case IPPROTO_TCP:
+ name = linux_to_bsd_tcp_sockopt(lga.optname);
+ break;
+ case IPPROTO_UDP:
+ name = linux_to_bsd_udp_sockopt(lga.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (name == -1)
+ return EINVAL;
+ SCARG(&bga, name) = name;
+
+ return sys_getsockopt(p, &bga, retval);
+}
+
+/*
+ * Entry point to all Linux socket calls. Just check which call to
+ * make and take appropriate action.
+ */
+int
+linux_sys_socketcall(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_socketcall_args /* {
+ syscallarg(int) what;
+ syscallarg(void *) args;
+ } */ *uap = v;
+
+ switch (SCARG(uap, what)) {
+ case LINUX_SYS_socket:
+ return linux_socket(p, SCARG(uap, args), retval);
+ case LINUX_SYS_bind:
+ return linux_bind(p, SCARG(uap, args), retval);
+ case LINUX_SYS_connect:
+ return linux_connect(p, SCARG(uap, args), retval);
+ case LINUX_SYS_listen:
+ return linux_listen(p, SCARG(uap, args), retval);
+ case LINUX_SYS_accept:
+ return linux_accept(p, SCARG(uap, args), retval);
+ case LINUX_SYS_getsockname:
+ return linux_getsockname(p, SCARG(uap, args), retval);
+ case LINUX_SYS_getpeername:
+ return linux_getpeername(p, SCARG(uap, args), retval);
+ case LINUX_SYS_socketpair:
+ return linux_socketpair(p, SCARG(uap, args), retval);
+ case LINUX_SYS_send:
+ return linux_send(p, SCARG(uap, args), retval);
+ case LINUX_SYS_recv:
+ return linux_recv(p, SCARG(uap, args), retval);
+ case LINUX_SYS_sendto:
+ return linux_sendto(p, SCARG(uap, args), retval);
+ case LINUX_SYS_recvfrom:
+ return linux_recvfrom(p, SCARG(uap, args), retval);
+ case LINUX_SYS_shutdown:
+ return linux_shutdown(p, SCARG(uap, args), retval);
+ case LINUX_SYS_setsockopt:
+ return linux_setsockopt(p, SCARG(uap, args), retval);
+ case LINUX_SYS_getsockopt:
+ return linux_getsockopt(p, SCARG(uap, args), retval);
+ default:
+ return ENOSYS;
+ }
+}
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
new file mode 100644
index 00000000000..a0da285cfa2
--- /dev/null
+++ b/sys/compat/linux/linux_socket.h
@@ -0,0 +1,107 @@
+/* $NetBSD: linux_socket.h,v 1.3 1995/05/28 10:16:34 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SOCKET_H
+#define _LINUX_SOCKET_H
+
+/*
+ * Various Linux socket defines. Everything that is not re-defined here
+ * is the same as in NetBSD.
+ *
+ * COMPAT_43 is assumed, and the osockaddr struct is used (it is what
+ * Linux uses)
+ */
+
+/*
+ * Address families. There are fewer of them, and they're numbered
+ * a bit different
+ */
+
+#define LINUX_AF_UNSPEC 0
+#define LINUX_AF_UNIX 1
+#define LINUX_AF_INET 2
+#define LINUX_AF_AX25 3
+#define LINUX_AF_IPX 4
+#define LINUX_AF_APPLETALK 5
+
+/*
+ * Option levels for [gs]etsockopt(2). Only SOL_SOCKET is different,
+ * the rest matches IPPROTO_XXX
+ */
+
+#define LINUX_SOL_SOCKET 1
+#define LINUX_SOL_IP 0
+#define LINUX_SOL_IPX 256
+#define LINUX_SOL_AX25 257
+#define LINUX_SOL_TCP 6
+#define LINUX_SOL_UDP 17
+
+/*
+ * Options for [gs]etsockopt(2), socket level. For Linux, they
+ * are not masks, but just increasing numbers.
+ */
+
+#define LINUX_SO_DEBUG 1
+#define LINUX_SO_REUSEADDR 2
+#define LINUX_SO_TYPE 3
+#define LINUX_SO_ERROR 4
+#define LINUX_SO_DONTROUTE 5
+#define LINUX_SO_BROADCAST 6
+#define LINUX_SO_SNDBUF 7
+#define LINUX_SO_RCVBUF 8
+#define LINUX_SO_KEEPALIVE 9
+#define LINUX_SO_OOBINLINE 10
+#define LINUX_SO_NO_CHECK 11
+#define LINUX_SO_PRIORITY 12
+#define LINUX_SO_LINGER 13
+
+/*
+ * Options vor [gs]etsockopt(2), IP level.
+ */
+
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+#define LINUX_IP_MULTICAST_IF 32
+#define LINUX_IP_MULTICAST_TTL 33
+#define LINUX_IP_MULTICAST_LOOP 34
+#define LINUX_IP_ADD_MEMBERSHIP 35
+#define LINUX_IP_DROP_MEMBERSHIP 36
+
+/*
+ * Options vor [gs]etsockopt(2), TCP level.
+ */
+
+#define LINUX_TCP_NODELAY 1
+#define LINUX_TCP_MAXSEG 2
+
+#endif /* _LINUX_SOCKET_H */
diff --git a/sys/compat/linux/linux_socketcall.h b/sys/compat/linux/linux_socketcall.h
new file mode 100644
index 00000000000..60b1156f2bc
--- /dev/null
+++ b/sys/compat/linux/linux_socketcall.h
@@ -0,0 +1,162 @@
+/* $NetBSD: linux_socketcall.h,v 1.1 1995/02/28 23:26:05 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SOCKETCALL_H
+#define _LINUX_SOCKETCALL_H
+
+/*
+ * Values passed to the Linux socketcall() syscall, determining the actual
+ * action to take.
+ */
+#define LINUX_SYS_socket 1
+#define LINUX_SYS_bind 2
+#define LINUX_SYS_connect 3
+#define LINUX_SYS_listen 4
+#define LINUX_SYS_accept 5
+#define LINUX_SYS_getsockname 6
+#define LINUX_SYS_getpeername 7
+#define LINUX_SYS_socketpair 8
+#define LINUX_SYS_send 9
+#define LINUX_SYS_recv 10
+#define LINUX_SYS_sendto 11
+#define LINUX_SYS_recvfrom 12
+#define LINUX_SYS_shutdown 13
+#define LINUX_SYS_setsockopt 14
+#define LINUX_SYS_getsockopt 15
+
+/*
+ * Structures for the arguments of the different system calls. This looks
+ * a little better than copyin() of all values one by one.
+ */
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+struct linux_bind_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+struct linux_connect_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+struct linux_accept_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+struct linux_getsockname_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+struct linux_getpeername_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+};
+
+struct linux_send_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+struct linux_recv_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+struct linux_sendto_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+ struct sockaddr *to;
+ int tolen;
+};
+
+struct linux_recvfrom_args {
+ int s;
+ void *buf;
+ int len;
+ int flags;
+ struct sockaddr *from;
+ int *fromlen;
+};
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int *optlen;
+};
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int optlen;
+};
+
+#endif /* _LINUX_SOCKETCALL_H */
diff --git a/sys/compat/linux/linux_sockio.h b/sys/compat/linux/linux_sockio.h
new file mode 100644
index 00000000000..62ae2bc26a4
--- /dev/null
+++ b/sys/compat/linux/linux_sockio.h
@@ -0,0 +1,40 @@
+/* $NetBSD: linux_sockio.h,v 1.2 1995/06/22 21:34:42 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_SOCKIO_H
+#define _LINUX_SOCKIO_H
+
+#define LINUX_SIOCADDMULTI 0x8931
+#define LINUX_SIOCDELMULTI 0x8932
+
+#endif /* _LINUX_SOCKIO_H */
diff --git a/sys/compat/linux/linux_syscall.h b/sys/compat/linux/linux_syscall.h
new file mode 100644
index 00000000000..4bc8e99b8e6
--- /dev/null
+++ b/sys/compat/linux/linux_syscall.h
@@ -0,0 +1,120 @@
+/*
+ * System call numbers.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * created from NetBSD: syscalls.master,v 1.13 1995/10/07 06:27:15 mycroft Exp
+ */
+
+#define LINUX_SYS_syscall 0
+#define LINUX_SYS_exit 1
+#define LINUX_SYS_fork 2
+#define LINUX_SYS_read 3
+#define LINUX_SYS_write 4
+#define LINUX_SYS_open 5
+#define LINUX_SYS_close 6
+#define LINUX_SYS_waitpid 7
+#define LINUX_SYS_creat 8
+#define LINUX_SYS_link 9
+#define LINUX_SYS_unlink 10
+#define LINUX_SYS_execve 11
+#define LINUX_SYS_chdir 12
+#define LINUX_SYS_time 13
+#define LINUX_SYS_mknod 14
+#define LINUX_SYS_chmod 15
+#define LINUX_SYS_chown 16
+#define LINUX_SYS_break 17
+ /* 18 is obsolete ostat */
+#define LINUX_SYS_lseek 19
+#define LINUX_SYS_getpid 20
+#define LINUX_SYS_setuid 23
+#define LINUX_SYS_getuid 24
+#define LINUX_SYS_alarm 27
+ /* 28 is obsolete ofstat */
+#define LINUX_SYS_pause 29
+#define LINUX_SYS_utime 30
+#define LINUX_SYS_access 33
+#define LINUX_SYS_sync 36
+#define LINUX_SYS_kill 37
+#define LINUX_SYS_rename 38
+#define LINUX_SYS_mkdir 39
+#define LINUX_SYS_rmdir 40
+#define LINUX_SYS_dup 41
+#define LINUX_SYS_pipe 42
+#define LINUX_SYS_times 43
+#define LINUX_SYS_brk 45
+#define LINUX_SYS_setgid 46
+#define LINUX_SYS_getgid 47
+#define LINUX_SYS_signal 48
+#define LINUX_SYS_geteuid 49
+#define LINUX_SYS_getegid 50
+#define LINUX_SYS_acct 51
+#define LINUX_SYS_ioctl 54
+#define LINUX_SYS_fcntl 55
+#define LINUX_SYS_setpgid 57
+#define LINUX_SYS_oldolduname 59
+#define LINUX_SYS_umask 60
+#define LINUX_SYS_chroot 61
+#define LINUX_SYS_dup2 63
+#define LINUX_SYS_getppid 64
+#define LINUX_SYS_getpgrp 65
+#define LINUX_SYS_setsid 66
+#define LINUX_SYS_sigaction 67
+#define LINUX_SYS_siggetmask 68
+#define LINUX_SYS_sigsetmask 69
+#define LINUX_SYS_setreuid 70
+#define LINUX_SYS_setregid 71
+#define LINUX_SYS_sigsuspend 72
+#define LINUX_SYS_sigpending 73
+#define LINUX_SYS_sethostname 74
+#define LINUX_SYS_setrlimit 75
+#define LINUX_SYS_getrlimit 76
+#define LINUX_SYS_getrusage 77
+#define LINUX_SYS_gettimeofday 78
+#define LINUX_SYS_settimeofday 79
+#define LINUX_SYS_getgroups 80
+#define LINUX_SYS_setgroups 81
+#define LINUX_SYS_oldselect 82
+#define LINUX_SYS_symlink 83
+#define LINUX_SYS_olstat 84
+#define LINUX_SYS_readlink 85
+#define LINUX_SYS_uselib 86
+#define LINUX_SYS_swapon 87
+#define LINUX_SYS_reboot 88
+#define LINUX_SYS_readdir 89
+#define LINUX_SYS_mmap 90
+#define LINUX_SYS_munmap 91
+#define LINUX_SYS_truncate 92
+#define LINUX_SYS_ftruncate 93
+#define LINUX_SYS_fchmod 94
+#define LINUX_SYS_fchown 95
+#define LINUX_SYS_getpriority 96
+#define LINUX_SYS_setpriority 97
+#define LINUX_SYS_profil 98
+#define LINUX_SYS_statfs 99
+#define LINUX_SYS_fstatfs 100
+#define LINUX_SYS_ioperm 101
+#define LINUX_SYS_socketcall 102
+#define LINUX_SYS_setitimer 104
+#define LINUX_SYS_getitimer 105
+#define LINUX_SYS_stat 106
+#define LINUX_SYS_lstat 107
+#define LINUX_SYS_fstat 108
+#define LINUX_SYS_olduname 109
+#define LINUX_SYS_iopl 110
+#define LINUX_SYS_wait4 114
+#define LINUX_SYS_ipc 117
+#define LINUX_SYS_fsync 118
+#define LINUX_SYS_sigreturn 119
+#define LINUX_SYS_setdomainname 121
+#define LINUX_SYS_uname 122
+#define LINUX_SYS_modify_ldt 123
+#define LINUX_SYS_mprotect 125
+#define LINUX_SYS_sigprocmask 126
+#define LINUX_SYS_getpgid 132
+#define LINUX_SYS_fchdir 133
+#define LINUX_SYS_personality 136
+#define LINUX_SYS_llseek 140
+#define LINUX_SYS_getdents 141
+#define LINUX_SYS_select 142
+#define LINUX_SYS_flock 143
+#define LINUX_SYS_MAXSYSCALL 144
diff --git a/sys/compat/linux/linux_syscallargs.h b/sys/compat/linux/linux_syscallargs.h
new file mode 100644
index 00000000000..a4d393b1a83
--- /dev/null
+++ b/sys/compat/linux/linux_syscallargs.h
@@ -0,0 +1,433 @@
+/*
+ * System call argument lists.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * created from NetBSD: syscalls.master,v 1.13 1995/10/07 06:27:15 mycroft Exp
+ */
+
+#define syscallarg(x) union { x datum; register_t pad; }
+
+struct linux_sys_open_args {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+ syscallarg(int) mode;
+};
+
+struct linux_sys_waitpid_args {
+ syscallarg(int) pid;
+ syscallarg(int *) status;
+ syscallarg(int) options;
+};
+
+struct linux_sys_creat_args {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+};
+
+struct linux_sys_unlink_args {
+ syscallarg(char *) path;
+};
+
+struct linux_sys_execve_args {
+ syscallarg(char *) path;
+ syscallarg(char **) argp;
+ syscallarg(char **) envp;
+};
+
+struct linux_sys_chdir_args {
+ syscallarg(char *) path;
+};
+
+struct linux_sys_time_args {
+ syscallarg(linux_time_t *) t;
+};
+
+struct linux_sys_mknod_args {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+ syscallarg(int) dev;
+};
+
+struct linux_sys_chmod_args {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+};
+
+struct linux_sys_chown_args {
+ syscallarg(char *) path;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+};
+
+struct linux_sys_break_args {
+ syscallarg(char *) nsize;
+};
+
+struct linux_sys_alarm_args {
+ syscallarg(unsigned int) secs;
+};
+
+struct linux_sys_utime_args {
+ syscallarg(char *) path;
+ syscallarg(struct linux_utimbuf *) times;
+};
+
+struct linux_sys_access_args {
+ syscallarg(char *) path;
+ syscallarg(int) flags;
+};
+
+struct linux_sys_kill_args {
+ syscallarg(int) pid;
+ syscallarg(int) signum;
+};
+
+struct linux_sys_rename_args {
+ syscallarg(char *) from;
+ syscallarg(char *) to;
+};
+
+struct linux_sys_mkdir_args {
+ syscallarg(char *) path;
+ syscallarg(int) mode;
+};
+
+struct linux_sys_rmdir_args {
+ syscallarg(char *) path;
+};
+
+struct linux_sys_pipe_args {
+ syscallarg(int *) pfds;
+};
+
+struct linux_sys_times_args {
+ syscallarg(struct times *) tms;
+};
+
+struct linux_sys_brk_args {
+ syscallarg(char *) nsize;
+};
+
+struct linux_sys_signal_args {
+ syscallarg(int) sig;
+ syscallarg(linux_handler_t) handler;
+};
+
+struct linux_sys_ioctl_args {
+ syscallarg(int) fd;
+ syscallarg(u_long) com;
+ syscallarg(caddr_t) data;
+};
+
+struct linux_sys_fcntl_args {
+ syscallarg(int) fd;
+ syscallarg(int) cmd;
+ syscallarg(void *) arg;
+};
+
+struct linux_sys_oldolduname_args {
+ syscallarg(struct linux_oldold_utsname *) up;
+};
+
+struct linux_sys_sigaction_args {
+ syscallarg(int) signum;
+ syscallarg(struct linux_sigaction *) nsa;
+ syscallarg(struct linux_sigaction *) osa;
+};
+
+struct linux_sys_sigsetmask_args {
+ syscallarg(linux_sigset_t) mask;
+};
+
+struct linux_sys_setreuid_args {
+ syscallarg(int) ruid;
+ syscallarg(int) euid;
+};
+
+struct linux_sys_setregid_args {
+ syscallarg(int) rgid;
+ syscallarg(int) egid;
+};
+
+struct linux_sys_sigsuspend_args {
+ syscallarg(caddr_t) restart;
+ syscallarg(int) oldmask;
+ syscallarg(int) mask;
+};
+
+struct linux_sys_sigpending_args {
+ syscallarg(linux_sigset_t *) mask;
+};
+
+struct linux_sys_oldselect_args {
+ syscallarg(struct linux_select *) lsp;
+};
+
+struct linux_sys_symlink_args {
+ syscallarg(char *) path;
+ syscallarg(char *) to;
+};
+
+struct linux_sys_readlink_args {
+ syscallarg(char *) name;
+ syscallarg(char *) buf;
+ syscallarg(int) count;
+};
+
+struct linux_sys_uselib_args {
+ syscallarg(char *) path;
+};
+
+struct linux_sys_readdir_args {
+ syscallarg(int) fd;
+ syscallarg(caddr_t) dent;
+ syscallarg(unsigned int) count;
+};
+
+struct linux_sys_mmap_args {
+ syscallarg(struct linux_mmap *) lmp;
+};
+
+struct linux_sys_truncate_args {
+ syscallarg(char *) path;
+ syscallarg(long) length;
+};
+
+struct linux_sys_fchown_args {
+ syscallarg(int) fd;
+ syscallarg(int) uid;
+ syscallarg(int) gid;
+};
+
+struct linux_sys_statfs_args {
+ syscallarg(char *) path;
+ syscallarg(struct linux_statfs *) sp;
+};
+
+struct linux_sys_fstatfs_args {
+ syscallarg(int) fd;
+ syscallarg(struct linux_statfs *) sp;
+};
+
+struct linux_sys_ioperm_args {
+ syscallarg(unsigned int) lo;
+ syscallarg(unsigned int) hi;
+ syscallarg(int) val;
+};
+
+struct linux_sys_socketcall_args {
+ syscallarg(int) what;
+ syscallarg(void *) args;
+};
+
+struct linux_sys_stat_args {
+ syscallarg(char *) path;
+ syscallarg(struct linux_stat *) sp;
+};
+
+struct linux_sys_lstat_args {
+ syscallarg(char *) path;
+ syscallarg(struct linux_stat *) sp;
+};
+
+struct linux_sys_fstat_args {
+ syscallarg(int) fd;
+ syscallarg(struct linux_stat *) sp;
+};
+
+struct linux_sys_olduname_args {
+ syscallarg(struct linux_old_utsname *) up;
+};
+
+struct linux_sys_iopl_args {
+ syscallarg(int) level;
+};
+
+struct linux_sys_wait4_args {
+ syscallarg(int) pid;
+ syscallarg(int *) status;
+ syscallarg(int) options;
+ syscallarg(struct rusage *) rusage;
+};
+
+struct linux_sys_ipc_args {
+ syscallarg(int) what;
+ syscallarg(int) a1;
+ syscallarg(int) a2;
+ syscallarg(int) a3;
+ syscallarg(caddr_t) ptr;
+};
+
+struct linux_sys_sigreturn_args {
+ syscallarg(struct linux_sigcontext *) scp;
+};
+
+struct linux_sys_uname_args {
+ syscallarg(struct linux_utsname *) up;
+};
+
+struct linux_sys_modify_ldt_args {
+ syscallarg(int) func;
+ syscallarg(void *) ptr;
+ syscallarg(size_t) bytecount;
+};
+
+struct linux_sys_sigprocmask_args {
+ syscallarg(int) how;
+ syscallarg(linux_sigset_t *) set;
+ syscallarg(linux_sigset_t *) oset;
+};
+
+struct linux_sys_getpgid_args {
+ syscallarg(int) pid;
+};
+
+struct linux_sys_personality_args {
+ syscallarg(int) per;
+};
+
+struct linux_sys_llseek_args {
+ syscallarg(int) fd;
+ syscallarg(u_int32_t) ohigh;
+ syscallarg(u_int32_t) olow;
+ syscallarg(caddr_t) res;
+ syscallarg(int) whence;
+};
+
+struct linux_sys_getdents_args {
+ syscallarg(int) fd;
+ syscallarg(void *) dirent;
+ syscallarg(unsigned) count;
+};
+
+struct linux_sys_select_args {
+ syscallarg(int) nfds;
+ syscallarg(fd_set *) readfds;
+ syscallarg(fd_set *) writefds;
+ syscallarg(fd_set *) exceptfds;
+ syscallarg(struct timeval *) timeout;
+};
+
+/*
+ * System call prototypes.
+ */
+
+int sys_nosys __P((struct proc *, void *, register_t *));
+int sys_exit __P((struct proc *, void *, register_t *));
+int linux_sys_fork __P((struct proc *, void *, register_t *));
+int sys_read __P((struct proc *, void *, register_t *));
+int sys_write __P((struct proc *, void *, register_t *));
+int linux_sys_open __P((struct proc *, void *, register_t *));
+int sys_close __P((struct proc *, void *, register_t *));
+int linux_sys_waitpid __P((struct proc *, void *, register_t *));
+int linux_sys_creat __P((struct proc *, void *, register_t *));
+int sys_link __P((struct proc *, void *, register_t *));
+int linux_sys_unlink __P((struct proc *, void *, register_t *));
+int linux_sys_execve __P((struct proc *, void *, register_t *));
+int linux_sys_chdir __P((struct proc *, void *, register_t *));
+int linux_sys_time __P((struct proc *, void *, register_t *));
+int linux_sys_mknod __P((struct proc *, void *, register_t *));
+int linux_sys_chmod __P((struct proc *, void *, register_t *));
+int linux_sys_chown __P((struct proc *, void *, register_t *));
+int linux_sys_break __P((struct proc *, void *, register_t *));
+int compat_43_sys_lseek __P((struct proc *, void *, register_t *));
+int sys_getpid __P((struct proc *, void *, register_t *));
+int sys_setuid __P((struct proc *, void *, register_t *));
+int sys_getuid __P((struct proc *, void *, register_t *));
+int linux_sys_alarm __P((struct proc *, void *, register_t *));
+int linux_sys_pause __P((struct proc *, void *, register_t *));
+int linux_sys_utime __P((struct proc *, void *, register_t *));
+int linux_sys_access __P((struct proc *, void *, register_t *));
+int sys_sync __P((struct proc *, void *, register_t *));
+int linux_sys_kill __P((struct proc *, void *, register_t *));
+int linux_sys_rename __P((struct proc *, void *, register_t *));
+int linux_sys_mkdir __P((struct proc *, void *, register_t *));
+int linux_sys_rmdir __P((struct proc *, void *, register_t *));
+int sys_dup __P((struct proc *, void *, register_t *));
+int linux_sys_pipe __P((struct proc *, void *, register_t *));
+int linux_sys_times __P((struct proc *, void *, register_t *));
+int linux_sys_brk __P((struct proc *, void *, register_t *));
+int sys_setgid __P((struct proc *, void *, register_t *));
+int sys_getgid __P((struct proc *, void *, register_t *));
+int linux_sys_signal __P((struct proc *, void *, register_t *));
+int sys_geteuid __P((struct proc *, void *, register_t *));
+int sys_getegid __P((struct proc *, void *, register_t *));
+int sys_acct __P((struct proc *, void *, register_t *));
+int linux_sys_ioctl __P((struct proc *, void *, register_t *));
+int linux_sys_fcntl __P((struct proc *, void *, register_t *));
+int sys_setpgid __P((struct proc *, void *, register_t *));
+int linux_sys_oldolduname __P((struct proc *, void *, register_t *));
+int sys_umask __P((struct proc *, void *, register_t *));
+int sys_chroot __P((struct proc *, void *, register_t *));
+int sys_dup2 __P((struct proc *, void *, register_t *));
+int sys_getppid __P((struct proc *, void *, register_t *));
+int sys_getpgrp __P((struct proc *, void *, register_t *));
+int sys_setsid __P((struct proc *, void *, register_t *));
+int linux_sys_sigaction __P((struct proc *, void *, register_t *));
+int linux_sys_siggetmask __P((struct proc *, void *, register_t *));
+int linux_sys_sigsetmask __P((struct proc *, void *, register_t *));
+int linux_sys_setreuid __P((struct proc *, void *, register_t *));
+int linux_sys_setregid __P((struct proc *, void *, register_t *));
+int linux_sys_sigsuspend __P((struct proc *, void *, register_t *));
+int linux_sys_sigpending __P((struct proc *, void *, register_t *));
+int compat_43_sys_sethostname __P((struct proc *, void *, register_t *));
+int compat_43_sys_setrlimit __P((struct proc *, void *, register_t *));
+int compat_43_sys_getrlimit __P((struct proc *, void *, register_t *));
+int sys_getrusage __P((struct proc *, void *, register_t *));
+int sys_gettimeofday __P((struct proc *, void *, register_t *));
+int sys_settimeofday __P((struct proc *, void *, register_t *));
+int sys_getgroups __P((struct proc *, void *, register_t *));
+int sys_setgroups __P((struct proc *, void *, register_t *));
+int linux_sys_oldselect __P((struct proc *, void *, register_t *));
+int linux_sys_symlink __P((struct proc *, void *, register_t *));
+int compat_43_sys_lstat __P((struct proc *, void *, register_t *));
+int linux_sys_readlink __P((struct proc *, void *, register_t *));
+int linux_sys_uselib __P((struct proc *, void *, register_t *));
+int sys_swapon __P((struct proc *, void *, register_t *));
+int sys_reboot __P((struct proc *, void *, register_t *));
+int linux_sys_readdir __P((struct proc *, void *, register_t *));
+int linux_sys_mmap __P((struct proc *, void *, register_t *));
+int sys_munmap __P((struct proc *, void *, register_t *));
+int linux_sys_truncate __P((struct proc *, void *, register_t *));
+int compat_43_sys_ftruncate __P((struct proc *, void *, register_t *));
+int sys_fchmod __P((struct proc *, void *, register_t *));
+int linux_sys_fchown __P((struct proc *, void *, register_t *));
+int sys_getpriority __P((struct proc *, void *, register_t *));
+int sys_setpriority __P((struct proc *, void *, register_t *));
+int sys_profil __P((struct proc *, void *, register_t *));
+int linux_sys_statfs __P((struct proc *, void *, register_t *));
+int linux_sys_fstatfs __P((struct proc *, void *, register_t *));
+#ifdef __i386__
+int linux_sys_ioperm __P((struct proc *, void *, register_t *));
+#else
+#endif
+int linux_sys_socketcall __P((struct proc *, void *, register_t *));
+int sys_setitimer __P((struct proc *, void *, register_t *));
+int sys_getitimer __P((struct proc *, void *, register_t *));
+int linux_sys_stat __P((struct proc *, void *, register_t *));
+int linux_sys_lstat __P((struct proc *, void *, register_t *));
+int linux_sys_fstat __P((struct proc *, void *, register_t *));
+int linux_sys_olduname __P((struct proc *, void *, register_t *));
+#ifdef __i386__
+int linux_sys_iopl __P((struct proc *, void *, register_t *));
+#else
+#endif
+int linux_sys_wait4 __P((struct proc *, void *, register_t *));
+int linux_sys_ipc __P((struct proc *, void *, register_t *));
+int sys_fsync __P((struct proc *, void *, register_t *));
+int linux_sys_sigreturn __P((struct proc *, void *, register_t *));
+int compat_09_sys_setdomainname __P((struct proc *, void *, register_t *));
+int linux_sys_uname __P((struct proc *, void *, register_t *));
+#ifdef __i386__
+int linux_sys_modify_ldt __P((struct proc *, void *, register_t *));
+#else
+#endif
+int sys_mprotect __P((struct proc *, void *, register_t *));
+int linux_sys_sigprocmask __P((struct proc *, void *, register_t *));
+int linux_sys_getpgid __P((struct proc *, void *, register_t *));
+int sys_fchdir __P((struct proc *, void *, register_t *));
+int linux_sys_personality __P((struct proc *, void *, register_t *));
+int linux_sys_llseek __P((struct proc *, void *, register_t *));
+int linux_sys_getdents __P((struct proc *, void *, register_t *));
+int linux_sys_select __P((struct proc *, void *, register_t *));
+int sys_flock __P((struct proc *, void *, register_t *));
diff --git a/sys/compat/linux/linux_syscalls.c b/sys/compat/linux/linux_syscalls.c
new file mode 100644
index 00000000000..237014c11bf
--- /dev/null
+++ b/sys/compat/linux/linux_syscalls.c
@@ -0,0 +1,165 @@
+/*
+ * System call names.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * created from NetBSD: syscalls.master,v 1.13 1995/10/07 06:27:15 mycroft Exp
+ */
+
+char *linux_syscallnames[] = {
+ "syscall", /* 0 = syscall */
+ "exit", /* 1 = exit */
+ "fork", /* 2 = fork */
+ "read", /* 3 = read */
+ "write", /* 4 = write */
+ "open", /* 5 = open */
+ "close", /* 6 = close */
+ "waitpid", /* 7 = waitpid */
+ "creat", /* 8 = creat */
+ "link", /* 9 = link */
+ "unlink", /* 10 = unlink */
+ "execve", /* 11 = execve */
+ "chdir", /* 12 = chdir */
+ "time", /* 13 = time */
+ "mknod", /* 14 = mknod */
+ "chmod", /* 15 = chmod */
+ "chown", /* 16 = chown */
+ "break", /* 17 = break */
+ "#18 (obsolete ostat)", /* 18 = obsolete ostat */
+ "lseek", /* 19 = lseek */
+ "getpid", /* 20 = getpid */
+ "#21 (unimplemented mount)", /* 21 = unimplemented mount */
+ "#22 (unimplemented umount)", /* 22 = unimplemented umount */
+ "setuid", /* 23 = setuid */
+ "getuid", /* 24 = getuid */
+ "#25 (unimplemented stime)", /* 25 = unimplemented stime */
+ "#26 (unimplemented ptrace)", /* 26 = unimplemented ptrace */
+ "alarm", /* 27 = alarm */
+ "#28 (obsolete ofstat)", /* 28 = obsolete ofstat */
+ "pause", /* 29 = pause */
+ "utime", /* 30 = utime */
+ "#31 (unimplemented stty)", /* 31 = unimplemented stty */
+ "#32 (unimplemented gtty)", /* 32 = unimplemented gtty */
+ "access", /* 33 = access */
+ "#34 (unimplemented nice)", /* 34 = unimplemented nice */
+ "#35 (unimplemented ftime)", /* 35 = unimplemented ftime */
+ "sync", /* 36 = sync */
+ "kill", /* 37 = kill */
+ "rename", /* 38 = rename */
+ "mkdir", /* 39 = mkdir */
+ "rmdir", /* 40 = rmdir */
+ "dup", /* 41 = dup */
+ "pipe", /* 42 = pipe */
+ "times", /* 43 = times */
+ "#44 (unimplemented prof)", /* 44 = unimplemented prof */
+ "brk", /* 45 = brk */
+ "setgid", /* 46 = setgid */
+ "getgid", /* 47 = getgid */
+ "signal", /* 48 = signal */
+ "geteuid", /* 49 = geteuid */
+ "getegid", /* 50 = getegid */
+ "acct", /* 51 = acct */
+ "#52 (unimplemented phys)", /* 52 = unimplemented phys */
+ "#53 (unimplemented lock)", /* 53 = unimplemented lock */
+ "ioctl", /* 54 = ioctl */
+ "fcntl", /* 55 = fcntl */
+ "#56 (unimplemented mpx)", /* 56 = unimplemented mpx */
+ "setpgid", /* 57 = setpgid */
+ "#58 (unimplemented ulimit)", /* 58 = unimplemented ulimit */
+ "oldolduname", /* 59 = oldolduname */
+ "umask", /* 60 = umask */
+ "chroot", /* 61 = chroot */
+ "#62 (unimplemented ustat)", /* 62 = unimplemented ustat */
+ "dup2", /* 63 = dup2 */
+ "getppid", /* 64 = getppid */
+ "getpgrp", /* 65 = getpgrp */
+ "setsid", /* 66 = setsid */
+ "sigaction", /* 67 = sigaction */
+ "siggetmask", /* 68 = siggetmask */
+ "sigsetmask", /* 69 = sigsetmask */
+ "setreuid", /* 70 = setreuid */
+ "setregid", /* 71 = setregid */
+ "sigsuspend", /* 72 = sigsuspend */
+ "sigpending", /* 73 = sigpending */
+ "sethostname", /* 74 = sethostname */
+ "setrlimit", /* 75 = setrlimit */
+ "getrlimit", /* 76 = getrlimit */
+ "getrusage", /* 77 = getrusage */
+ "gettimeofday", /* 78 = gettimeofday */
+ "settimeofday", /* 79 = settimeofday */
+ "getgroups", /* 80 = getgroups */
+ "setgroups", /* 81 = setgroups */
+ "oldselect", /* 82 = oldselect */
+ "symlink", /* 83 = symlink */
+ "olstat", /* 84 = olstat */
+ "readlink", /* 85 = readlink */
+ "uselib", /* 86 = uselib */
+ "swapon", /* 87 = swapon */
+ "reboot", /* 88 = reboot */
+ "readdir", /* 89 = readdir */
+ "mmap", /* 90 = mmap */
+ "munmap", /* 91 = munmap */
+ "truncate", /* 92 = truncate */
+ "ftruncate", /* 93 = ftruncate */
+ "fchmod", /* 94 = fchmod */
+ "fchown", /* 95 = fchown */
+ "getpriority", /* 96 = getpriority */
+ "setpriority", /* 97 = setpriority */
+ "profil", /* 98 = profil */
+ "statfs", /* 99 = statfs */
+ "fstatfs", /* 100 = fstatfs */
+#ifdef __i386__
+ "ioperm", /* 101 = ioperm */
+#else
+ "#101 (unimplemented ioperm)", /* 101 = unimplemented ioperm */
+#endif
+ "socketcall", /* 102 = socketcall */
+ "#103 (unimplemented klog)", /* 103 = unimplemented klog */
+ "setitimer", /* 104 = setitimer */
+ "getitimer", /* 105 = getitimer */
+ "stat", /* 106 = stat */
+ "lstat", /* 107 = lstat */
+ "fstat", /* 108 = fstat */
+ "olduname", /* 109 = olduname */
+#ifdef __i386__
+ "iopl", /* 110 = iopl */
+#else
+ "#110 (unimplemented iopl)", /* 110 = unimplemented iopl */
+#endif
+ "#111 (unimplemented vhangup)", /* 111 = unimplemented vhangup */
+ "#112 (unimplemented idle)", /* 112 = unimplemented idle */
+ "#113 (unimplemented vm86)", /* 113 = unimplemented vm86 */
+ "wait4", /* 114 = wait4 */
+ "#115 (unimplemented swapoff)", /* 115 = unimplemented swapoff */
+ "#116 (unimplemented sysinfo)", /* 116 = unimplemented sysinfo */
+ "ipc", /* 117 = ipc */
+ "fsync", /* 118 = fsync */
+ "sigreturn", /* 119 = sigreturn */
+ "#120 (unimplemented clone)", /* 120 = unimplemented clone */
+ "setdomainname", /* 121 = setdomainname */
+ "uname", /* 122 = uname */
+#ifdef __i386__
+ "modify_ldt", /* 123 = modify_ldt */
+#else
+ "#123 (unimplemented modify_ldt)", /* 123 = unimplemented modify_ldt */
+#endif
+ "#124 (unimplemented adjtimex)", /* 124 = unimplemented adjtimex */
+ "mprotect", /* 125 = mprotect */
+ "sigprocmask", /* 126 = sigprocmask */
+ "#127 (unimplemented create_module)", /* 127 = unimplemented create_module */
+ "#128 (unimplemented init_module)", /* 128 = unimplemented init_module */
+ "#129 (unimplemented delete_module)", /* 129 = unimplemented delete_module */
+ "#130 (unimplemented get_kernel_syms)", /* 130 = unimplemented get_kernel_syms */
+ "#131 (unimplemented quotactl)", /* 131 = unimplemented quotactl */
+ "getpgid", /* 132 = getpgid */
+ "fchdir", /* 133 = fchdir */
+ "#134 (unimplemented bdflush)", /* 134 = unimplemented bdflush */
+ "#135 (unimplemented sysfs)", /* 135 = unimplemented sysfs */
+ "personality", /* 136 = personality */
+ "#137 (unimplemented afs_syscall)", /* 137 = unimplemented afs_syscall */
+ "#138 (unimplemented setfsuid)", /* 138 = unimplemented setfsuid */
+ "#139 (unimplemented getfsuid)", /* 139 = unimplemented getfsuid */
+ "llseek", /* 140 = llseek */
+ "getdents", /* 141 = getdents */
+ "select", /* 142 = select */
+ "flock", /* 143 = flock */
+};
diff --git a/sys/compat/linux/linux_sysent.c b/sys/compat/linux/linux_sysent.c
new file mode 100644
index 00000000000..0469f99ecd1
--- /dev/null
+++ b/sys/compat/linux/linux_sysent.c
@@ -0,0 +1,325 @@
+/*
+ * System call switch table.
+ *
+ * DO NOT EDIT-- this file is automatically generated.
+ * created from NetBSD: syscalls.master,v 1.13 1995/10/07 06:27:15 mycroft Exp
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signal.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <machine/linux_machdep.h>
+
+#define s(type) sizeof(type)
+
+struct sysent linux_sysent[] = {
+ { 0, 0,
+ sys_nosys }, /* 0 = syscall */
+ { 1, s(struct sys_exit_args),
+ sys_exit }, /* 1 = exit */
+ { 0, 0,
+ linux_sys_fork }, /* 2 = fork */
+ { 3, s(struct sys_read_args),
+ sys_read }, /* 3 = read */
+ { 3, s(struct sys_write_args),
+ sys_write }, /* 4 = write */
+ { 3, s(struct linux_sys_open_args),
+ linux_sys_open }, /* 5 = open */
+ { 1, s(struct sys_close_args),
+ sys_close }, /* 6 = close */
+ { 3, s(struct linux_sys_waitpid_args),
+ linux_sys_waitpid }, /* 7 = waitpid */
+ { 2, s(struct linux_sys_creat_args),
+ linux_sys_creat }, /* 8 = creat */
+ { 2, s(struct sys_link_args),
+ sys_link }, /* 9 = link */
+ { 1, s(struct linux_sys_unlink_args),
+ linux_sys_unlink }, /* 10 = unlink */
+ { 3, s(struct linux_sys_execve_args),
+ linux_sys_execve }, /* 11 = execve */
+ { 1, s(struct linux_sys_chdir_args),
+ linux_sys_chdir }, /* 12 = chdir */
+ { 1, s(struct linux_sys_time_args),
+ linux_sys_time }, /* 13 = time */
+ { 3, s(struct linux_sys_mknod_args),
+ linux_sys_mknod }, /* 14 = mknod */
+ { 2, s(struct linux_sys_chmod_args),
+ linux_sys_chmod }, /* 15 = chmod */
+ { 3, s(struct linux_sys_chown_args),
+ linux_sys_chown }, /* 16 = chown */
+ { 1, s(struct linux_sys_break_args),
+ linux_sys_break }, /* 17 = break */
+ { 0, 0,
+ sys_nosys }, /* 18 = obsolete ostat */
+ { 3, s(struct compat_43_sys_lseek_args),
+ compat_43_sys_lseek }, /* 19 = lseek */
+ { 0, 0,
+ sys_getpid }, /* 20 = getpid */
+ { 0, 0,
+ sys_nosys }, /* 21 = unimplemented mount */
+ { 0, 0,
+ sys_nosys }, /* 22 = unimplemented umount */
+ { 1, s(struct sys_setuid_args),
+ sys_setuid }, /* 23 = setuid */
+ { 0, 0,
+ sys_getuid }, /* 24 = getuid */
+ { 0, 0,
+ sys_nosys }, /* 25 = unimplemented stime */
+ { 0, 0,
+ sys_nosys }, /* 26 = unimplemented ptrace */
+ { 1, s(struct linux_sys_alarm_args),
+ linux_sys_alarm }, /* 27 = alarm */
+ { 0, 0,
+ sys_nosys }, /* 28 = obsolete ofstat */
+ { 0, 0,
+ linux_sys_pause }, /* 29 = pause */
+ { 2, s(struct linux_sys_utime_args),
+ linux_sys_utime }, /* 30 = utime */
+ { 0, 0,
+ sys_nosys }, /* 31 = unimplemented stty */
+ { 0, 0,
+ sys_nosys }, /* 32 = unimplemented gtty */
+ { 2, s(struct linux_sys_access_args),
+ linux_sys_access }, /* 33 = access */
+ { 0, 0,
+ sys_nosys }, /* 34 = unimplemented nice */
+ { 0, 0,
+ sys_nosys }, /* 35 = unimplemented ftime */
+ { 0, 0,
+ sys_sync }, /* 36 = sync */
+ { 2, s(struct linux_sys_kill_args),
+ linux_sys_kill }, /* 37 = kill */
+ { 2, s(struct linux_sys_rename_args),
+ linux_sys_rename }, /* 38 = rename */
+ { 2, s(struct linux_sys_mkdir_args),
+ linux_sys_mkdir }, /* 39 = mkdir */
+ { 1, s(struct linux_sys_rmdir_args),
+ linux_sys_rmdir }, /* 40 = rmdir */
+ { 1, s(struct sys_dup_args),
+ sys_dup }, /* 41 = dup */
+ { 1, s(struct linux_sys_pipe_args),
+ linux_sys_pipe }, /* 42 = pipe */
+ { 1, s(struct linux_sys_times_args),
+ linux_sys_times }, /* 43 = times */
+ { 0, 0,
+ sys_nosys }, /* 44 = unimplemented prof */
+ { 1, s(struct linux_sys_brk_args),
+ linux_sys_brk }, /* 45 = brk */
+ { 1, s(struct sys_setgid_args),
+ sys_setgid }, /* 46 = setgid */
+ { 0, 0,
+ sys_getgid }, /* 47 = getgid */
+ { 2, s(struct linux_sys_signal_args),
+ linux_sys_signal }, /* 48 = signal */
+ { 0, 0,
+ sys_geteuid }, /* 49 = geteuid */
+ { 0, 0,
+ sys_getegid }, /* 50 = getegid */
+ { 1, s(struct sys_acct_args),
+ sys_acct }, /* 51 = acct */
+ { 0, 0,
+ sys_nosys }, /* 52 = unimplemented phys */
+ { 0, 0,
+ sys_nosys }, /* 53 = unimplemented lock */
+ { 3, s(struct linux_sys_ioctl_args),
+ linux_sys_ioctl }, /* 54 = ioctl */
+ { 3, s(struct linux_sys_fcntl_args),
+ linux_sys_fcntl }, /* 55 = fcntl */
+ { 0, 0,
+ sys_nosys }, /* 56 = unimplemented mpx */
+ { 2, s(struct sys_setpgid_args),
+ sys_setpgid }, /* 57 = setpgid */
+ { 0, 0,
+ sys_nosys }, /* 58 = unimplemented ulimit */
+ { 1, s(struct linux_sys_oldolduname_args),
+ linux_sys_oldolduname }, /* 59 = oldolduname */
+ { 1, s(struct sys_umask_args),
+ sys_umask }, /* 60 = umask */
+ { 1, s(struct sys_chroot_args),
+ sys_chroot }, /* 61 = chroot */
+ { 0, 0,
+ sys_nosys }, /* 62 = unimplemented ustat */
+ { 2, s(struct sys_dup2_args),
+ sys_dup2 }, /* 63 = dup2 */
+ { 0, 0,
+ sys_getppid }, /* 64 = getppid */
+ { 0, 0,
+ sys_getpgrp }, /* 65 = getpgrp */
+ { 0, 0,
+ sys_setsid }, /* 66 = setsid */
+ { 3, s(struct linux_sys_sigaction_args),
+ linux_sys_sigaction }, /* 67 = sigaction */
+ { 0, 0,
+ linux_sys_siggetmask }, /* 68 = siggetmask */
+ { 1, s(struct linux_sys_sigsetmask_args),
+ linux_sys_sigsetmask }, /* 69 = sigsetmask */
+ { 2, s(struct linux_sys_setreuid_args),
+ linux_sys_setreuid }, /* 70 = setreuid */
+ { 2, s(struct linux_sys_setregid_args),
+ linux_sys_setregid }, /* 71 = setregid */
+ { 3, s(struct linux_sys_sigsuspend_args),
+ linux_sys_sigsuspend }, /* 72 = sigsuspend */
+ { 1, s(struct linux_sys_sigpending_args),
+ linux_sys_sigpending }, /* 73 = sigpending */
+ { 2, s(struct compat_43_sys_sethostname_args),
+ compat_43_sys_sethostname }, /* 74 = sethostname */
+ { 2, s(struct compat_43_sys_setrlimit_args),
+ compat_43_sys_setrlimit }, /* 75 = setrlimit */
+ { 2, s(struct compat_43_sys_getrlimit_args),
+ compat_43_sys_getrlimit }, /* 76 = getrlimit */
+ { 2, s(struct sys_getrusage_args),
+ sys_getrusage }, /* 77 = getrusage */
+ { 2, s(struct sys_gettimeofday_args),
+ sys_gettimeofday }, /* 78 = gettimeofday */
+ { 2, s(struct sys_settimeofday_args),
+ sys_settimeofday }, /* 79 = settimeofday */
+ { 2, s(struct sys_getgroups_args),
+ sys_getgroups }, /* 80 = getgroups */
+ { 2, s(struct sys_setgroups_args),
+ sys_setgroups }, /* 81 = setgroups */
+ { 1, s(struct linux_sys_oldselect_args),
+ linux_sys_oldselect }, /* 82 = oldselect */
+ { 2, s(struct linux_sys_symlink_args),
+ linux_sys_symlink }, /* 83 = symlink */
+ { 2, s(struct compat_43_sys_lstat_args),
+ compat_43_sys_lstat }, /* 84 = olstat */
+ { 3, s(struct linux_sys_readlink_args),
+ linux_sys_readlink }, /* 85 = readlink */
+ { 1, s(struct linux_sys_uselib_args),
+ linux_sys_uselib }, /* 86 = uselib */
+ { 1, s(struct sys_swapon_args),
+ sys_swapon }, /* 87 = swapon */
+ { 1, s(struct sys_reboot_args),
+ sys_reboot }, /* 88 = reboot */
+ { 3, s(struct linux_sys_readdir_args),
+ linux_sys_readdir }, /* 89 = readdir */
+ { 1, s(struct linux_sys_mmap_args),
+ linux_sys_mmap }, /* 90 = mmap */
+ { 2, s(struct sys_munmap_args),
+ sys_munmap }, /* 91 = munmap */
+ { 2, s(struct linux_sys_truncate_args),
+ linux_sys_truncate }, /* 92 = truncate */
+ { 2, s(struct compat_43_sys_ftruncate_args),
+ compat_43_sys_ftruncate }, /* 93 = ftruncate */
+ { 2, s(struct sys_fchmod_args),
+ sys_fchmod }, /* 94 = fchmod */
+ { 3, s(struct linux_sys_fchown_args),
+ linux_sys_fchown }, /* 95 = fchown */
+ { 2, s(struct sys_getpriority_args),
+ sys_getpriority }, /* 96 = getpriority */
+ { 3, s(struct sys_setpriority_args),
+ sys_setpriority }, /* 97 = setpriority */
+ { 4, s(struct sys_profil_args),
+ sys_profil }, /* 98 = profil */
+ { 2, s(struct linux_sys_statfs_args),
+ linux_sys_statfs }, /* 99 = statfs */
+ { 2, s(struct linux_sys_fstatfs_args),
+ linux_sys_fstatfs }, /* 100 = fstatfs */
+#ifdef __i386__
+ { 3, s(struct linux_sys_ioperm_args),
+ linux_sys_ioperm }, /* 101 = ioperm */
+#else
+ { 0, 0,
+ sys_nosys }, /* 101 = unimplemented ioperm */
+#endif
+ { 2, s(struct linux_sys_socketcall_args),
+ linux_sys_socketcall }, /* 102 = socketcall */
+ { 0, 0,
+ sys_nosys }, /* 103 = unimplemented klog */
+ { 3, s(struct sys_setitimer_args),
+ sys_setitimer }, /* 104 = setitimer */
+ { 2, s(struct sys_getitimer_args),
+ sys_getitimer }, /* 105 = getitimer */
+ { 2, s(struct linux_sys_stat_args),
+ linux_sys_stat }, /* 106 = stat */
+ { 2, s(struct linux_sys_lstat_args),
+ linux_sys_lstat }, /* 107 = lstat */
+ { 2, s(struct linux_sys_fstat_args),
+ linux_sys_fstat }, /* 108 = fstat */
+ { 1, s(struct linux_sys_olduname_args),
+ linux_sys_olduname }, /* 109 = olduname */
+#ifdef __i386__
+ { 1, s(struct linux_sys_iopl_args),
+ linux_sys_iopl }, /* 110 = iopl */
+#else
+ { 0, 0,
+ sys_nosys }, /* 110 = unimplemented iopl */
+#endif
+ { 0, 0,
+ sys_nosys }, /* 111 = unimplemented vhangup */
+ { 0, 0,
+ sys_nosys }, /* 112 = unimplemented idle */
+ { 0, 0,
+ sys_nosys }, /* 113 = unimplemented vm86 */
+ { 4, s(struct linux_sys_wait4_args),
+ linux_sys_wait4 }, /* 114 = wait4 */
+ { 0, 0,
+ sys_nosys }, /* 115 = unimplemented swapoff */
+ { 0, 0,
+ sys_nosys }, /* 116 = unimplemented sysinfo */
+ { 5, s(struct linux_sys_ipc_args),
+ linux_sys_ipc }, /* 117 = ipc */
+ { 1, s(struct sys_fsync_args),
+ sys_fsync }, /* 118 = fsync */
+ { 1, s(struct linux_sys_sigreturn_args),
+ linux_sys_sigreturn }, /* 119 = sigreturn */
+ { 0, 0,
+ sys_nosys }, /* 120 = unimplemented clone */
+ { 2, s(struct compat_09_sys_setdomainname_args),
+ compat_09_sys_setdomainname }, /* 121 = setdomainname */
+ { 1, s(struct linux_sys_uname_args),
+ linux_sys_uname }, /* 122 = uname */
+#ifdef __i386__
+ { 3, s(struct linux_sys_modify_ldt_args),
+ linux_sys_modify_ldt }, /* 123 = modify_ldt */
+#else
+ { 0, 0,
+ sys_nosys }, /* 123 = unimplemented modify_ldt */
+#endif
+ { 0, 0,
+ sys_nosys }, /* 124 = unimplemented adjtimex */
+ { 3, s(struct sys_mprotect_args),
+ sys_mprotect }, /* 125 = mprotect */
+ { 3, s(struct linux_sys_sigprocmask_args),
+ linux_sys_sigprocmask }, /* 126 = sigprocmask */
+ { 0, 0,
+ sys_nosys }, /* 127 = unimplemented create_module */
+ { 0, 0,
+ sys_nosys }, /* 128 = unimplemented init_module */
+ { 0, 0,
+ sys_nosys }, /* 129 = unimplemented delete_module */
+ { 0, 0,
+ sys_nosys }, /* 130 = unimplemented get_kernel_syms */
+ { 0, 0,
+ sys_nosys }, /* 131 = unimplemented quotactl */
+ { 1, s(struct linux_sys_getpgid_args),
+ linux_sys_getpgid }, /* 132 = getpgid */
+ { 1, s(struct sys_fchdir_args),
+ sys_fchdir }, /* 133 = fchdir */
+ { 0, 0,
+ sys_nosys }, /* 134 = unimplemented bdflush */
+ { 0, 0,
+ sys_nosys }, /* 135 = unimplemented sysfs */
+ { 1, s(struct linux_sys_personality_args),
+ linux_sys_personality }, /* 136 = personality */
+ { 0, 0,
+ sys_nosys }, /* 137 = unimplemented afs_syscall */
+ { 0, 0,
+ sys_nosys }, /* 138 = unimplemented setfsuid */
+ { 0, 0,
+ sys_nosys }, /* 139 = unimplemented getfsuid */
+ { 5, s(struct linux_sys_llseek_args),
+ linux_sys_llseek }, /* 140 = llseek */
+ { 3, s(struct linux_sys_getdents_args),
+ linux_sys_getdents }, /* 141 = getdents */
+ { 5, s(struct linux_sys_select_args),
+ linux_sys_select }, /* 142 = select */
+ { 2, s(struct sys_flock_args),
+ sys_flock }, /* 143 = flock */
+};
+
diff --git a/sys/compat/linux/linux_types.h b/sys/compat/linux/linux_types.h
new file mode 100644
index 00000000000..c931a2ab560
--- /dev/null
+++ b/sys/compat/linux/linux_types.h
@@ -0,0 +1,151 @@
+/* $NetBSD: linux_types.h,v 1.4 1995/08/21 03:42:11 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 for the NetBSD Project
+ * by Frank van der Linden
+ * 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.
+ */
+
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+typedef struct {
+ long val[2];
+} linux_fsid_t;
+
+typedef unsigned short linux_uid_t;
+typedef unsigned short linux_gid_t;
+typedef unsigned short linux_dev_t;
+typedef unsigned long linux_ino_t;
+typedef unsigned short linux_mode_t;
+typedef unsigned short linux_nlink_t;
+typedef long linux_time_t;
+typedef long linux_clock_t;
+typedef long linux_off_t;
+typedef int linux_pid_t;
+
+struct linux_statfs {
+ long l_ftype;
+ long l_fbsize;
+ long l_fblocks;
+ long l_fbfree;
+ long l_fbavail;
+ long l_ffiles;
+ long l_fffree;
+ linux_fsid_t l_ffsid;
+ long l_fnamelen;
+ long l_fspare[6];
+};
+
+/*
+ * Structure for uname(2)
+ */
+struct linux_utsname {
+ char l_sysname[65];
+ char l_nodename[65];
+ char l_release[65];
+ char l_version[65];
+ char l_machine[65];
+ char l_domainname[65];
+};
+
+struct linux_oldutsname {
+ char l_sysname[65];
+ char l_nodename[65];
+ char l_release[65];
+ char l_version[65];
+ char l_machine[65];
+};
+
+struct linux_oldoldutsname {
+ char l_sysname[9];
+ char l_nodename[9];
+ char l_release[9];
+ char l_version[9];
+ char l_machine[9];
+};
+
+/*
+ * Passed to the mmap() system call
+ */
+struct linux_mmap {
+ caddr_t lm_addr;
+ int lm_len;
+ int lm_prot;
+ int lm_flags;
+ int lm_fd;
+ int lm_pos;
+};
+
+/*
+ * Passed to the select() system call
+ */
+struct linux_select {
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ struct timeval *timeout;
+};
+
+struct linux_stat {
+ linux_dev_t lst_dev;
+ unsigned short pad1;
+ linux_ino_t lst_ino;
+ linux_mode_t lst_mode;
+ linux_nlink_t lst_nlink;
+ linux_uid_t lst_uid;
+ linux_gid_t lst_gid;
+ linux_dev_t lst_rdev;
+ unsigned short pad2;
+ linux_off_t lst_size;
+ unsigned long lst_blksize;
+ unsigned long lst_blocks;
+ linux_time_t lst_atime;
+ unsigned long unused1;
+ linux_time_t lst_mtime;
+ unsigned long unused2;
+ linux_time_t lst_ctime;
+ unsigned long unused3;
+ unsigned long unused4;
+ unsigned long unused5;
+};
+
+struct linux_tms {
+ linux_clock_t ltms_utime;
+ linux_clock_t ltms_stime;
+ linux_clock_t ltms_cutime;
+ linux_clock_t ltms_cstime;
+};
+
+struct linux_utimbuf {
+ linux_time_t l_actime;
+ linux_time_t l_modtime;
+};
+
+#endif /* !_LINUX_TYPES_H */
diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h
new file mode 100644
index 00000000000..72fcdbd62c1
--- /dev/null
+++ b/sys/compat/linux/linux_util.h
@@ -0,0 +1,48 @@
+/* $NetBSD: linux_util.h,v 1.5 1995/06/24 20:20:42 christos Exp $ */
+
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * 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 _LINUX_UTIL_H_
+#define _LINUX_UTIL_H_
+
+#include <compat/common/compat_util.h>
+
+#define cvtto_linux_mask(flags,bmask,lmask) (((flags) & bmask) ? lmask : 0)
+#define cvtto_bsd_mask(flags,lmask,bmask) (((flags) & lmask) ? bmask : 0)
+
+extern const char linux_emul_path[];
+
+#define LINUX_CHECK_ALT_EXIST(p, sgp, path) \
+ CHECK_ALT_EXIST(p, sgp, linux_emul_path, path)
+
+#define LINUX_CHECK_ALT_CREAT(p, sgp, path) \
+ CHECK_ALT_CREAT(p, sgp, linux_emul_path, path)
+
+#endif /* !_LINUX_UTIL_H_ */
diff --git a/sys/compat/linux/syscalls.conf b/sys/compat/linux/syscalls.conf
new file mode 100644
index 00000000000..3b8796db129
--- /dev/null
+++ b/sys/compat/linux/syscalls.conf
@@ -0,0 +1,12 @@
+# $NetBSD: syscalls.conf,v 1.1 1995/02/28 23:26:24 fvdl Exp $
+
+sysnames="linux_syscalls.c"
+sysnumhdr="linux_syscall.h"
+syssw="linux_sysent.c"
+sysarghdr="linux_syscallargs.h"
+compatopts=""
+libcompatopts=""
+
+switchname="linux_sysent"
+namesname="linux_syscallnames"
+constprefix="LINUX_SYS_"
diff --git a/sys/compat/linux/syscalls.master b/sys/compat/linux/syscalls.master
new file mode 100644
index 00000000000..20241fba899
--- /dev/null
+++ b/sys/compat/linux/syscalls.master
@@ -0,0 +1,235 @@
+ $NetBSD: syscalls.master,v 1.13 1995/10/07 06:27:15 mycroft Exp $
+
+; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
+
+; NetBSD COMPAT_LINUX system call name/number "master" file.
+; (See syscalls.conf to see what it is processed into.)
+;
+; Fields: number type [type-dependent ...]
+; number system call number, must be in order
+; type one of STD, OBSOL, UNIMPL, NODEF, NOARGS, or one of
+; the compatibility options defined in syscalls.conf.
+;
+; types:
+; STD always included
+; OBSOL obsolete, not included in system
+; UNIMPL unimplemented, not included in system
+; NODEF included, but don't define the syscall number
+; NOARGS included, but don't define the syscall args structure
+;
+; The compat options are defined in the syscalls.conf file, and the
+; compat option name is prefixed to the syscall name. Other than
+; that, they're like NODEF (for 'compat' options), or STD (for
+; 'libcompat' options).
+;
+; The type-dependent arguments are as follows:
+; For STD, NODEF, NOARGS, and compat syscalls:
+; { pseudo-proto } [alias]
+; For other syscalls:
+; [comment]
+;
+; #ifdef's, etc. may be included, and are copied to the output files.
+; #include's are copied to the syscall switch definition file only.
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signal.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+
+#include <machine/linux_machdep.h>
+
+0 NOARGS { int sys_nosys(void); } syscall
+1 NOARGS { int sys_exit(int rval); }
+2 STD { int linux_sys_fork(void); }
+3 NOARGS { int sys_read(int fd, char *buf, u_int nbyte); }
+4 NOARGS { int sys_write(int fd, char *buf, u_int nbyte); }
+5 STD { int linux_sys_open(char *path, int flags, int mode); }
+6 NOARGS { int sys_close(int fd); }
+7 STD { int linux_sys_waitpid(int pid, int *status, \
+ int options);}
+8 STD { int linux_sys_creat(char *path, int mode); }
+9 NOARGS { int sys_link(char *path, char *link); }
+10 STD { int linux_sys_unlink(char *path); }
+11 STD { int linux_sys_execve(char *path, char **argp, \
+ char **envp); }
+12 STD { int linux_sys_chdir(char *path); }
+13 STD { int linux_sys_time(linux_time_t *t); }
+14 STD { int linux_sys_mknod(char *path, int mode, int dev); }
+15 STD { int linux_sys_chmod(char *path, int mode); }
+16 STD { int linux_sys_chown(char *path, int uid, int gid); }
+17 STD { int linux_sys_break(char *nsize); }
+18 OBSOL ostat
+19 NOARGS { long compat_43_sys_lseek(int fd, long offset, \
+ int whence); }
+20 NOARGS { pid_t sys_getpid(void); }
+21 UNIMPL mount
+22 UNIMPL umount
+23 NOARGS { int sys_setuid(uid_t uid); }
+24 NOARGS { uid_t sys_getuid(void); }
+25 UNIMPL stime
+26 UNIMPL ptrace
+27 STD { int linux_sys_alarm(unsigned int secs); }
+28 OBSOL ofstat
+29 STD { int linux_sys_pause(void); }
+30 STD { int linux_sys_utime(char *path, \
+ struct linux_utimbuf *times); }
+31 UNIMPL stty
+32 UNIMPL gtty
+33 STD { int linux_sys_access(char *path, int flags); }
+34 UNIMPL nice
+35 UNIMPL ftime
+36 NOARGS { int sys_sync(void); }
+37 STD { int linux_sys_kill(int pid, int signum); }
+38 STD { int linux_sys_rename(char *from, char *to); }
+39 STD { int linux_sys_mkdir(char *path, int mode); }
+40 STD { int linux_sys_rmdir(char *path); }
+41 NOARGS { int sys_dup(u_int fd); }
+42 STD { int linux_sys_pipe(int *pfds); }
+43 STD { int linux_sys_times(struct times *tms); }
+44 UNIMPL prof
+45 STD { int linux_sys_brk(char *nsize); }
+46 NOARGS { int sys_setgid(gid_t gid); }
+47 NOARGS { gid_t sys_getgid(void); }
+48 STD { int linux_sys_signal(int sig, \
+ linux_handler_t handler); }
+49 NOARGS { uid_t sys_geteuid(void); }
+50 NOARGS { gid_t sys_getegid(void); }
+51 NOARGS { int sys_acct(char *path); }
+52 UNIMPL phys
+53 UNIMPL lock
+54 STD { int linux_sys_ioctl(int fd, u_long com, \
+ caddr_t data); }
+55 STD { int linux_sys_fcntl(int fd, int cmd, void *arg); }
+56 UNIMPL mpx
+57 NOARGS { int sys_setpgid(int pid, int pgid); }
+58 UNIMPL ulimit
+59 STD { int linux_sys_oldolduname(struct linux_oldold_utsname *up); }
+60 NOARGS { int sys_umask(int newmask); }
+61 NOARGS { int sys_chroot(char *path); }
+62 UNIMPL ustat
+63 NOARGS { int sys_dup2(u_int from, u_int to); }
+64 NOARGS { pid_t sys_getppid(void); }
+65 NOARGS { int sys_getpgrp(void); }
+66 NOARGS { int sys_setsid(void); }
+67 STD { int linux_sys_sigaction(int signum, \
+ struct linux_sigaction *nsa, \
+ struct linux_sigaction *osa); }
+68 STD { int linux_sys_siggetmask(void); }
+69 STD { int linux_sys_sigsetmask(linux_sigset_t mask); }
+70 STD { int linux_sys_setreuid(int ruid, int euid); }
+71 STD { int linux_sys_setregid(int rgid, int egid); }
+72 STD { int linux_sys_sigsuspend(caddr_t restart, \
+ int oldmask, int mask); }
+73 STD { int linux_sys_sigpending(linux_sigset_t *mask); }
+74 NOARGS { int compat_43_sys_sethostname(char *hostname, \
+ u_int len);}
+75 NOARGS { int compat_43_sys_setrlimit(u_int which, \
+ struct ogetrlimit *rlp); }
+76 NOARGS { int compat_43_sys_getrlimit(u_int which, \
+ struct ogetrlimit *rlp); }
+77 NOARGS { int sys_getrusage(int who, struct rusage *rusage); }
+78 NOARGS { int sys_gettimeofday(struct timeval *tp, \
+ struct timezone *tzp); }
+79 NOARGS { int sys_settimeofday(struct timeval *tp, \
+ struct timezone *tzp); }
+80 NOARGS { int sys_getgroups(u_int gidsetsize, gid_t *gidset); }
+81 NOARGS { int sys_setgroups(u_int gidsetsize, gid_t *gidset); }
+82 STD { int linux_sys_oldselect(struct linux_select *lsp); }
+83 STD { int linux_sys_symlink(char *path, char *to); }
+84 NOARGS { int compat_43_sys_lstat(char *path, \
+ struct ostat *up); } olstat
+85 STD { int linux_sys_readlink(char *name, char *buf, \
+ int count); }
+86 STD { int linux_sys_uselib(char *path); }
+87 NOARGS { int sys_swapon(char *name); }
+88 NOARGS { int sys_reboot(int opt); }
+89 STD { int linux_sys_readdir(int fd, caddr_t dent, \
+ unsigned int count); }
+90 STD { int linux_sys_mmap(struct linux_mmap *lmp); }
+91 NOARGS { int sys_munmap(caddr_t addr, int len); }
+92 STD { int linux_sys_truncate(char *path, long length); }
+93 NOARGS { int compat_43_sys_ftruncate(int fd, long length); }
+94 NOARGS { int sys_fchmod(int fd, int mode); }
+95 STD { int linux_sys_fchown(int fd, int uid, int gid); }
+96 NOARGS { int sys_getpriority(int which, int who); }
+97 NOARGS { int sys_setpriority(int which, int who, int prio); }
+98 NOARGS { int sys_profil(caddr_t samples, u_int size, \
+ u_int offset, u_int scale); }
+99 STD { int linux_sys_statfs(char *path, \
+ struct linux_statfs *sp); }
+100 STD { int linux_sys_fstatfs(int fd, \
+ struct linux_statfs *sp); }
+#ifdef __i386__
+101 STD { int linux_sys_ioperm(unsigned int lo, \
+ unsigned int hi, int val); }
+#else
+101 UNIMPL ioperm
+#endif
+102 STD { int linux_sys_socketcall(int what, void *args); }
+103 UNIMPL klog
+104 NOARGS { int sys_setitimer(u_int which, \
+ struct itimerval *itv, struct itimerval *oitv); }
+105 NOARGS { int sys_getitimer(u_int which, \
+ struct itimerval *itv); }
+106 STD { int linux_sys_stat(char *path, \
+ struct linux_stat *sp); }
+107 STD { int linux_sys_lstat(char *path, \
+ struct linux_stat *sp); }
+108 STD { int linux_sys_fstat(int fd, struct linux_stat *sp); }
+109 STD { int linux_sys_olduname(struct linux_old_utsname *up); }
+#ifdef __i386__
+110 STD { int linux_sys_iopl(int level); }
+#else
+110 UNIMPL iopl
+#endif
+111 UNIMPL vhangup
+112 UNIMPL idle
+113 UNIMPL vm86
+114 STD { int linux_sys_wait4(int pid, int *status, \
+ int options, struct rusage *rusage); }
+115 UNIMPL swapoff
+116 UNIMPL sysinfo
+117 STD { int linux_sys_ipc(int what, int a1, int a2, int a3, \
+ caddr_t ptr); }
+118 NOARGS { int sys_fsync(int fd); }
+119 STD { int linux_sys_sigreturn(struct linux_sigcontext *scp); }
+120 UNIMPL clone
+121 NOARGS { int compat_09_sys_setdomainname(char *name, \
+ int len); }
+122 STD { int linux_sys_uname(struct linux_utsname *up); }
+#ifdef __i386__
+123 STD { int linux_sys_modify_ldt(int func, void *ptr, \
+ size_t bytecount); }
+#else
+123 UNIMPL modify_ldt
+#endif
+124 UNIMPL adjtimex
+125 NOARGS { int sys_mprotect(caddr_t addr, int len, int prot); }
+126 STD { int linux_sys_sigprocmask(int how, \
+ linux_sigset_t *set, linux_sigset_t *oset); }
+127 UNIMPL create_module
+128 UNIMPL init_module
+129 UNIMPL delete_module
+130 UNIMPL get_kernel_syms
+131 UNIMPL quotactl
+132 STD { int linux_sys_getpgid(int pid); }
+133 NOARGS { int sys_fchdir(int fd); }
+134 UNIMPL bdflush
+135 UNIMPL sysfs
+136 STD { int linux_sys_personality(int per); }
+137 UNIMPL afs_syscall
+138 UNIMPL setfsuid
+139 UNIMPL getfsuid
+140 STD { int linux_sys_llseek(int fd, u_int32_t ohigh, \
+ u_int32_t olow, caddr_t res, int whence); }
+141 STD { int linux_sys_getdents(int fd, void *dirent, \
+ unsigned count); }
+142 STD { int linux_sys_select(int nfds, fd_set *readfds, \
+ fd_set *writefds, fd_set *exceptfds, \
+ struct timeval *timeout); }
+143 NOARGS { int sys_flock(int fd, int how); }