summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>1995-06-25 17:32:43 +0000
committersos <sos@FreeBSD.org>1995-06-25 17:32:43 +0000
commitf14ea10694ed07a2d0627c9efa2b79c03b19639d (patch)
treea104b48d590fdc08acc1a23e9f4430c22923749e /sys
parentc54e2295b7f2db09802e0bc1874072840e4d75f7 (diff)
downloadFreeBSD-src-f14ea10694ed07a2d0627c9efa2b79c03b19639d.zip
FreeBSD-src-f14ea10694ed07a2d0627c9efa2b79c03b19639d.tar.gz
First incarnation of our Linux emulator or rather compatibility code.
This first shot only incorporaties so much functionality that DOOM can run (the X version), signal handling is VERY weak, so is many other things. But it meets my milestone number one (you guessed it - running DOOM). Uses /compat/linux as prefix for loading shared libs, so it won't conflict with our own libs. Kernel must be compiled with "options COMPAT_LINUX" for this to work.
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/linux/linux.h406
-rw-r--r--sys/alpha/linux/linux_dummy.c316
-rw-r--r--sys/compat/linux/linux_file.c436
-rw-r--r--sys/compat/linux/linux_ioctl.c495
-rw-r--r--sys/compat/linux/linux_ipc.c308
-rw-r--r--sys/compat/linux/linux_misc.c660
-rw-r--r--sys/compat/linux/linux_signal.c259
-rw-r--r--sys/compat/linux/linux_socket.c595
-rw-r--r--sys/compat/linux/linux_stats.c273
-rw-r--r--sys/i386/linux/imgact_linux.c235
-rw-r--r--sys/i386/linux/linux.h406
-rw-r--r--sys/i386/linux/linux_dummy.c316
-rw-r--r--sys/i386/linux/linux_file.c436
-rw-r--r--sys/i386/linux/linux_generic.c63
-rw-r--r--sys/i386/linux/linux_ioctl.c495
-rw-r--r--sys/i386/linux/linux_ipc.c308
-rw-r--r--sys/i386/linux/linux_misc.c660
-rw-r--r--sys/i386/linux/linux_signal.c259
-rw-r--r--sys/i386/linux/linux_socket.c595
-rw-r--r--sys/i386/linux/linux_stats.c273
-rw-r--r--sys/i386/linux/linux_sysent.c367
-rw-r--r--sys/modules/Makefile4
-rw-r--r--sys/modules/linux/Makefile16
-rw-r--r--sys/modules/linux/linux3
-rw-r--r--sys/modules/linux/linux.c58
-rw-r--r--sys/modules/linux/linux.sh3
26 files changed, 8243 insertions, 2 deletions
diff --git a/sys/alpha/linux/linux.h b/sys/alpha/linux/linux.h
new file mode 100644
index 0000000..9d13bd1
--- /dev/null
+++ b/sys/alpha/linux/linux.h
@@ -0,0 +1,406 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux.h,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#ifndef LINUX_H
+#define LINUX_H
+
+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 char * linux_caddr_t;
+typedef long linux_off_t;
+typedef struct {
+ long val[2];
+} linux_fsid_t;
+typedef int linux_pid_t;
+typedef unsigned long linux_sigset_t;
+typedef void (*linux_handler_t)(int);
+typedef struct {
+ void (*sa_handler)(int);
+ linux_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+} linux_sigaction_t;
+typedef int linux_key_t;
+
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
+/* misc defines */
+#define LINUX_NAME_MAX 255
+
+/* signal numbers */
+#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_SIGUNUSED 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_SIGIO 23
+#define LINUX_SIGPOLL LINUX_SIGIO
+#define LINUX_SIGURG LINUX_SIGIO
+#define LINUX_SIGXCPU 24
+#define LINUX_SIGXFSZ 25
+#define LINUX_SIGVTALRM 26
+#define LINUX_SIGPROF 27
+#define LINUX_SIGWINCH 28
+#define LINUX_SIGLOST 29
+#define LINUX_SIGPWR 30
+#define LINUX_SIGBUS LINUX_SIGUNUSED
+#define LINUX_NSIG 32
+
+/* sigaction 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
+
+/* sigprocmask actions */
+#define LINUX_SIG_BLOCK 0
+#define LINUX_SIG_UNBLOCK 1
+#define LINUX_SIG_SETMASK 2
+
+/* termio commands */
+#define LINUX_TCGETS 0x5401
+#define LINUX_TCSETS 0x5402
+#define LINUX_TCSETSW 0x5403
+#define LINUX_TCSETSF 0x5404
+#define LINUX_TCGETA 0x5405
+#define LINUX_TCSETA 0x5406
+#define LINUX_TCSETAW 0x5407
+#define LINUX_TCSETAF 0x5408
+#define LINUX_TCSBRK 0x5409
+#define LINUX_TCXONC 0x540A
+#define LINUX_TCFLSH 0x540B
+#define LINUX_TIOCEXCL 0x540C
+#define LINUX_TIOCNXCL 0x540D
+#define LINUX_TIOCSCTTY 0x540E
+#define LINUX_TIOCGPGRP 0x540F
+#define LINUX_TIOCSPGRP 0x5410
+#define LINUX_TIOCOUTQ 0x5411
+#define LINUX_TIOCSTI 0x5412
+#define LINUX_TIOCGWINSZ 0x5413
+#define LINUX_TIOCSWINSZ 0x5414
+#define LINUX_TIOCMGET 0x5415
+#define LINUX_TIOCMBIS 0x5416
+#define LINUX_TIOCMBIC 0x5417
+#define LINUX_TIOCMSET 0x5418
+#define LINUX_TIOCGSOFTCAR 0x5419
+#define LINUX_TIOCSSOFTCAR 0x541A
+#define LINUX_FIONREAD 0x541B
+#define LINUX_TIOCINQ FIONREAD
+#define LINUX_TIOCLINUX 0x541C
+#define LINUX_TIOCCONS 0x541D
+#define LINUX_TIOCGSERIAL 0x541E
+#define LINUX_TIOCSSERIAL 0x541F
+#define LINUX_TIOCPKT 0x5420
+#define LINUX_FIONBIO 0x5421
+#define LINUX_TIOCNOTTY 0x5422
+#define LINUX_TIOCSETD 0x5423
+#define LINUX_TIOCGETD 0x5424
+#define LINUX_TCSBRKP 0x5425
+#define LINUX_TIOCTTYGSTRUCT 0x5426
+#define LINUX_FIONCLEX 0x5450
+#define LINUX_FIOCLEX 0x5451
+#define LINUX_FIOASYNC 0x5452
+#define LINUX_TIOCSERCONFIG 0x5453
+#define LINUX_TIOCSERGWILD 0x5454
+#define LINUX_TIOCSERSWILD 0x5455
+#define LINUX_TIOCGLCKTRMIOS 0x5456
+#define LINUX_TIOCSLCKTRMIOS 0x5457
+
+/* line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+/* Linux termio c_cc values */
+#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
+#define LINUX_NCC 8
+
+/* Linux termios c_cc values */
+#define LINUX_VSTART 8
+#define LINUX_VSTOP 9
+#define LINUX_VSUSP 10
+#define LINUX_VEOL 11
+#define LINUX_VREPRINT 12
+#define LINUX_VDISCARD 13
+#define LINUX_VWERASE 14
+#define LINUX_VLNEXT 15
+#define LINUX_VEOL2 16
+#define LINUX_NCCS 17
+
+/* 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
+
+#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_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
+
+/* open/fcntl flags */
+#define LINUX_O_RDONLY 00
+#define LINUX_O_WRONLY 01
+#define LINUX_O_RDWR 02
+#define LINUX_O_CREAT 0100
+#define LINUX_O_EXCL 0200
+#define LINUX_O_NOCTTY 0400
+#define LINUX_O_TRUNC 01000
+#define LINUX_O_APPEND 02000
+#define LINUX_O_NONBLOCK 04000
+#define LINUX_O_NDELAY LINUX_O_NONBLOCK
+#define LINUX_O_SYNC 010000
+#define LINUX_FASYNC 020000
+
+/* fcntl flags */
+#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
+
+/* mmap options */
+#define LINUX_MAP_SHARED 0x0001
+#define LINUX_MAP_PRIVATE 0x0002
+#define LINUX_MAP_FIXED 0x0010
+#define LINUX_MAP_ANON 0x0020
+
+/* SystemV ipc defines */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* Socket defines */
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+
+#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
+
+#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
+
+#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
+
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+
+#endif /* LINUX_H */
diff --git a/sys/alpha/linux/linux_dummy.c b/sys/alpha/linux/linux_dummy.c
new file mode 100644
index 0000000..13288ac
--- /dev/null
+++ b/sys/alpha/linux/linux_dummy.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_dummy.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/errno.h>
+#include <vm/vm.h>
+
+int
+linux_setup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): setup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_break(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): break() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_fstat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): fstat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_umount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): umount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ptrace(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ptrace() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_pause(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): pause() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_gtty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): gtty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_nice(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): nice() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ftime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ftime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_prof(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): prof() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_signal(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): signal() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_phys(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): phys() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_lock(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): lock() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mpx(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mpx() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ulimit(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ulimit() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_olduname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): olduname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ustat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ustat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ioperm(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ioperm() not supported\n", p->p_pid);
+ return 0; /* EINVAL SOS XXX */
+}
+
+int
+linux_syslog(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): syslog() not supported (BSD sigreturn)\n",p->p_pid);
+ return sigreturn(p, args, retval);
+}
+
+int
+linux_iopl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): iopl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vhangup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vhangup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_idle(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): idle() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vm86(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vm86() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_swapoff(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): swapoff() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sysinfo(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sysinfo() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sigreturn(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sigreturn() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_clone(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_uname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_modify_ldt(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): modify_ldt() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_adjtimex(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): adjtimex() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_create_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): create_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_init_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): init_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_delete_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): delete_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_get_kernel_syms(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): get_kernel_syms() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_quotactl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): quotactl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_bdflush(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): bdflush() not supported\n", p->p_pid);
+ return ENOSYS;
+}
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
new file mode 100644
index 0000000..b846068
--- /dev/null
+++ b/sys/compat/linux/linux_file.c
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_file.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/exec.h>
+#include <sys/dirent.h>
+#include <vm/vm.h>
+#include <ufs/ufs/dir.h>
+
+
+struct linux_creat_args {
+ char *path;
+ int mode;
+};
+
+int
+linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): creat(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+ bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
+ return open(p, &bsd_open_args, retval);
+}
+
+struct linux_open_args {
+ char *path;
+ int flags;
+ int mode;
+};
+
+int
+linux_open(struct proc *p, struct linux_open_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
+ p->p_pid, args->path, args->flags, args->mode);
+#endif
+ bsd_open_args.flags = 0;
+ if (args->flags & LINUX_O_RDONLY)
+ bsd_open_args.flags |= O_RDONLY;
+ if (args->flags & LINUX_O_WRONLY)
+ bsd_open_args.flags |= O_WRONLY;
+ if (args->flags & LINUX_O_RDWR)
+ bsd_open_args.flags |= O_RDWR;
+ if (args->flags & LINUX_O_NDELAY)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_O_APPEND)
+ bsd_open_args.flags |= O_APPEND;
+ if (args->flags & LINUX_O_SYNC)
+ bsd_open_args.flags |= O_FSYNC;
+ if (args->flags & LINUX_O_NONBLOCK)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_FASYNC)
+ bsd_open_args.flags |= O_ASYNC;
+ if (args->flags & LINUX_O_CREAT)
+ bsd_open_args.flags |= O_CREAT;
+ if (args->flags & LINUX_O_TRUNC)
+ bsd_open_args.flags |= O_TRUNC;
+ if (args->flags & LINUX_O_EXCL)
+ bsd_open_args.flags |= O_EXCL;
+ if (args->flags & LINUX_O_NOCTTY)
+ bsd_open_args.flags |= O_NOCTTY;
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+
+ error = open(p, &bsd_open_args, retval);
+ if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp = fdp->fd_ofiles[*retval];
+
+ if (fp->f_type == DTYPE_VNODE)
+ (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
+ }
+ return error;
+}
+
+struct linux_flock {
+ short l_type;
+ short l_whence;
+ linux_off_t l_start;
+ linux_off_t l_len;
+ linux_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
+}
+
+struct linux_fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
+{
+ int error, result;
+ struct fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+ } fcntl_args;
+ struct linux_flock linux_flock;
+ struct flock *bsd_flock =
+ (struct flock *)ua_alloc_init(sizeof(struct flock));
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ fcntl_args.fd = args->fd;
+ fcntl_args.arg = 0;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ fcntl_args.cmd = F_DUPFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFD:
+ fcntl_args.cmd = F_GETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETFD:
+ fcntl_args.cmd = F_SETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFL:
+ fcntl_args.cmd = F_GETFL;
+ error = fcntl(p, &fcntl_args, &result);
+ *retval = 0;
+ if (result & O_RDONLY) *retval |= LINUX_O_RDONLY;
+ if (result & O_WRONLY) *retval |= LINUX_O_WRONLY;
+ if (result & O_RDWR) *retval |= LINUX_O_RDWR;
+ if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND) *retval |= LINUX_O_APPEND;
+ if (result & O_FSYNC) *retval |= LINUX_O_SYNC;
+ return error;
+
+ case LINUX_F_SETFL:
+ if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
+ fcntl_args.cmd = F_SETFL;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ if (error = fcntl(p, &fcntl_args, retval))
+ return error;
+ bsd_to_linux_flock(bsd_flock, &linux_flock);
+ return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
+ sizeof(struct linux_flock));
+
+ case LINUX_F_SETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETLKW:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETOWN:
+ fcntl_args.cmd = F_SETOWN;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETOWN:
+ fcntl_args.cmd = F_GETOWN;
+ return fcntl(p, &fcntl_args, retval);
+ }
+ return EINVAL;
+}
+
+struct linux_lseek_args {
+ int fdes;
+ unsigned long off;
+ int whence;
+};
+
+int
+linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
+{
+
+ struct lseek_args {
+ int fdes;
+ int pad;
+ off_t off;
+ int whence;
+ } tmp_args;
+ off_t tmp_retval;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): lseek(%d, %d, %d)\n",
+ p->p_pid, args->fdes, args->off, args->whence);
+#endif
+ tmp_args.fdes = args->fdes;
+ tmp_args.off = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = lseek(p, &tmp_args, &tmp_retval);
+ *retval = (int)tmp_retval;
+ return error;
+}
+
+struct linux_dirent {
+ long dino;
+ linux_off_t doff;
+ unsigned short dreclen;
+ char dname[LINUX_NAME_MAX + 1];
+};
+
+#define LINUX_RECLEN(de,namlen) \
+ ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
+
+struct linux_readdir_args {
+ int fd;
+ struct linux_dirent *dent;
+ unsigned int count;
+};
+
+int
+linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct linux_dirent linux_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): readdir(%d, *, %d)\n",
+ p->p_pid, args->fd, args->count);
+#endif
+ if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ nbytes = sizeof (struct linux_dirent);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ buflen = max(va.va_blocksize, nbytes);
+ buf = malloc(buflen, 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;
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0);
+ if (error)
+ goto out;
+
+ inp = buf;
+ outp = (caddr_t) args->dent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) == 0)
+ goto eof;
+
+ while (len > 0) {
+ reclen = ((struct dirent *) inp)->d_reclen;
+ if (reclen & 3)
+ panic("linux_readdir");
+ off += reclen;
+ bdp = (struct dirent *) inp;
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ continue;
+ }
+ linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+ linux_dirent.dino = (long) bdp->d_fileno;
+ linux_dirent.doff = (linux_off_t) linuxreclen;
+ linux_dirent.dreclen = (u_short) bdp->d_namlen;
+ strcpy(linux_dirent.dname, bdp->d_name);
+ if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen)))
+ goto out;
+ inp += reclen;
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) args->dent)
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + linuxreclen;
+eof:
+ *retval = nbytes - resid;
+out:
+ VOP_UNLOCK(vp);
+ free(buf, M_TEMP);
+ return error;
+}
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
new file mode 100644
index 0000000..12adff4
--- /dev/null
+++ b/sys/compat/linux/linux_ioctl.c
@@ -0,0 +1,495 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ioctl.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <machine/console.h>
+
+
+struct linux_termios {
+ unsigned long c_iflag;
+ unsigned long c_oflag;
+ unsigned long c_cflag;
+ unsigned long c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCCS];
+};
+
+struct linux_winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+
+static struct speedtab sptab[] = {
+ { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 },
+ { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 },
+ { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 },
+ { 2400, 11 }, { 4800, 12 }, { 9600, 13 },
+ { 19200, 14 }, { 38400, 15 },
+ { 57600, 4097 }, { 115200, 4098 }, {-1, -1 }
+};
+
+static int
+linux_to_bsd_speed(int code, struct speedtab *table)
+{
+ for ( ; table->sp_code != -1; table++)
+ if (table->sp_code == code)
+ return (table->sp_speed);
+ return -1;
+}
+
+static int
+bsd_to_linux_speed(int speed, struct speedtab *table)
+{
+ for ( ; table->sp_speed != -1; table++)
+ if (table->sp_speed == speed)
+ return (table->sp_code);
+ return -1;
+}
+
+static void
+bsd_to_linux_termios(struct termios *bsd_termios,
+ struct linux_termios *linux_termios)
+{
+ int i, speed;
+
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+ linux_termios->c_iflag = 0;
+ if (bsd_termios->c_iflag & IGNBRK)
+ linux_termios->c_iflag |= LINUX_IGNBRK;
+ if (bsd_termios->c_iflag & BRKINT)
+ linux_termios->c_iflag |= LINUX_BRKINT;
+ if (bsd_termios->c_iflag & IGNPAR)
+ linux_termios->c_iflag |= LINUX_IGNPAR;
+ if (bsd_termios->c_iflag & PARMRK)
+ linux_termios->c_iflag |= LINUX_PARMRK;
+ if (bsd_termios->c_iflag & INPCK)
+ linux_termios->c_iflag |= LINUX_INPCK;
+ if (bsd_termios->c_iflag & ISTRIP)
+ linux_termios->c_iflag |= LINUX_ISTRIP;
+ if (bsd_termios->c_iflag & INLCR)
+ linux_termios->c_iflag |= LINUX_INLCR;
+ if (bsd_termios->c_iflag & IGNCR)
+ linux_termios->c_iflag |= LINUX_IGNCR;
+ if (bsd_termios->c_iflag & ICRNL)
+ linux_termios->c_iflag |= LINUX_ICRNL;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXANY;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXON;
+ if (bsd_termios->c_iflag & IXOFF)
+ linux_termios->c_iflag |= LINUX_IXOFF;
+ if (bsd_termios->c_iflag & IMAXBEL)
+ linux_termios->c_iflag |= LINUX_IMAXBEL;
+
+ linux_termios->c_oflag = 0;
+ if (bsd_termios->c_oflag & OPOST)
+ linux_termios->c_oflag |= LINUX_OPOST;
+ if (bsd_termios->c_oflag & ONLCR)
+ linux_termios->c_oflag |= LINUX_ONLCR;
+ if (bsd_termios->c_oflag & OXTABS)
+ linux_termios->c_oflag |= LINUX_XTABS;
+
+ linux_termios->c_cflag =
+ bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
+ linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
+ if (bsd_termios->c_cflag & CSTOPB)
+ linux_termios->c_cflag |= LINUX_CSTOPB;
+ if (bsd_termios->c_cflag & CREAD)
+ linux_termios->c_cflag |= LINUX_CREAD;
+ if (bsd_termios->c_cflag & PARENB)
+ linux_termios->c_cflag |= LINUX_PARENB;
+ if (bsd_termios->c_cflag & PARODD)
+ linux_termios->c_cflag |= LINUX_PARODD;
+ if (bsd_termios->c_cflag & HUPCL)
+ linux_termios->c_cflag |= LINUX_HUPCL;
+ if (bsd_termios->c_cflag & CLOCAL)
+ linux_termios->c_cflag |= LINUX_CLOCAL;
+ if (bsd_termios->c_cflag & CRTSCTS)
+ linux_termios->c_cflag |= LINUX_CRTSCTS;
+
+ linux_termios->c_lflag = 0;
+ if (bsd_termios->c_lflag & ISIG)
+ linux_termios->c_lflag |= LINUX_ISIG;
+ if (bsd_termios->c_lflag & ICANON)
+ linux_termios->c_lflag |= LINUX_ICANON;
+ if (bsd_termios->c_lflag & ECHO)
+ linux_termios->c_lflag |= LINUX_ECHO;
+ if (bsd_termios->c_lflag & ECHOE)
+ linux_termios->c_lflag |= LINUX_ECHOE;
+ if (bsd_termios->c_lflag & ECHOK)
+ linux_termios->c_lflag |= LINUX_ECHOK;
+ if (bsd_termios->c_lflag & ECHONL)
+ linux_termios->c_lflag |= LINUX_ECHONL;
+ if (bsd_termios->c_lflag & NOFLSH)
+ linux_termios->c_lflag |= LINUX_NOFLSH;
+ if (bsd_termios->c_lflag & TOSTOP)
+ linux_termios->c_lflag |= LINUX_TOSTOP;
+ if (bsd_termios->c_lflag & ECHOCTL)
+ linux_termios->c_lflag |= LINUX_ECHOCTL;
+ if (bsd_termios->c_lflag & ECHOPRT)
+ linux_termios->c_lflag |= LINUX_ECHOPRT;
+ if (bsd_termios->c_lflag & ECHOKE)
+ linux_termios->c_lflag |= LINUX_ECHOKE;
+ if (bsd_termios->c_lflag & FLUSHO)
+ linux_termios->c_lflag |= LINUX_FLUSHO;
+ if (bsd_termios->c_lflag & PENDIN)
+ linux_termios->c_lflag |= LINUX_PENDIN;
+ if (bsd_termios->c_lflag & IEXTEN)
+ linux_termios->c_lflag |= LINUX_IEXTEN;
+
+ for (i=0; i<LINUX_NCCS; i++)
+ linux_termios->c_cc[i] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
+ linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
+ linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
+ linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
+ linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
+ linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
+ linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
+ linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
+ linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
+ linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
+ linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
+ linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
+ linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
+ linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
+ linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
+ linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
+
+ linux_termios->c_line = 0;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+static void
+linux_to_bsd_termios(struct linux_termios *linux_termios,
+ struct termios *bsd_termios)
+{
+ int i, speed;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+ bsd_termios->c_iflag = 0;
+ if (linux_termios->c_iflag & LINUX_IGNBRK)
+ bsd_termios->c_iflag |= IGNBRK;
+ if (linux_termios->c_iflag & LINUX_BRKINT)
+ bsd_termios->c_iflag |= BRKINT;
+ if (linux_termios->c_iflag & LINUX_IGNPAR)
+ bsd_termios->c_iflag |= IGNPAR;
+ if (linux_termios->c_iflag & LINUX_PARMRK)
+ bsd_termios->c_iflag |= PARMRK;
+ if (linux_termios->c_iflag & LINUX_INPCK)
+ bsd_termios->c_iflag |= INPCK;
+ if (linux_termios->c_iflag & LINUX_ISTRIP)
+ bsd_termios->c_iflag |= ISTRIP;
+ if (linux_termios->c_iflag & LINUX_INLCR)
+ bsd_termios->c_iflag |= INLCR;
+ if (linux_termios->c_iflag & LINUX_IGNCR)
+ bsd_termios->c_iflag |= IGNCR;
+ if (linux_termios->c_iflag & LINUX_ICRNL)
+ bsd_termios->c_iflag |= ICRNL;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXANY;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXON;
+ if (linux_termios->c_iflag & LINUX_IXOFF)
+ bsd_termios->c_iflag |= IXOFF;
+ if (linux_termios->c_iflag & LINUX_IMAXBEL)
+ bsd_termios->c_iflag |= IMAXBEL;
+
+ bsd_termios->c_oflag = 0;
+ if (linux_termios->c_oflag & LINUX_OPOST)
+ bsd_termios->c_oflag |= OPOST;
+ if (linux_termios->c_oflag & LINUX_ONLCR)
+ bsd_termios->c_oflag |= ONLCR;
+ if (linux_termios->c_oflag & LINUX_XTABS)
+ bsd_termios->c_oflag |= OXTABS;
+
+ bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
+ if (linux_termios->c_cflag & LINUX_CSTOPB)
+ bsd_termios->c_cflag |= CSTOPB;
+ if (linux_termios->c_cflag & LINUX_PARENB)
+ bsd_termios->c_cflag |= PARENB;
+ if (linux_termios->c_cflag & LINUX_PARODD)
+ bsd_termios->c_cflag |= PARODD;
+ if (linux_termios->c_cflag & LINUX_HUPCL)
+ bsd_termios->c_cflag |= HUPCL;
+ if (linux_termios->c_cflag & LINUX_CLOCAL)
+ bsd_termios->c_cflag |= CLOCAL;
+ if (linux_termios->c_cflag & LINUX_CRTSCTS)
+ bsd_termios->c_cflag |= CRTSCTS;
+
+ bsd_termios->c_lflag = 0;
+ if (linux_termios->c_lflag & LINUX_ISIG)
+ bsd_termios->c_lflag |= ISIG;
+ if (linux_termios->c_lflag & LINUX_ICANON)
+ bsd_termios->c_lflag |= ICANON;
+ if (linux_termios->c_lflag & LINUX_ECHO)
+ bsd_termios->c_lflag |= ECHO;
+ if (linux_termios->c_lflag & LINUX_ECHOE)
+ bsd_termios->c_lflag |= ECHOE;
+ if (linux_termios->c_lflag & LINUX_ECHOK)
+ bsd_termios->c_lflag |= ECHOK;
+ if (linux_termios->c_lflag & LINUX_ECHONL)
+ bsd_termios->c_lflag |= ECHONL;
+ if (linux_termios->c_lflag & LINUX_NOFLSH)
+ bsd_termios->c_lflag |= NOFLSH;
+ if (linux_termios->c_lflag & LINUX_TOSTOP)
+ bsd_termios->c_lflag |= TOSTOP;
+ if (linux_termios->c_lflag & LINUX_ECHOCTL)
+ bsd_termios->c_lflag |= ECHOCTL;
+ if (linux_termios->c_lflag & LINUX_ECHOPRT)
+ bsd_termios->c_lflag |= ECHOPRT;
+ if (linux_termios->c_lflag & LINUX_ECHOKE)
+ bsd_termios->c_lflag |= ECHOKE;
+ if (linux_termios->c_lflag & LINUX_FLUSHO)
+ bsd_termios->c_lflag |= FLUSHO;
+ if (linux_termios->c_lflag & LINUX_PENDIN)
+ bsd_termios->c_lflag |= PENDIN;
+ if (linux_termios->c_lflag & IEXTEN)
+ bsd_termios->c_lflag |= IEXTEN;
+
+ for (i=0; i<NCCS; i++)
+ bsd_termios->c_cc[i] = _POSIX_VDISABLE;
+ bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
+ bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
+ bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
+ bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
+ bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
+ bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
+ bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
+ bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
+ bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
+ bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
+ bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
+ bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
+ bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
+ bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
+ bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
+ bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
+
+ bsd_termios->c_ispeed = bsd_termios->c_ospeed =
+ linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+
+struct linux_ioctl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
+{
+ struct termios bsd_termios;
+ struct winsize bsd_winsize;
+ struct linux_termios linux_termios;
+ struct linux_winsize linux_winsize;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ int (*func)();
+ int bsd_line, linux_line;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): ioctl(%d, %04x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == 0)
+ return EBADF;
+
+ if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
+ return EBADF;
+ }
+
+ func = fp->f_ops->fo_ioctl;
+ switch (args->cmd) {
+ case LINUX_TCGETS:
+ if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
+ return error;
+ bsd_to_linux_termios(&bsd_termios, &linux_termios);
+ return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
+ sizeof(linux_termios));
+
+ case LINUX_TCSETS:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSW:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSF:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TIOCGPGRP:
+ args->cmd = TIOCGPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSPGRP:
+ args->cmd = TIOCSPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCGWINSZ:
+ args->cmd = TIOCGWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSWINSZ:
+ args->cmd = TIOCSWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONREAD:
+ args->cmd = FIONREAD;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONBIO:
+ args->cmd = FIONBIO;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOASYNC:
+ args->cmd = FIOASYNC;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONCLEX:
+ args->cmd = FIONCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOCLEX:
+ args->cmd = FIOCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCEXCL:
+ args->cmd = TIOCEXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNXCL:
+ args->cmd = TIOCNXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCCONS:
+ args->cmd = TIOCCONS;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNOTTY:
+ args->cmd = TIOCNOTTY;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSETD:
+ switch (args->arg) {
+ case LINUX_N_TTY:
+ bsd_line = TTYDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_SLIP:
+ bsd_line = SLIPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_PPP:
+ bsd_line = PPPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ default:
+ return EINVAL;
+ }
+ break;
+
+ case LINUX_TIOCGETD:
+ bsd_line = TTYDISC;
+ if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p))
+ return error;
+ switch (bsd_line) {
+ case TTYDISC:
+ linux_line = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ linux_line = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ linux_line = LINUX_N_PPP;
+ break;
+ default:
+ return EINVAL;
+ }
+ return copyout(&linux_line, (caddr_t)args->arg,
+ sizeof(int));
+ }
+ uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
+ args->fd, (args->cmd&0xffff00)>>8,
+ (args->cmd&0xffff00)>>8, args->cmd&0xff);
+ return EINVAL;
+}
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
new file mode 100644
index 0000000..b38b229
--- /dev/null
+++ b/sys/compat/linux/linux_ipc.c
@@ -0,0 +1,308 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ipc.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+
+#include <vm/vm.h>
+
+struct linux_ipc_perm {
+ linux_key_t key;
+ unsigned short uid;
+ unsigned short gid;
+ unsigned short cuid;
+ unsigned short cgid;
+ unsigned short mode;
+ unsigned short seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
+{
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct linux_shmid_ds {
+ struct linux_ipc_perm shm_perm;
+ int shm_segsz;
+ linux_time_t shm_atime;
+ linux_time_t shm_dtime;
+ linux_time_t shm_ctime;
+ ushort shm_cpid;
+ ushort shm_lpid;
+ short shm_nattch;
+ ushort private1;
+ void *private2;
+ void *private3;
+};
+
+static void
+linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
+}
+
+struct linux_ipc_args {
+ int what;
+ int arg1;
+ int arg2;
+ int arg3;
+ caddr_t ptr;
+};
+
+int
+linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmat_args {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } bsd_args;
+ int error;
+
+ bsd_args.shmid = args->arg1;
+ bsd_args.shmaddr = args->ptr;
+ bsd_args.shmflg = args->arg2;
+ if ((error = shmat(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
+ return error;
+ retval[0] = 0;
+ return 0;
+}
+
+int
+linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmdt_args {
+ void *shmaddr;
+ } bsd_args;
+
+ bsd_args.shmaddr = args->ptr;
+ return shmdt(p, &bsd_args, retval);
+}
+
+int
+linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmget_args {
+ key_t key;
+ int size;
+ int shmflg;
+ } bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.size = args->arg2;
+ bsd_args.shmflg = args->arg3;
+ return shmget(p, &bsd_args, retval);
+}
+
+int
+linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmid_ds bsd_shmid;
+ struct linux_shmid_ds linux_shmid;
+ struct shmctl_args {
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+ } bsd_args;
+ int error;
+
+ switch (args->arg2) {
+ case LINUX_IPC_STAT:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_STAT;
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = shmctl(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+ return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
+
+ case LINUX_IPC_SET:
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_SET;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_RMID:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_RMID;
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_INFO:
+ case LINUX_SHM_STAT:
+ case LINUX_SHM_INFO:
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return EINVAL;
+ }
+}
+
+int
+linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ switch (args->what) {
+ case LINUX_SEMOP:
+ return linux_semop(p, args, retval);
+ case LINUX_SEMGET:
+ return linux_semget(p, args, retval);
+ case LINUX_SEMCTL:
+ return linux_semctl(p, args, retval);
+ case LINUX_MSGSND:
+ return linux_msgsnd(p, args, retval);
+ case LINUX_MSGRCV:
+ return linux_msgrcv(p, args, retval);
+ case LINUX_MSGGET:
+ return linux_msgget(p, args, retval);
+ case LINUX_MSGCTL:
+ return linux_msgctl(p, args, retval);
+ case LINUX_SHMAT:
+ return linux_shmat(p, args, retval);
+ case LINUX_SHMDT:
+ return linux_shmdt(p, args, retval);
+ case LINUX_SHMGET:
+ return linux_shmget(p, args, retval);
+ case LINUX_SHMCTL:
+ return linux_shmctl(p, args, retval);
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
new file mode 100644
index 0000000..bf40786
--- /dev/null
+++ b/sys/compat/linux/linux_misc.c
@@ -0,0 +1,660 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_misc.c,v 1.4 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/proc.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/imgact_aout.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+
+struct linux_alarm_args {
+ unsigned int secs;
+};
+
+int
+linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
+{
+ extern struct timeval time;
+ struct itimerval it, old_it;
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs);
+#endif
+ it.it_value.tv_sec = (long)args->secs;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ s = splclock();
+ old_it = p->p_realtimer;
+ if (timerisset(&old_it.it_value))
+ if (timercmp(&old_it.it_value, &time, <))
+ timerclear(&old_it.it_value);
+ else
+ timevalsub(&old_it.it_value, &time);
+ splx(s);
+ if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
+ return EINVAL;
+ s = splclock();
+ untimeout(realitexpire, (caddr_t)p);
+ if (timerisset(&it.it_value)) {
+ timevaladd(&it.it_value, &time);
+ timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
+ }
+ p->p_realtimer = it;
+ splx(s);
+ if (old_it.it_value.tv_usec)
+ old_it.it_value.tv_sec++;
+ *retval = old_it.it_value.tv_sec;
+ return 0;
+}
+
+struct linux_brk_args {
+ linux_caddr_t dsend;
+};
+
+int
+linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
+{
+#if 0
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ int error;
+ extern int swap_pager_full;
+
+ if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
+ return EINVAL;
+ if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
+ > p->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return ENOMEM;
+
+ old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
+ new = round_page((vm_offset_t)args->dsend);
+ *retval = old;
+ if ((new-old) > 0) {
+ if (swap_pager_full)
+ return ENOMEM;
+ error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE);
+ if (error)
+ return error;
+ vm->vm_dsize += btoc((new-old));
+ *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
+ }
+ return 0;
+#else
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ struct obreak_args {
+ vm_offset_t newsize;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend);
+#endif
+ old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
+ new = (vm_offset_t)args->dsend;
+ tmp.newsize = new;
+ if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval))
+ retval[0] = (int)new;
+ else
+ retval[0] = (int)old;
+
+ return 0;
+#endif
+}
+
+struct linux_uselib_args {
+ char *library;
+};
+
+int
+linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
+{
+ struct nameidata ni;
+ struct vnode *vnodep;
+ struct exec *a_out = 0;
+ struct vattr attr;
+ unsigned long vmaddr, virtual_offset, file_offset;
+ unsigned long buffer, bss_size;
+ char *ptr;
+ char path[MAXPATHLEN];
+ const char *prefix = "/compat/linux";
+ size_t sz, len;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
+#endif
+
+ for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ;
+ sz = MAXPATHLEN - (ptr - path);
+ if (error = copyinstr(args->library, ptr, sz, &len))
+ return error;
+ if (*ptr != '/')
+ return EINVAL;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path);
+#endif
+
+ NDINIT(&ni, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
+ if (error = namei(&ni))
+ return error;
+
+ vnodep = ni.ni_vp;
+ if (vnodep == NULL)
+ return ENOEXEC;
+
+ if (vnodep->v_writecount)
+ return ETXTBSY;
+
+ if (error = VOP_GETATTR(vnodep, &attr, p->p_ucred, p))
+ return error;
+
+ if ((vnodep->v_mount->mnt_flag & MNT_NOEXEC)
+ || ((attr.va_mode & 0111) == 0)
+ || (attr.va_type != VREG))
+ return ENOEXEC;
+
+ if (attr.va_size == 0)
+ return ENOEXEC;
+
+ if (error = VOP_ACCESS(vnodep, VEXEC, p->p_ucred, p))
+ return error;
+
+ if (error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p))
+ return error;
+
+ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, 1024,
+ VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vnodep, 0);
+ if (error)
+ return (error);
+
+ /*
+ * Is it a Linux binary ?
+ */
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413: /* ZMAGIC */
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314: /* QMAGIC */
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+
+ vnodep->v_flag |= VTEXT;
+ bss_size = round_page(a_out->a_bss);
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PGOFSET) {
+#ifdef DEBUG
+printf("uselib: Non page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text+data read/write/execute
+ */
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_text + a_out->a_data), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t)vnodep, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text + a_out->a_data);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_text + a_out->a_data + file_offset));
+
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr,
+ round_page(a_out->a_text + a_out->a_data),
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+printf("uselib: Page aligned binary %d\n", file_offset);
+#endif
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data,
+ VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)vnodep, file_offset);
+ if (error)
+ return (error);
+ }
+#ifdef DEBUG
+printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
+#endif
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + round_page(a_out->a_entry) +
+ round_page(a_out->a_text + a_out->a_data);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE);
+ if (error)
+ return error;
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr, bss_size,
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+struct linux_select_args {
+ void *ptr;
+};
+
+int
+linux_select(struct proc *p, struct linux_select_args *args, int *retval)
+{
+ struct {
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ struct timeval *timeout;
+ } linux_args;
+ struct {
+ unsigned int nd;
+ fd_set *in;
+ fd_set *ou;
+ fd_set *ex;
+ struct timeval *tv;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n",
+ p->p_pid, linux_args.nfds, linux_args.readfds,
+ linux_args.writefds, linux_args.exceptfds,
+ linux_args.timeout);
+#endif
+ bsd_args.nd = linux_args.nfds;
+ bsd_args.in = linux_args.readfds;
+ bsd_args.ou = linux_args.writefds;
+ bsd_args.ex = linux_args.exceptfds;
+ bsd_args.tv = linux_args.timeout;
+ return select(p, &bsd_args, retval);
+}
+
+struct linux_getpgid_args {
+ int pid;
+};
+
+int
+linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
+{
+ struct proc *curproc;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid);
+#endif
+ if (args->pid != p->p_pid) {
+ if (!(curproc = pfind(args->pid)))
+ return ESRCH;
+ }
+ else
+ curproc = p;
+ *retval = curproc->p_pgid;
+ return 0;
+}
+
+int
+linux_fork(struct proc *p, void *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fork()\n", p->p_pid);
+#endif
+ if (error = fork(p, args, retval))
+ return error;
+ if (retval[1] == 1)
+ retval[0] = 0;
+ return 0;
+}
+
+struct linux_mmap_args {
+ void *ptr;
+};
+
+int
+linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
+{
+ struct {
+ linux_caddr_t addr;
+ int len;
+ int prot;
+ int flags;
+ int fd;
+ int pos;
+ } linux_args;
+ struct {
+ caddr_t addr;
+ size_t len;
+ int prot;
+ int flags;
+ int fd;
+ long pad;
+ off_t pos;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
+ p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
+ linux_args.flags, linux_args.fd, linux_args.pos);
+#endif
+ bsd_args.flags = 0;
+ if (linux_args.flags & LINUX_MAP_SHARED)
+ bsd_args.flags |= MAP_SHARED;
+ if (linux_args.flags & LINUX_MAP_PRIVATE)
+ bsd_args.flags |= MAP_PRIVATE;
+ if (linux_args.flags & LINUX_MAP_FIXED)
+ bsd_args.flags |= MAP_FIXED;
+ if (linux_args.flags & LINUX_MAP_ANON)
+ bsd_args.flags |= MAP_ANON;
+ bsd_args.addr = linux_args.addr;
+ bsd_args.len = linux_args.len;
+ bsd_args.prot = linux_args.prot;
+ bsd_args.fd = linux_args.fd;
+ bsd_args.pos = linux_args.pos;
+ bsd_args.pad = 0;
+ return mmap(p, &bsd_args, retval);
+}
+
+struct linux_pipe_args {
+ int *pipefds;
+};
+
+int
+linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): pipe(*)\n", p->p_pid);
+#endif
+ if (error = pipe(p, 0, retval))
+ return error;
+ if (error = copyout(retval, args->pipefds, 2*sizeof(int)))
+ return error;
+ *retval = 0;
+ return 0;
+}
+
+struct linux_time_args {
+ linux_time_t *tm;
+};
+
+int
+linux_time(struct proc *p, struct linux_time_args *args, int *retval)
+{
+ struct timeval tv;
+ linux_time_t tm;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): time(*)\n", p->p_pid);
+#endif
+ microtime(&tv);
+ tm = tv.tv_sec;
+ if (error = copyout(&tm, args->tm, sizeof(linux_time_t)))
+ return error;
+ *retval = tv.tv_sec;
+ return 0;
+}
+
+struct linux_tms {
+ long tms_utime;
+ long tms_stime;
+ long tms_cutime;
+ long tms_cstime;
+};
+
+struct linux_tms_args {
+ char *buf;
+};
+
+int
+linux_times(struct proc *p, struct linux_tms_args *args, int *retval)
+{
+ extern int hz;
+ struct timeval tv;
+ struct linux_tms tms;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): times(*)\n", p->p_pid);
+#endif
+ tms.tms_utime = p->p_uticks;
+ tms.tms_stime = p->p_sticks;
+ tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000);
+ tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000);
+ microtime(&tv);
+ *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
+ return (copyout((caddr_t)&tms, (caddr_t)args->buf,
+ sizeof(struct linux_tms)));
+}
+
+struct linux_newuname_t {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+ char domainname[65];
+};
+
+struct linux_newuname_args {
+ char *buf;
+};
+
+int
+linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
+{
+ struct linux_newuname_t linux_newuname;
+ extern char ostype[], osrelease[], machine[];
+ extern char hostname[], domainname[];
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newuname(*)\n", p->p_pid);
+#endif
+ bzero(&linux_newuname, sizeof(struct linux_newuname_args));
+ strncpy(linux_newuname.sysname, ostype, 64);
+ strncpy(linux_newuname.nodename, hostname, 64);
+ strncpy(linux_newuname.release, osrelease, 64);
+ strncpy(linux_newuname.version, version, 64);
+ strncpy(linux_newuname.machine, machine, 64);
+ strncpy(linux_newuname.domainname, domainname, 64);
+ return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf,
+ sizeof(struct linux_newuname_t)));
+}
+
+struct linux_utime_args {
+ char *fname;
+ linux_time_t *timeptr;
+};
+
+int
+linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
+{
+ struct bsd_utimes_args {
+ char *fname;
+ struct timeval *tptr;
+ } bsdutimes;
+ struct timeval tv;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
+#endif
+ tv.tv_sec = (long)args->timeptr;
+ tv.tv_usec = 0;
+ bsdutimes.tptr = &tv;
+ bsdutimes.fname = args->fname;
+ return utimes(p, &bsdutimes, retval);
+}
+
+struct linux_waitpid_args {
+ int pid;
+ int *status;
+ int options;
+};
+
+int
+linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): waitpid(%d, *, %d)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = NULL;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
+
+struct linux_wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+};
+
+int
+linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): wait4(%d, *, %d, *)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = args->rusage;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
new file mode 100644
index 0000000..528bb62
--- /dev/null
+++ b/sys/compat/linux/linux_signal.c
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_signal.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/exec.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+
+#include <vm/vm.h>
+
+#include <i386/linux/linux.h>
+
+#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
+
+static sigset_t
+linux_to_bsd_sigmask(linux_sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= LINUX_NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (linux_to_bsd_signal[i]-1));
+ return new;
+}
+
+static linux_sigset_t
+bsd_to_linux_sigmask(sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (bsd_to_linux_signal[i]-1));
+ return new;
+}
+
+struct linux_sigaction_args {
+ int sig;
+ linux_sigaction_t *nsa;
+ linux_sigaction_t *osa;
+};
+
+int
+linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
+{
+ linux_sigaction_t linux_sa;
+ struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
+ struct sigaction_args {
+ int sig;
+ struct sigaction *nsa;
+ struct sigaction *osa;
+ } sa;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
+#endif
+ if (args->osa)
+ osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
+
+ if (args->nsa) {
+ nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
+ if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
+ return error;
+ bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
+ bsd_sa.sa_handler = linux_sa.sa_handler;
+ bsd_sa.sa_flags = 0;
+ if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
+ bsd_sa.sa_flags |= SA_NOCLDSTOP;
+ if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
+ bsd_sa.sa_flags |= SA_ONSTACK;
+ if (linux_sa.sa_flags & LINUX_SA_RESTART)
+ bsd_sa.sa_flags |= SA_RESTART;
+ if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
+ return error;
+ }
+ sa.sig = linux_to_bsd_signal[args->sig];
+ sa.nsa = nsa;
+ sa.osa = osa;
+ if ((error = sigaction(p, &sa, retval)))
+ return error;
+
+ if (args->osa) {
+ if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
+ return error;
+ linux_sa.sa_handler = bsd_sa.sa_handler;
+ linux_sa.sa_restorer = NULL;
+ linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
+ linux_sa.sa_flags = 0;
+ if (bsd_sa.sa_flags & SA_NOCLDSTOP)
+ linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsd_sa.sa_flags & SA_ONSTACK)
+ linux_sa.sa_flags |= LINUX_SA_ONSTACK;
+ if (bsd_sa.sa_flags & SA_RESTART)
+ linux_sa.sa_flags |= LINUX_SA_RESTART;
+ if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
+ return error;
+ }
+ return 0;
+}
+
+struct linux_sigprocmask_args {
+ int how;
+ linux_sigset_t *mask;
+ linux_sigset_t *omask;
+};
+
+int
+linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
+ int *retval)
+{
+ int error, s;
+ sigset_t mask;
+ sigset_t omask;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
+#endif
+ if (args->omask != NULL) {
+ omask = bsd_to_linux_sigmask(p->p_sigmask);
+ if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
+ return error;
+ }
+ if (!(args->mask))
+ return 0;
+ if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
+ return error;
+
+ mask = linux_to_bsd_sigmask(mask);
+ s = splhigh();
+ switch (args->how) {
+ case LINUX_SIG_BLOCK:
+ p->p_sigmask |= (mask & ~DONTMASK);
+ break;
+ case LINUX_SIG_UNBLOCK:
+ p->p_sigmask &= ~mask;
+ break;
+ case LINUX_SIG_SETMASK:
+ p->p_sigmask = (mask & ~DONTMASK);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(s);
+ return error;
+}
+
+int
+linux_siggetmask(struct proc *p, void *args, int *retval)
+{
+#ifdef DEBUG
+ printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
+#endif
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigsetmask_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
+{
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
+#endif
+ s = splhigh();
+ p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK);
+ splx(s);
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigpending_args {
+ linux_sigset_t *mask;
+};
+
+int
+linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
+{
+ linux_sigset_t linux_sig;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
+#endif
+ linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask);
+ return copyout(&linux_sig, args->mask, sizeof(linux_sig));
+}
+
+struct linux_sigsuspend_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
+{
+ sigset_t tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
+#endif
+ tmp = linux_to_bsd_sigmask(args->mask);
+ return sigsuspend(p, &tmp , retval);
+}
+
+struct linux_kill_args {
+ int pid;
+ int signum;
+};
+
+int
+linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
+{
+ struct {
+ int pid;
+ int signum;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): kill(%d, %d)\n",
+ p->p_pid, args->pid, args->signum);
+#endif
+ tmp.pid = args->pid;
+ tmp.signum = linux_to_bsd_signal[args->signum];
+ return kill(p, &tmp, retval);
+}
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
new file mode 100644
index 0000000..9267063
--- /dev/null
+++ b/sys/compat/linux/linux_socket.c
@@ -0,0 +1,595 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_socket.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <netinet/in.h>
+
+
+static int
+linux_to_bsd_domain(int domain)
+{
+ switch (domain) {
+ case LINUX_AF_UNSPEC:
+ return AF_UNSPEC;
+ case LINUX_AF_UNIX:
+ return AF_LOCAL;
+ case LINUX_AF_INET:
+ return AF_INET;
+ case LINUX_AF_AX25:
+ return AF_CCITT;
+ case LINUX_AF_IPX:
+ return AF_IPX;
+ case LINUX_AF_APPLETALK:
+ return AF_APPLETALK;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+ switch (level) {
+ case LINUX_SOL_SOCKET:
+ return SOL_SOCKET;
+ default:
+ return level;
+ }
+}
+
+static int linux_to_bsd_ip_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_IP_TOS:
+ return IP_TOS;
+ case LINUX_IP_TTL:
+ return IP_TTL;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_so_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_SO_DEBUG:
+ return SO_DEBUG;
+ case LINUX_SO_REUSEADDR:
+ return SO_REUSEADDR;
+ case LINUX_SO_TYPE:
+ return SO_TYPE;
+ case LINUX_SO_ERROR:
+ return SO_ERROR;
+ case LINUX_SO_DONTROUTE:
+ return SO_DONTROUTE;
+ case LINUX_SO_BROADCAST:
+ return SO_BROADCAST;
+ case LINUX_SO_SNDBUF:
+ return SO_SNDBUF;
+ case LINUX_SO_RCVBUF:
+ return SO_RCVBUF;
+ case LINUX_SO_KEEPALIVE:
+ return SO_KEEPALIVE;
+ case LINUX_SO_OOBINLINE:
+ return SO_OOBINLINE;
+ case LINUX_SO_LINGER:
+ return SO_LINGER;
+ case LINUX_SO_PRIORITY:
+ case LINUX_SO_NO_CHECK:
+ default:
+ return -1;
+ }
+}
+
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+static int
+linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
+{
+ struct linux_socket_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.type = linux_args.type;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ return socket(p, &bsd_args, retval);
+}
+
+struct linux_bind_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+static int
+linux_bind(struct proc *p, struct linux_bind_args *args, int *retval)
+{
+ struct linux_bind_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return bind(p, &bsd_args, retval);
+}
+
+struct linux_connect_args {
+ int s;
+ struct sockaddr * name;
+ int namelen;
+};
+
+static int
+linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
+{
+ struct linux_connect_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return connect(p, &bsd_args, retval);
+}
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+static int
+linux_listen(struct proc *p, struct linux_listen_args *args, int *retval)
+{
+ struct linux_listen_args linux_args;
+ struct {
+ int s;
+ int backlog;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.backlog = linux_args.backlog;
+ return listen(p, &bsd_args, retval);
+}
+
+struct linux_accept_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_accept(struct proc *p, struct linux_accept_args *args, int *retval)
+{
+ struct linux_accept_args linux_args;
+ struct accept_args {
+ int s;
+ caddr_t name;
+ int *anamelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.addr;
+ bsd_args.anamelen = linux_args.namelen;
+ return oaccept(p, &bsd_args, retval);
+}
+
+struct linux_getsockname_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval)
+{
+ struct linux_getsockname_args linux_args;
+ struct {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetsockname(p, &bsd_args, retval);
+}
+
+struct linux_getpeername_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval)
+{
+ struct linux_getpeername_args linux_args;
+ struct getpeername_args {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetpeername(p, &bsd_args, retval);
+}
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+};
+
+static int
+linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval)
+{
+ struct linux_socketpair_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ bsd_args.type = linux_args.type;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.rsv = linux_args.rsv;
+ return socketpair(p, &bsd_args, retval);
+}
+
+struct linux_send_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_send(struct proc *p, struct linux_send_args *args, int *retval)
+{
+ struct linux_send_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return osend(p, &bsd_args, retval);
+}
+
+struct linux_recv_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_recv(struct proc *p, struct linux_recv_args *args, int *retval)
+{
+ struct linux_recv_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return orecv(p, &bsd_args, retval);
+}
+
+struct linux_sendto_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+};
+
+static int
+linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval)
+{
+ struct linux_sendto_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.to = linux_args.to;
+ bsd_args.tolen = linux_args.tolen;
+ return sendto(p, &bsd_args, retval);
+}
+
+struct linux_recvfrom_args {
+ int s;
+ void *buf;
+ int len;
+ int flags;
+ caddr_t from;
+ int *fromlen;
+};
+
+static int
+linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval)
+{
+ struct linux_recvfrom_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t from;
+ int *fromlenaddr;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.buf;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.from = linux_args.from;
+ bsd_args.fromlenaddr = linux_args.fromlen;
+ return orecvfrom(p, &bsd_args, retval);
+}
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+static int
+linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval)
+{
+ struct linux_shutdown_args linux_args;
+ struct {
+ int s;
+ int how;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.how = linux_args.how;
+ return shutdown(p, &bsd_args, retval);
+}
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int optlen;
+};
+
+static int
+linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval)
+{
+ struct linux_setsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.name = name;
+ bsd_args.val = linux_args.optval;
+ bsd_args.valsize = linux_args.optlen;
+ return setsockopt(p, &bsd_args, retval);
+}
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int *optlen;
+};
+
+static int
+linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval)
+{
+ struct linux_getsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.val = linux_args.optval;
+ bsd_args.avalsize = linux_args.optlen;
+ return getsockopt(p, &bsd_args, retval);
+}
+
+struct linux_socketcall_args {
+ int what;
+ void *args;
+};
+
+int
+linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
+{
+ switch (args->what) {
+ case LINUX_SOCKET:
+ return linux_socket(p, args->args, retval);
+ case LINUX_BIND:
+ return linux_bind(p, args->args, retval);
+ case LINUX_CONNECT:
+ return linux_connect(p, args->args, retval);
+ case LINUX_LISTEN:
+ return linux_listen(p, args->args, retval);
+ case LINUX_ACCEPT:
+ return linux_accept(p, args->args, retval);
+ case LINUX_GETSOCKNAME:
+ return linux_getsockname(p, args->args, retval);
+ case LINUX_GETPEERNAME:
+ return linux_getpeername(p, args->args, retval);
+ case LINUX_SOCKETPAIR:
+ return linux_socketpair(p, args->args, retval);
+ case LINUX_SEND:
+ return linux_send(p, args->args, retval);
+ case LINUX_RECV:
+ return linux_recv(p, args->args, retval);
+ case LINUX_SENDTO:
+ return linux_sendto(p, args->args, retval);
+ case LINUX_RECVFROM:
+ return linux_recvfrom(p, args->args, retval);
+ case LINUX_SHUTDOWN:
+ return linux_shutdown(p, args->args, retval);
+ case LINUX_SETSOCKOPT:
+ return linux_setsockopt(p, args->args, retval);
+ case LINUX_GETSOCKOPT:
+ return linux_getsockopt(p, args->args, retval);
+ default:
+ uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
new file mode 100644
index 0000000..1dbfcf1
--- /dev/null
+++ b/sys/compat/linux/linux_stats.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_stats.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <i386/linux/linux.h>
+
+struct linux_newstat {
+ unsigned short stat_dev;
+ unsigned short __pad1;
+ unsigned long stat_ino;
+ unsigned short stat_mode;
+ unsigned short stat_nlink;
+ unsigned short stat_uid;
+ unsigned short stat_gid;
+ unsigned short stat_rdev;
+ unsigned short __pad2;
+ unsigned long stat_size;
+ unsigned long stat_blksize;
+ unsigned long stat_blocks;
+ unsigned long stat_atime;
+ unsigned long __unused1;
+ unsigned long stat_mtime;
+ unsigned long __unused2;
+ unsigned long stat_ctime;
+ unsigned long __unused3;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct linux_newstat_args {
+ char *path;
+ struct linux_newstat *buf;
+};
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct linux_newstat tbuf;
+
+ tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10);
+ tbuf.stat_ino = buf->st_ino;
+ tbuf.stat_mode = buf->st_mode;
+ tbuf.stat_nlink = buf->st_nlink;
+ tbuf.stat_uid = buf->st_uid;
+ tbuf.stat_gid = buf->st_gid;
+ tbuf.stat_rdev = buf->st_rdev;
+ tbuf.stat_size = buf->st_size;
+ tbuf.stat_atime = buf->st_atime;
+ tbuf.stat_mtime = buf->st_mtime;
+ tbuf.stat_ctime = buf->st_ctime;
+ tbuf.stat_blksize = buf->st_blksize;
+ tbuf.stat_blocks = buf->st_blocks;
+ return copyout(&tbuf, ubuf, sizeof(tbuf));
+}
+
+int
+linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+int
+linux_newlstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_newfstat_args {
+ int fd;
+ struct linux_newstat *buf;
+};
+
+int
+linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
+{
+ struct linux_newstat tbuf;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return EBADF;
+ switch (fp->f_type) {
+ case DTYPE_VNODE:
+ error = vn_stat((struct vnode *)fp->f_data, &buf, p);
+ break;
+ case DTYPE_SOCKET:
+ error = soo_stat((struct socket *)fp->f_data, &buf);
+ break;
+ default:
+ panic("LINUX newfstat");
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_statfs {
+ long ftype;
+ long fbsize;
+ long fblocks;
+ long fbfree;
+ long fbavail;
+ long ffiles;
+ long fffree;
+ linux_fsid_t ffsid;
+ long fnamelen;
+ long fspare[6];
+};
+
+
+struct linux_statfs_args {
+ char *path;
+ struct statfs *buf;
+};
+
+int
+linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
+{
+ struct mount *mp;
+ struct nameidata *ndp;
+ struct statfs *bsd_statfs;
+ struct nameidata nd;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
+#endif
+ ndp = &nd;
+ ndp->ni_cnd.cn_nameiop = LOOKUP;
+ ndp->ni_cnd.cn_flags = FOLLOW;
+ ndp->ni_cnd.cn_proc = curproc;
+ ndp->ni_cnd.cn_cred = curproc->p_cred->pc_ucred;
+ ndp->ni_segflg = UIO_USERSPACE;
+ ndp->ni_dirp = args->path;
+ if (error = namei(ndp))
+ return error;
+ mp = ndp->ni_vp->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ vrele(ndp->ni_vp);
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
+
+struct linux_fstatfs_args {
+ int fd;
+ struct statfs *buf;
+};
+
+int
+linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *bsd_statfs;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if (error = getvnode(p->p_fd, args->fd, &fp))
+ return error;
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c
new file mode 100644
index 0000000..d9650d3
--- /dev/null
+++ b/sys/i386/linux/imgact_linux.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Based heavily on /sys/kern/imgact_aout.c which is:
+ * Copyright (c) 1993, David Greenman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: imgact_linux.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/resourcevar.h>
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/imgact.h>
+#include <sys/imgact_aout.h>
+#include <sys/kernel.h>
+#include <sys/sysent.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+int
+exec_linux_imgact(iparams)
+ struct image_params *iparams;
+{
+ struct exec *a_out = (struct exec *) iparams->image_header;
+ struct vmspace *vmspace = iparams->proc->p_vmspace;
+ unsigned long vmaddr, virtual_offset, file_offset;
+ unsigned long buffer, bss_size;
+ int error;
+ extern struct sysentvec linux_sysvec;
+
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413:
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314:
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+ bss_size = round_page(a_out->a_bss);
+
+ /*
+ * Check various fields in header for validity/bounds.
+ */
+ if (a_out->a_entry < virtual_offset ||
+ a_out->a_entry >= virtual_offset + a_out->a_text ||
+ a_out->a_text % NBPG || a_out->a_data % NBPG)
+ return (-1);
+
+ /* text + data can't exceed file size */
+ if (a_out->a_data + a_out->a_text > iparams->attr->va_size)
+ return (EFAULT);
+ /*
+ * text/data/bss must not exceed limits
+ */
+ if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ ||
+ a_out->a_data+bss_size > iparams->proc->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return (ENOMEM);
+
+ /* copy in arguments and/or environment from old process */
+ error = exec_extract_strings(iparams);
+ if (error)
+ return (error);
+
+ /*
+ * Destroy old process VM and create a new one (with a new stack)
+ */
+ exec_new_vmspace(iparams);
+
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PGOFSET) {
+#ifdef DEBUG
+ printf("imgact: Non page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_text), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t) iparams->vnodep, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_text + file_offset));
+
+ error = vm_map_protect(&vmspace->vm_map, vmaddr,
+ round_page(a_out->a_text),
+ VM_PROT_EXECUTE|VM_PROT_READ, TRUE);
+ if (error)
+ return error;
+ /*
+ * Map data read/write
+ */
+ vmaddr = virtual_offset + a_out->a_text;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_data + bss_size), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t) iparams->vnodep,
+ trunc_page(a_out->a_text + file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset),
+ (caddr_t)vmaddr,
+ a_out->a_data);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_data + file_offset));
+
+ error = vm_map_protect(&vmspace->vm_map, vmaddr,
+ round_page(a_out->a_data + bss_size),
+ VM_PROT_WRITE|VM_PROT_READ, TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+ printf("imgact: Page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text read/execute
+ */
+ vmaddr = virtual_offset;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_text,
+ VM_PROT_READ | VM_PROT_EXECUTE,
+ VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)iparams->vnodep, file_offset);
+ if (error)
+ return (error);
+
+ /*
+ * Map data read/write
+ */
+ vmaddr = virtual_offset + a_out->a_text;
+ error = vm_mmap(&vmspace->vm_map, &vmaddr, a_out->a_data,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)iparams->vnodep, file_offset + a_out->a_text);
+ if (error)
+ return (error);
+
+ /*
+ * Allocate demand-zeroed area for uninitialized data
+ */
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
+ error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE);
+ if (error)
+ return (error);
+ }
+ }
+ /* Fill in process VM information */
+ vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
+ vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
+ vmspace->vm_taddr = (caddr_t)virtual_offset;
+ vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
+
+ /* Fill in image_params */
+ iparams->interpreted = 0;
+ iparams->entry_addr = a_out->a_entry;
+
+ iparams->proc->p_sysent = &linux_sysvec;
+ return (0);
+}
+
+/*
+ * Tell kern_execve.c about it, with a little help from the linker.
+ * Since `const' objects end up in the text segment, TEXT_SET is the
+ * correct directive to use.
+ */
+const struct execsw linux_execsw = { exec_linux_imgact, "linux" };
+TEXT_SET(execsw_set, linux_execsw);
+
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
new file mode 100644
index 0000000..9d13bd1
--- /dev/null
+++ b/sys/i386/linux/linux.h
@@ -0,0 +1,406 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux.h,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#ifndef LINUX_H
+#define LINUX_H
+
+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 char * linux_caddr_t;
+typedef long linux_off_t;
+typedef struct {
+ long val[2];
+} linux_fsid_t;
+typedef int linux_pid_t;
+typedef unsigned long linux_sigset_t;
+typedef void (*linux_handler_t)(int);
+typedef struct {
+ void (*sa_handler)(int);
+ linux_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+} linux_sigaction_t;
+typedef int linux_key_t;
+
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+
+/* misc defines */
+#define LINUX_NAME_MAX 255
+
+/* signal numbers */
+#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_SIGUNUSED 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_SIGIO 23
+#define LINUX_SIGPOLL LINUX_SIGIO
+#define LINUX_SIGURG LINUX_SIGIO
+#define LINUX_SIGXCPU 24
+#define LINUX_SIGXFSZ 25
+#define LINUX_SIGVTALRM 26
+#define LINUX_SIGPROF 27
+#define LINUX_SIGWINCH 28
+#define LINUX_SIGLOST 29
+#define LINUX_SIGPWR 30
+#define LINUX_SIGBUS LINUX_SIGUNUSED
+#define LINUX_NSIG 32
+
+/* sigaction 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
+
+/* sigprocmask actions */
+#define LINUX_SIG_BLOCK 0
+#define LINUX_SIG_UNBLOCK 1
+#define LINUX_SIG_SETMASK 2
+
+/* termio commands */
+#define LINUX_TCGETS 0x5401
+#define LINUX_TCSETS 0x5402
+#define LINUX_TCSETSW 0x5403
+#define LINUX_TCSETSF 0x5404
+#define LINUX_TCGETA 0x5405
+#define LINUX_TCSETA 0x5406
+#define LINUX_TCSETAW 0x5407
+#define LINUX_TCSETAF 0x5408
+#define LINUX_TCSBRK 0x5409
+#define LINUX_TCXONC 0x540A
+#define LINUX_TCFLSH 0x540B
+#define LINUX_TIOCEXCL 0x540C
+#define LINUX_TIOCNXCL 0x540D
+#define LINUX_TIOCSCTTY 0x540E
+#define LINUX_TIOCGPGRP 0x540F
+#define LINUX_TIOCSPGRP 0x5410
+#define LINUX_TIOCOUTQ 0x5411
+#define LINUX_TIOCSTI 0x5412
+#define LINUX_TIOCGWINSZ 0x5413
+#define LINUX_TIOCSWINSZ 0x5414
+#define LINUX_TIOCMGET 0x5415
+#define LINUX_TIOCMBIS 0x5416
+#define LINUX_TIOCMBIC 0x5417
+#define LINUX_TIOCMSET 0x5418
+#define LINUX_TIOCGSOFTCAR 0x5419
+#define LINUX_TIOCSSOFTCAR 0x541A
+#define LINUX_FIONREAD 0x541B
+#define LINUX_TIOCINQ FIONREAD
+#define LINUX_TIOCLINUX 0x541C
+#define LINUX_TIOCCONS 0x541D
+#define LINUX_TIOCGSERIAL 0x541E
+#define LINUX_TIOCSSERIAL 0x541F
+#define LINUX_TIOCPKT 0x5420
+#define LINUX_FIONBIO 0x5421
+#define LINUX_TIOCNOTTY 0x5422
+#define LINUX_TIOCSETD 0x5423
+#define LINUX_TIOCGETD 0x5424
+#define LINUX_TCSBRKP 0x5425
+#define LINUX_TIOCTTYGSTRUCT 0x5426
+#define LINUX_FIONCLEX 0x5450
+#define LINUX_FIOCLEX 0x5451
+#define LINUX_FIOASYNC 0x5452
+#define LINUX_TIOCSERCONFIG 0x5453
+#define LINUX_TIOCSERGWILD 0x5454
+#define LINUX_TIOCSERSWILD 0x5455
+#define LINUX_TIOCGLCKTRMIOS 0x5456
+#define LINUX_TIOCSLCKTRMIOS 0x5457
+
+/* line disciplines */
+#define LINUX_N_TTY 0
+#define LINUX_N_SLIP 1
+#define LINUX_N_MOUSE 2
+#define LINUX_N_PPP 3
+
+/* Linux termio c_cc values */
+#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
+#define LINUX_NCC 8
+
+/* Linux termios c_cc values */
+#define LINUX_VSTART 8
+#define LINUX_VSTOP 9
+#define LINUX_VSUSP 10
+#define LINUX_VEOL 11
+#define LINUX_VREPRINT 12
+#define LINUX_VDISCARD 13
+#define LINUX_VWERASE 14
+#define LINUX_VLNEXT 15
+#define LINUX_VEOL2 16
+#define LINUX_NCCS 17
+
+/* 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
+
+#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_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
+
+/* open/fcntl flags */
+#define LINUX_O_RDONLY 00
+#define LINUX_O_WRONLY 01
+#define LINUX_O_RDWR 02
+#define LINUX_O_CREAT 0100
+#define LINUX_O_EXCL 0200
+#define LINUX_O_NOCTTY 0400
+#define LINUX_O_TRUNC 01000
+#define LINUX_O_APPEND 02000
+#define LINUX_O_NONBLOCK 04000
+#define LINUX_O_NDELAY LINUX_O_NONBLOCK
+#define LINUX_O_SYNC 010000
+#define LINUX_FASYNC 020000
+
+/* fcntl flags */
+#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
+
+/* mmap options */
+#define LINUX_MAP_SHARED 0x0001
+#define LINUX_MAP_PRIVATE 0x0002
+#define LINUX_MAP_FIXED 0x0010
+#define LINUX_MAP_ANON 0x0020
+
+/* SystemV ipc defines */
+#define LINUX_SEMOP 1
+#define LINUX_SEMGET 2
+#define LINUX_SEMCTL 3
+#define LINUX_MSGSND 11
+#define LINUX_MSGRCV 12
+#define LINUX_MSGGET 13
+#define LINUX_MSGCTL 14
+#define LINUX_SHMAT 21
+#define LINUX_SHMDT 22
+#define LINUX_SHMGET 23
+#define LINUX_SHMCTL 24
+
+#define LINUX_IPC_RMID 0
+#define LINUX_IPC_SET 1
+#define LINUX_IPC_STAT 2
+#define LINUX_IPC_INFO 3
+
+#define LINUX_SHM_LOCK 11
+#define LINUX_SHM_UNLOCK 12
+#define LINUX_SHM_STAT 13
+#define LINUX_SHM_INFO 14
+
+#define LINUX_SHM_RDONLY 0x1000
+#define LINUX_SHM_RND 0x2000
+#define LINUX_SHM_REMAP 0x4000
+
+/* Socket defines */
+#define LINUX_SOCKET 1
+#define LINUX_BIND 2
+#define LINUX_CONNECT 3
+#define LINUX_LISTEN 4
+#define LINUX_ACCEPT 5
+#define LINUX_GETSOCKNAME 6
+#define LINUX_GETPEERNAME 7
+#define LINUX_SOCKETPAIR 8
+#define LINUX_SEND 9
+#define LINUX_RECV 10
+#define LINUX_SENDTO 11
+#define LINUX_RECVFROM 12
+#define LINUX_SHUTDOWN 13
+#define LINUX_SETSOCKOPT 14
+#define LINUX_GETSOCKOPT 15
+
+#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
+
+#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
+
+#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
+
+#define LINUX_IP_TOS 1
+#define LINUX_IP_TTL 2
+
+#endif /* LINUX_H */
diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c
new file mode 100644
index 0000000..13288ac
--- /dev/null
+++ b/sys/i386/linux/linux_dummy.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_dummy.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/errno.h>
+#include <vm/vm.h>
+
+int
+linux_setup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): setup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_break(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): break() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_fstat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): fstat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_umount(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): umount() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ptrace(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ptrace() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_pause(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): pause() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_stty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): stty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_gtty(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): gtty() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_nice(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): nice() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ftime(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ftime() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_prof(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): prof() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_signal(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): signal() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_phys(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): phys() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_lock(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): lock() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_mpx(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): mpx() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ulimit(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ulimit() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_olduname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): olduname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ustat(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ustat() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_ioperm(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): ioperm() not supported\n", p->p_pid);
+ return 0; /* EINVAL SOS XXX */
+}
+
+int
+linux_syslog(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): syslog() not supported (BSD sigreturn)\n",p->p_pid);
+ return sigreturn(p, args, retval);
+}
+
+int
+linux_iopl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): iopl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vhangup(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vhangup() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_idle(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): idle() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_vm86(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): vm86() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_swapoff(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): swapoff() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sysinfo(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sysinfo() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_sigreturn(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): sigreturn() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_clone(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_uname(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_modify_ldt(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): modify_ldt() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_adjtimex(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): adjtimex() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_create_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): create_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_init_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): init_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_delete_module(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): delete_module() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_get_kernel_syms(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): get_kernel_syms() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_quotactl(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): quotactl() not supported\n", p->p_pid);
+ return ENOSYS;
+}
+
+int
+linux_bdflush(struct proc *p, void *args, int *retval)
+{
+ printf("Linux-emul(%d): bdflush() not supported\n", p->p_pid);
+ return ENOSYS;
+}
diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c
new file mode 100644
index 0000000..b846068
--- /dev/null
+++ b/sys/i386/linux/linux_file.c
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_file.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/exec.h>
+#include <sys/dirent.h>
+#include <vm/vm.h>
+#include <ufs/ufs/dir.h>
+
+
+struct linux_creat_args {
+ char *path;
+ int mode;
+};
+
+int
+linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): creat(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+ bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC;
+ return open(p, &bsd_open_args, retval);
+}
+
+struct linux_open_args {
+ char *path;
+ int flags;
+ int mode;
+};
+
+int
+linux_open(struct proc *p, struct linux_open_args *args, int *retval)
+{
+ struct {
+ char *path;
+ int flags;
+ int mode;
+ } bsd_open_args;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
+ p->p_pid, args->path, args->flags, args->mode);
+#endif
+ bsd_open_args.flags = 0;
+ if (args->flags & LINUX_O_RDONLY)
+ bsd_open_args.flags |= O_RDONLY;
+ if (args->flags & LINUX_O_WRONLY)
+ bsd_open_args.flags |= O_WRONLY;
+ if (args->flags & LINUX_O_RDWR)
+ bsd_open_args.flags |= O_RDWR;
+ if (args->flags & LINUX_O_NDELAY)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_O_APPEND)
+ bsd_open_args.flags |= O_APPEND;
+ if (args->flags & LINUX_O_SYNC)
+ bsd_open_args.flags |= O_FSYNC;
+ if (args->flags & LINUX_O_NONBLOCK)
+ bsd_open_args.flags |= O_NONBLOCK;
+ if (args->flags & LINUX_FASYNC)
+ bsd_open_args.flags |= O_ASYNC;
+ if (args->flags & LINUX_O_CREAT)
+ bsd_open_args.flags |= O_CREAT;
+ if (args->flags & LINUX_O_TRUNC)
+ bsd_open_args.flags |= O_TRUNC;
+ if (args->flags & LINUX_O_EXCL)
+ bsd_open_args.flags |= O_EXCL;
+ if (args->flags & LINUX_O_NOCTTY)
+ bsd_open_args.flags |= O_NOCTTY;
+ bsd_open_args.path = args->path;
+ bsd_open_args.mode = args->mode;
+
+ error = open(p, &bsd_open_args, retval);
+ if (!error && !(bsd_open_args.flags & O_NOCTTY) &&
+ SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp = fdp->fd_ofiles[*retval];
+
+ if (fp->f_type == DTYPE_VNODE)
+ (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
+ }
+ return error;
+}
+
+struct linux_flock {
+ short l_type;
+ short l_whence;
+ linux_off_t l_start;
+ linux_off_t l_len;
+ linux_pid_t l_pid;
+};
+
+static void
+linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock)
+{
+ switch (linux_flock->l_type) {
+ case LINUX_F_RDLCK:
+ bsd_flock->l_type = F_RDLCK;
+ break;
+ case LINUX_F_WRLCK:
+ bsd_flock->l_type = F_WRLCK;
+ break;
+ case LINUX_F_UNLCK:
+ bsd_flock->l_type = F_UNLCK;
+ break;
+ }
+ bsd_flock->l_whence = linux_flock->l_whence;
+ bsd_flock->l_start = (off_t)linux_flock->l_start;
+ bsd_flock->l_len = (off_t)linux_flock->l_len;
+ bsd_flock->l_pid = (pid_t)linux_flock->l_pid;
+}
+
+static void
+bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
+{
+ switch (bsd_flock->l_type) {
+ case F_RDLCK:
+ linux_flock->l_type = LINUX_F_RDLCK;
+ break;
+ case F_WRLCK:
+ linux_flock->l_type = LINUX_F_WRLCK;
+ break;
+ case F_UNLCK:
+ linux_flock->l_type = LINUX_F_UNLCK;
+ break;
+ }
+ linux_flock->l_whence = bsd_flock->l_whence;
+ linux_flock->l_start = (linux_off_t)bsd_flock->l_start;
+ linux_flock->l_len = (linux_off_t)bsd_flock->l_len;
+ linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
+}
+
+struct linux_fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
+{
+ int error, result;
+ struct fcntl_args {
+ int fd;
+ int cmd;
+ int arg;
+ } fcntl_args;
+ struct linux_flock linux_flock;
+ struct flock *bsd_flock =
+ (struct flock *)ua_alloc_init(sizeof(struct flock));
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ fcntl_args.fd = args->fd;
+ fcntl_args.arg = 0;
+
+ switch (args->cmd) {
+ case LINUX_F_DUPFD:
+ fcntl_args.cmd = F_DUPFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFD:
+ fcntl_args.cmd = F_GETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETFD:
+ fcntl_args.cmd = F_SETFD;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETFL:
+ fcntl_args.cmd = F_GETFL;
+ error = fcntl(p, &fcntl_args, &result);
+ *retval = 0;
+ if (result & O_RDONLY) *retval |= LINUX_O_RDONLY;
+ if (result & O_WRONLY) *retval |= LINUX_O_WRONLY;
+ if (result & O_RDWR) *retval |= LINUX_O_RDWR;
+ if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK;
+ if (result & O_APPEND) *retval |= LINUX_O_APPEND;
+ if (result & O_FSYNC) *retval |= LINUX_O_SYNC;
+ return error;
+
+ case LINUX_F_SETFL:
+ if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK;
+ if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND;
+ if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC;
+ fcntl_args.cmd = F_SETFL;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_GETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ if (error = fcntl(p, &fcntl_args, retval))
+ return error;
+ bsd_to_linux_flock(bsd_flock, &linux_flock);
+ return copyout((caddr_t)&linux_flock, (caddr_t)args->arg,
+ sizeof(struct linux_flock));
+
+ case LINUX_F_SETLK:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLK;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETLKW:
+ if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock,
+ sizeof(struct linux_flock))))
+ return error;
+ linux_to_bsd_flock(&linux_flock, bsd_flock);
+ fcntl_args.cmd = F_SETLKW;
+ fcntl_args.arg = (int)bsd_flock;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_SETOWN:
+ fcntl_args.cmd = F_SETOWN;
+ return fcntl(p, &fcntl_args, retval);
+
+ case LINUX_F_GETOWN:
+ fcntl_args.cmd = F_GETOWN;
+ return fcntl(p, &fcntl_args, retval);
+ }
+ return EINVAL;
+}
+
+struct linux_lseek_args {
+ int fdes;
+ unsigned long off;
+ int whence;
+};
+
+int
+linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
+{
+
+ struct lseek_args {
+ int fdes;
+ int pad;
+ off_t off;
+ int whence;
+ } tmp_args;
+ off_t tmp_retval;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): lseek(%d, %d, %d)\n",
+ p->p_pid, args->fdes, args->off, args->whence);
+#endif
+ tmp_args.fdes = args->fdes;
+ tmp_args.off = (off_t)args->off;
+ tmp_args.whence = args->whence;
+ error = lseek(p, &tmp_args, &tmp_retval);
+ *retval = (int)tmp_retval;
+ return error;
+}
+
+struct linux_dirent {
+ long dino;
+ linux_off_t doff;
+ unsigned short dreclen;
+ char dname[LINUX_NAME_MAX + 1];
+};
+
+#define LINUX_RECLEN(de,namlen) \
+ ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
+
+struct linux_readdir_args {
+ int fd;
+ struct linux_dirent *dent;
+ unsigned int count;
+};
+
+int
+linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
+{
+ register struct dirent *bdp;
+ struct vnode *vp;
+ caddr_t inp, buf; /* BSD-format */
+ int len, reclen; /* BSD-format */
+ caddr_t outp; /* Linux-format */
+ int resid, linuxreclen=0; /* Linux-format */
+ struct file *fp;
+ struct uio auio;
+ struct iovec aiov;
+ struct vattr va;
+ off_t off;
+ struct linux_dirent linux_dirent;
+ int buflen, error, eofflag, nbytes, justone;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): readdir(%d, *, %d)\n",
+ p->p_pid, args->fd, args->count);
+#endif
+ if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
+ return (error);
+
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+ vp = (struct vnode *) fp->f_data;
+
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ nbytes = args->count;
+ if (nbytes == 1) {
+ nbytes = sizeof (struct linux_dirent);
+ justone = 1;
+ }
+ else
+ justone = 0;
+
+ buflen = max(va.va_blocksize, nbytes);
+ buf = malloc(buflen, 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;
+
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0);
+ if (error)
+ goto out;
+
+ inp = buf;
+ outp = (caddr_t) args->dent;
+ resid = nbytes;
+ if ((len = buflen - auio.uio_resid) == 0)
+ goto eof;
+
+ while (len > 0) {
+ reclen = ((struct dirent *) inp)->d_reclen;
+ if (reclen & 3)
+ panic("linux_readdir");
+ off += reclen;
+ bdp = (struct dirent *) inp;
+ if (bdp->d_fileno == 0) {
+ inp += reclen;
+ continue;
+ }
+ linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
+ if (reclen > len || resid < linuxreclen) {
+ outp++;
+ break;
+ }
+ linux_dirent.dino = (long) bdp->d_fileno;
+ linux_dirent.doff = (linux_off_t) linuxreclen;
+ linux_dirent.dreclen = (u_short) bdp->d_namlen;
+ strcpy(linux_dirent.dname, bdp->d_name);
+ if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen)))
+ goto out;
+ inp += reclen;
+ outp += linuxreclen;
+ resid -= linuxreclen;
+ len -= reclen;
+ if (justone)
+ break;
+ }
+
+ if (outp == (caddr_t) args->dent)
+ goto again;
+ fp->f_offset = off;
+
+ if (justone)
+ nbytes = resid + linuxreclen;
+eof:
+ *retval = nbytes - resid;
+out:
+ VOP_UNLOCK(vp);
+ free(buf, M_TEMP);
+ return error;
+}
diff --git a/sys/i386/linux/linux_generic.c b/sys/i386/linux/linux_generic.c
new file mode 100644
index 0000000..48df332
--- /dev/null
+++ b/sys/i386/linux/linux_generic.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_generic.c,v 1.3 1995/06/25 17:30:46 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include <vm/vm.h>
+
+
+static caddr_t ua_ptr = NULL;
+
+caddr_t ua_alloc_init(int len)
+{
+ caddr_t ptr;
+
+ ptr = (caddr_t)ALIGN((PS_STRINGS));
+ ptr += sizeof(struct ps_strings);
+ ua_ptr = (caddr_t)(ptr + ALIGN(len));
+ return ptr;
+}
+
+caddr_t ua_alloc(int len)
+{
+ caddr_t ptr;
+
+ ptr = ua_ptr;
+ ua_ptr += ALIGN(len);
+ return ptr;
+}
diff --git a/sys/i386/linux/linux_ioctl.c b/sys/i386/linux/linux_ioctl.c
new file mode 100644
index 0000000..12adff4
--- /dev/null
+++ b/sys/i386/linux/linux_ioctl.c
@@ -0,0 +1,495 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ioctl.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/ioctl_compat.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <machine/console.h>
+
+
+struct linux_termios {
+ unsigned long c_iflag;
+ unsigned long c_oflag;
+ unsigned long c_cflag;
+ unsigned long c_lflag;
+ unsigned char c_line;
+ unsigned char c_cc[LINUX_NCCS];
+};
+
+struct linux_winsize {
+ unsigned short ws_row, ws_col;
+ unsigned short ws_xpixel, ws_ypixel;
+};
+
+static struct speedtab sptab[] = {
+ { 0, 0 }, { 50, 1 }, { 75, 2 }, { 110, 3 },
+ { 134, 4 }, { 135, 4 }, { 150, 5 }, { 200, 6 },
+ { 300, 7 }, { 600, 8 }, { 1200, 9 }, { 1800, 10 },
+ { 2400, 11 }, { 4800, 12 }, { 9600, 13 },
+ { 19200, 14 }, { 38400, 15 },
+ { 57600, 4097 }, { 115200, 4098 }, {-1, -1 }
+};
+
+static int
+linux_to_bsd_speed(int code, struct speedtab *table)
+{
+ for ( ; table->sp_code != -1; table++)
+ if (table->sp_code == code)
+ return (table->sp_speed);
+ return -1;
+}
+
+static int
+bsd_to_linux_speed(int speed, struct speedtab *table)
+{
+ for ( ; table->sp_speed != -1; table++)
+ if (table->sp_speed == speed)
+ return (table->sp_code);
+ return -1;
+}
+
+static void
+bsd_to_linux_termios(struct termios *bsd_termios,
+ struct linux_termios *linux_termios)
+{
+ int i, speed;
+
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+ linux_termios->c_iflag = 0;
+ if (bsd_termios->c_iflag & IGNBRK)
+ linux_termios->c_iflag |= LINUX_IGNBRK;
+ if (bsd_termios->c_iflag & BRKINT)
+ linux_termios->c_iflag |= LINUX_BRKINT;
+ if (bsd_termios->c_iflag & IGNPAR)
+ linux_termios->c_iflag |= LINUX_IGNPAR;
+ if (bsd_termios->c_iflag & PARMRK)
+ linux_termios->c_iflag |= LINUX_PARMRK;
+ if (bsd_termios->c_iflag & INPCK)
+ linux_termios->c_iflag |= LINUX_INPCK;
+ if (bsd_termios->c_iflag & ISTRIP)
+ linux_termios->c_iflag |= LINUX_ISTRIP;
+ if (bsd_termios->c_iflag & INLCR)
+ linux_termios->c_iflag |= LINUX_INLCR;
+ if (bsd_termios->c_iflag & IGNCR)
+ linux_termios->c_iflag |= LINUX_IGNCR;
+ if (bsd_termios->c_iflag & ICRNL)
+ linux_termios->c_iflag |= LINUX_ICRNL;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXANY;
+ if (bsd_termios->c_iflag & IXON)
+ linux_termios->c_iflag |= LINUX_IXON;
+ if (bsd_termios->c_iflag & IXOFF)
+ linux_termios->c_iflag |= LINUX_IXOFF;
+ if (bsd_termios->c_iflag & IMAXBEL)
+ linux_termios->c_iflag |= LINUX_IMAXBEL;
+
+ linux_termios->c_oflag = 0;
+ if (bsd_termios->c_oflag & OPOST)
+ linux_termios->c_oflag |= LINUX_OPOST;
+ if (bsd_termios->c_oflag & ONLCR)
+ linux_termios->c_oflag |= LINUX_ONLCR;
+ if (bsd_termios->c_oflag & OXTABS)
+ linux_termios->c_oflag |= LINUX_XTABS;
+
+ linux_termios->c_cflag =
+ bsd_to_linux_speed(bsd_termios->c_ispeed, sptab);
+ linux_termios->c_cflag |= (bsd_termios->c_cflag & CSIZE) >> 4;
+ if (bsd_termios->c_cflag & CSTOPB)
+ linux_termios->c_cflag |= LINUX_CSTOPB;
+ if (bsd_termios->c_cflag & CREAD)
+ linux_termios->c_cflag |= LINUX_CREAD;
+ if (bsd_termios->c_cflag & PARENB)
+ linux_termios->c_cflag |= LINUX_PARENB;
+ if (bsd_termios->c_cflag & PARODD)
+ linux_termios->c_cflag |= LINUX_PARODD;
+ if (bsd_termios->c_cflag & HUPCL)
+ linux_termios->c_cflag |= LINUX_HUPCL;
+ if (bsd_termios->c_cflag & CLOCAL)
+ linux_termios->c_cflag |= LINUX_CLOCAL;
+ if (bsd_termios->c_cflag & CRTSCTS)
+ linux_termios->c_cflag |= LINUX_CRTSCTS;
+
+ linux_termios->c_lflag = 0;
+ if (bsd_termios->c_lflag & ISIG)
+ linux_termios->c_lflag |= LINUX_ISIG;
+ if (bsd_termios->c_lflag & ICANON)
+ linux_termios->c_lflag |= LINUX_ICANON;
+ if (bsd_termios->c_lflag & ECHO)
+ linux_termios->c_lflag |= LINUX_ECHO;
+ if (bsd_termios->c_lflag & ECHOE)
+ linux_termios->c_lflag |= LINUX_ECHOE;
+ if (bsd_termios->c_lflag & ECHOK)
+ linux_termios->c_lflag |= LINUX_ECHOK;
+ if (bsd_termios->c_lflag & ECHONL)
+ linux_termios->c_lflag |= LINUX_ECHONL;
+ if (bsd_termios->c_lflag & NOFLSH)
+ linux_termios->c_lflag |= LINUX_NOFLSH;
+ if (bsd_termios->c_lflag & TOSTOP)
+ linux_termios->c_lflag |= LINUX_TOSTOP;
+ if (bsd_termios->c_lflag & ECHOCTL)
+ linux_termios->c_lflag |= LINUX_ECHOCTL;
+ if (bsd_termios->c_lflag & ECHOPRT)
+ linux_termios->c_lflag |= LINUX_ECHOPRT;
+ if (bsd_termios->c_lflag & ECHOKE)
+ linux_termios->c_lflag |= LINUX_ECHOKE;
+ if (bsd_termios->c_lflag & FLUSHO)
+ linux_termios->c_lflag |= LINUX_FLUSHO;
+ if (bsd_termios->c_lflag & PENDIN)
+ linux_termios->c_lflag |= LINUX_PENDIN;
+ if (bsd_termios->c_lflag & IEXTEN)
+ linux_termios->c_lflag |= LINUX_IEXTEN;
+
+ for (i=0; i<LINUX_NCCS; i++)
+ linux_termios->c_cc[i] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VINTR] = bsd_termios->c_cc[VINTR];
+ linux_termios->c_cc[LINUX_VQUIT] = bsd_termios->c_cc[VQUIT];
+ linux_termios->c_cc[LINUX_VERASE] = bsd_termios->c_cc[VERASE];
+ linux_termios->c_cc[LINUX_VKILL] = bsd_termios->c_cc[VKILL];
+ linux_termios->c_cc[LINUX_VEOF] = bsd_termios->c_cc[VEOF];
+ linux_termios->c_cc[LINUX_VEOL] = bsd_termios->c_cc[VEOL];
+ linux_termios->c_cc[LINUX_VMIN] = bsd_termios->c_cc[VMIN];
+ linux_termios->c_cc[LINUX_VTIME] = bsd_termios->c_cc[VTIME];
+ linux_termios->c_cc[LINUX_VEOL2] = bsd_termios->c_cc[VEOL2];
+ linux_termios->c_cc[LINUX_VSWTC] = _POSIX_VDISABLE;
+ linux_termios->c_cc[LINUX_VSUSP] = bsd_termios->c_cc[VSUSP];
+ linux_termios->c_cc[LINUX_VSTART] = bsd_termios->c_cc[VSTART];
+ linux_termios->c_cc[LINUX_VSTOP] = bsd_termios->c_cc[VSTOP];
+ linux_termios->c_cc[LINUX_VREPRINT] = bsd_termios->c_cc[VREPRINT];
+ linux_termios->c_cc[LINUX_VDISCARD] = bsd_termios->c_cc[VDISCARD];
+ linux_termios->c_cc[LINUX_VWERASE] = bsd_termios->c_cc[VWERASE];
+ linux_termios->c_cc[LINUX_VLNEXT] = bsd_termios->c_cc[VLNEXT];
+
+ linux_termios->c_line = 0;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+static void
+linux_to_bsd_termios(struct linux_termios *linux_termios,
+ struct termios *bsd_termios)
+{
+ int i, speed;
+#ifdef DEBUG
+ printf("LINUX: LINUX termios structure (input):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
+ linux_termios->c_iflag, linux_termios->c_oflag,
+ linux_termios->c_cflag, linux_termios->c_lflag,
+ linux_termios->c_line);
+ printf("c_cc ");
+ for (i=0; i<LINUX_NCCS; i++)
+ printf("%02x ", linux_termios->c_cc[i]);
+ printf("\n");
+#endif
+ bsd_termios->c_iflag = 0;
+ if (linux_termios->c_iflag & LINUX_IGNBRK)
+ bsd_termios->c_iflag |= IGNBRK;
+ if (linux_termios->c_iflag & LINUX_BRKINT)
+ bsd_termios->c_iflag |= BRKINT;
+ if (linux_termios->c_iflag & LINUX_IGNPAR)
+ bsd_termios->c_iflag |= IGNPAR;
+ if (linux_termios->c_iflag & LINUX_PARMRK)
+ bsd_termios->c_iflag |= PARMRK;
+ if (linux_termios->c_iflag & LINUX_INPCK)
+ bsd_termios->c_iflag |= INPCK;
+ if (linux_termios->c_iflag & LINUX_ISTRIP)
+ bsd_termios->c_iflag |= ISTRIP;
+ if (linux_termios->c_iflag & LINUX_INLCR)
+ bsd_termios->c_iflag |= INLCR;
+ if (linux_termios->c_iflag & LINUX_IGNCR)
+ bsd_termios->c_iflag |= IGNCR;
+ if (linux_termios->c_iflag & LINUX_ICRNL)
+ bsd_termios->c_iflag |= ICRNL;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXANY;
+ if (linux_termios->c_iflag & LINUX_IXON)
+ bsd_termios->c_iflag |= IXON;
+ if (linux_termios->c_iflag & LINUX_IXOFF)
+ bsd_termios->c_iflag |= IXOFF;
+ if (linux_termios->c_iflag & LINUX_IMAXBEL)
+ bsd_termios->c_iflag |= IMAXBEL;
+
+ bsd_termios->c_oflag = 0;
+ if (linux_termios->c_oflag & LINUX_OPOST)
+ bsd_termios->c_oflag |= OPOST;
+ if (linux_termios->c_oflag & LINUX_ONLCR)
+ bsd_termios->c_oflag |= ONLCR;
+ if (linux_termios->c_oflag & LINUX_XTABS)
+ bsd_termios->c_oflag |= OXTABS;
+
+ bsd_termios->c_cflag = (linux_termios->c_cflag & LINUX_CSIZE) << 4;
+ if (linux_termios->c_cflag & LINUX_CSTOPB)
+ bsd_termios->c_cflag |= CSTOPB;
+ if (linux_termios->c_cflag & LINUX_PARENB)
+ bsd_termios->c_cflag |= PARENB;
+ if (linux_termios->c_cflag & LINUX_PARODD)
+ bsd_termios->c_cflag |= PARODD;
+ if (linux_termios->c_cflag & LINUX_HUPCL)
+ bsd_termios->c_cflag |= HUPCL;
+ if (linux_termios->c_cflag & LINUX_CLOCAL)
+ bsd_termios->c_cflag |= CLOCAL;
+ if (linux_termios->c_cflag & LINUX_CRTSCTS)
+ bsd_termios->c_cflag |= CRTSCTS;
+
+ bsd_termios->c_lflag = 0;
+ if (linux_termios->c_lflag & LINUX_ISIG)
+ bsd_termios->c_lflag |= ISIG;
+ if (linux_termios->c_lflag & LINUX_ICANON)
+ bsd_termios->c_lflag |= ICANON;
+ if (linux_termios->c_lflag & LINUX_ECHO)
+ bsd_termios->c_lflag |= ECHO;
+ if (linux_termios->c_lflag & LINUX_ECHOE)
+ bsd_termios->c_lflag |= ECHOE;
+ if (linux_termios->c_lflag & LINUX_ECHOK)
+ bsd_termios->c_lflag |= ECHOK;
+ if (linux_termios->c_lflag & LINUX_ECHONL)
+ bsd_termios->c_lflag |= ECHONL;
+ if (linux_termios->c_lflag & LINUX_NOFLSH)
+ bsd_termios->c_lflag |= NOFLSH;
+ if (linux_termios->c_lflag & LINUX_TOSTOP)
+ bsd_termios->c_lflag |= TOSTOP;
+ if (linux_termios->c_lflag & LINUX_ECHOCTL)
+ bsd_termios->c_lflag |= ECHOCTL;
+ if (linux_termios->c_lflag & LINUX_ECHOPRT)
+ bsd_termios->c_lflag |= ECHOPRT;
+ if (linux_termios->c_lflag & LINUX_ECHOKE)
+ bsd_termios->c_lflag |= ECHOKE;
+ if (linux_termios->c_lflag & LINUX_FLUSHO)
+ bsd_termios->c_lflag |= FLUSHO;
+ if (linux_termios->c_lflag & LINUX_PENDIN)
+ bsd_termios->c_lflag |= PENDIN;
+ if (linux_termios->c_lflag & IEXTEN)
+ bsd_termios->c_lflag |= IEXTEN;
+
+ for (i=0; i<NCCS; i++)
+ bsd_termios->c_cc[i] = _POSIX_VDISABLE;
+ bsd_termios->c_cc[VINTR] = linux_termios->c_cc[LINUX_VINTR];
+ bsd_termios->c_cc[VQUIT] = linux_termios->c_cc[LINUX_VQUIT];
+ bsd_termios->c_cc[VERASE] = linux_termios->c_cc[LINUX_VERASE];
+ bsd_termios->c_cc[VKILL] = linux_termios->c_cc[LINUX_VKILL];
+ bsd_termios->c_cc[VEOF] = linux_termios->c_cc[LINUX_VEOF];
+ bsd_termios->c_cc[VEOL] = linux_termios->c_cc[LINUX_VEOL];
+ bsd_termios->c_cc[VMIN] = linux_termios->c_cc[LINUX_VMIN];
+ bsd_termios->c_cc[VTIME] = linux_termios->c_cc[LINUX_VTIME];
+ bsd_termios->c_cc[VEOL2] = linux_termios->c_cc[LINUX_VEOL2];
+ bsd_termios->c_cc[VSUSP] = linux_termios->c_cc[LINUX_VSUSP];
+ bsd_termios->c_cc[VSTART] = linux_termios->c_cc[LINUX_VSTART];
+ bsd_termios->c_cc[VSTOP] = linux_termios->c_cc[LINUX_VSTOP];
+ bsd_termios->c_cc[VREPRINT] = linux_termios->c_cc[LINUX_VREPRINT];
+ bsd_termios->c_cc[VDISCARD] = linux_termios->c_cc[LINUX_VDISCARD];
+ bsd_termios->c_cc[VWERASE] = linux_termios->c_cc[LINUX_VWERASE];
+ bsd_termios->c_cc[VLNEXT] = linux_termios->c_cc[LINUX_VLNEXT];
+
+ bsd_termios->c_ispeed = bsd_termios->c_ospeed =
+ linux_to_bsd_speed(linux_termios->c_cflag & LINUX_CBAUD, sptab);
+#ifdef DEBUG
+ printf("LINUX: BSD termios structure (output):\n");
+ printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
+ bsd_termios->c_iflag, bsd_termios->c_oflag,
+ bsd_termios->c_cflag, bsd_termios->c_lflag,
+ bsd_termios->c_ispeed, bsd_termios->c_ospeed);
+ printf("c_cc ");
+ for (i=0; i<NCCS; i++)
+ printf("%02x ", bsd_termios->c_cc[i]);
+ printf("\n");
+#endif
+}
+
+
+struct linux_ioctl_args {
+ int fd;
+ int cmd;
+ int arg;
+};
+
+int
+linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
+{
+ struct termios bsd_termios;
+ struct winsize bsd_winsize;
+ struct linux_termios linux_termios;
+ struct linux_winsize linux_winsize;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ int (*func)();
+ int bsd_line, linux_line;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): ioctl(%d, %04x, *)\n",
+ p->p_pid, args->fd, args->cmd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == 0)
+ return EBADF;
+
+ if (!fp || (fp->f_flag & (FREAD | FWRITE)) == 0) {
+ return EBADF;
+ }
+
+ func = fp->f_ops->fo_ioctl;
+ switch (args->cmd) {
+ case LINUX_TCGETS:
+ if ((error = (*func)(fp, TIOCGETA, (caddr_t)&bsd_termios, p)) != 0)
+ return error;
+ bsd_to_linux_termios(&bsd_termios, &linux_termios);
+ return copyout((caddr_t)&linux_termios, (caddr_t)args->arg,
+ sizeof(linux_termios));
+
+ case LINUX_TCSETS:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETA, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSW:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAW, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TCSETSF:
+ linux_to_bsd_termios((struct linux_termios *)args->arg, &bsd_termios);
+ return (*func)(fp, TIOCSETAF, (caddr_t)&bsd_termios, p);
+
+ case LINUX_TIOCGPGRP:
+ args->cmd = TIOCGPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSPGRP:
+ args->cmd = TIOCSPGRP;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCGWINSZ:
+ args->cmd = TIOCGWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSWINSZ:
+ args->cmd = TIOCSWINSZ;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONREAD:
+ args->cmd = FIONREAD;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONBIO:
+ args->cmd = FIONBIO;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOASYNC:
+ args->cmd = FIOASYNC;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIONCLEX:
+ args->cmd = FIONCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_FIOCLEX:
+ args->cmd = FIOCLEX;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCEXCL:
+ args->cmd = TIOCEXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNXCL:
+ args->cmd = TIOCNXCL;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCCONS:
+ args->cmd = TIOCCONS;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCNOTTY:
+ args->cmd = TIOCNOTTY;
+ return ioctl(p, args, retval);
+
+ case LINUX_TIOCSETD:
+ switch (args->arg) {
+ case LINUX_N_TTY:
+ bsd_line = TTYDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_SLIP:
+ bsd_line = SLIPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ case LINUX_N_PPP:
+ bsd_line = PPPDISC;
+ return (*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p);
+ default:
+ return EINVAL;
+ }
+ break;
+
+ case LINUX_TIOCGETD:
+ bsd_line = TTYDISC;
+ if (error =(*func)(fp, TIOCSETD, (caddr_t)&bsd_line, p))
+ return error;
+ switch (bsd_line) {
+ case TTYDISC:
+ linux_line = LINUX_N_TTY;
+ break;
+ case SLIPDISC:
+ linux_line = LINUX_N_SLIP;
+ break;
+ case PPPDISC:
+ linux_line = LINUX_N_PPP;
+ break;
+ default:
+ return EINVAL;
+ }
+ return copyout(&linux_line, (caddr_t)args->arg,
+ sizeof(int));
+ }
+ uprintf("LINUX: 'ioctl' fd=%d, typ=0x%x(%c), num=0x%x not implemented\n",
+ args->fd, (args->cmd&0xffff00)>>8,
+ (args->cmd&0xffff00)>>8, args->cmd&0xff);
+ return EINVAL;
+}
diff --git a/sys/i386/linux/linux_ipc.c b/sys/i386/linux/linux_ipc.c
new file mode 100644
index 0000000..b38b229
--- /dev/null
+++ b/sys/i386/linux/linux_ipc.c
@@ -0,0 +1,308 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_ipc.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/proc.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+
+#include <vm/vm.h>
+
+struct linux_ipc_perm {
+ linux_key_t key;
+ unsigned short uid;
+ unsigned short gid;
+ unsigned short cuid;
+ unsigned short cgid;
+ unsigned short mode;
+ unsigned short seq;
+};
+
+static void
+linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
+{
+ bpp->key = lpp->key;
+ bpp->uid = lpp->uid;
+ bpp->gid = lpp->gid;
+ bpp->cuid = lpp->cuid;
+ bpp->cgid = lpp->cgid;
+ bpp->mode = lpp->mode;
+ bpp->seq = lpp->seq;
+}
+
+
+static void
+bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
+{
+ lpp->key = bpp->key;
+ lpp->uid = bpp->uid;
+ lpp->gid = bpp->gid;
+ lpp->cuid = bpp->cuid;
+ lpp->cgid = bpp->cgid;
+ lpp->mode = bpp->mode;
+ lpp->seq = bpp->seq;
+}
+
+struct linux_shmid_ds {
+ struct linux_ipc_perm shm_perm;
+ int shm_segsz;
+ linux_time_t shm_atime;
+ linux_time_t shm_dtime;
+ linux_time_t shm_ctime;
+ ushort shm_cpid;
+ ushort shm_lpid;
+ short shm_nattch;
+ ushort private1;
+ void *private2;
+ void *private3;
+};
+
+static void
+linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
+{
+ linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
+ bsp->shm_segsz = lsp->shm_segsz;
+ bsp->shm_lpid = lsp->shm_lpid;
+ bsp->shm_cpid = lsp->shm_cpid;
+ bsp->shm_nattch = lsp->shm_nattch;
+ bsp->shm_atime = lsp->shm_atime;
+ bsp->shm_dtime = lsp->shm_dtime;
+ bsp->shm_ctime = lsp->shm_ctime;
+ bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
+}
+
+static void
+bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
+{
+ bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
+ lsp->shm_segsz = bsp->shm_segsz;
+ lsp->shm_lpid = bsp->shm_lpid;
+ lsp->shm_cpid = bsp->shm_cpid;
+ lsp->shm_nattch = bsp->shm_nattch;
+ lsp->shm_atime = bsp->shm_atime;
+ lsp->shm_dtime = bsp->shm_dtime;
+ lsp->shm_ctime = bsp->shm_ctime;
+ lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
+}
+
+struct linux_ipc_args {
+ int what;
+ int arg1;
+ int arg2;
+ int arg3;
+ caddr_t ptr;
+};
+
+int
+linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ return ENOSYS;
+}
+
+int
+linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmat_args {
+ int shmid;
+ void *shmaddr;
+ int shmflg;
+ } bsd_args;
+ int error;
+
+ bsd_args.shmid = args->arg1;
+ bsd_args.shmaddr = args->ptr;
+ bsd_args.shmflg = args->arg2;
+ if ((error = shmat(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
+ return error;
+ retval[0] = 0;
+ return 0;
+}
+
+int
+linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmdt_args {
+ void *shmaddr;
+ } bsd_args;
+
+ bsd_args.shmaddr = args->ptr;
+ return shmdt(p, &bsd_args, retval);
+}
+
+int
+linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmget_args {
+ key_t key;
+ int size;
+ int shmflg;
+ } bsd_args;
+
+ bsd_args.key = args->arg1;
+ bsd_args.size = args->arg2;
+ bsd_args.shmflg = args->arg3;
+ return shmget(p, &bsd_args, retval);
+}
+
+int
+linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ struct shmid_ds bsd_shmid;
+ struct linux_shmid_ds linux_shmid;
+ struct shmctl_args {
+ int shmid;
+ int cmd;
+ struct shmid_ds *buf;
+ } bsd_args;
+ int error;
+
+ switch (args->arg2) {
+ case LINUX_IPC_STAT:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_STAT;
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = shmctl(p, &bsd_args, retval)))
+ return error;
+ if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
+ return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
+
+ case LINUX_IPC_SET:
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_SET;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_RMID:
+ bsd_args.shmid = args->arg1;
+ bsd_args.cmd = IPC_RMID;
+ if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
+ sizeof(linux_shmid))))
+ return error;
+ linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
+ bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
+ sizeof(struct shmid_ds))))
+ return error;
+ return shmctl(p, &bsd_args, retval);
+
+ case LINUX_IPC_INFO:
+ case LINUX_SHM_STAT:
+ case LINUX_SHM_INFO:
+ case LINUX_SHM_LOCK:
+ case LINUX_SHM_UNLOCK:
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return EINVAL;
+ }
+}
+
+int
+linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
+{
+ switch (args->what) {
+ case LINUX_SEMOP:
+ return linux_semop(p, args, retval);
+ case LINUX_SEMGET:
+ return linux_semget(p, args, retval);
+ case LINUX_SEMCTL:
+ return linux_semctl(p, args, retval);
+ case LINUX_MSGSND:
+ return linux_msgsnd(p, args, retval);
+ case LINUX_MSGRCV:
+ return linux_msgrcv(p, args, retval);
+ case LINUX_MSGGET:
+ return linux_msgget(p, args, retval);
+ case LINUX_MSGCTL:
+ return linux_msgctl(p, args, retval);
+ case LINUX_SHMAT:
+ return linux_shmat(p, args, retval);
+ case LINUX_SHMDT:
+ return linux_shmdt(p, args, retval);
+ case LINUX_SHMGET:
+ return linux_shmget(p, args, retval);
+ case LINUX_SHMCTL:
+ return linux_shmctl(p, args, retval);
+ default:
+ uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c
new file mode 100644
index 0000000..bf40786
--- /dev/null
+++ b/sys/i386/linux/linux_misc.c
@@ -0,0 +1,660 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_misc.c,v 1.4 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/mman.h>
+#include <sys/proc.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/imgact_aout.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/utsname.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <vm/vm.h>
+#include <vm/vm_kern.h>
+
+
+struct linux_alarm_args {
+ unsigned int secs;
+};
+
+int
+linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
+{
+ extern struct timeval time;
+ struct itimerval it, old_it;
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs);
+#endif
+ it.it_value.tv_sec = (long)args->secs;
+ it.it_value.tv_usec = 0;
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ s = splclock();
+ old_it = p->p_realtimer;
+ if (timerisset(&old_it.it_value))
+ if (timercmp(&old_it.it_value, &time, <))
+ timerclear(&old_it.it_value);
+ else
+ timevalsub(&old_it.it_value, &time);
+ splx(s);
+ if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
+ return EINVAL;
+ s = splclock();
+ untimeout(realitexpire, (caddr_t)p);
+ if (timerisset(&it.it_value)) {
+ timevaladd(&it.it_value, &time);
+ timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
+ }
+ p->p_realtimer = it;
+ splx(s);
+ if (old_it.it_value.tv_usec)
+ old_it.it_value.tv_sec++;
+ *retval = old_it.it_value.tv_sec;
+ return 0;
+}
+
+struct linux_brk_args {
+ linux_caddr_t dsend;
+};
+
+int
+linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
+{
+#if 0
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ int error;
+ extern int swap_pager_full;
+
+ if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
+ return EINVAL;
+ if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
+ > p->p_rlimit[RLIMIT_DATA].rlim_cur)
+ return ENOMEM;
+
+ old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
+ new = round_page((vm_offset_t)args->dsend);
+ *retval = old;
+ if ((new-old) > 0) {
+ if (swap_pager_full)
+ return ENOMEM;
+ error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE);
+ if (error)
+ return error;
+ vm->vm_dsize += btoc((new-old));
+ *retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
+ }
+ return 0;
+#else
+ struct vmspace *vm = p->p_vmspace;
+ vm_offset_t new, old;
+ struct obreak_args {
+ vm_offset_t newsize;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend);
+#endif
+ old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
+ new = (vm_offset_t)args->dsend;
+ tmp.newsize = new;
+ if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval))
+ retval[0] = (int)new;
+ else
+ retval[0] = (int)old;
+
+ return 0;
+#endif
+}
+
+struct linux_uselib_args {
+ char *library;
+};
+
+int
+linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
+{
+ struct nameidata ni;
+ struct vnode *vnodep;
+ struct exec *a_out = 0;
+ struct vattr attr;
+ unsigned long vmaddr, virtual_offset, file_offset;
+ unsigned long buffer, bss_size;
+ char *ptr;
+ char path[MAXPATHLEN];
+ const char *prefix = "/compat/linux";
+ size_t sz, len;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
+#endif
+
+ for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ;
+ sz = MAXPATHLEN - (ptr - path);
+ if (error = copyinstr(args->library, ptr, sz, &len))
+ return error;
+ if (*ptr != '/')
+ return EINVAL;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path);
+#endif
+
+ NDINIT(&ni, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
+ if (error = namei(&ni))
+ return error;
+
+ vnodep = ni.ni_vp;
+ if (vnodep == NULL)
+ return ENOEXEC;
+
+ if (vnodep->v_writecount)
+ return ETXTBSY;
+
+ if (error = VOP_GETATTR(vnodep, &attr, p->p_ucred, p))
+ return error;
+
+ if ((vnodep->v_mount->mnt_flag & MNT_NOEXEC)
+ || ((attr.va_mode & 0111) == 0)
+ || (attr.va_type != VREG))
+ return ENOEXEC;
+
+ if (attr.va_size == 0)
+ return ENOEXEC;
+
+ if (error = VOP_ACCESS(vnodep, VEXEC, p->p_ucred, p))
+ return error;
+
+ if (error = VOP_OPEN(vnodep, FREAD, p->p_ucred, p))
+ return error;
+
+ error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, 1024,
+ VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vnodep, 0);
+ if (error)
+ return (error);
+
+ /*
+ * Is it a Linux binary ?
+ */
+ if (((a_out->a_magic >> 16) & 0xff) != 0x64)
+ return -1;
+
+ /*
+ * Set file/virtual offset based on a.out variant.
+ */
+ switch ((int)(a_out->a_magic & 0xffff)) {
+ case 0413: /* ZMAGIC */
+ virtual_offset = 0;
+ file_offset = 1024;
+ break;
+ case 0314: /* QMAGIC */
+ virtual_offset = 4096;
+ file_offset = 0;
+ break;
+ default:
+ return (-1);
+ }
+
+ vnodep->v_flag |= VTEXT;
+ bss_size = round_page(a_out->a_bss);
+ /*
+ * Check if file_offset page aligned,.
+ * Currently we cannot handle misalinged file offsets,
+ * and so we read in the entire image (what a waste).
+ */
+ if (file_offset & PGOFSET) {
+#ifdef DEBUG
+printf("uselib: Non page aligned binary %d\n", file_offset);
+#endif
+ /*
+ * Map text+data read/write/execute
+ */
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ round_page(a_out->a_text + a_out->a_data), FALSE);
+ if (error)
+ return error;
+
+ error = vm_mmap(kernel_map, &buffer,
+ round_page(a_out->a_text + a_out->a_data + file_offset),
+ VM_PROT_READ, VM_PROT_READ, MAP_FILE,
+ (caddr_t)vnodep, trunc_page(file_offset));
+ if (error)
+ return error;
+
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ a_out->a_text + a_out->a_data);
+ if (error)
+ return error;
+
+ vm_map_remove(kernel_map, trunc_page(vmaddr),
+ round_page(a_out->a_text + a_out->a_data + file_offset));
+
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr,
+ round_page(a_out->a_text + a_out->a_data),
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ else {
+#ifdef DEBUG
+printf("uselib: Page aligned binary %d\n", file_offset);
+#endif
+ vmaddr = virtual_offset + round_page(a_out->a_entry);
+ error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
+ a_out->a_text + a_out->a_data,
+ VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
+ (caddr_t)vnodep, file_offset);
+ if (error)
+ return (error);
+ }
+#ifdef DEBUG
+printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
+#endif
+ if (bss_size != 0) {
+ vmaddr = virtual_offset + round_page(a_out->a_entry) +
+ round_page(a_out->a_text + a_out->a_data);
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ bss_size, FALSE);
+ if (error)
+ return error;
+ error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr, bss_size,
+ VM_PROT_ALL, TRUE);
+ if (error)
+ return error;
+ }
+ return 0;
+}
+
+struct linux_select_args {
+ void *ptr;
+};
+
+int
+linux_select(struct proc *p, struct linux_select_args *args, int *retval)
+{
+ struct {
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ struct timeval *timeout;
+ } linux_args;
+ struct {
+ unsigned int nd;
+ fd_set *in;
+ fd_set *ou;
+ fd_set *ex;
+ struct timeval *tv;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n",
+ p->p_pid, linux_args.nfds, linux_args.readfds,
+ linux_args.writefds, linux_args.exceptfds,
+ linux_args.timeout);
+#endif
+ bsd_args.nd = linux_args.nfds;
+ bsd_args.in = linux_args.readfds;
+ bsd_args.ou = linux_args.writefds;
+ bsd_args.ex = linux_args.exceptfds;
+ bsd_args.tv = linux_args.timeout;
+ return select(p, &bsd_args, retval);
+}
+
+struct linux_getpgid_args {
+ int pid;
+};
+
+int
+linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
+{
+ struct proc *curproc;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid);
+#endif
+ if (args->pid != p->p_pid) {
+ if (!(curproc = pfind(args->pid)))
+ return ESRCH;
+ }
+ else
+ curproc = p;
+ *retval = curproc->p_pgid;
+ return 0;
+}
+
+int
+linux_fork(struct proc *p, void *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fork()\n", p->p_pid);
+#endif
+ if (error = fork(p, args, retval))
+ return error;
+ if (retval[1] == 1)
+ retval[0] = 0;
+ return 0;
+}
+
+struct linux_mmap_args {
+ void *ptr;
+};
+
+int
+linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
+{
+ struct {
+ linux_caddr_t addr;
+ int len;
+ int prot;
+ int flags;
+ int fd;
+ int pos;
+ } linux_args;
+ struct {
+ caddr_t addr;
+ size_t len;
+ int prot;
+ int flags;
+ int fd;
+ long pad;
+ off_t pos;
+ } bsd_args;
+ int error;
+
+ if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
+ sizeof(linux_args))))
+ return error;
+#ifdef DEBUG
+ printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
+ p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
+ linux_args.flags, linux_args.fd, linux_args.pos);
+#endif
+ bsd_args.flags = 0;
+ if (linux_args.flags & LINUX_MAP_SHARED)
+ bsd_args.flags |= MAP_SHARED;
+ if (linux_args.flags & LINUX_MAP_PRIVATE)
+ bsd_args.flags |= MAP_PRIVATE;
+ if (linux_args.flags & LINUX_MAP_FIXED)
+ bsd_args.flags |= MAP_FIXED;
+ if (linux_args.flags & LINUX_MAP_ANON)
+ bsd_args.flags |= MAP_ANON;
+ bsd_args.addr = linux_args.addr;
+ bsd_args.len = linux_args.len;
+ bsd_args.prot = linux_args.prot;
+ bsd_args.fd = linux_args.fd;
+ bsd_args.pos = linux_args.pos;
+ bsd_args.pad = 0;
+ return mmap(p, &bsd_args, retval);
+}
+
+struct linux_pipe_args {
+ int *pipefds;
+};
+
+int
+linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
+{
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): pipe(*)\n", p->p_pid);
+#endif
+ if (error = pipe(p, 0, retval))
+ return error;
+ if (error = copyout(retval, args->pipefds, 2*sizeof(int)))
+ return error;
+ *retval = 0;
+ return 0;
+}
+
+struct linux_time_args {
+ linux_time_t *tm;
+};
+
+int
+linux_time(struct proc *p, struct linux_time_args *args, int *retval)
+{
+ struct timeval tv;
+ linux_time_t tm;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): time(*)\n", p->p_pid);
+#endif
+ microtime(&tv);
+ tm = tv.tv_sec;
+ if (error = copyout(&tm, args->tm, sizeof(linux_time_t)))
+ return error;
+ *retval = tv.tv_sec;
+ return 0;
+}
+
+struct linux_tms {
+ long tms_utime;
+ long tms_stime;
+ long tms_cutime;
+ long tms_cstime;
+};
+
+struct linux_tms_args {
+ char *buf;
+};
+
+int
+linux_times(struct proc *p, struct linux_tms_args *args, int *retval)
+{
+ extern int hz;
+ struct timeval tv;
+ struct linux_tms tms;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): times(*)\n", p->p_pid);
+#endif
+ tms.tms_utime = p->p_uticks;
+ tms.tms_stime = p->p_sticks;
+ tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000);
+ tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz +
+ ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000);
+ microtime(&tv);
+ *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
+ return (copyout((caddr_t)&tms, (caddr_t)args->buf,
+ sizeof(struct linux_tms)));
+}
+
+struct linux_newuname_t {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+ char domainname[65];
+};
+
+struct linux_newuname_args {
+ char *buf;
+};
+
+int
+linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
+{
+ struct linux_newuname_t linux_newuname;
+ extern char ostype[], osrelease[], machine[];
+ extern char hostname[], domainname[];
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newuname(*)\n", p->p_pid);
+#endif
+ bzero(&linux_newuname, sizeof(struct linux_newuname_args));
+ strncpy(linux_newuname.sysname, ostype, 64);
+ strncpy(linux_newuname.nodename, hostname, 64);
+ strncpy(linux_newuname.release, osrelease, 64);
+ strncpy(linux_newuname.version, version, 64);
+ strncpy(linux_newuname.machine, machine, 64);
+ strncpy(linux_newuname.domainname, domainname, 64);
+ return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf,
+ sizeof(struct linux_newuname_t)));
+}
+
+struct linux_utime_args {
+ char *fname;
+ linux_time_t *timeptr;
+};
+
+int
+linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
+{
+ struct bsd_utimes_args {
+ char *fname;
+ struct timeval *tptr;
+ } bsdutimes;
+ struct timeval tv;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
+#endif
+ tv.tv_sec = (long)args->timeptr;
+ tv.tv_usec = 0;
+ bsdutimes.tptr = &tv;
+ bsdutimes.fname = args->fname;
+ return utimes(p, &bsdutimes, retval);
+}
+
+struct linux_waitpid_args {
+ int pid;
+ int *status;
+ int options;
+};
+
+int
+linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): waitpid(%d, *, %d)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = NULL;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
+
+struct linux_wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+};
+
+int
+linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
+{
+ struct wait4_args {
+ int pid;
+ int *status;
+ int options;
+ struct rusage *rusage;
+ int compat;
+ } tmp;
+ int error, tmpstat;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): wait4(%d, *, %d, *)\n",
+ p->p_pid, args->pid, args->options);
+#endif
+ tmp.pid = args->pid;
+ tmp.status = args->status;
+ tmp.options = args->options;
+ tmp.rusage = args->rusage;
+ tmp.compat = 0;
+
+ if (error = wait4(p, &tmp, retval))
+ return error;
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+}
diff --git a/sys/i386/linux/linux_signal.c b/sys/i386/linux/linux_signal.c
new file mode 100644
index 0000000..528bb62
--- /dev/null
+++ b/sys/i386/linux/linux_signal.c
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_signal.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/exec.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+
+#include <vm/vm.h>
+
+#include <i386/linux/linux.h>
+
+#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
+
+static sigset_t
+linux_to_bsd_sigmask(linux_sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= LINUX_NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (linux_to_bsd_signal[i]-1));
+ return new;
+}
+
+static linux_sigset_t
+bsd_to_linux_sigmask(sigset_t mask) {
+ int i;
+ sigset_t new = 0;
+
+ for (i = 1; i <= NSIG; i++)
+ if (mask & (1 << i-1))
+ new |= (1 << (bsd_to_linux_signal[i]-1));
+ return new;
+}
+
+struct linux_sigaction_args {
+ int sig;
+ linux_sigaction_t *nsa;
+ linux_sigaction_t *osa;
+};
+
+int
+linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
+{
+ linux_sigaction_t linux_sa;
+ struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
+ struct sigaction_args {
+ int sig;
+ struct sigaction *nsa;
+ struct sigaction *osa;
+ } sa;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
+#endif
+ if (args->osa)
+ osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
+
+ if (args->nsa) {
+ nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
+ if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
+ return error;
+ bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
+ bsd_sa.sa_handler = linux_sa.sa_handler;
+ bsd_sa.sa_flags = 0;
+ if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
+ bsd_sa.sa_flags |= SA_NOCLDSTOP;
+ if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
+ bsd_sa.sa_flags |= SA_ONSTACK;
+ if (linux_sa.sa_flags & LINUX_SA_RESTART)
+ bsd_sa.sa_flags |= SA_RESTART;
+ if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
+ return error;
+ }
+ sa.sig = linux_to_bsd_signal[args->sig];
+ sa.nsa = nsa;
+ sa.osa = osa;
+ if ((error = sigaction(p, &sa, retval)))
+ return error;
+
+ if (args->osa) {
+ if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
+ return error;
+ linux_sa.sa_handler = bsd_sa.sa_handler;
+ linux_sa.sa_restorer = NULL;
+ linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
+ linux_sa.sa_flags = 0;
+ if (bsd_sa.sa_flags & SA_NOCLDSTOP)
+ linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsd_sa.sa_flags & SA_ONSTACK)
+ linux_sa.sa_flags |= LINUX_SA_ONSTACK;
+ if (bsd_sa.sa_flags & SA_RESTART)
+ linux_sa.sa_flags |= LINUX_SA_RESTART;
+ if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
+ return error;
+ }
+ return 0;
+}
+
+struct linux_sigprocmask_args {
+ int how;
+ linux_sigset_t *mask;
+ linux_sigset_t *omask;
+};
+
+int
+linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
+ int *retval)
+{
+ int error, s;
+ sigset_t mask;
+ sigset_t omask;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
+#endif
+ if (args->omask != NULL) {
+ omask = bsd_to_linux_sigmask(p->p_sigmask);
+ if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
+ return error;
+ }
+ if (!(args->mask))
+ return 0;
+ if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
+ return error;
+
+ mask = linux_to_bsd_sigmask(mask);
+ s = splhigh();
+ switch (args->how) {
+ case LINUX_SIG_BLOCK:
+ p->p_sigmask |= (mask & ~DONTMASK);
+ break;
+ case LINUX_SIG_UNBLOCK:
+ p->p_sigmask &= ~mask;
+ break;
+ case LINUX_SIG_SETMASK:
+ p->p_sigmask = (mask & ~DONTMASK);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(s);
+ return error;
+}
+
+int
+linux_siggetmask(struct proc *p, void *args, int *retval)
+{
+#ifdef DEBUG
+ printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
+#endif
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigsetmask_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
+{
+ int s;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
+#endif
+ s = splhigh();
+ p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK);
+ splx(s);
+ *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ return 0;
+}
+
+struct linux_sigpending_args {
+ linux_sigset_t *mask;
+};
+
+int
+linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
+{
+ linux_sigset_t linux_sig;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
+#endif
+ linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask);
+ return copyout(&linux_sig, args->mask, sizeof(linux_sig));
+}
+
+struct linux_sigsuspend_args {
+ linux_sigset_t mask;
+};
+
+int
+linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
+{
+ sigset_t tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
+#endif
+ tmp = linux_to_bsd_sigmask(args->mask);
+ return sigsuspend(p, &tmp , retval);
+}
+
+struct linux_kill_args {
+ int pid;
+ int signum;
+};
+
+int
+linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
+{
+ struct {
+ int pid;
+ int signum;
+ } tmp;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): kill(%d, %d)\n",
+ p->p_pid, args->pid, args->signum);
+#endif
+ tmp.pid = args->pid;
+ tmp.signum = linux_to_bsd_signal[args->signum];
+ return kill(p, &tmp, retval);
+}
diff --git a/sys/i386/linux/linux_socket.c b/sys/i386/linux/linux_socket.c
new file mode 100644
index 0000000..9267063
--- /dev/null
+++ b/sys/i386/linux/linux_socket.c
@@ -0,0 +1,595 @@
+/*-
+ * Copyright (c) 1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_socket.c,v 1.2 1995/06/07 21:27:57 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <netinet/in.h>
+
+
+static int
+linux_to_bsd_domain(int domain)
+{
+ switch (domain) {
+ case LINUX_AF_UNSPEC:
+ return AF_UNSPEC;
+ case LINUX_AF_UNIX:
+ return AF_LOCAL;
+ case LINUX_AF_INET:
+ return AF_INET;
+ case LINUX_AF_AX25:
+ return AF_CCITT;
+ case LINUX_AF_IPX:
+ return AF_IPX;
+ case LINUX_AF_APPLETALK:
+ return AF_APPLETALK;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_sockopt_level(int level)
+{
+ switch (level) {
+ case LINUX_SOL_SOCKET:
+ return SOL_SOCKET;
+ default:
+ return level;
+ }
+}
+
+static int linux_to_bsd_ip_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_IP_TOS:
+ return IP_TOS;
+ case LINUX_IP_TTL:
+ return IP_TTL;
+ default:
+ return -1;
+ }
+}
+
+static int
+linux_to_bsd_so_sockopt(int opt)
+{
+ switch (opt) {
+ case LINUX_SO_DEBUG:
+ return SO_DEBUG;
+ case LINUX_SO_REUSEADDR:
+ return SO_REUSEADDR;
+ case LINUX_SO_TYPE:
+ return SO_TYPE;
+ case LINUX_SO_ERROR:
+ return SO_ERROR;
+ case LINUX_SO_DONTROUTE:
+ return SO_DONTROUTE;
+ case LINUX_SO_BROADCAST:
+ return SO_BROADCAST;
+ case LINUX_SO_SNDBUF:
+ return SO_SNDBUF;
+ case LINUX_SO_RCVBUF:
+ return SO_RCVBUF;
+ case LINUX_SO_KEEPALIVE:
+ return SO_KEEPALIVE;
+ case LINUX_SO_OOBINLINE:
+ return SO_OOBINLINE;
+ case LINUX_SO_LINGER:
+ return SO_LINGER;
+ case LINUX_SO_PRIORITY:
+ case LINUX_SO_NO_CHECK:
+ default:
+ return -1;
+ }
+}
+
+struct linux_socket_args {
+ int domain;
+ int type;
+ int protocol;
+};
+
+static int
+linux_socket(struct proc *p, struct linux_socket_args *args, int *retval)
+{
+ struct linux_socket_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.type = linux_args.type;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ return socket(p, &bsd_args, retval);
+}
+
+struct linux_bind_args {
+ int s;
+ struct sockaddr *name;
+ int namelen;
+};
+
+static int
+linux_bind(struct proc *p, struct linux_bind_args *args, int *retval)
+{
+ struct linux_bind_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return bind(p, &bsd_args, retval);
+}
+
+struct linux_connect_args {
+ int s;
+ struct sockaddr * name;
+ int namelen;
+};
+
+static int
+linux_connect(struct proc *p, struct linux_connect_args *args, int *retval)
+{
+ struct linux_connect_args linux_args;
+ struct {
+ int s;
+ caddr_t name;
+ int namelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.name;
+ bsd_args.namelen = linux_args.namelen;
+ return connect(p, &bsd_args, retval);
+}
+
+struct linux_listen_args {
+ int s;
+ int backlog;
+};
+
+static int
+linux_listen(struct proc *p, struct linux_listen_args *args, int *retval)
+{
+ struct linux_listen_args linux_args;
+ struct {
+ int s;
+ int backlog;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.backlog = linux_args.backlog;
+ return listen(p, &bsd_args, retval);
+}
+
+struct linux_accept_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_accept(struct proc *p, struct linux_accept_args *args, int *retval)
+{
+ struct linux_accept_args linux_args;
+ struct accept_args {
+ int s;
+ caddr_t name;
+ int *anamelen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.name = (caddr_t)linux_args.addr;
+ bsd_args.anamelen = linux_args.namelen;
+ return oaccept(p, &bsd_args, retval);
+}
+
+struct linux_getsockname_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getsockname(struct proc *p, struct linux_getsockname_args *args, int *retval)
+{
+ struct linux_getsockname_args linux_args;
+ struct {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetsockname(p, &bsd_args, retval);
+}
+
+struct linux_getpeername_args {
+ int s;
+ struct sockaddr *addr;
+ int *namelen;
+};
+
+static int
+linux_getpeername(struct proc *p, struct linux_getpeername_args *args, int *retval)
+{
+ struct linux_getpeername_args linux_args;
+ struct getpeername_args {
+ int fdes;
+ caddr_t asa;
+ int *alen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.fdes = linux_args.s;
+ bsd_args.asa = (caddr_t) linux_args.addr;
+ bsd_args.alen = linux_args.namelen;
+ return ogetpeername(p, &bsd_args, retval);
+}
+
+struct linux_socketpair_args {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+};
+
+static int
+linux_socketpair(struct proc *p, struct linux_socketpair_args *args, int *retval)
+{
+ struct linux_socketpair_args linux_args;
+ struct {
+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.domain = linux_to_bsd_domain(linux_args.domain);
+ if (bsd_args.domain == -1)
+ return EINVAL;
+ bsd_args.type = linux_args.type;
+ bsd_args.protocol = linux_args.protocol;
+ bsd_args.rsv = linux_args.rsv;
+ return socketpair(p, &bsd_args, retval);
+}
+
+struct linux_send_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_send(struct proc *p, struct linux_send_args *args, int *retval)
+{
+ struct linux_send_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return osend(p, &bsd_args, retval);
+}
+
+struct linux_recv_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+};
+
+static int
+linux_recv(struct proc *p, struct linux_recv_args *args, int *retval)
+{
+ struct linux_recv_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ return orecv(p, &bsd_args, retval);
+}
+
+struct linux_sendto_args {
+ int s;
+ void *msg;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+};
+
+static int
+linux_sendto(struct proc *p, struct linux_sendto_args *args, int *retval)
+{
+ struct linux_sendto_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.msg;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.to = linux_args.to;
+ bsd_args.tolen = linux_args.tolen;
+ return sendto(p, &bsd_args, retval);
+}
+
+struct linux_recvfrom_args {
+ int s;
+ void *buf;
+ int len;
+ int flags;
+ caddr_t from;
+ int *fromlen;
+};
+
+static int
+linux_recvfrom(struct proc *p, struct linux_recvfrom_args *args, int *retval)
+{
+ struct linux_recvfrom_args linux_args;
+ struct {
+ int s;
+ caddr_t buf;
+ size_t len;
+ int flags;
+ caddr_t from;
+ int *fromlenaddr;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.buf = linux_args.buf;
+ bsd_args.len = linux_args.len;
+ bsd_args.flags = linux_args.flags;
+ bsd_args.from = linux_args.from;
+ bsd_args.fromlenaddr = linux_args.fromlen;
+ return orecvfrom(p, &bsd_args, retval);
+}
+
+struct linux_shutdown_args {
+ int s;
+ int how;
+};
+
+static int
+linux_shutdown(struct proc *p, struct linux_shutdown_args *args, int *retval)
+{
+ struct linux_shutdown_args linux_args;
+ struct {
+ int s;
+ int how;
+ } bsd_args;
+ int error;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.how = linux_args.how;
+ return shutdown(p, &bsd_args, retval);
+}
+
+struct linux_setsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int optlen;
+};
+
+static int
+linux_setsockopt(struct proc *p, struct linux_setsockopt_args *args, int *retval)
+{
+ struct linux_setsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int valsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.name = name;
+ bsd_args.val = linux_args.optval;
+ bsd_args.valsize = linux_args.optlen;
+ return setsockopt(p, &bsd_args, retval);
+}
+
+struct linux_getsockopt_args {
+ int s;
+ int level;
+ int optname;
+ void *optval;
+ int *optlen;
+};
+
+static int
+linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval)
+{
+ struct linux_getsockopt_args linux_args;
+ struct {
+ int s;
+ int level;
+ int name;
+ caddr_t val;
+ int *avalsize;
+ } bsd_args;
+ int error, name;
+
+ if ((error=copyin((caddr_t)args, (caddr_t)&linux_args, sizeof(linux_args))))
+ return error;
+ bsd_args.s = linux_args.s;
+ bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level);
+ switch (bsd_args.level) {
+ case SOL_SOCKET:
+ name = linux_to_bsd_so_sockopt(linux_args.optname);
+ break;
+ case IPPROTO_IP:
+ name = linux_to_bsd_ip_sockopt(linux_args.optname);
+ break;
+ default:
+ return EINVAL;
+ }
+ if (name == -1)
+ return EINVAL;
+ bsd_args.val = linux_args.optval;
+ bsd_args.avalsize = linux_args.optlen;
+ return getsockopt(p, &bsd_args, retval);
+}
+
+struct linux_socketcall_args {
+ int what;
+ void *args;
+};
+
+int
+linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
+{
+ switch (args->what) {
+ case LINUX_SOCKET:
+ return linux_socket(p, args->args, retval);
+ case LINUX_BIND:
+ return linux_bind(p, args->args, retval);
+ case LINUX_CONNECT:
+ return linux_connect(p, args->args, retval);
+ case LINUX_LISTEN:
+ return linux_listen(p, args->args, retval);
+ case LINUX_ACCEPT:
+ return linux_accept(p, args->args, retval);
+ case LINUX_GETSOCKNAME:
+ return linux_getsockname(p, args->args, retval);
+ case LINUX_GETPEERNAME:
+ return linux_getpeername(p, args->args, retval);
+ case LINUX_SOCKETPAIR:
+ return linux_socketpair(p, args->args, retval);
+ case LINUX_SEND:
+ return linux_send(p, args->args, retval);
+ case LINUX_RECV:
+ return linux_recv(p, args->args, retval);
+ case LINUX_SENDTO:
+ return linux_sendto(p, args->args, retval);
+ case LINUX_RECVFROM:
+ return linux_recvfrom(p, args->args, retval);
+ case LINUX_SHUTDOWN:
+ return linux_shutdown(p, args->args, retval);
+ case LINUX_SETSOCKOPT:
+ return linux_setsockopt(p, args->args, retval);
+ case LINUX_GETSOCKOPT:
+ return linux_getsockopt(p, args->args, retval);
+ default:
+ uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what);
+ return ENOSYS;
+ }
+}
diff --git a/sys/i386/linux/linux_stats.c b/sys/i386/linux/linux_stats.c
new file mode 100644
index 0000000..1dbfcf1
--- /dev/null
+++ b/sys/i386/linux/linux_stats.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_stats.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/stat.h>
+#include <sys/vnode.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+
+#include <i386/linux/linux.h>
+
+struct linux_newstat {
+ unsigned short stat_dev;
+ unsigned short __pad1;
+ unsigned long stat_ino;
+ unsigned short stat_mode;
+ unsigned short stat_nlink;
+ unsigned short stat_uid;
+ unsigned short stat_gid;
+ unsigned short stat_rdev;
+ unsigned short __pad2;
+ unsigned long stat_size;
+ unsigned long stat_blksize;
+ unsigned long stat_blocks;
+ unsigned long stat_atime;
+ unsigned long __unused1;
+ unsigned long stat_mtime;
+ unsigned long __unused2;
+ unsigned long stat_ctime;
+ unsigned long __unused3;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct linux_newstat_args {
+ char *path;
+ struct linux_newstat *buf;
+};
+
+static int
+newstat_copyout(struct stat *buf, void *ubuf)
+{
+ struct linux_newstat tbuf;
+
+ tbuf.stat_dev = (buf->st_dev & 0xff) | ((buf->st_dev & 0xff00)<<10);
+ tbuf.stat_ino = buf->st_ino;
+ tbuf.stat_mode = buf->st_mode;
+ tbuf.stat_nlink = buf->st_nlink;
+ tbuf.stat_uid = buf->st_uid;
+ tbuf.stat_gid = buf->st_gid;
+ tbuf.stat_rdev = buf->st_rdev;
+ tbuf.stat_size = buf->st_size;
+ tbuf.stat_atime = buf->st_atime;
+ tbuf.stat_mtime = buf->st_mtime;
+ tbuf.stat_ctime = buf->st_ctime;
+ tbuf.stat_blksize = buf->st_blksize;
+ tbuf.stat_blocks = buf->st_blocks;
+ return copyout(&tbuf, ubuf, sizeof(tbuf));
+}
+
+int
+linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+int
+linux_newlstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+{
+ struct stat buf;
+ struct linux_newstat tbuf;
+ struct nameidata nd;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, args->path);
+#endif
+ NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
+ error = namei(&nd);
+ if (!error) {
+ error = vn_stat(nd.ni_vp, &buf, p);
+ vput(nd.ni_vp);
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_newfstat_args {
+ int fd;
+ struct linux_newstat *buf;
+};
+
+int
+linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
+{
+ struct linux_newstat tbuf;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct stat buf;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): newlstat(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if ((unsigned)args->fd >= fdp->fd_nfiles
+ || (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return EBADF;
+ switch (fp->f_type) {
+ case DTYPE_VNODE:
+ error = vn_stat((struct vnode *)fp->f_data, &buf, p);
+ break;
+ case DTYPE_SOCKET:
+ error = soo_stat((struct socket *)fp->f_data, &buf);
+ break;
+ default:
+ panic("LINUX newfstat");
+ }
+ if (!error)
+ error = newstat_copyout(&buf, args->buf);
+ return error;
+}
+
+struct linux_statfs {
+ long ftype;
+ long fbsize;
+ long fblocks;
+ long fbfree;
+ long fbavail;
+ long ffiles;
+ long fffree;
+ linux_fsid_t ffsid;
+ long fnamelen;
+ long fspare[6];
+};
+
+
+struct linux_statfs_args {
+ char *path;
+ struct statfs *buf;
+};
+
+int
+linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
+{
+ struct mount *mp;
+ struct nameidata *ndp;
+ struct statfs *bsd_statfs;
+ struct nameidata nd;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
+#endif
+ ndp = &nd;
+ ndp->ni_cnd.cn_nameiop = LOOKUP;
+ ndp->ni_cnd.cn_flags = FOLLOW;
+ ndp->ni_cnd.cn_proc = curproc;
+ ndp->ni_cnd.cn_cred = curproc->p_cred->pc_ucred;
+ ndp->ni_segflg = UIO_USERSPACE;
+ ndp->ni_dirp = args->path;
+ if (error = namei(ndp))
+ return error;
+ mp = ndp->ni_vp->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ vrele(ndp->ni_vp);
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
+
+struct linux_fstatfs_args {
+ int fd;
+ struct statfs *buf;
+};
+
+int
+linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
+{
+ struct file *fp;
+ struct mount *mp;
+ struct statfs *bsd_statfs;
+ struct linux_statfs linux_statfs;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): fstatfs(%d, *)\n", p->p_pid, args->fd);
+#endif
+ if (error = getvnode(p->p_fd, args->fd, &fp))
+ return error;
+ mp = ((struct vnode *)fp->f_data)->v_mount;
+ bsd_statfs = &mp->mnt_stat;
+ if (error = VFS_STATFS(mp, bsd_statfs, p))
+ return error;
+ bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+ linux_statfs.ftype = bsd_statfs->f_type;
+ linux_statfs.fbsize = bsd_statfs->f_bsize;
+ linux_statfs.fblocks = bsd_statfs->f_blocks;
+ linux_statfs.fbfree = bsd_statfs->f_bfree;
+ linux_statfs.fbavail = bsd_statfs->f_bavail;
+ linux_statfs.fffree = bsd_statfs->f_ffree;
+ linux_statfs.ffiles = bsd_statfs->f_files;
+ linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
+ sizeof(struct linux_statfs));
+}
diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c
new file mode 100644
index 0000000..015d49a
--- /dev/null
+++ b/sys/i386/linux/linux_sysent.c
@@ -0,0 +1,367 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux_sysent.c,v 1.3 1995/06/08 13:50:52 sos Exp $
+ */
+
+#include <i386/linux/linux.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysent.h>
+#include <sys/imgact.h>
+#include <sys/errno.h>
+#include <sys/signal.h>
+
+extern int access();
+extern int acct();
+extern int linux_adjtimex();
+extern int linux_alarm();
+extern int linux_bdflush();
+extern int linux_break();
+extern int linux_brk();
+extern int chdir();
+extern int chmod();
+extern int chown();
+extern int chroot();
+extern int linux_clone();
+extern int close();
+extern int linux_creat();
+extern int linux_create_module();
+extern int linux_delete_module();
+extern int dup();
+extern int dup2();
+extern int execve();
+extern int exit();
+extern int fchdir();
+extern int fchmod();
+extern int fchown();
+extern int linux_fcntl();
+extern int linux_fork();
+extern int linux_fstat();
+extern int linux_fstatfs();
+extern int fsync();
+extern int linux_ftime();
+extern int oftruncate();
+extern int linux_get_kernel_syms();
+extern int getegid();
+extern int geteuid();
+extern int getgid();
+extern int getgroups();
+extern int getitimer();
+extern int linux_getpgid();
+extern int getpgrp();
+extern int getpid();
+extern int getppid();
+extern int getpriority();
+extern int ogetrlimit();
+extern int getrusage();
+extern int gettimeofday();
+extern int getuid();
+extern int linux_gtty();
+extern int linux_idle();
+extern int linux_init_module();
+extern int linux_ioctl();
+extern int linux_ioperm();
+extern int linux_iopl();
+extern int linux_ipc();
+extern int linux_kill();
+extern int link();
+extern int linux_lock();
+extern int linux_lseek();
+extern int ostat();
+extern int mkdir();
+extern int mknod();
+extern int linux_mmap();
+extern int linux_modify_ldt();
+extern int linux_mount();
+extern int mprotect();
+extern int linux_mpx();
+extern int munmap();
+extern int linux_newfstat();
+extern int linux_newlstat();
+extern int linux_newstat();
+extern int linux_newuname();
+extern int linux_nice();
+extern int linux_olduname();
+extern int linux_open();
+extern int linux_pause();
+extern int linux_phys();
+extern int linux_pipe();
+extern int linux_prof();
+extern int profil();
+extern int linux_ptrace();
+extern int linux_quotactl();
+extern int read();
+extern int linux_readdir();
+extern int readlink();
+extern int reboot();
+extern int rename();
+extern int rmdir();
+extern int linux_select();
+extern int setdomainname();
+extern int setgid();
+extern int setgroups();
+extern int osethostname();
+extern int setitimer();
+extern int setpgid();
+extern int setpriority();
+extern int setregid();
+extern int setreuid();
+extern int osetrlimit();
+extern int setsid();
+extern int settimeofday();
+extern int setuid();
+extern int sigreturn();
+extern int linux_setup();
+extern int linux_sigaction();
+extern int linux_siggetmask();
+extern int linux_signal();
+extern int linux_sigpending();
+extern int linux_sigprocmask();
+extern int linux_sigreturn();
+extern int linux_sigsetmask();
+extern int linux_sigsuspend();
+extern int linux_socketcall();
+extern int linux_stat();
+extern int linux_statfs();
+extern int linux_stime();
+extern int linux_stty();
+extern int linux_swapoff();
+extern int swapon();
+extern int symlink();
+extern int sync();
+extern int linux_sysinfo();
+extern int linux_syslog();
+extern int linux_time();
+extern int linux_times();
+extern int otruncate();
+extern int linux_ulimit();
+extern int umask();
+extern int linux_umount();
+extern int linux_uname();
+extern int unlink();
+extern int linux_uselib();
+extern int linux_ustat();
+extern int linux_utime();
+extern int linux_vhangup();
+extern int linux_vm86();
+extern int linux_wait4();
+extern int linux_waitpid();
+extern int write();
+
+static struct sysent linux_sysent[] = {
+ 0, linux_setup, /* 0 */
+ 1, exit, /* 1 */
+ 0, linux_fork, /* 2 */
+ 3, read, /* 3 */
+ 3, write, /* 4 */
+ 3, linux_open, /* 5 */
+ 1, close, /* 6 */
+ 3, linux_waitpid, /* 7 */
+ 2, linux_creat, /* 8 */
+ 2, link, /* 9 */
+ 1, unlink, /* 10 */
+ 3, execve, /* 11 */
+ 1, chdir, /* 12 */
+ 1, linux_time, /* 13 */
+ 3, mknod, /* 14 */
+ 2, chmod, /* 15 */
+ 3, chown, /* 16 */
+ 1, linux_break, /* 17 */
+ 2, linux_stat, /* 18 */
+ 3, linux_lseek, /* 19 */
+ 0, getpid, /* 20 */
+ 5, linux_mount, /* 21 */
+ 1, linux_umount, /* 22 */
+ 1, setuid, /* 23 */
+ 0, getuid, /* 24 */
+ 1, linux_stime, /* 25 */
+ 4, linux_ptrace, /* 26 */
+ 1, linux_alarm, /* 27 */
+ 2, linux_fstat, /* 28 */
+ 0, linux_pause, /* 29 */
+ 2, linux_utime, /* 30 */
+ 0, linux_stty, /* 31 */
+ 0, linux_gtty, /* 32 */
+ 2, access, /* 33 */
+ 1, linux_nice, /* 34 */
+ 0, linux_ftime, /* 35 */
+ 0, sync, /* 36 */
+ 2, linux_kill, /* 37 */
+ 2, rename, /* 38 */
+ 2, mkdir, /* 39 */
+ 1, rmdir, /* 40 */
+ 1, dup, /* 41 */
+ 1, linux_pipe, /* 42 */
+ 1, linux_times, /* 43 */
+ 0, linux_prof, /* 44 */
+ 1, linux_brk, /* 45 */
+ 1, setgid, /* 46 */
+ 0, getgid, /* 47 */
+ 2, linux_signal, /* 48 */
+ 0, geteuid, /* 49 */
+ 0, getegid, /* 50 */
+ 0, acct, /* 51 */
+ 0, linux_phys, /* 52 */
+ 0, linux_lock, /* 53 */
+ 3, linux_ioctl, /* 54 */
+ 3, linux_fcntl, /* 55 */
+ 0, linux_mpx, /* 56 */
+ 2, setpgid, /* 57 */
+ 0, linux_ulimit, /* 58 */
+ 1, linux_olduname, /* 59 */
+ 1, umask, /* 60 */
+ 1, chroot, /* 61 */
+ 2, linux_ustat, /* 62 */
+ 2, dup2, /* 63 */
+ 0, getppid, /* 64 */
+ 0, getpgrp, /* 65 */
+ 0, setsid, /* 66 */
+ 3, linux_sigaction, /* 67 */
+ 0, linux_siggetmask, /* 68 */
+ 1, linux_sigsetmask, /* 69 */
+ 2, setreuid, /* 70 */
+ 2, setregid, /* 71 */
+ 1, linux_sigsuspend, /* 72 */
+ 1, linux_sigpending, /* 73 */
+ 2, osethostname, /* 74 */
+ 2, osetrlimit, /* 75 */
+ 2, ogetrlimit, /* 76 */
+ 2, getrusage, /* 77 */
+ 2, gettimeofday, /* 78 */
+ 2, settimeofday, /* 79 */
+ 2, getgroups, /* 80 */
+ 2, setgroups, /* 81 */
+ 1, linux_select, /* 82 */
+ 2, symlink, /* 83 */
+ 2, ostat, /* 84 */
+ 3, readlink, /* 85 */
+ 1, linux_uselib, /* 86 */
+ 1, swapon, /* 87 */
+ 3, reboot, /* 88 */
+ 3, linux_readdir, /* 89 */
+ 1, linux_mmap, /* 90 */
+ 2, munmap, /* 91 */
+ 2, otruncate, /* 92 */
+ 2, oftruncate, /* 93 */
+ 2, fchmod, /* 94 */
+ 3, fchown, /* 95 */
+ 2, getpriority, /* 96 */
+ 3, setpriority, /* 97 */
+ 0, profil, /* 98 */
+ 2, linux_statfs, /* 99 */
+ 2, linux_fstatfs, /* 100 */
+ 3, linux_ioperm, /* 101 */
+ 2, linux_socketcall, /* 102 */
+ 3, linux_syslog, /* 103 */
+ 3, setitimer, /* 104 */
+ 2, getitimer, /* 105 */
+ 2, linux_newstat, /* 106 */
+ 2, linux_newlstat, /* 107 */
+ 2, linux_newfstat, /* 108 */
+ 2, linux_uname, /* 109 */
+ 1, linux_iopl, /* 110 */
+ 0, linux_vhangup, /* 111 */
+ 0, linux_idle, /* 112 */
+ 1, linux_vm86, /* 113 */
+ 4, linux_wait4, /* 114 */
+ 1, linux_swapoff, /* 115 */
+ 1, linux_sysinfo, /* 116 */
+ 4, linux_ipc, /* 117 */
+ 1, fsync, /* 118 */
+ 1, linux_sigreturn, /* 119 */
+ 0, linux_clone, /* 120 */
+ 2, setdomainname, /* 121 */
+ 1, linux_newuname, /* 122 */
+ 3, linux_modify_ldt, /* 123 */
+ 1, linux_adjtimex, /* 124 */
+ 3, mprotect, /* 125 */
+ 3, linux_sigprocmask, /* 126 */
+ 2, linux_create_module, /* 127 */
+ 4, linux_init_module, /* 128 */
+ 1, linux_delete_module, /* 129 */
+ 1, linux_get_kernel_syms, /* 130 */
+ 0, linux_quotactl, /* 131 */
+ 1, linux_getpgid, /* 132 */
+ 1, fchdir, /* 133 */
+ 0, linux_bdflush, /* 134 */
+};
+
+int bsd_to_linux_errno[ELAST] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 35, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 11,115,114, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100,101,102,103,104,105,106,107,108,109,
+ 110,111, 40, 36,112,113, 39, 11, 87,122,
+ 116, 66, 6, 6, 6, 6, 6, 37, 38, 9,
+ 6,
+};
+
+int bsd_to_linux_signal[NSIG] = {
+ 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_signal[LINUX_NSIG] = {
+ 0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
+ SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
+ SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
+ SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
+};
+
+int linux_fixup(int **stack_base, struct image_params *iparams)
+{
+ int *argv, *envp;
+
+ argv = *stack_base;
+ envp = *stack_base + (iparams->argc + 1);
+ (*stack_base)--;
+ **stack_base = (int)envp;
+ (*stack_base)--;
+ **stack_base = (int)argv;
+ (*stack_base)--;
+ **stack_base = (int)iparams->argc;
+}
+
+struct sysentvec linux_sysvec = {
+ sizeof (linux_sysent) / sizeof(linux_sysent[0]),
+ linux_sysent,
+ 0xff,
+ NSIG,
+ bsd_to_linux_signal,
+ ELAST,
+ bsd_to_linux_errno,
+ linux_fixup
+};
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index da92672..c9ebc81 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -1,7 +1,7 @@
-# $Id: Makefile,v 1.9 1995/03/20 19:25:38 wollman Exp $
+# $Id: Makefile,v 1.10 1995/06/13 20:51:13 wollman Exp $
SUBDIR= cd9660 coff fdesc ibcs2 if_disc if_ppp if_sl if_tun \
- ipfw kernfs msdos nfs nullfs \
+ ipfw kernfs linux msdos nfs nullfs \
portal procfs socksys syscons umapfs union
#
# Doesn't work:
diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile
new file mode 100644
index 0000000..11650c5
--- /dev/null
+++ b/sys/modules/linux/Makefile
@@ -0,0 +1,16 @@
+# $Id$
+
+.PATH: ${.CURDIR}/../../sys/i386/linux
+KMOD= linux_mod
+SRCS= linux.c linux_file.c linux_ioctl.c linux_misc.c linux_signal.c \
+ linux_generic.c linux_ipc.c linux_socket.c linux_stats.c \
+ linux_dummy.c linux_sysent.c imgact_linux.c vnode_if.h
+NOMAN=
+CFLAGS+= -DLKM -I. -DCOMPAT_LINUX -DSYSVSHM #-DSYSVMSG -DSYSVSEM #-DDEBUG
+CLEANFILES+= vnode_if.h vnode_if.c
+
+afterinstall:
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/linux /usr/bin
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/linux/linux b/sys/modules/linux/linux
new file mode 100644
index 0000000..e4c3606
--- /dev/null
+++ b/sys/modules/linux/linux
@@ -0,0 +1,3 @@
+#!/bin/sh
+# $Id$
+modload -e linux_init /lkm/linux_mod.o
diff --git a/sys/modules/linux/linux.c b/sys/modules/linux/linux.c
new file mode 100644
index 0000000..183ad3e
--- /dev/null
+++ b/sys/modules/linux/linux.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1994 Søren Schmidt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software withough specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: linux.c,v 1.1 1994/10/14 08:46:12 sos Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/conf.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+#include <sys/errno.h>
+
+extern const struct execsw linux_execsw;
+
+MOD_EXEC("linux_emulator", -1, (struct execsw*)&linux_execsw)
+
+linux_load(struct lkm_table *lkmtp, int cmd)
+{
+ uprintf("Linux emulator installed\n");
+ return 0;
+}
+
+linux_unload(struct lkm_table *lkmtp, int cmd)
+{
+ uprintf("Linux emulator removed\n");
+ return 0;
+}
+
+linux_init(struct lkm_table *lkmtp, int cmd, int ver)
+{
+ DISPATCH(lkmtp, cmd, ver, linux_load, linux_unload, nosys);
+}
diff --git a/sys/modules/linux/linux.sh b/sys/modules/linux/linux.sh
new file mode 100644
index 0000000..e4c3606
--- /dev/null
+++ b/sys/modules/linux/linux.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+# $Id$
+modload -e linux_init /lkm/linux_mod.o
OpenPOWER on IntegriCloud