diff options
author | sos <sos@FreeBSD.org> | 1995-06-25 17:32:43 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 1995-06-25 17:32:43 +0000 |
commit | f14ea10694ed07a2d0627c9efa2b79c03b19639d (patch) | |
tree | a104b48d590fdc08acc1a23e9f4430c22923749e /sys/i386 | |
parent | c54e2295b7f2db09802e0bc1874072840e4d75f7 (diff) | |
download | FreeBSD-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/i386')
-rw-r--r-- | sys/i386/linux/imgact_linux.c | 235 | ||||
-rw-r--r-- | sys/i386/linux/linux.h | 406 | ||||
-rw-r--r-- | sys/i386/linux/linux_dummy.c | 316 | ||||
-rw-r--r-- | sys/i386/linux/linux_file.c | 436 | ||||
-rw-r--r-- | sys/i386/linux/linux_generic.c | 63 | ||||
-rw-r--r-- | sys/i386/linux/linux_ioctl.c | 495 | ||||
-rw-r--r-- | sys/i386/linux/linux_ipc.c | 308 | ||||
-rw-r--r-- | sys/i386/linux/linux_misc.c | 660 | ||||
-rw-r--r-- | sys/i386/linux/linux_signal.c | 259 | ||||
-rw-r--r-- | sys/i386/linux/linux_socket.c | 595 | ||||
-rw-r--r-- | sys/i386/linux/linux_stats.c | 273 | ||||
-rw-r--r-- | sys/i386/linux/linux_sysent.c | 367 |
12 files changed, 4413 insertions, 0 deletions
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 +}; |