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