diff options
Diffstat (limited to 'sys/compat')
90 files changed, 29471 insertions, 0 deletions
diff --git a/sys/compat/freebsd32/Makefile b/sys/compat/freebsd32/Makefile new file mode 100644 index 0000000..1184ef4 --- /dev/null +++ b/sys/compat/freebsd32/Makefile @@ -0,0 +1,15 @@ +# Makefile for syscall tables +# +# $FreeBSD$ + +all: + @echo "make sysent only" + +sysent: ia32_sysent.c ia32_syscall.h ia32_proto.h + +ia32_sysent.c ia32_syscall.h ia32_proto.h: ../../kern/makesyscalls.sh \ + syscalls.master syscalls.conf + -mv -f ia32_sysent.c ia32_sysent.c.bak + -mv -f ia32_syscall.h ia32_syscall.h.bak + -mv -f ia32_proto.h ia32_proto.h.bak + sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h new file mode 100644 index 0000000..943b24c --- /dev/null +++ b/sys/compat/freebsd32/freebsd32.h @@ -0,0 +1,103 @@ +/*- + * Copyright (c) 2001 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _IA64_IA32_IA32_H_ +#define _IA64_IA32_IA32_H_ + +#define PTRIN(v) (void *)(uintptr_t) (v) +#define PTROUT(v) (u_int32_t)(uintptr_t) (v) + +#define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) +#define PTRIN_CP(src,dst,fld) \ + do { (dst).fld = PTRIN((src).fld); } while (0) +#define PTROUT_CP(src,dst,fld) \ + do { (dst).fld = PTROUT((src).fld); } while (0) + +struct timeval32 { + int32_t tv_sec; + int32_t tv_usec; +}; +#define TV_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_usec); \ +} while (0); + +struct timespec32 { + u_int32_t tv_sec; + u_int32_t tv_nsec; +}; +#define TS_CP(src,dst,fld) do { \ + CP((src).fld,(dst).fld,tv_sec); \ + CP((src).fld,(dst).fld,tv_nsec); \ +} while (0); + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int32_t ru_maxrss; + int32_t ru_ixrss; + int32_t ru_idrss; + int32_t ru_isrss; + int32_t ru_minflt; + int32_t ru_majflt; + int32_t ru_nswap; + int32_t ru_inblock; + int32_t ru_oublock; + int32_t ru_msgsnd; + int32_t ru_msgrcv; + int32_t ru_nsignals; + int32_t ru_nvcsw; + int32_t ru_nivcsw; +}; + +struct statfs32 { + int32_t f_spare2; + int32_t f_bsize; + int32_t f_iosize; + int32_t f_blocks; + int32_t f_bfree; + int32_t f_bavail; + int32_t f_files; + int32_t f_ffree; + fsid_t f_fsid; + uid_t f_owner; + int32_t f_type; + int32_t f_flags; + int32_t f_syncwrites; + int32_t f_asyncwrites; + char f_fstypename[MFSNAMELEN]; + char f_mntonname[MNAMELEN]; + int32_t f_syncreads; + int32_t f_asyncreads; + int16_t f_spares1; + char f_mntfromname[MNAMELEN]; + int16_t f_spares2; + int32_t f_spare[2]; +}; + +#endif /* !_IA64_IA32_IA32_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c new file mode 100644 index 0000000..8b28bce --- /dev/null +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -0,0 +1,1339 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/dkstat.h> +#include <sys/exec.h> +#include <sys/fcntl.h> +#include <sys/filedesc.h> +#include <sys/imgact.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/file.h> /* Must come after sys/malloc.h */ +#include <sys/mman.h> +#include <sys/module.h> +#include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> +#include <sys/selinfo.h> +#include <sys/pipe.h> /* Must come after sys/selinfo.h */ +#include <sys/signal.h> +#include <sys/signalvar.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <sys/systm.h> +#include <sys/unistd.h> +#include <sys/user.h> +#include <sys/utsname.h> +#include <sys/vnode.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> + +#include <ia64/ia32/ia32_util.h> +#include <ia64/ia32/ia32.h> +#include <ia64/ia32/ia32_proto.h> + +static const char ia32_emul_path[] = "/compat/ia32"; +/* + * [ taken from the linux emulator ] + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +ia32_emul_find(td, sgp, prefix, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + int error; + size_t len, sz; + char *buf, *cp, *ptr; + struct ucred *ucred; + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--) + ; + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the ia32_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + + ucred = td->td_ucred; + if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { + goto bad; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, + td)) != 0) { + goto bad; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto bad; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + + return error; + +bad: + vrele(ndroot.ni_vp); + vrele(nd.ni_vp); + free(buf, M_TEMP); + return error; +} + +int +ia32_open(struct thread *td, struct ia32_open_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return open(td, (struct open_args *) uap); +} + +int +ia32_wait4(struct thread *td, struct ia32_wait4_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *rusage32, ru32; + struct rusage *rusage = NULL, ru; + + rusage32 = SCARG(uap, rusage); + if (rusage32) { + sg = stackgap_init(); + rusage = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)rusage; + } + error = wait4(td, (struct wait_args *)uap); + if (error) + return (error); + if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { + TV_CP(ru, ru32, ru_utime); + TV_CP(ru, ru32, ru_stime); + CP(ru, ru32, ru_maxrss); + CP(ru, ru32, ru_ixrss); + CP(ru, ru32, ru_idrss); + CP(ru, ru32, ru_isrss); + CP(ru, ru32, ru_minflt); + CP(ru, ru32, ru_majflt); + CP(ru, ru32, ru_nswap); + CP(ru, ru32, ru_inblock); + CP(ru, ru32, ru_oublock); + CP(ru, ru32, ru_msgsnd); + CP(ru, ru32, ru_msgrcv); + CP(ru, ru32, ru_nsignals); + CP(ru, ru32, ru_nvcsw); + CP(ru, ru32, ru_nivcsw); + error = copyout(&ru32, rusage32, sizeof(ru32)); + } + return (error); +} + +static void +copy_statfs(struct statfs *in, struct statfs32 *out) +{ + CP(*in, *out, f_bsize); + CP(*in, *out, f_iosize); + CP(*in, *out, f_blocks); + CP(*in, *out, f_bfree); + CP(*in, *out, f_bavail); + CP(*in, *out, f_files); + CP(*in, *out, f_ffree); + CP(*in, *out, f_fsid); + CP(*in, *out, f_owner); + CP(*in, *out, f_type); + CP(*in, *out, f_flags); + CP(*in, *out, f_flags); + CP(*in, *out, f_syncwrites); + CP(*in, *out, f_asyncwrites); + bcopy(in->f_fstypename, + out->f_fstypename, MFSNAMELEN); + bcopy(in->f_mntonname, + out->f_mntonname, MNAMELEN); + CP(*in, *out, f_syncreads); + CP(*in, *out, f_asyncreads); + bcopy(in->f_mntfromname, + out->f_mntfromname, MNAMELEN); +} + +int +ia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *sp32, stat32; + struct statfs *sp = NULL, stat; + int maxcount, count, i; + + sp32 = SCARG(uap, buf); + maxcount = SCARG(uap, bufsize) / sizeof(struct statfs32); + + if (sp32) { + sg = stackgap_init(); + sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); + SCARG(uap, buf) = (struct statfs32 *)sp; + } + error = getfsstat(td, (struct getfsstat_args *) uap); + if (sp32 && !error) { + count = td->td_retval[0]; + for (i = 0; i < count; i++) { + error = copyin(&sp[i], &stat, sizeof(stat)); + if (error) + return (error); + copy_statfs(&stat, &stat32); + error = copyout(&stat32, &sp32[i], sizeof(stat32)); + if (error) + return (error); + } + } + return (error); +} + +int +ia32_access(struct thread *td, struct ia32_access_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return access(td, (struct access_args *)uap); +} + +int +ia32_chflags(struct thread *td, struct ia32_chflags_args *uap) +{ + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + return chflags(td, (struct chflags_args *)uap); +} + +struct sigaltstack32 { + u_int32_t ss_sp; + u_int32_t ss_size; + int ss_flags; +}; + +int +ia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) +{ + int error; + caddr_t sg; + struct sigaltstack32 *p32, *op32, s32; + struct sigaltstack *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, ss); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, ss) = (struct sigaltstack32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + PTRIN_CP(s32, s, ss_sp); + CP(s32, s, ss_size); + CP(s32, s, ss_flags); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oss); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + SCARG(uap, oss) = (struct sigaltstack32 *)op; + } + error = sigaltstack(td, (struct sigaltstack_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + PTROUT_CP(s, s32, ss_sp); + CP(s, s32, ss_size); + CP(s, s32, ss_flags); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_execve(struct thread *td, struct ia32_execve_args *uap) +{ + int error; + caddr_t sg; + struct execve_args ap; + u_int32_t *p32, arg; + char **p; + int count; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, fname)); + SCARG(&ap, fname) = SCARG(uap, fname); + + if (SCARG(uap, argv)) { + count = 0; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, argv) = p; + p32 = SCARG(uap, argv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + if (SCARG(uap, envv)) { + count = 0; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + count++; + } while (arg != 0); + p = stackgap_alloc(&sg, count * sizeof(char *)); + SCARG(&ap, envv) = p; + p32 = SCARG(uap, envv); + do { + error = copyin(p32++, &arg, sizeof(arg)); + if (error) + return error; + *p++ = PTRIN(arg); + } while (arg != 0); + } + + return execve(td, &ap); +} + +static int +ia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, + int prot, int fd, off_t pos) +{ + vm_map_t map; + vm_map_entry_t entry; + int rv; + + map = &td->td_proc->p_vmspace->vm_map; + if (fd != -1) + prot |= VM_PROT_WRITE; + + if (vm_map_lookup_entry(map, start, &entry)) { + if ((entry->protection & prot) != prot) { + rv = vm_map_protect(map, + trunc_page(start), + round_page(end), + entry->protection | prot, + FALSE); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + } else { + vm_offset_t addr = trunc_page(start); + rv = vm_map_find(map, 0, 0, + &addr, PAGE_SIZE, FALSE, prot, + VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + } + + if (fd != -1) { + struct pread_args r; + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + return (pread(td, &r)); + } else { + while (start < end) { + subyte((void *) start, 0); + start++; + } + return (0); + } +} + +int +ia32_mmap(struct thread *td, struct ia32_mmap_args *uap) +{ + struct mmap_args ap; + vm_offset_t addr = (vm_offset_t) SCARG(uap, addr); + vm_size_t len = SCARG(uap, len); + int prot = SCARG(uap, prot); + int flags = SCARG(uap, flags); + int fd = SCARG(uap, fd); + off_t pos = (SCARG(uap, poslo) + | ((off_t)SCARG(uap, poshi) << 32)); + vm_size_t pageoff; + int error; + + /* + * Attempt to handle page size hassles. + */ + pageoff = (pos & PAGE_MASK); + if (flags & MAP_FIXED) { + vm_offset_t start, end; + start = addr; + end = addr + len; + + if (start != trunc_page(start)) { + error = ia32_mmap_partial(td, start, round_page(start), + prot, fd, pos); + if (fd != -1) + pos += round_page(start) - start; + start = round_page(start); + } + if (end != round_page(end)) { + vm_offset_t t = trunc_page(end); + error = ia32_mmap_partial(td, t, end, + prot, fd, + pos + t - start); + end = trunc_page(end); + } + if (end > start && fd != -1 && (pos & PAGE_MASK)) { + /* + * We can't map this region at all. The specified + * address doesn't have the same alignment as the file + * position. Fake the mapping by simply reading the + * entire region into memory. First we need to make + * sure the region exists. + */ + vm_map_t map; + struct pread_args r; + int rv; + + prot |= VM_PROT_WRITE; + map = &td->td_proc->p_vmspace->vm_map; + rv = vm_map_remove(map, start, end); + if (rv != KERN_SUCCESS) + return (EINVAL); + rv = vm_map_find(map, 0, 0, + &start, end - start, FALSE, + prot, VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) + return (EINVAL); + SCARG(&r, fd) = fd; + SCARG(&r, buf) = (void *) start; + SCARG(&r, nbyte) = end - start; + SCARG(&r, offset) = pos; + error = pread(td, &r); + if (error) + return (error); + + td->td_retval[0] = addr; + return (0); + } + if (end == start) { + /* + * After dealing with the ragged ends, there + * might be none left. + */ + td->td_retval[0] = addr; + return (0); + } + addr = start; + len = end - start; + } + + SCARG(&ap, addr) = (void *) addr; + SCARG(&ap, len) = len; + SCARG(&ap, prot) = prot; + SCARG(&ap, flags) = flags; + SCARG(&ap, fd) = fd; + SCARG(&ap, pos) = pos; + + return (mmap(td, &ap)); +} + +struct itimerval32 { + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +int +ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) +{ + int error; + caddr_t sg; + struct itimerval32 *p32, *op32, s32; + struct itimerval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, itv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, itv) = (struct itimerval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + TV_CP(s32, s, it_interval); + TV_CP(s32, s, it_value); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oitv); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct itimerval)); + SCARG(uap, oitv) = (struct itimerval32 *)op; + } + error = setitimer(td, (struct setitimer_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, it_interval); + TV_CP(s, s32, it_value); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_select(struct thread *td, struct ia32_select_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + /* + * XXX big-endian needs to convert the fd_sets too. + */ + return (select(td, (struct select_args *) uap)); +} + +int +ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tp); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tp) = (struct timeval32 *)p; + } + error = gettimeofday(td, (struct gettimeofday_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, p32, sizeof(s32)); + if (error) + return (error); + } + return (error); +} + +int +ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) +{ + int error; + caddr_t sg; + struct rusage32 *p32, s32; + struct rusage *p = NULL, s; + + p32 = SCARG(uap, rusage); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct rusage)); + SCARG(uap, rusage) = (struct rusage32 *)p; + } + error = getrusage(td, (struct getrusage_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + TV_CP(s, s32, ru_utime); + TV_CP(s, s32, ru_stime); + CP(s, s32, ru_maxrss); + CP(s, s32, ru_ixrss); + CP(s, s32, ru_idrss); + CP(s, s32, ru_isrss); + CP(s, s32, ru_minflt); + CP(s, s32, ru_majflt); + CP(s, s32, ru_nswap); + CP(s, s32, ru_inblock); + CP(s, s32, ru_oublock); + CP(s, s32, ru_msgsnd); + CP(s, s32, ru_msgrcv); + CP(s, s32, ru_nsignals); + CP(s, s32, ru_nvcsw); + CP(s, s32, ru_nivcsw); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +struct iovec32 { + u_int32_t iov_base; + int iov_len; +}; +#define STACKGAPLEN 400 + +int +ia32_readv(struct thread *td, struct ia32_readv_args *uap) +{ + int error, osize, nsize, i; + caddr_t sg; + struct readv_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = readv(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_writev(struct thread *td, struct ia32_writev_args *uap) +{ + int error, i, nsize, osize; + caddr_t sg; + struct writev_args /* { + syscallarg(int) fd; + syscallarg(struct iovec *) iovp; + syscallarg(u_int) iovcnt; + } */ a; + struct iovec32 *oio; + struct iovec *nio; + + sg = stackgap_init(); + + if (SCARG(uap, iovcnt) > (STACKGAPLEN / sizeof (struct iovec))) + return (EINVAL); + + osize = SCARG(uap, iovcnt) * sizeof (struct iovec32); + nsize = SCARG(uap, iovcnt) * sizeof (struct iovec); + + oio = malloc(osize, M_TEMP, M_WAITOK); + nio = malloc(nsize, M_TEMP, M_WAITOK); + + error = 0; + if ((error = copyin(SCARG(uap, iovp), oio, osize))) + goto punt; + for (i = 0; i < SCARG(uap, iovcnt); i++) { + nio[i].iov_base = PTRIN(oio[i].iov_base); + nio[i].iov_len = oio[i].iov_len; + } + + SCARG(&a, fd) = SCARG(uap, fd); + SCARG(&a, iovp) = stackgap_alloc(&sg, nsize); + SCARG(&a, iovcnt) = SCARG(uap, iovcnt); + + if ((error = copyout(nio, (caddr_t)SCARG(&a, iovp), nsize))) + goto punt; + error = writev(td, &a); + +punt: + free(oio, M_TEMP); + free(nio, M_TEMP); + return (error); +} + +int +ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32; + struct timeval *p = NULL, s; + + p32 = SCARG(uap, tv); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, tv) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + return (settimeofday(td, (struct settimeofday_args *) uap)); +} + +int +ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, s32[2]; + struct timeval *p = NULL, s[2]; + + p32 = SCARG(uap, tptr); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); + SCARG(uap, tptr) = (struct timeval32 *)p; + error = copyin(p32, s32, sizeof(s32)); + if (error) + return (error); + CP(s32[0], s[0], tv_sec); + CP(s32[0], s[0], tv_usec); + CP(s32[1], s[1], tv_sec); + CP(s32[1], s[1], tv_usec); + error = copyout(s, p, sizeof(s)); + if (error) + return (error); + } + return (utimes(td, (struct utimes_args *) uap)); +} + +int +ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) +{ + int error; + caddr_t sg; + struct timeval32 *p32, *op32, s32; + struct timeval *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, delta); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, delta) = (struct timeval32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + CP(s32, s, tv_sec); + CP(s32, s, tv_usec); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, olddelta); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct timeval)); + SCARG(uap, olddelta) = (struct timeval32 *)op; + } + error = utimes(td, (struct utimes_args *) uap); + if (error) + return error; + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + CP(s, s32, tv_sec); + CP(s, s32, tv_usec); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +int +ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = statfs(td, (struct statfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) +{ + int error; + caddr_t sg; + struct statfs32 *p32, s32; + struct statfs *p = NULL, s; + + p32 = SCARG(uap, buf); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct statfs)); + SCARG(uap, buf) = (struct statfs32 *)p; + } + error = fstatfs(td, (struct fstatfs_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_statfs(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) +{ + /* + * Vector through to semsys if it is loaded. + */ + return sysent[169].sy_call(td, uap); +} + +int +ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) +{ + /* + * Vector through to msgsys if it is loaded. + */ + return sysent[170].sy_call(td, uap); +} + +int +ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) +{ + /* + * Vector through to shmsys if it is loaded. + */ + return sysent[171].sy_call(td, uap); +} + +int +ia32_pread(struct thread *td, struct ia32_pread_args *uap) +{ + struct pread_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pread(td, &ap)); +} + +int +ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) +{ + struct pwrite_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, buf) = SCARG(uap, buf); + SCARG(&ap, nbyte) = SCARG(uap, nbyte); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + return (pwrite(td, &ap)); +} + +int +ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) +{ + int error; + struct lseek_args ap; + off_t pos; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, whence) = SCARG(uap, whence); + error = lseek(td, &ap); + /* Expand the quad return into two parts for eax and edx */ + pos = *(off_t *)(td->td_retval); + td->td_retval[0] = pos & 0xffffffff; /* %eax */ + td->td_retval[1] = pos >> 32; /* %edx */ + return error; +} + +int +ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) +{ + struct truncate_args ap; + + SCARG(&ap, path) = SCARG(uap, path); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (truncate(td, &ap)); +} + +int +ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) +{ + struct ftruncate_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, length) = (SCARG(uap, lengthlo) + | ((off_t)SCARG(uap, lengthhi) << 32)); + return (ftruncate(td, &ap)); +} + +int +ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) +{ + struct sendfile_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + SCARG(&ap, s) = SCARG(uap, s); + SCARG(&ap, offset) = (SCARG(uap, offsetlo) + | ((off_t)SCARG(uap, offsethi) << 32)); + SCARG(&ap, nbytes) = SCARG(uap, nbytes); /* XXX check */ + SCARG(&ap, hdtr) = SCARG(uap, hdtr); /* XXX check */ + SCARG(&ap, sbytes) = SCARG(uap, sbytes); /* XXX FIXME!! */ + SCARG(&ap, flags) = SCARG(uap, flags); + return (sendfile(td, &ap)); +} + +struct stat32 { + udev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + udev_t st_rdev; + struct timespec32 st_atimespec; + struct timespec32 st_mtimespec; + struct timespec32 st_ctimespec; + off_t st_size; + int64_t st_blocks; + u_int32_t st_blksize; + u_int32_t st_flags; + u_int32_t st_gen; +}; + +static void +copy_stat( struct stat *in, struct stat32 *out) +{ + CP(*in, *out, st_dev); + CP(*in, *out, st_ino); + CP(*in, *out, st_mode); + CP(*in, *out, st_nlink); + CP(*in, *out, st_uid); + CP(*in, *out, st_gid); + CP(*in, *out, st_rdev); + TS_CP(*in, *out, st_atimespec); + TS_CP(*in, *out, st_mtimespec); + TS_CP(*in, *out, st_ctimespec); + CP(*in, *out, st_size); + CP(*in, *out, st_blocks); + CP(*in, *out, st_blksize); + CP(*in, *out, st_flags); + CP(*in, *out, st_gen); +} + +int +ia32_stat(struct thread *td, struct ia32_stat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = stat(td, (struct stat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = fstat(td, (struct fstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +int +ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) +{ + int error; + caddr_t sg; + struct stat32 *p32, s32; + struct stat *p = NULL, s; + + p32 = SCARG(uap, ub); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct stat)); + SCARG(uap, ub) = (struct stat32 *)p; + } + error = lstat(td, (struct lstat_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + copy_stat(&s, &s32); + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +/* + * MPSAFE + */ +int +ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) +{ + int error, name[CTL_MAXNAME]; + size_t j, oldlen; + + if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) + return (EINVAL); + + error = copyin(uap->name, &name, uap->namelen * sizeof(int)); + if (error) + return (error); + + mtx_lock(&Giant); + + if (uap->oldlenp) + oldlen = fuword32(uap->oldlenp); + else + oldlen = 0; + error = userland_sysctl(td, name, uap->namelen, + uap->old, &oldlen, 1, + uap->new, uap->newlen, &j); + if (error && error != ENOMEM) + goto done2; + if (uap->oldlenp) { + suword32(uap->oldlenp, j); + } +done2: + mtx_unlock(&Giant); + return (error); +} + +struct sigaction32 { + u_int32_t sa_u; + int sa_flags; + sigset_t sa_mask; +}; + +int +ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) +{ + int error; + caddr_t sg; + struct sigaction32 *p32, *op32, s32; + struct sigaction *p = NULL, *op = NULL, s; + + p32 = SCARG(uap, act); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, act) = (struct sigaction32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + s.sa_handler = PTRIN(s32.sa_u); + CP(s32, s, sa_flags); + CP(s32, s, sa_mask); + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + op32 = SCARG(uap, oact); + if (op32) { + sg = stackgap_init(); + op = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(uap, oact) = (struct sigaction32 *)op; + } + error = sigaction(td, (struct sigaction_args *) uap); + if (error) + return (error); + if (op32) { + error = copyin(op, &s, sizeof(s)); + if (error) + return (error); + s32.sa_u = PTROUT(s.sa_handler); + CP(s, s32, sa_flags); + CP(s, s32, sa_mask); + error = copyout(&s32, op32, sizeof(s32)); + } + return (error); +} + +#if 0 + +int +ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) +{ + int error; + caddr_t sg; + struct yyy32 *p32, s32; + struct yyy *p = NULL, s; + + p32 = SCARG(uap, zzz); + if (p32) { + sg = stackgap_init(); + p = stackgap_alloc(&sg, sizeof(struct yyy)); + SCARG(uap, zzz) = (struct yyy32 *)p; + error = copyin(p32, &s32, sizeof(s32)); + if (error) + return (error); + /* translate in */ + error = copyout(&s, p, sizeof(s)); + if (error) + return (error); + } + error = xxx(td, (struct xxx_args *) uap); + if (error) + return (error); + if (p32) { + error = copyin(p, &s, sizeof(s)); + if (error) + return (error); + /* translate out */ + error = copyout(&s32, p32, sizeof(s32)); + } + return (error); +} + +#endif diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h new file mode 100644 index 0000000..36b9e73 --- /dev/null +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -0,0 +1,264 @@ +/* + * System call prototypes. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp + */ + +#ifndef _IA32_SYSPROTO_H_ +#define _IA32_SYSPROTO_H_ + +#include <sys/signal.h> + +#include <sys/acl.h> + +struct proc; + +struct thread; + +#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ + 0 : sizeof(register_t) - sizeof(t)) + +#if BYTE_ORDER == LITTLE_ENDIAN +#define PADL_(t) 0 +#define PADR_(t) PAD_(t) +#else +#define PADL_(t) PAD_(t) +#define PADR_(t) 0 +#endif + +struct ia32_open_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; + char mode_l_[PADL_(int)]; int mode; char mode_r_[PADR_(int)]; +}; +struct ia32_wait4_args { + char pid_l_[PADL_(int)]; int pid; char pid_r_[PADR_(int)]; + char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)]; + char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)]; + char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)]; +}; +struct ia32_getfsstat_args { + char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)]; + char bufsize_l_[PADL_(long)]; long bufsize; char bufsize_r_[PADR_(long)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; +struct ia32_access_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; +struct ia32_chflags_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; +struct ia32_sigaltstack_args { + char ss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * ss; char ss_r_[PADR_(struct sigaltstack32 *)]; + char oss_l_[PADL_(struct sigaltstack32 *)]; struct sigaltstack32 * oss; char oss_r_[PADR_(struct sigaltstack32 *)]; +}; +struct ia32_execve_args { + char fname_l_[PADL_(char *)]; char * fname; char fname_r_[PADR_(char *)]; + char argv_l_[PADL_(u_int32_t *)]; u_int32_t * argv; char argv_r_[PADR_(u_int32_t *)]; + char envv_l_[PADL_(u_int32_t *)]; u_int32_t * envv; char envv_r_[PADR_(u_int32_t *)]; +}; +struct ia32_setitimer_args { + char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)]; + char itv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * itv; char itv_r_[PADR_(struct itimerval32 *)]; + char oitv_l_[PADL_(struct itimerval32 *)]; struct itimerval32 * oitv; char oitv_r_[PADR_(struct itimerval32 *)]; +}; +struct ia32_select_args { + char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)]; + char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)]; + char ou_l_[PADL_(fd_set *)]; fd_set * ou; char ou_r_[PADR_(fd_set *)]; + char ex_l_[PADL_(fd_set *)]; fd_set * ex; char ex_r_[PADR_(fd_set *)]; + char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)]; +}; +struct ia32_gettimeofday_args { + char tp_l_[PADL_(struct timeval32 *)]; struct timeval32 * tp; char tp_r_[PADR_(struct timeval32 *)]; + char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)]; +}; +struct ia32_getrusage_args { + char who_l_[PADL_(int)]; int who; char who_r_[PADR_(int)]; + char rusage_l_[PADL_(struct rusage32 *)]; struct rusage32 * rusage; char rusage_r_[PADR_(struct rusage32 *)]; +}; +struct ia32_readv_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)]; + char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; +}; +struct ia32_writev_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char iovp_l_[PADL_(struct iovec32 *)]; struct iovec32 * iovp; char iovp_r_[PADR_(struct iovec32 *)]; + char iovcnt_l_[PADL_(u_int)]; u_int iovcnt; char iovcnt_r_[PADR_(u_int)]; +}; +struct ia32_settimeofday_args { + char tv_l_[PADL_(struct timeval32 *)]; struct timeval32 * tv; char tv_r_[PADR_(struct timeval32 *)]; + char tzp_l_[PADL_(struct timezone *)]; struct timezone * tzp; char tzp_r_[PADR_(struct timezone *)]; +}; +struct ia32_utimes_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char tptr_l_[PADL_(struct timeval32 *)]; struct timeval32 * tptr; char tptr_r_[PADR_(struct timeval32 *)]; +}; +struct ia32_adjtime_args { + char delta_l_[PADL_(struct timeval32 *)]; struct timeval32 * delta; char delta_r_[PADR_(struct timeval32 *)]; + char olddelta_l_[PADL_(struct timeval32 *)]; struct timeval32 * olddelta; char olddelta_r_[PADR_(struct timeval32 *)]; +}; +struct ia32_statfs_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)]; +}; +struct ia32_fstatfs_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char buf_l_[PADL_(struct statfs32 *)]; struct statfs32 * buf; char buf_r_[PADR_(struct statfs32 *)]; +}; +struct ia32_semsys_args { + char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; + char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; + char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; + char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; + char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; +}; +struct ia32_msgsys_args { + char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; + char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; + char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; + char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; + char a5_l_[PADL_(int)]; int a5; char a5_r_[PADR_(int)]; + char a6_l_[PADL_(int)]; int a6; char a6_r_[PADR_(int)]; +}; +struct ia32_shmsys_args { + char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)]; + char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)]; + char a3_l_[PADL_(int)]; int a3; char a3_r_[PADR_(int)]; + char a4_l_[PADL_(int)]; int a4; char a4_r_[PADR_(int)]; +}; +struct ia32_pread_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)]; + char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)]; + char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)]; +}; +struct ia32_pwrite_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char buf_l_[PADL_(const void *)]; const void * buf; char buf_r_[PADR_(const void *)]; + char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)]; + char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)]; +}; +struct ia32_stat_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)]; +}; +struct ia32_fstat_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)]; +}; +struct ia32_lstat_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char ub_l_[PADL_(struct stat32 *)]; struct stat32 * ub; char ub_r_[PADR_(struct stat32 *)]; +}; +struct ia32_mmap_args { + char addr_l_[PADL_(caddr_t)]; caddr_t addr; char addr_r_[PADR_(caddr_t)]; + char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)]; + char prot_l_[PADL_(int)]; int prot; char prot_r_[PADR_(int)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char poslo_l_[PADL_(u_int32_t)]; u_int32_t poslo; char poslo_r_[PADR_(u_int32_t)]; + char poshi_l_[PADL_(u_int32_t)]; u_int32_t poshi; char poshi_r_[PADR_(u_int32_t)]; +}; +struct ia32_lseek_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)]; + char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)]; + char whence_l_[PADL_(int)]; int whence; char whence_r_[PADR_(int)]; +}; +struct ia32_truncate_args { + char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char lengthlo_l_[PADL_(u_int32_t)]; u_int32_t lengthlo; char lengthlo_r_[PADR_(u_int32_t)]; + char lengthhi_l_[PADL_(u_int32_t)]; u_int32_t lengthhi; char lengthhi_r_[PADR_(u_int32_t)]; +}; +struct ia32_ftruncate_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char pad_l_[PADL_(int)]; int pad; char pad_r_[PADR_(int)]; + char lengthlo_l_[PADL_(u_int32_t)]; u_int32_t lengthlo; char lengthlo_r_[PADR_(u_int32_t)]; + char lengthhi_l_[PADL_(u_int32_t)]; u_int32_t lengthhi; char lengthhi_r_[PADR_(u_int32_t)]; +}; +struct ia32_sysctl_args { + char name_l_[PADL_(int *)]; int * name; char name_r_[PADR_(int *)]; + char namelen_l_[PADL_(u_int)]; u_int namelen; char namelen_r_[PADR_(u_int)]; + char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)]; + char oldlenp_l_[PADL_(u_int32_t *)]; u_int32_t * oldlenp; char oldlenp_r_[PADR_(u_int32_t *)]; + char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)]; + char newlen_l_[PADL_(u_int32_t)]; u_int32_t newlen; char newlen_r_[PADR_(u_int32_t)]; +}; +struct ia32_sendfile_args { + char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)]; + char s_l_[PADL_(int)]; int s; char s_r_[PADR_(int)]; + char offsetlo_l_[PADL_(u_int32_t)]; u_int32_t offsetlo; char offsetlo_r_[PADR_(u_int32_t)]; + char offsethi_l_[PADL_(u_int32_t)]; u_int32_t offsethi; char offsethi_r_[PADR_(u_int32_t)]; + char nbytes_l_[PADL_(size_t)]; size_t nbytes; char nbytes_r_[PADR_(size_t)]; + char hdtr_l_[PADL_(struct sf_hdtr *)]; struct sf_hdtr * hdtr; char hdtr_r_[PADR_(struct sf_hdtr *)]; + char sbytes_l_[PADL_(off_t *)]; off_t * sbytes; char sbytes_r_[PADR_(off_t *)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; +struct ia32_sigaction_args { + char sig_l_[PADL_(int)]; int sig; char sig_r_[PADR_(int)]; + char act_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * act; char act_r_[PADR_(struct sigaction32 *)]; + char oact_l_[PADL_(struct sigaction32 *)]; struct sigaction32 * oact; char oact_r_[PADR_(struct sigaction32 *)]; +}; +int ia32_open(struct thread *, struct ia32_open_args *); +int ia32_wait4(struct thread *, struct ia32_wait4_args *); +int ia32_getfsstat(struct thread *, struct ia32_getfsstat_args *); +int ia32_access(struct thread *, struct ia32_access_args *); +int ia32_chflags(struct thread *, struct ia32_chflags_args *); +int ia32_sigaltstack(struct thread *, struct ia32_sigaltstack_args *); +int ia32_execve(struct thread *, struct ia32_execve_args *); +int ia32_setitimer(struct thread *, struct ia32_setitimer_args *); +int ia32_select(struct thread *, struct ia32_select_args *); +int ia32_gettimeofday(struct thread *, struct ia32_gettimeofday_args *); +int ia32_getrusage(struct thread *, struct ia32_getrusage_args *); +int ia32_readv(struct thread *, struct ia32_readv_args *); +int ia32_writev(struct thread *, struct ia32_writev_args *); +int ia32_settimeofday(struct thread *, struct ia32_settimeofday_args *); +int ia32_utimes(struct thread *, struct ia32_utimes_args *); +int ia32_adjtime(struct thread *, struct ia32_adjtime_args *); +int ia32_statfs(struct thread *, struct ia32_statfs_args *); +int ia32_fstatfs(struct thread *, struct ia32_fstatfs_args *); +int ia32_semsys(struct thread *, struct ia32_semsys_args *); +int ia32_msgsys(struct thread *, struct ia32_msgsys_args *); +int ia32_shmsys(struct thread *, struct ia32_shmsys_args *); +int ia32_pread(struct thread *, struct ia32_pread_args *); +int ia32_pwrite(struct thread *, struct ia32_pwrite_args *); +int ia32_stat(struct thread *, struct ia32_stat_args *); +int ia32_fstat(struct thread *, struct ia32_fstat_args *); +int ia32_lstat(struct thread *, struct ia32_lstat_args *); +int ia32_mmap(struct thread *, struct ia32_mmap_args *); +int ia32_lseek(struct thread *, struct ia32_lseek_args *); +int ia32_truncate(struct thread *, struct ia32_truncate_args *); +int ia32_ftruncate(struct thread *, struct ia32_ftruncate_args *); +int ia32_sysctl(struct thread *, struct ia32_sysctl_args *); +int ia32_sendfile(struct thread *, struct ia32_sendfile_args *); +int ia32_sigaction(struct thread *, struct ia32_sigaction_args *); + +#ifdef COMPAT_43 + + +#endif /* COMPAT_43 */ + + +#ifdef COMPAT_FREEBSD4 + + +#endif /* COMPAT_FREEBSD4 */ + +#undef PAD_ +#undef PADL_ +#undef PADR_ + +#endif /* !_IA32_SYSPROTO_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h new file mode 100644 index 0000000..e457152 --- /dev/null +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -0,0 +1,288 @@ +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp + */ + +#define IA32_SYS_syscall 0 +#define IA32_SYS_exit 1 +#define IA32_SYS_fork 2 +#define IA32_SYS_read 3 +#define IA32_SYS_write 4 +#define IA32_SYS_ia32_open 5 +#define IA32_SYS_close 6 +#define IA32_SYS_ia32_wait4 7 + /* 8 is obsolete old creat */ +#define IA32_SYS_link 9 +#define IA32_SYS_unlink 10 + /* 11 is obsolete execv */ +#define IA32_SYS_chdir 12 +#define IA32_SYS_fchdir 13 +#define IA32_SYS_mknod 14 +#define IA32_SYS_chmod 15 +#define IA32_SYS_chown 16 +#define IA32_SYS_break 17 +#define IA32_SYS_ia32_getfsstat 18 + /* 19 is obsolete olseek */ +#define IA32_SYS_getpid 20 +#define IA32_SYS_mount 21 +#define IA32_SYS_unmount 22 +#define IA32_SYS_setuid 23 +#define IA32_SYS_getuid 24 +#define IA32_SYS_geteuid 25 +#define IA32_SYS_ptrace 26 +#define IA32_SYS_sendmsg 28 +#define IA32_SYS_recvfrom 29 +#define IA32_SYS_accept 30 +#define IA32_SYS_getpeername 31 +#define IA32_SYS_getsockname 32 +#define IA32_SYS_ia32_access 33 +#define IA32_SYS_ia32_chflags 34 +#define IA32_SYS_fchflags 35 +#define IA32_SYS_sync 36 +#define IA32_SYS_kill 37 +#define IA32_SYS_getppid 39 +#define IA32_SYS_dup 41 +#define IA32_SYS_pipe 42 +#define IA32_SYS_getegid 43 +#define IA32_SYS_profil 44 +#define IA32_SYS_ktrace 45 +#define IA32_SYS_getgid 47 +#define IA32_SYS_getlogin 49 +#define IA32_SYS_setlogin 50 +#define IA32_SYS_acct 51 +#define IA32_SYS_sigpending 52 +#define IA32_SYS_ia32_sigaltstack 53 +#define IA32_SYS_ioctl 54 +#define IA32_SYS_reboot 55 +#define IA32_SYS_revoke 56 +#define IA32_SYS_symlink 57 +#define IA32_SYS_readlink 58 +#define IA32_SYS_ia32_execve 59 +#define IA32_SYS_umask 60 +#define IA32_SYS_chroot 61 + /* 62 is obsolete ofstat */ + /* 63 is obsolete ogetkerninfo */ + /* 64 is obsolete ogetpagesize */ + /* 65 is obsolete omsync */ + /* 66 is obsolete ovfork */ + /* 67 is obsolete vread */ + /* 68 is obsolete vwrite */ +#define IA32_SYS_sbrk 69 +#define IA32_SYS_sstk 70 + /* 71 is obsolete ommap */ +#define IA32_SYS_vadvise 72 +#define IA32_SYS_munmap 73 +#define IA32_SYS_mprotect 74 +#define IA32_SYS_madvise 75 + /* 76 is obsolete vhangup */ + /* 77 is obsolete vlimit */ +#define IA32_SYS_mincore 78 +#define IA32_SYS_getgroups 79 +#define IA32_SYS_setgroups 80 +#define IA32_SYS_getpgrp 81 +#define IA32_SYS_setpgid 82 +#define IA32_SYS_ia32_setitimer 83 + /* 84 is obsolete owait */ + /* 85 is obsolete oswapon */ + /* 86 is obsolete ogetitimer */ + /* 87 is obsolete ogethostname */ + /* 88 is obsolete osethostname */ +#define IA32_SYS_getdtablesize 89 +#define IA32_SYS_dup2 90 +#define IA32_SYS_fcntl 92 +#define IA32_SYS_ia32_select 93 +#define IA32_SYS_fsync 95 +#define IA32_SYS_setpriority 96 +#define IA32_SYS_socket 97 +#define IA32_SYS_connect 98 +#define IA32_SYS_accept 99 +#define IA32_SYS_getpriority 100 + /* 101 is obsolete osend */ + /* 102 is obsolete orecv */ + /* 103 is obsolete osigreturn */ +#define IA32_SYS_bind 104 +#define IA32_SYS_setsockopt 105 +#define IA32_SYS_listen 106 + /* 107 is obsolete vtimes */ + /* 108 is obsolete osigvec */ + /* 109 is obsolete osigblock */ + /* 110 is obsolete osigsetmask */ + /* 111 is obsolete osigsuspend */ + /* 112 is obsolete osigstack */ + /* 113 is obsolete orecvmsg */ + /* 114 is obsolete osendmsg */ + /* 115 is obsolete vtrace */ +#define IA32_SYS_ia32_gettimeofday 116 +#define IA32_SYS_ia32_getrusage 117 +#define IA32_SYS_getsockopt 118 +#define IA32_SYS_ia32_readv 120 +#define IA32_SYS_ia32_writev 121 +#define IA32_SYS_ia32_settimeofday 122 +#define IA32_SYS_fchown 123 +#define IA32_SYS_fchmod 124 +#define IA32_SYS_recvfrom 125 +#define IA32_SYS_setreuid 126 +#define IA32_SYS_setregid 127 +#define IA32_SYS_rename 128 + /* 129 is obsolete otruncate */ + /* 130 is obsolete ftruncate */ +#define IA32_SYS_flock 131 +#define IA32_SYS_mkfifo 132 +#define IA32_SYS_sendto 133 +#define IA32_SYS_shutdown 134 +#define IA32_SYS_socketpair 135 +#define IA32_SYS_mkdir 136 +#define IA32_SYS_rmdir 137 +#define IA32_SYS_ia32_utimes 138 + /* 139 is obsolete 4.2 sigreturn */ +#define IA32_SYS_ia32_adjtime 140 + /* 141 is obsolete ogetpeername */ + /* 142 is obsolete ogethostid */ + /* 143 is obsolete sethostid */ + /* 144 is obsolete getrlimit */ + /* 145 is obsolete setrlimit */ + /* 146 is obsolete killpg */ +#define IA32_SYS_setsid 147 +#define IA32_SYS_quotactl 148 + /* 149 is obsolete oquota */ + /* 150 is obsolete ogetsockname */ +#define IA32_SYS_getdirentries 156 +#define IA32_SYS_ia32_statfs 157 +#define IA32_SYS_ia32_fstatfs 158 +#define IA32_SYS_getfh 161 +#define IA32_SYS_getdomainname 162 +#define IA32_SYS_setdomainname 163 +#define IA32_SYS_uname 164 +#define IA32_SYS_sysarch 165 +#define IA32_SYS_rtprio 166 +#define IA32_SYS_ia32_semsys 169 +#define IA32_SYS_ia32_msgsys 170 +#define IA32_SYS_ia32_shmsys 171 +#define IA32_SYS_ia32_pread 173 +#define IA32_SYS_ia32_pwrite 174 +#define IA32_SYS_ntp_adjtime 176 +#define IA32_SYS_setgid 181 +#define IA32_SYS_setegid 182 +#define IA32_SYS_seteuid 183 +#define IA32_SYS_ia32_stat 188 +#define IA32_SYS_ia32_fstat 189 +#define IA32_SYS_ia32_lstat 190 +#define IA32_SYS_pathconf 191 +#define IA32_SYS_fpathconf 192 +#define IA32_SYS_getrlimit 194 +#define IA32_SYS_setrlimit 195 +#define IA32_SYS_getdirentries 196 +#define IA32_SYS_ia32_mmap 197 +#define IA32_SYS___syscall 198 +#define IA32_SYS_ia32_lseek 199 +#define IA32_SYS_ia32_truncate 200 +#define IA32_SYS_ia32_ftruncate 201 +#define IA32_SYS_ia32_sysctl 202 +#define IA32_SYS_mlock 203 +#define IA32_SYS_munlock 204 +#define IA32_SYS_undelete 205 +#define IA32_SYS_futimes 206 +#define IA32_SYS_getpgid 207 +#define IA32_SYS_poll 209 +#define IA32_SYS___semctl 220 +#define IA32_SYS_semget 221 +#define IA32_SYS_semop 222 +#define IA32_SYS_msgctl 224 +#define IA32_SYS_msgget 225 +#define IA32_SYS_msgsnd 226 +#define IA32_SYS_msgrcv 227 +#define IA32_SYS_shmat 228 +#define IA32_SYS_shmctl 229 +#define IA32_SYS_shmdt 230 +#define IA32_SYS_shmget 231 +#define IA32_SYS_clock_gettime 232 +#define IA32_SYS_clock_settime 233 +#define IA32_SYS_clock_getres 234 +#define IA32_SYS_nanosleep 240 +#define IA32_SYS_minherit 250 +#define IA32_SYS_rfork 251 +#define IA32_SYS_openbsd_poll 252 +#define IA32_SYS_issetugid 253 +#define IA32_SYS_lchown 254 +#define IA32_SYS_getdents 272 +#define IA32_SYS_lchmod 274 +#define IA32_SYS_netbsd_lchown 275 +#define IA32_SYS_lutimes 276 +#define IA32_SYS_netbsd_msync 277 +#define IA32_SYS_nstat 278 +#define IA32_SYS_nfstat 279 +#define IA32_SYS_nlstat 280 +#define IA32_SYS_fhstatfs 297 +#define IA32_SYS_fhopen 298 +#define IA32_SYS_fhstat 299 +#define IA32_SYS_modnext 300 +#define IA32_SYS_modstat 301 +#define IA32_SYS_modfnext 302 +#define IA32_SYS_modfind 303 +#define IA32_SYS_kldload 304 +#define IA32_SYS_kldunload 305 +#define IA32_SYS_kldfind 306 +#define IA32_SYS_kldnext 307 +#define IA32_SYS_kldstat 308 +#define IA32_SYS_kldfirstmod 309 +#define IA32_SYS_getsid 310 +#define IA32_SYS_setresuid 311 +#define IA32_SYS_setresgid 312 + /* 313 is obsolete signanosleep */ +#define IA32_SYS_yield 321 + /* 322 is obsolete thr_sleep */ + /* 323 is obsolete thr_wakeup */ +#define IA32_SYS_mlockall 324 +#define IA32_SYS_munlockall 325 +#define IA32_SYS___getcwd 326 +#define IA32_SYS_sched_setparam 327 +#define IA32_SYS_sched_getparam 328 +#define IA32_SYS_sched_setscheduler 329 +#define IA32_SYS_sched_getscheduler 330 +#define IA32_SYS_sched_yield 331 +#define IA32_SYS_sched_get_priority_max 332 +#define IA32_SYS_sched_get_priority_min 333 +#define IA32_SYS_sched_rr_get_interval 334 +#define IA32_SYS_utrace 335 +#define IA32_SYS_ia32_sendfile 336 +#define IA32_SYS_kldsym 337 +#define IA32_SYS_jail 338 +#define IA32_SYS_sigprocmask 340 +#define IA32_SYS_sigsuspend 341 +#define IA32_SYS_ia32_sigaction 342 +#define IA32_SYS_sigpending 343 +#define IA32_SYS_sigreturn 344 +#define IA32_SYS___acl_get_file 347 +#define IA32_SYS___acl_set_file 348 +#define IA32_SYS___acl_get_fd 349 +#define IA32_SYS___acl_set_fd 350 +#define IA32_SYS___acl_delete_file 351 +#define IA32_SYS___acl_delete_fd 352 +#define IA32_SYS___acl_aclcheck_file 353 +#define IA32_SYS___acl_aclcheck_fd 354 +#define IA32_SYS_extattrctl 355 +#define IA32_SYS_extattr_set_file 356 +#define IA32_SYS_extattr_get_file 357 +#define IA32_SYS_extattr_delete_file 358 +#define IA32_SYS_getresuid 360 +#define IA32_SYS_getresgid 361 +#define IA32_SYS_kqueue 362 +#define IA32_SYS_kevent 363 +#define IA32_SYS_extattr_set_fd 371 +#define IA32_SYS_extattr_get_fd 372 +#define IA32_SYS_extattr_delete_fd 373 +#define IA32_SYS___setugid 374 +#define IA32_SYS_eaccess 376 +#define IA32_SYS_nmount 378 +#define IA32_SYS_kse_exit 379 +#define IA32_SYS_kse_wakeup 380 +#define IA32_SYS_kse_new 381 +#define IA32_SYS_thread_wakeup 382 +#define IA32_SYS_kse_yield 383 +#define IA32_SYS_kenv 390 +#define IA32_SYS_lchflags 391 +#define IA32_SYS_uuidgen 392 +#define IA32_SYS_MAXSYSCALL 393 diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c new file mode 100644 index 0000000..a385596 --- /dev/null +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -0,0 +1,413 @@ +/* + * System call switch table. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/ia64/ia32/syscalls.master,v 1.2 2002/07/20 02:56:10 peter Exp + */ + +#include <sys/param.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <sys/mount.h> +#include <ia64/ia32/ia32.h> +#include <ia64/ia32/ia32_proto.h> + +#define AS(name) (sizeof(struct name) / sizeof(register_t)) + +/* The casts are bogus but will do for now. */ +struct sysent ia32_sysent[] = { + { SYF_MPSAFE | 0, (sy_call_t *)nosys }, /* 0 = syscall */ + { SYF_MPSAFE | AS(sys_exit_args), (sy_call_t *)sys_exit }, /* 1 = exit */ + { SYF_MPSAFE | 0, (sy_call_t *)fork }, /* 2 = fork */ + { SYF_MPSAFE | AS(read_args), (sy_call_t *)read }, /* 3 = read */ + { SYF_MPSAFE | AS(write_args), (sy_call_t *)write }, /* 4 = write */ + { AS(ia32_open_args), (sy_call_t *)ia32_open }, /* 5 = ia32_open */ + { SYF_MPSAFE | AS(close_args), (sy_call_t *)close }, /* 6 = close */ + { SYF_MPSAFE | AS(ia32_wait4_args), (sy_call_t *)ia32_wait4 }, /* 7 = ia32_wait4 */ + { 0, (sy_call_t *)nosys }, /* 8 = obsolete old creat */ + { AS(link_args), (sy_call_t *)link }, /* 9 = link */ + { AS(unlink_args), (sy_call_t *)unlink }, /* 10 = unlink */ + { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */ + { AS(chdir_args), (sy_call_t *)chdir }, /* 12 = chdir */ + { AS(fchdir_args), (sy_call_t *)fchdir }, /* 13 = fchdir */ + { AS(mknod_args), (sy_call_t *)mknod }, /* 14 = mknod */ + { AS(chmod_args), (sy_call_t *)chmod }, /* 15 = chmod */ + { AS(chown_args), (sy_call_t *)chown }, /* 16 = chown */ + { SYF_MPSAFE | AS(obreak_args), (sy_call_t *)obreak }, /* 17 = break */ + { AS(ia32_getfsstat_args), (sy_call_t *)ia32_getfsstat }, /* 18 = ia32_getfsstat */ + { 0, (sy_call_t *)nosys }, /* 19 = obsolete olseek */ + { SYF_MPSAFE | 0, (sy_call_t *)getpid }, /* 20 = getpid */ + { AS(mount_args), (sy_call_t *)mount }, /* 21 = mount */ + { AS(unmount_args), (sy_call_t *)unmount }, /* 22 = unmount */ + { SYF_MPSAFE | AS(setuid_args), (sy_call_t *)setuid }, /* 23 = setuid */ + { SYF_MPSAFE | 0, (sy_call_t *)getuid }, /* 24 = getuid */ + { SYF_MPSAFE | 0, (sy_call_t *)geteuid }, /* 25 = geteuid */ + { AS(ptrace_args), (sy_call_t *)ptrace }, /* 26 = ptrace */ + { 0, (sy_call_t *)nosys }, /* 27 = recvmsg */ + { SYF_MPSAFE | AS(sendmsg_args), (sy_call_t *)sendmsg }, /* 28 = sendmsg */ + { SYF_MPSAFE | AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 29 = recvfrom */ + { SYF_MPSAFE | AS(accept_args), (sy_call_t *)accept }, /* 30 = accept */ + { SYF_MPSAFE | AS(getpeername_args), (sy_call_t *)getpeername }, /* 31 = getpeername */ + { SYF_MPSAFE | AS(getsockname_args), (sy_call_t *)getsockname }, /* 32 = getsockname */ + { AS(ia32_access_args), (sy_call_t *)ia32_access }, /* 33 = ia32_access */ + { AS(ia32_chflags_args), (sy_call_t *)ia32_chflags }, /* 34 = ia32_chflags */ + { AS(fchflags_args), (sy_call_t *)fchflags }, /* 35 = fchflags */ + { 0, (sy_call_t *)sync }, /* 36 = sync */ + { SYF_MPSAFE | AS(kill_args), (sy_call_t *)kill }, /* 37 = kill */ + { 0, (sy_call_t *)nosys }, /* 38 = ostat */ + { SYF_MPSAFE | 0, (sy_call_t *)getppid }, /* 39 = getppid */ + { 0, (sy_call_t *)nosys }, /* 40 = olstat */ + { AS(dup_args), (sy_call_t *)dup }, /* 41 = dup */ + { 0, (sy_call_t *)pipe }, /* 42 = pipe */ + { SYF_MPSAFE | 0, (sy_call_t *)getegid }, /* 43 = getegid */ + { SYF_MPSAFE | AS(profil_args), (sy_call_t *)profil }, /* 44 = profil */ + { AS(ktrace_args), (sy_call_t *)ktrace }, /* 45 = ktrace */ + { 0, (sy_call_t *)nosys }, /* 46 = osigaction */ + { SYF_MPSAFE | 0, (sy_call_t *)getgid }, /* 47 = getgid */ + { 0, (sy_call_t *)nosys }, /* 48 = osigprocmask */ + { SYF_MPSAFE | AS(getlogin_args), (sy_call_t *)getlogin }, /* 49 = getlogin */ + { SYF_MPSAFE | AS(setlogin_args), (sy_call_t *)setlogin }, /* 50 = setlogin */ + { SYF_MPSAFE | AS(acct_args), (sy_call_t *)acct }, /* 51 = acct */ + { SYF_MPSAFE | 0, (sy_call_t *)sigpending }, /* 52 = sigpending */ + { AS(ia32_sigaltstack_args), (sy_call_t *)ia32_sigaltstack }, /* 53 = ia32_sigaltstack */ + { SYF_MPSAFE | AS(ioctl_args), (sy_call_t *)ioctl }, /* 54 = ioctl */ + { SYF_MPSAFE | AS(reboot_args), (sy_call_t *)reboot }, /* 55 = reboot */ + { AS(revoke_args), (sy_call_t *)revoke }, /* 56 = revoke */ + { AS(symlink_args), (sy_call_t *)symlink }, /* 57 = symlink */ + { AS(readlink_args), (sy_call_t *)readlink }, /* 58 = readlink */ + { AS(ia32_execve_args), (sy_call_t *)ia32_execve }, /* 59 = ia32_execve */ + { SYF_MPSAFE | AS(umask_args), (sy_call_t *)umask }, /* 60 = umask */ + { AS(chroot_args), (sy_call_t *)chroot }, /* 61 = chroot */ + { 0, (sy_call_t *)nosys }, /* 62 = obsolete ofstat */ + { 0, (sy_call_t *)nosys }, /* 63 = obsolete ogetkerninfo */ + { 0, (sy_call_t *)nosys }, /* 64 = obsolete ogetpagesize */ + { 0, (sy_call_t *)nosys }, /* 65 = obsolete omsync */ + { 0, (sy_call_t *)nosys }, /* 66 = obsolete ovfork */ + { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */ + { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */ + { SYF_MPSAFE | AS(sbrk_args), (sy_call_t *)sbrk }, /* 69 = sbrk */ + { SYF_MPSAFE | AS(sstk_args), (sy_call_t *)sstk }, /* 70 = sstk */ + { 0, (sy_call_t *)nosys }, /* 71 = obsolete ommap */ + { SYF_MPSAFE | AS(ovadvise_args), (sy_call_t *)ovadvise }, /* 72 = vadvise */ + { SYF_MPSAFE | AS(munmap_args), (sy_call_t *)munmap }, /* 73 = munmap */ + { SYF_MPSAFE | AS(mprotect_args), (sy_call_t *)mprotect }, /* 74 = mprotect */ + { SYF_MPSAFE | AS(madvise_args), (sy_call_t *)madvise }, /* 75 = madvise */ + { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */ + { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */ + { SYF_MPSAFE | AS(mincore_args), (sy_call_t *)mincore }, /* 78 = mincore */ + { SYF_MPSAFE | AS(getgroups_args), (sy_call_t *)getgroups }, /* 79 = getgroups */ + { SYF_MPSAFE | AS(setgroups_args), (sy_call_t *)setgroups }, /* 80 = setgroups */ + { SYF_MPSAFE | 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */ + { SYF_MPSAFE | AS(setpgid_args), (sy_call_t *)setpgid }, /* 82 = setpgid */ + { AS(ia32_setitimer_args), (sy_call_t *)ia32_setitimer }, /* 83 = ia32_setitimer */ + { 0, (sy_call_t *)nosys }, /* 84 = obsolete owait */ + { 0, (sy_call_t *)nosys }, /* 85 = obsolete oswapon */ + { 0, (sy_call_t *)nosys }, /* 86 = obsolete ogetitimer */ + { 0, (sy_call_t *)nosys }, /* 87 = obsolete ogethostname */ + { 0, (sy_call_t *)nosys }, /* 88 = obsolete osethostname */ + { SYF_MPSAFE | 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */ + { SYF_MPSAFE | AS(dup2_args), (sy_call_t *)dup2 }, /* 90 = dup2 */ + { 0, (sy_call_t *)nosys }, /* 91 = getdopt */ + { SYF_MPSAFE | AS(fcntl_args), (sy_call_t *)fcntl }, /* 92 = fcntl */ + { AS(ia32_select_args), (sy_call_t *)ia32_select }, /* 93 = ia32_select */ + { 0, (sy_call_t *)nosys }, /* 94 = setdopt */ + { AS(fsync_args), (sy_call_t *)fsync }, /* 95 = fsync */ + { SYF_MPSAFE | AS(setpriority_args), (sy_call_t *)setpriority }, /* 96 = setpriority */ + { SYF_MPSAFE | AS(socket_args), (sy_call_t *)socket }, /* 97 = socket */ + { SYF_MPSAFE | AS(connect_args), (sy_call_t *)connect }, /* 98 = connect */ + { SYF_MPSAFE | AS(accept_args), (sy_call_t *)accept }, /* 99 = accept */ + { SYF_MPSAFE | AS(getpriority_args), (sy_call_t *)getpriority }, /* 100 = getpriority */ + { 0, (sy_call_t *)nosys }, /* 101 = obsolete osend */ + { 0, (sy_call_t *)nosys }, /* 102 = obsolete orecv */ + { 0, (sy_call_t *)nosys }, /* 103 = obsolete osigreturn */ + { SYF_MPSAFE | AS(bind_args), (sy_call_t *)bind }, /* 104 = bind */ + { SYF_MPSAFE | AS(setsockopt_args), (sy_call_t *)setsockopt }, /* 105 = setsockopt */ + { SYF_MPSAFE | AS(listen_args), (sy_call_t *)listen }, /* 106 = listen */ + { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */ + { 0, (sy_call_t *)nosys }, /* 108 = obsolete osigvec */ + { 0, (sy_call_t *)nosys }, /* 109 = obsolete osigblock */ + { 0, (sy_call_t *)nosys }, /* 110 = obsolete osigsetmask */ + { 0, (sy_call_t *)nosys }, /* 111 = obsolete osigsuspend */ + { 0, (sy_call_t *)nosys }, /* 112 = obsolete osigstack */ + { 0, (sy_call_t *)nosys }, /* 113 = obsolete orecvmsg */ + { 0, (sy_call_t *)nosys }, /* 114 = obsolete osendmsg */ + { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */ + { AS(ia32_gettimeofday_args), (sy_call_t *)ia32_gettimeofday }, /* 116 = ia32_gettimeofday */ + { AS(ia32_getrusage_args), (sy_call_t *)ia32_getrusage }, /* 117 = ia32_getrusage */ + { SYF_MPSAFE | AS(getsockopt_args), (sy_call_t *)getsockopt }, /* 118 = getsockopt */ + { 0, (sy_call_t *)nosys }, /* 119 = resuba */ + { AS(ia32_readv_args), (sy_call_t *)ia32_readv }, /* 120 = ia32_readv */ + { AS(ia32_writev_args), (sy_call_t *)ia32_writev }, /* 121 = ia32_writev */ + { AS(ia32_settimeofday_args), (sy_call_t *)ia32_settimeofday }, /* 122 = ia32_settimeofday */ + { AS(fchown_args), (sy_call_t *)fchown }, /* 123 = fchown */ + { AS(fchmod_args), (sy_call_t *)fchmod }, /* 124 = fchmod */ + { SYF_MPSAFE | AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 125 = recvfrom */ + { SYF_MPSAFE | AS(setreuid_args), (sy_call_t *)setreuid }, /* 126 = setreuid */ + { SYF_MPSAFE | AS(setregid_args), (sy_call_t *)setregid }, /* 127 = setregid */ + { AS(rename_args), (sy_call_t *)rename }, /* 128 = rename */ + { 0, (sy_call_t *)nosys }, /* 129 = obsolete otruncate */ + { 0, (sy_call_t *)nosys }, /* 130 = obsolete ftruncate */ + { SYF_MPSAFE | AS(flock_args), (sy_call_t *)flock }, /* 131 = flock */ + { AS(mkfifo_args), (sy_call_t *)mkfifo }, /* 132 = mkfifo */ + { SYF_MPSAFE | AS(sendto_args), (sy_call_t *)sendto }, /* 133 = sendto */ + { SYF_MPSAFE | AS(shutdown_args), (sy_call_t *)shutdown }, /* 134 = shutdown */ + { SYF_MPSAFE | AS(socketpair_args), (sy_call_t *)socketpair }, /* 135 = socketpair */ + { AS(mkdir_args), (sy_call_t *)mkdir }, /* 136 = mkdir */ + { AS(rmdir_args), (sy_call_t *)rmdir }, /* 137 = rmdir */ + { AS(ia32_utimes_args), (sy_call_t *)ia32_utimes }, /* 138 = ia32_utimes */ + { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */ + { AS(ia32_adjtime_args), (sy_call_t *)ia32_adjtime }, /* 140 = ia32_adjtime */ + { 0, (sy_call_t *)nosys }, /* 141 = obsolete ogetpeername */ + { 0, (sy_call_t *)nosys }, /* 142 = obsolete ogethostid */ + { 0, (sy_call_t *)nosys }, /* 143 = obsolete sethostid */ + { 0, (sy_call_t *)nosys }, /* 144 = obsolete getrlimit */ + { 0, (sy_call_t *)nosys }, /* 145 = obsolete setrlimit */ + { 0, (sy_call_t *)nosys }, /* 146 = obsolete killpg */ + { SYF_MPSAFE | 0, (sy_call_t *)setsid }, /* 147 = setsid */ + { AS(quotactl_args), (sy_call_t *)quotactl }, /* 148 = quotactl */ + { 0, (sy_call_t *)nosys }, /* 149 = obsolete oquota */ + { 0, (sy_call_t *)nosys }, /* 150 = obsolete ogetsockname */ + { 0, (sy_call_t *)nosys }, /* 151 = sem_lock */ + { 0, (sy_call_t *)nosys }, /* 152 = sem_wakeup */ + { 0, (sy_call_t *)nosys }, /* 153 = asyncdaemon */ + { 0, (sy_call_t *)nosys }, /* 154 = nosys */ + { 0, (sy_call_t *)nosys }, /* 155 = nfssvc */ + { AS(getdirentries_args), (sy_call_t *)getdirentries }, /* 156 = getdirentries */ + { AS(ia32_statfs_args), (sy_call_t *)ia32_statfs }, /* 157 = ia32_statfs */ + { AS(ia32_fstatfs_args), (sy_call_t *)ia32_fstatfs }, /* 158 = ia32_fstatfs */ + { 0, (sy_call_t *)nosys }, /* 159 = nosys */ + { 0, (sy_call_t *)nosys }, /* 160 = nosys */ + { AS(getfh_args), (sy_call_t *)getfh }, /* 161 = getfh */ + { SYF_MPSAFE | AS(getdomainname_args), (sy_call_t *)getdomainname }, /* 162 = getdomainname */ + { SYF_MPSAFE | AS(setdomainname_args), (sy_call_t *)setdomainname }, /* 163 = setdomainname */ + { SYF_MPSAFE | AS(uname_args), (sy_call_t *)uname }, /* 164 = uname */ + { AS(sysarch_args), (sy_call_t *)sysarch }, /* 165 = sysarch */ + { SYF_MPSAFE | AS(rtprio_args), (sy_call_t *)rtprio }, /* 166 = rtprio */ + { 0, (sy_call_t *)nosys }, /* 167 = nosys */ + { 0, (sy_call_t *)nosys }, /* 168 = nosys */ + { AS(ia32_semsys_args), (sy_call_t *)ia32_semsys }, /* 169 = ia32_semsys */ + { AS(ia32_msgsys_args), (sy_call_t *)ia32_msgsys }, /* 170 = ia32_msgsys */ + { AS(ia32_shmsys_args), (sy_call_t *)ia32_shmsys }, /* 171 = ia32_shmsys */ + { 0, (sy_call_t *)nosys }, /* 172 = nosys */ + { AS(ia32_pread_args), (sy_call_t *)ia32_pread }, /* 173 = ia32_pread */ + { AS(ia32_pwrite_args), (sy_call_t *)ia32_pwrite }, /* 174 = ia32_pwrite */ + { 0, (sy_call_t *)nosys }, /* 175 = nosys */ + { SYF_MPSAFE | AS(ntp_adjtime_args), (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */ + { 0, (sy_call_t *)nosys }, /* 177 = sfork */ + { 0, (sy_call_t *)nosys }, /* 178 = getdescriptor */ + { 0, (sy_call_t *)nosys }, /* 179 = setdescriptor */ + { 0, (sy_call_t *)nosys }, /* 180 = nosys */ + { SYF_MPSAFE | AS(setgid_args), (sy_call_t *)setgid }, /* 181 = setgid */ + { SYF_MPSAFE | AS(setegid_args), (sy_call_t *)setegid }, /* 182 = setegid */ + { SYF_MPSAFE | AS(seteuid_args), (sy_call_t *)seteuid }, /* 183 = seteuid */ + { 0, (sy_call_t *)nosys }, /* 184 = lfs_bmapv */ + { 0, (sy_call_t *)nosys }, /* 185 = lfs_markv */ + { 0, (sy_call_t *)nosys }, /* 186 = lfs_segclean */ + { 0, (sy_call_t *)nosys }, /* 187 = lfs_segwait */ + { AS(ia32_stat_args), (sy_call_t *)ia32_stat }, /* 188 = ia32_stat */ + { AS(ia32_fstat_args), (sy_call_t *)ia32_fstat }, /* 189 = ia32_fstat */ + { AS(ia32_lstat_args), (sy_call_t *)ia32_lstat }, /* 190 = ia32_lstat */ + { AS(pathconf_args), (sy_call_t *)pathconf }, /* 191 = pathconf */ + { SYF_MPSAFE | AS(fpathconf_args), (sy_call_t *)fpathconf }, /* 192 = fpathconf */ + { 0, (sy_call_t *)nosys }, /* 193 = nosys */ + { SYF_MPSAFE | AS(__getrlimit_args), (sy_call_t *)getrlimit }, /* 194 = getrlimit */ + { SYF_MPSAFE | AS(__setrlimit_args), (sy_call_t *)setrlimit }, /* 195 = setrlimit */ + { AS(getdirentries_args), (sy_call_t *)getdirentries }, /* 196 = getdirentries */ + { AS(ia32_mmap_args), (sy_call_t *)ia32_mmap }, /* 197 = ia32_mmap */ + { 0, (sy_call_t *)nosys }, /* 198 = __syscall */ + { AS(ia32_lseek_args), (sy_call_t *)ia32_lseek }, /* 199 = ia32_lseek */ + { AS(ia32_truncate_args), (sy_call_t *)ia32_truncate }, /* 200 = ia32_truncate */ + { AS(ia32_ftruncate_args), (sy_call_t *)ia32_ftruncate }, /* 201 = ia32_ftruncate */ + { SYF_MPSAFE | AS(ia32_sysctl_args), (sy_call_t *)ia32_sysctl }, /* 202 = ia32_sysctl */ + { SYF_MPSAFE | AS(mlock_args), (sy_call_t *)mlock }, /* 203 = mlock */ + { SYF_MPSAFE | AS(munlock_args), (sy_call_t *)munlock }, /* 204 = munlock */ + { AS(undelete_args), (sy_call_t *)undelete }, /* 205 = undelete */ + { AS(futimes_args), (sy_call_t *)futimes }, /* 206 = futimes */ + { SYF_MPSAFE | AS(getpgid_args), (sy_call_t *)getpgid }, /* 207 = getpgid */ + { 0, (sy_call_t *)nosys }, /* 208 = newreboot */ + { SYF_MPSAFE | AS(poll_args), (sy_call_t *)poll }, /* 209 = poll */ + { 0, (sy_call_t *)nosys }, /* 210 = */ + { 0, (sy_call_t *)nosys }, /* 211 = */ + { 0, (sy_call_t *)nosys }, /* 212 = */ + { 0, (sy_call_t *)nosys }, /* 213 = */ + { 0, (sy_call_t *)nosys }, /* 214 = */ + { 0, (sy_call_t *)nosys }, /* 215 = */ + { 0, (sy_call_t *)nosys }, /* 216 = */ + { 0, (sy_call_t *)nosys }, /* 217 = */ + { 0, (sy_call_t *)nosys }, /* 218 = */ + { 0, (sy_call_t *)nosys }, /* 219 = */ + { SYF_MPSAFE | AS(__semctl_args), (sy_call_t *)__semctl }, /* 220 = __semctl */ + { SYF_MPSAFE | AS(semget_args), (sy_call_t *)semget }, /* 221 = semget */ + { SYF_MPSAFE | AS(semop_args), (sy_call_t *)semop }, /* 222 = semop */ + { 0, (sy_call_t *)nosys }, /* 223 = semconfig */ + { SYF_MPSAFE | AS(msgctl_args), (sy_call_t *)msgctl }, /* 224 = msgctl */ + { SYF_MPSAFE | AS(msgget_args), (sy_call_t *)msgget }, /* 225 = msgget */ + { SYF_MPSAFE | AS(msgsnd_args), (sy_call_t *)msgsnd }, /* 226 = msgsnd */ + { SYF_MPSAFE | AS(msgrcv_args), (sy_call_t *)msgrcv }, /* 227 = msgrcv */ + { SYF_MPSAFE | AS(shmat_args), (sy_call_t *)shmat }, /* 228 = shmat */ + { SYF_MPSAFE | AS(shmctl_args), (sy_call_t *)shmctl }, /* 229 = shmctl */ + { SYF_MPSAFE | AS(shmdt_args), (sy_call_t *)shmdt }, /* 230 = shmdt */ + { SYF_MPSAFE | AS(shmget_args), (sy_call_t *)shmget }, /* 231 = shmget */ + { SYF_MPSAFE | AS(clock_gettime_args), (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */ + { SYF_MPSAFE | AS(clock_settime_args), (sy_call_t *)clock_settime }, /* 233 = clock_settime */ + { SYF_MPSAFE | AS(clock_getres_args), (sy_call_t *)clock_getres }, /* 234 = clock_getres */ + { 0, (sy_call_t *)nosys }, /* 235 = timer_create */ + { 0, (sy_call_t *)nosys }, /* 236 = timer_delete */ + { 0, (sy_call_t *)nosys }, /* 237 = timer_settime */ + { 0, (sy_call_t *)nosys }, /* 238 = timer_gettime */ + { 0, (sy_call_t *)nosys }, /* 239 = timer_getoverrun */ + { SYF_MPSAFE | AS(nanosleep_args), (sy_call_t *)nanosleep }, /* 240 = nanosleep */ + { 0, (sy_call_t *)nosys }, /* 241 = nosys */ + { 0, (sy_call_t *)nosys }, /* 242 = nosys */ + { 0, (sy_call_t *)nosys }, /* 243 = nosys */ + { 0, (sy_call_t *)nosys }, /* 244 = nosys */ + { 0, (sy_call_t *)nosys }, /* 245 = nosys */ + { 0, (sy_call_t *)nosys }, /* 246 = nosys */ + { 0, (sy_call_t *)nosys }, /* 247 = nosys */ + { 0, (sy_call_t *)nosys }, /* 248 = nosys */ + { 0, (sy_call_t *)nosys }, /* 249 = nosys */ + { SYF_MPSAFE | AS(minherit_args), (sy_call_t *)minherit }, /* 250 = minherit */ + { SYF_MPSAFE | AS(rfork_args), (sy_call_t *)rfork }, /* 251 = rfork */ + { SYF_MPSAFE | AS(openbsd_poll_args), (sy_call_t *)openbsd_poll }, /* 252 = openbsd_poll */ + { 0, (sy_call_t *)issetugid }, /* 253 = issetugid */ + { AS(lchown_args), (sy_call_t *)lchown }, /* 254 = lchown */ + { 0, (sy_call_t *)nosys }, /* 255 = nosys */ + { 0, (sy_call_t *)nosys }, /* 256 = nosys */ + { 0, (sy_call_t *)nosys }, /* 257 = nosys */ + { 0, (sy_call_t *)nosys }, /* 258 = nosys */ + { 0, (sy_call_t *)nosys }, /* 259 = nosys */ + { 0, (sy_call_t *)nosys }, /* 260 = nosys */ + { 0, (sy_call_t *)nosys }, /* 261 = nosys */ + { 0, (sy_call_t *)nosys }, /* 262 = nosys */ + { 0, (sy_call_t *)nosys }, /* 263 = nosys */ + { 0, (sy_call_t *)nosys }, /* 264 = nosys */ + { 0, (sy_call_t *)nosys }, /* 265 = nosys */ + { 0, (sy_call_t *)nosys }, /* 266 = nosys */ + { 0, (sy_call_t *)nosys }, /* 267 = nosys */ + { 0, (sy_call_t *)nosys }, /* 268 = nosys */ + { 0, (sy_call_t *)nosys }, /* 269 = nosys */ + { 0, (sy_call_t *)nosys }, /* 270 = nosys */ + { 0, (sy_call_t *)nosys }, /* 271 = nosys */ + { AS(getdents_args), (sy_call_t *)getdents }, /* 272 = getdents */ + { 0, (sy_call_t *)nosys }, /* 273 = nosys */ + { AS(lchmod_args), (sy_call_t *)lchmod }, /* 274 = lchmod */ + { AS(lchown_args), (sy_call_t *)lchown }, /* 275 = netbsd_lchown */ + { AS(lutimes_args), (sy_call_t *)lutimes }, /* 276 = lutimes */ + { SYF_MPSAFE | AS(msync_args), (sy_call_t *)msync }, /* 277 = netbsd_msync */ + { AS(nstat_args), (sy_call_t *)nstat }, /* 278 = nstat */ + { SYF_MPSAFE | AS(nfstat_args), (sy_call_t *)nfstat }, /* 279 = nfstat */ + { AS(nlstat_args), (sy_call_t *)nlstat }, /* 280 = nlstat */ + { 0, (sy_call_t *)nosys }, /* 281 = nosys */ + { 0, (sy_call_t *)nosys }, /* 282 = nosys */ + { 0, (sy_call_t *)nosys }, /* 283 = nosys */ + { 0, (sy_call_t *)nosys }, /* 284 = nosys */ + { 0, (sy_call_t *)nosys }, /* 285 = nosys */ + { 0, (sy_call_t *)nosys }, /* 286 = nosys */ + { 0, (sy_call_t *)nosys }, /* 287 = nosys */ + { 0, (sy_call_t *)nosys }, /* 288 = nosys */ + { 0, (sy_call_t *)nosys }, /* 289 = nosys */ + { 0, (sy_call_t *)nosys }, /* 290 = nosys */ + { 0, (sy_call_t *)nosys }, /* 291 = nosys */ + { 0, (sy_call_t *)nosys }, /* 292 = nosys */ + { 0, (sy_call_t *)nosys }, /* 293 = nosys */ + { 0, (sy_call_t *)nosys }, /* 294 = nosys */ + { 0, (sy_call_t *)nosys }, /* 295 = nosys */ + { 0, (sy_call_t *)nosys }, /* 296 = nosys */ + { AS(fhstatfs_args), (sy_call_t *)fhstatfs }, /* 297 = fhstatfs */ + { AS(fhopen_args), (sy_call_t *)fhopen }, /* 298 = fhopen */ + { AS(fhstat_args), (sy_call_t *)fhstat }, /* 299 = fhstat */ + { SYF_MPSAFE | AS(modnext_args), (sy_call_t *)modnext }, /* 300 = modnext */ + { SYF_MPSAFE | AS(modstat_args), (sy_call_t *)modstat }, /* 301 = modstat */ + { SYF_MPSAFE | AS(modfnext_args), (sy_call_t *)modfnext }, /* 302 = modfnext */ + { SYF_MPSAFE | AS(modfind_args), (sy_call_t *)modfind }, /* 303 = modfind */ + { SYF_MPSAFE | AS(kldload_args), (sy_call_t *)kldload }, /* 304 = kldload */ + { SYF_MPSAFE | AS(kldunload_args), (sy_call_t *)kldunload }, /* 305 = kldunload */ + { SYF_MPSAFE | AS(kldfind_args), (sy_call_t *)kldfind }, /* 306 = kldfind */ + { SYF_MPSAFE | AS(kldnext_args), (sy_call_t *)kldnext }, /* 307 = kldnext */ + { SYF_MPSAFE | AS(kldstat_args), (sy_call_t *)kldstat }, /* 308 = kldstat */ + { SYF_MPSAFE | AS(kldfirstmod_args), (sy_call_t *)kldfirstmod }, /* 309 = kldfirstmod */ + { SYF_MPSAFE | AS(getsid_args), (sy_call_t *)getsid }, /* 310 = getsid */ + { SYF_MPSAFE | AS(setresuid_args), (sy_call_t *)setresuid }, /* 311 = setresuid */ + { SYF_MPSAFE | AS(setresgid_args), (sy_call_t *)setresgid }, /* 312 = setresgid */ + { 0, (sy_call_t *)nosys }, /* 313 = obsolete signanosleep */ + { 0, (sy_call_t *)nosys }, /* 314 = aio_return */ + { 0, (sy_call_t *)nosys }, /* 315 = aio_suspend */ + { 0, (sy_call_t *)nosys }, /* 316 = aio_cancel */ + { 0, (sy_call_t *)nosys }, /* 317 = aio_error */ + { 0, (sy_call_t *)nosys }, /* 318 = aio_read */ + { 0, (sy_call_t *)nosys }, /* 319 = aio_write */ + { 0, (sy_call_t *)nosys }, /* 320 = lio_listio */ + { SYF_MPSAFE | 0, (sy_call_t *)yield }, /* 321 = yield */ + { 0, (sy_call_t *)nosys }, /* 322 = obsolete thr_sleep */ + { 0, (sy_call_t *)nosys }, /* 323 = obsolete thr_wakeup */ + { SYF_MPSAFE | AS(mlockall_args), (sy_call_t *)mlockall }, /* 324 = mlockall */ + { SYF_MPSAFE | 0, (sy_call_t *)munlockall }, /* 325 = munlockall */ + { AS(__getcwd_args), (sy_call_t *)__getcwd }, /* 326 = __getcwd */ + { SYF_MPSAFE | AS(sched_setparam_args), (sy_call_t *)sched_setparam }, /* 327 = sched_setparam */ + { SYF_MPSAFE | AS(sched_getparam_args), (sy_call_t *)sched_getparam }, /* 328 = sched_getparam */ + { SYF_MPSAFE | AS(sched_setscheduler_args), (sy_call_t *)sched_setscheduler }, /* 329 = sched_setscheduler */ + { SYF_MPSAFE | AS(sched_getscheduler_args), (sy_call_t *)sched_getscheduler }, /* 330 = sched_getscheduler */ + { SYF_MPSAFE | 0, (sy_call_t *)sched_yield }, /* 331 = sched_yield */ + { SYF_MPSAFE | AS(sched_get_priority_max_args), (sy_call_t *)sched_get_priority_max }, /* 332 = sched_get_priority_max */ + { SYF_MPSAFE | AS(sched_get_priority_min_args), (sy_call_t *)sched_get_priority_min }, /* 333 = sched_get_priority_min */ + { SYF_MPSAFE | AS(sched_rr_get_interval_args), (sy_call_t *)sched_rr_get_interval }, /* 334 = sched_rr_get_interval */ + { AS(utrace_args), (sy_call_t *)utrace }, /* 335 = utrace */ + { SYF_MPSAFE | AS(ia32_sendfile_args), (sy_call_t *)ia32_sendfile }, /* 336 = ia32_sendfile */ + { AS(kldsym_args), (sy_call_t *)kldsym }, /* 337 = kldsym */ + { SYF_MPSAFE | AS(jail_args), (sy_call_t *)jail }, /* 338 = jail */ + { 0, (sy_call_t *)nosys }, /* 339 = pioctl */ + { SYF_MPSAFE | AS(sigprocmask_args), (sy_call_t *)sigprocmask }, /* 340 = sigprocmask */ + { SYF_MPSAFE | AS(sigsuspend_args), (sy_call_t *)sigsuspend }, /* 341 = sigsuspend */ + { AS(ia32_sigaction_args), (sy_call_t *)ia32_sigaction }, /* 342 = ia32_sigaction */ + { SYF_MPSAFE | AS(sigpending_args), (sy_call_t *)sigpending }, /* 343 = sigpending */ + { SYF_MPSAFE | AS(sigreturn_args), (sy_call_t *)sigreturn }, /* 344 = sigreturn */ + { 0, (sy_call_t *)nosys }, /* 345 = sigtimedwait */ + { 0, (sy_call_t *)nosys }, /* 346 = sigwaitinfo */ + { SYF_MPSAFE | AS(__acl_get_file_args), (sy_call_t *)__acl_get_file }, /* 347 = __acl_get_file */ + { SYF_MPSAFE | AS(__acl_set_file_args), (sy_call_t *)__acl_set_file }, /* 348 = __acl_set_file */ + { SYF_MPSAFE | AS(__acl_get_fd_args), (sy_call_t *)__acl_get_fd }, /* 349 = __acl_get_fd */ + { SYF_MPSAFE | AS(__acl_set_fd_args), (sy_call_t *)__acl_set_fd }, /* 350 = __acl_set_fd */ + { SYF_MPSAFE | AS(__acl_delete_file_args), (sy_call_t *)__acl_delete_file }, /* 351 = __acl_delete_file */ + { SYF_MPSAFE | AS(__acl_delete_fd_args), (sy_call_t *)__acl_delete_fd }, /* 352 = __acl_delete_fd */ + { SYF_MPSAFE | AS(__acl_aclcheck_file_args), (sy_call_t *)__acl_aclcheck_file }, /* 353 = __acl_aclcheck_file */ + { SYF_MPSAFE | AS(__acl_aclcheck_fd_args), (sy_call_t *)__acl_aclcheck_fd }, /* 354 = __acl_aclcheck_fd */ + { AS(extattrctl_args), (sy_call_t *)extattrctl }, /* 355 = extattrctl */ + { AS(extattr_set_file_args), (sy_call_t *)extattr_set_file }, /* 356 = extattr_set_file */ + { AS(extattr_get_file_args), (sy_call_t *)extattr_get_file }, /* 357 = extattr_get_file */ + { AS(extattr_delete_file_args), (sy_call_t *)extattr_delete_file }, /* 358 = extattr_delete_file */ + { 0, (sy_call_t *)nosys }, /* 359 = aio_waitcomplete */ + { SYF_MPSAFE | AS(getresuid_args), (sy_call_t *)getresuid }, /* 360 = getresuid */ + { SYF_MPSAFE | AS(getresgid_args), (sy_call_t *)getresgid }, /* 361 = getresgid */ + { SYF_MPSAFE | 0, (sy_call_t *)kqueue }, /* 362 = kqueue */ + { SYF_MPSAFE | AS(kevent_args), (sy_call_t *)kevent }, /* 363 = kevent */ + { 0, (sy_call_t *)nosys }, /* 364 = __cap_get_proc */ + { 0, (sy_call_t *)nosys }, /* 365 = __cap_set_proc */ + { 0, (sy_call_t *)nosys }, /* 366 = __cap_get_fd */ + { 0, (sy_call_t *)nosys }, /* 367 = __cap_get_file */ + { 0, (sy_call_t *)nosys }, /* 368 = __cap_set_fd */ + { 0, (sy_call_t *)nosys }, /* 369 = __cap_set_file */ + { 0, (sy_call_t *)nosys }, /* 370 = lkmressys */ + { AS(extattr_set_fd_args), (sy_call_t *)extattr_set_fd }, /* 371 = extattr_set_fd */ + { AS(extattr_get_fd_args), (sy_call_t *)extattr_get_fd }, /* 372 = extattr_get_fd */ + { AS(extattr_delete_fd_args), (sy_call_t *)extattr_delete_fd }, /* 373 = extattr_delete_fd */ + { SYF_MPSAFE | AS(__setugid_args), (sy_call_t *)__setugid }, /* 374 = __setugid */ + { 0, (sy_call_t *)nosys }, /* 375 = nfsclnt */ + { AS(eaccess_args), (sy_call_t *)eaccess }, /* 376 = eaccess */ + { 0, (sy_call_t *)nosys }, /* 377 = afs_syscall */ + { AS(nmount_args), (sy_call_t *)nmount }, /* 378 = nmount */ + { 0, (sy_call_t *)kse_exit }, /* 379 = kse_exit */ + { 0, (sy_call_t *)kse_wakeup }, /* 380 = kse_wakeup */ + { AS(kse_new_args), (sy_call_t *)kse_new }, /* 381 = kse_new */ + { AS(thread_wakeup_args), (sy_call_t *)thread_wakeup }, /* 382 = thread_wakeup */ + { 0, (sy_call_t *)kse_yield }, /* 383 = kse_yield */ + { 0, (sy_call_t *)nosys }, /* 384 = __mac_get_proc */ + { 0, (sy_call_t *)nosys }, /* 385 = __mac_set_proc */ + { 0, (sy_call_t *)nosys }, /* 386 = __mac_get_fd */ + { 0, (sy_call_t *)nosys }, /* 387 = __mac_get_file */ + { 0, (sy_call_t *)nosys }, /* 388 = __mac_set_fd */ + { 0, (sy_call_t *)nosys }, /* 389 = __mac_set_file */ + { AS(kenv_args), (sy_call_t *)kenv }, /* 390 = kenv */ + { AS(lchflags_args), (sy_call_t *)lchflags }, /* 391 = lchflags */ + { AS(uuidgen_args), (sy_call_t *)uuidgen }, /* 392 = uuidgen */ +}; diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h new file mode 100644 index 0000000..b9e0a7c --- /dev/null +++ b/sys/compat/freebsd32/freebsd32_util.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + + +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/cdefs.h> + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) diff --git a/sys/compat/freebsd32/syscalls.conf b/sys/compat/freebsd32/syscalls.conf new file mode 100644 index 0000000..16d94ea --- /dev/null +++ b/sys/compat/freebsd32/syscalls.conf @@ -0,0 +1,12 @@ +# $FreeBSD$ +sysnames="/dev/null" +sysproto="ia32_proto.h" +sysproto_h=_IA32_SYSPROTO_H_ +syshdr="ia32_syscall.h" +syssw="ia32_sysent.c" +sysmk="/dev/null" +syshide="/dev/null" +syscallprefix="IA32_SYS_" +switchname="ia32_sysent" +namesname="ia32_syscallnames" +sysvec="\n" diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master new file mode 100644 index 0000000..6de1c57 --- /dev/null +++ b/sys/compat/freebsd32/syscalls.master @@ -0,0 +1,563 @@ + $FreeBSD$ +; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94 +; from: src/sys/kern/syscalls.master 1.107 +; +; System call name/number master file. +; Processed to created init_sysent.c, syscalls.c and syscall.h. + +; Columns: number [M]type nargs namespc name alt{name,tag,rtyp}/comments +; number system call number, must be in order +; type one of [M]STD, [M]OBSOL, [M]UNIMPL, [M]COMPAT, [M]CPT_NOA, +; [M]LIBCOMPAT, [M]NODEF, [M]NOARGS, [M]NOPROTO, [M]NOIMPL, +; [M]NOSTD +; namespc one of POSIX, BSD, NOHIDE +; name psuedo-prototype of syscall routine +; If one of the following alts is different, then all appear: +; altname name of system call if different +; alttag name of args struct tag if different from [o]`name'"_args" +; altrtyp return type if not int (bogus - syscalls always return int) +; for UNIMPL/OBSOL, name continues with comments + +; types: +; [M] e.g. like MSTD -- means the system call is MP-safe. If no +; M prefix is used, the syscall wrapper will obtain the Giant +; lock for the syscall. +; STD always included +; COMPAT included on COMPAT #ifdef +; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h +; OBSOL obsolete, not included in system, only specifies name +; UNIMPL not implemented, placeholder only +; NOSTD implemented but as a lkm that can be statically +; compiled in sysent entry will be filled with lkmsys +; so the SYSCALL_MODULE macro works + +; #ifdef's, etc. may be included, and are copied to the output files. + +#include <sys/param.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <sys/mount.h> +#include <ia64/ia32/ia32.h> +#include <ia64/ia32/ia32_proto.h> + +; Reserved/unimplemented system calls in the range 0-150 inclusive +; are reserved for use in future Berkeley releases. +; Additional system calls implemented in vendor and other +; redistributions should be placed in the reserved range at the end +; of the current calls. + +0 MNOPROTO NOHIDE { int nosys(void); } syscall nosys_args int +1 MNOPROTO NOHIDE { void sys_exit(int rval); } exit sys_exit_args void +2 MNOPROTO POSIX { int fork(void); } +3 MNOPROTO POSIX { ssize_t read(int fd, void *buf, size_t nbyte); } +4 MNOPROTO POSIX { ssize_t write(int fd, const void *buf, size_t nbyte); } +5 STD POSIX { int ia32_open(char *path, int flags, int mode); } +; XXX should be { int open(const char *path, int flags, ...); } +; but we're not ready for `const' or varargs. +; XXX man page says `mode_t mode'. +6 MNOPROTO POSIX { int close(int fd); } +7 MSTD BSD { int ia32_wait4(int pid, int *status, int options, \ + struct rusage32 *rusage); } +8 OBSOL BSD old creat +9 NOPROTO POSIX { int link(char *path, char *link); } +10 NOPROTO POSIX { int unlink(char *path); } +11 OBSOL NOHIDE execv +12 NOPROTO POSIX { int chdir(char *path); } +13 NOPROTO BSD { int fchdir(int fd); } +14 NOPROTO POSIX { int mknod(char *path, int mode, int dev); } +15 NOPROTO POSIX { int chmod(char *path, int mode); } +16 NOPROTO POSIX { int chown(char *path, int uid, int gid); } +17 MNOPROTO BSD { int obreak(char *nsize); } break obreak_args int +18 STD BSD { int ia32_getfsstat(struct statfs32 *buf, \ + long bufsize, int flags); } +19 OBSOL POSIX olseek +20 MNOPROTO POSIX { pid_t getpid(void); } +21 NOPROTO BSD { int mount(char *type, char *path, int flags, \ + caddr_t data); } +; XXX `path' should have type `const char *' but we're not ready for that. +22 NOPROTO BSD { int unmount(char *path, int flags); } +23 MNOPROTO POSIX { int setuid(uid_t uid); } +24 MNOPROTO POSIX { uid_t getuid(void); } +25 MNOPROTO POSIX { uid_t geteuid(void); } +26 NOPROTO BSD { int ptrace(int req, pid_t pid, caddr_t addr, \ + int data); } +27 UNIMPL BSD recvmsg +28 MNOPROTO BSD { int sendmsg(int s, caddr_t msg, int flags); } +29 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ + int flags, caddr_t from, int *fromlenaddr); } +30 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } +31 MNOPROTO BSD { int getpeername(int fdes, caddr_t asa, int *alen); } +32 MNOPROTO BSD { int getsockname(int fdes, caddr_t asa, int *alen); } +33 STD POSIX { int ia32_access(char *path, int flags); } +34 STD BSD { int ia32_chflags(char *path, int flags); } +35 NOPROTO BSD { int fchflags(int fd, int flags); } +36 NOPROTO BSD { int sync(void); } +37 MNOPROTO POSIX { int kill(int pid, int signum); } +38 UNIMPL POSIX ostat +39 MNOPROTO POSIX { pid_t getppid(void); } +40 UNIMPL POSIX olstat +41 NOPROTO POSIX { int dup(u_int fd); } +42 NOPROTO POSIX { int pipe(void); } +43 MNOPROTO POSIX { gid_t getegid(void); } +44 MNOPROTO BSD { int profil(caddr_t samples, size_t size, \ + size_t offset, u_int scale); } +45 NOPROTO BSD { int ktrace(const char *fname, int ops, int facs, \ + int pid); } +46 UNIMPL POSIX osigaction +47 MNOPROTO POSIX { gid_t getgid(void); } +48 UNIMPL POSIX osigprocmask +49 MNOPROTO BSD { int getlogin(char *namebuf, u_int namelen); } +50 MNOPROTO BSD { int setlogin(char *namebuf); } +51 MNOPROTO BSD { int acct(char *path); } +52 MNOPROTO POSIX { int sigpending(void); } +53 STD BSD { int ia32_sigaltstack(struct sigaltstack32 *ss, struct sigaltstack32 *oss); } +54 MNOPROTO POSIX { int ioctl(int fd, u_long com, caddr_t data); } +55 MNOPROTO BSD { int reboot(int opt); } +56 NOPROTO POSIX { int revoke(char *path); } +57 NOPROTO POSIX { int symlink(char *path, char *link); } +58 NOPROTO POSIX { int readlink(char *path, char *buf, int count); } +59 STD POSIX { int ia32_execve(char *fname, u_int32_t *argv, u_int32_t *envv); } +60 MNOPROTO POSIX { int umask(int newmask); } umask umask_args int +61 NOPROTO BSD { int chroot(char *path); } +62 OBSOL POSIX ofstat +63 OBSOL BSD ogetkerninfo +64 OBSOL BSD ogetpagesize +65 OBSOL BSD omsync +66 OBSOL BSD ovfork +67 OBSOL NOHIDE vread +68 OBSOL NOHIDE vwrite +69 MNOPROTO BSD { int sbrk(int incr); } +70 MNOPROTO BSD { int sstk(int incr); } +71 OBSOL BSD ommap +72 MNOPROTO BSD { int ovadvise(int anom); } vadvise ovadvise_args int +73 MNOPROTO BSD { int munmap(void *addr, size_t len); } +74 MNOPROTO BSD { int mprotect(const void *addr, size_t len, int prot); } +75 MNOPROTO BSD { int madvise(void *addr, size_t len, int behav); } +76 OBSOL NOHIDE vhangup +77 OBSOL NOHIDE vlimit +78 MNOPROTO BSD { int mincore(const void *addr, size_t len, \ + char *vec); } +79 MNOPROTO POSIX { int getgroups(u_int gidsetsize, gid_t *gidset); } +80 MNOPROTO POSIX { int setgroups(u_int gidsetsize, gid_t *gidset); } +81 MNOPROTO POSIX { int getpgrp(void); } +82 MNOPROTO POSIX { int setpgid(int pid, int pgid); } +83 STD BSD { int ia32_setitimer(u_int which, \ + struct itimerval32 *itv, \ + struct itimerval32 *oitv); } +84 OBSOL BSD owait +85 OBSOL BSD oswapon +86 OBSOL BSD ogetitimer +87 OBSOL BSD ogethostname +88 OBSOL BSD osethostname +89 MNOPROTO BSD { int getdtablesize(void); } +90 MNOPROTO POSIX { int dup2(u_int from, u_int to); } +91 UNIMPL BSD getdopt +92 MNOPROTO POSIX { int fcntl(int fd, int cmd, long arg); } +; XXX should be { int fcntl(int fd, int cmd, ...); } +; but we're not ready for varargs. +; XXX man page says `int arg' too. +93 STD BSD { int ia32_select(int nd, fd_set *in, fd_set *ou, \ + fd_set *ex, struct timeval32 *tv); } +; XXX need to override for big-endian - little-endian should work fine. +94 UNIMPL BSD setdopt +95 NOPROTO POSIX { int fsync(int fd); } +96 MNOPROTO BSD { int setpriority(int which, int who, int prio); } +97 MNOPROTO BSD { int socket(int domain, int type, int protocol); } +98 MNOPROTO BSD { int connect(int s, caddr_t name, int namelen); } +99 MNOPROTO BSD { int accept(int s, caddr_t name, int *anamelen); } \ + accept accept_args int +100 MNOPROTO BSD { int getpriority(int which, int who); } +101 OBSOL BSD osend +102 OBSOL BSD orecv +103 OBSOL BSD osigreturn +104 MNOPROTO BSD { int bind(int s, caddr_t name, int namelen); } +105 MNOPROTO BSD { int setsockopt(int s, int level, int name, \ + caddr_t val, int valsize); } +106 MNOPROTO BSD { int listen(int s, int backlog); } +107 OBSOL NOHIDE vtimes +108 OBSOL BSD osigvec +109 OBSOL BSD osigblock +110 OBSOL BSD osigsetmask +111 OBSOL POSIX osigsuspend +112 OBSOL BSD osigstack +113 OBSOL BSD orecvmsg +114 OBSOL BSD osendmsg +115 OBSOL NOHIDE vtrace +116 STD BSD { int ia32_gettimeofday(struct timeval32 *tp, \ + struct timezone *tzp); } +117 STD BSD { int ia32_getrusage(int who, struct rusage32 *rusage); } +118 MNOPROTO BSD { int getsockopt(int s, int level, int name, \ + caddr_t val, int *avalsize); } +119 UNIMPL NOHIDE resuba (BSD/OS 2.x) +120 STD BSD { int ia32_readv(int fd, struct iovec32 *iovp, u_int iovcnt); } +121 STD BSD { int ia32_writev(int fd, struct iovec32 *iovp, \ + u_int iovcnt); } +122 STD BSD { int ia32_settimeofday(struct timeval32 *tv, \ + struct timezone *tzp); } +123 NOPROTO BSD { int fchown(int fd, int uid, int gid); } +124 NOPROTO BSD { int fchmod(int fd, int mode); } +125 MNOPROTO BSD { int recvfrom(int s, caddr_t buf, size_t len, \ + int flags, caddr_t from, int *fromlenaddr); } \ + recvfrom recvfrom_args int +126 MNOPROTO BSD { int setreuid(int ruid, int euid); } +127 MNOPROTO BSD { int setregid(int rgid, int egid); } +128 NOPROTO POSIX { int rename(char *from, char *to); } +129 OBSOL BSD otruncate +130 OBSOL BSD ftruncate +131 MNOPROTO BSD { int flock(int fd, int how); } +132 NOPROTO POSIX { int mkfifo(char *path, int mode); } +133 MNOPROTO BSD { int sendto(int s, caddr_t buf, size_t len, \ + int flags, caddr_t to, int tolen); } +134 MNOPROTO BSD { int shutdown(int s, int how); } +135 MNOPROTO BSD { int socketpair(int domain, int type, int protocol, \ + int *rsv); } +136 NOPROTO POSIX { int mkdir(char *path, int mode); } +137 NOPROTO POSIX { int rmdir(char *path); } +138 STD BSD { int ia32_utimes(char *path, \ + struct timeval32 *tptr); } +139 OBSOL NOHIDE 4.2 sigreturn +140 STD BSD { int ia32_adjtime(struct timeval32 *delta, \ + struct timeval32 *olddelta); } +141 OBSOL BSD ogetpeername +142 OBSOL BSD ogethostid +143 OBSOL BSD sethostid +144 OBSOL BSD getrlimit +145 OBSOL BSD setrlimit +146 OBSOL BSD killpg +147 MNOPROTO POSIX { int setsid(void); } +148 NOPROTO BSD { int quotactl(char *path, int cmd, int uid, \ + caddr_t arg); } +149 OBSOL BSD oquota +150 OBSOL BSD ogetsockname + +; Syscalls 151-180 inclusive are reserved for vendor-specific +; system calls. (This includes various calls added for compatibity +; with other Unix variants.) +; Some of these calls are now supported by BSD... +151 UNIMPL NOHIDE sem_lock (BSD/OS 2.x) +152 UNIMPL NOHIDE sem_wakeup (BSD/OS 2.x) +153 UNIMPL NOHIDE asyncdaemon (BSD/OS 2.x) +154 UNIMPL NOHIDE nosys +; 155 is initialized by the NFS code, if present. +155 UNIMPL NOHIDE nfssvc +156 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ + long *basep); } +157 STD BSD { int ia32_statfs(char *path, struct statfs32 *buf); } +158 STD BSD { int ia32_fstatfs(int fd, struct statfs32 *buf); } +159 UNIMPL NOHIDE nosys +160 UNIMPL NOHIDE nosys +161 NOPROTO BSD { int getfh(char *fname, struct fhandle *fhp); } +162 MNOPROTO BSD { int getdomainname(char *domainname, int len); } +163 MNOPROTO BSD { int setdomainname(char *domainname, int len); } +164 MNOPROTO BSD { int uname(struct utsname *name); } +165 NOPROTO BSD { int sysarch(int op, char *parms); } +166 MNOPROTO BSD { int rtprio(int function, pid_t pid, \ + struct rtprio *rtp); } +167 UNIMPL NOHIDE nosys +168 UNIMPL NOHIDE nosys +169 STD BSD { int ia32_semsys(int which, int a2, int a3, int a4, \ + int a5); } +170 STD BSD { int ia32_msgsys(int which, int a2, int a3, int a4, \ + int a5, int a6); } +171 STD BSD { int ia32_shmsys(int which, int a2, int a3, int a4); } +172 UNIMPL NOHIDE nosys +173 STD POSIX { ssize_t ia32_pread(int fd, void *buf, size_t nbyte, \ + int pad, u_int32_t offsetlo, u_int32_t offsethi); } +; XXX note - bigendian is different +174 STD POSIX { ssize_t ia32_pwrite(int fd, const void *buf, \ + size_t nbyte, int pad, u_int32_t offsetlo, \ + u_int32_t offsethi); } +; XXX note - bigendian is different +175 UNIMPL NOHIDE nosys +176 MNOPROTO BSD { int ntp_adjtime(struct timex *tp); } +177 UNIMPL NOHIDE sfork (BSD/OS 2.x) +178 UNIMPL NOHIDE getdescriptor (BSD/OS 2.x) +179 UNIMPL NOHIDE setdescriptor (BSD/OS 2.x) +180 UNIMPL NOHIDE nosys + +; Syscalls 181-199 are used by/reserved for BSD +181 MNOPROTO POSIX { int setgid(gid_t gid); } +182 MNOPROTO BSD { int setegid(gid_t egid); } +183 MNOPROTO BSD { int seteuid(uid_t euid); } +184 UNIMPL BSD lfs_bmapv +185 UNIMPL BSD lfs_markv +186 UNIMPL BSD lfs_segclean +187 UNIMPL BSD lfs_segwait +188 STD POSIX { int ia32_stat(char *path, struct stat32 *ub); } +189 STD POSIX { int ia32_fstat(int fd, struct stat32 *ub); } +190 STD POSIX { int ia32_lstat(char *path, struct stat32 *ub); } +191 NOPROTO POSIX { int pathconf(char *path, int name); } +192 MNOPROTO POSIX { int fpathconf(int fd, int name); } +193 UNIMPL NOHIDE nosys +194 MNOPROTO BSD { int getrlimit(u_int which, \ + struct rlimit *rlp); } \ + getrlimit __getrlimit_args int +195 MNOPROTO BSD { int setrlimit(u_int which, \ + struct rlimit *rlp); } \ + setrlimit __setrlimit_args int +196 NOPROTO BSD { int getdirentries(int fd, char *buf, u_int count, \ + long *basep); } +197 STD BSD { caddr_t ia32_mmap(caddr_t addr, size_t len, \ + int prot, int flags, int fd, int pad, \ + u_int32_t poslo, u_int32_t poshi); } +198 NOPROTO NOHIDE { int nosys(void); } __syscall __syscall_args int +; XXX note - bigendian is different +199 STD POSIX { off_t ia32_lseek(int fd, int pad, \ + u_int32_t offsetlo, u_int32_t offsethi, \ + int whence); } +; XXX note - bigendian is different +200 STD BSD { int ia32_truncate(char *path, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +; XXX note - bigendian is different +201 STD BSD { int ia32_ftruncate(int fd, int pad, \ + u_int32_t lengthlo, u_int32_t lengthhi); } +202 MSTD BSD { int ia32_sysctl(int *name, u_int namelen, \ + void *old, u_int32_t *oldlenp, void *new, \ + u_int32_t newlen); } +203 MNOPROTO BSD { int mlock(const void *addr, size_t len); } +204 MNOPROTO BSD { int munlock(const void *addr, size_t len); } +205 NOPROTO BSD { int undelete(char *path); } +206 NOPROTO BSD { int futimes(int fd, struct timeval *tptr); } +207 MNOPROTO BSD { int getpgid(pid_t pid); } +208 UNIMPL NOHIDE newreboot (NetBSD) +209 MNOPROTO BSD { int poll(struct pollfd *fds, u_int nfds, \ + int timeout); } + +; +; The following are reserved for loadable syscalls +; +210 UNIMPL NOHIDE +211 UNIMPL NOHIDE +212 UNIMPL NOHIDE +213 UNIMPL NOHIDE +214 UNIMPL NOHIDE +215 UNIMPL NOHIDE +216 UNIMPL NOHIDE +217 UNIMPL NOHIDE +218 UNIMPL NOHIDE +219 UNIMPL NOHIDE + +; +; The following were introduced with NetBSD/4.4Lite-2 +; They are initialized by thier respective modules/sysinits +220 MNOPROTO BSD { int __semctl(int semid, int semnum, int cmd, \ + union semun *arg); } +221 MNOPROTO BSD { int semget(key_t key, int nsems, int semflg); } +222 MNOPROTO BSD { int semop(int semid, struct sembuf *sops, \ + u_int nsops); } +223 UNIMPL NOHIDE semconfig +224 MNOPROTO BSD { int msgctl(int msqid, int cmd, \ + struct msqid_ds *buf); } +225 MNOPROTO BSD { int msgget(key_t key, int msgflg); } +226 MNOPROTO BSD { int msgsnd(int msqid, void *msgp, size_t msgsz, \ + int msgflg); } +227 MNOPROTO BSD { int msgrcv(int msqid, void *msgp, size_t msgsz, \ + long msgtyp, int msgflg); } +228 MNOPROTO BSD { int shmat(int shmid, void *shmaddr, int shmflg); } +229 MNOPROTO BSD { int shmctl(int shmid, int cmd, \ + struct shmid_ds *buf); } +230 MNOPROTO BSD { int shmdt(void *shmaddr); } +231 MNOPROTO BSD { int shmget(key_t key, int size, int shmflg); } +; +232 MNOPROTO POSIX { int clock_gettime(clockid_t clock_id, \ + struct timespec *tp); } +233 MNOPROTO POSIX { int clock_settime(clockid_t clock_id, \ + const struct timespec *tp); } +234 MNOPROTO POSIX { int clock_getres(clockid_t clock_id, \ + struct timespec *tp); } +235 UNIMPL NOHIDE timer_create +236 UNIMPL NOHIDE timer_delete +237 UNIMPL NOHIDE timer_settime +238 UNIMPL NOHIDE timer_gettime +239 UNIMPL NOHIDE timer_getoverrun +240 MNOPROTO POSIX { int nanosleep(const struct timespec *rqtp, \ + struct timespec *rmtp); } +241 UNIMPL NOHIDE nosys +242 UNIMPL NOHIDE nosys +243 UNIMPL NOHIDE nosys +244 UNIMPL NOHIDE nosys +245 UNIMPL NOHIDE nosys +246 UNIMPL NOHIDE nosys +247 UNIMPL NOHIDE nosys +248 UNIMPL NOHIDE nosys +249 UNIMPL NOHIDE nosys +; syscall numbers initially used in OpenBSD +250 MNOPROTO BSD { int minherit(void *addr, size_t len, int inherit); } +251 MNOPROTO BSD { int rfork(int flags); } +252 MNOPROTO BSD { int openbsd_poll(struct pollfd *fds, u_int nfds, \ + int timeout); } +253 NOPROTO BSD { int issetugid(void); } +254 NOPROTO BSD { int lchown(char *path, int uid, int gid); } +255 UNIMPL NOHIDE nosys +256 UNIMPL NOHIDE nosys +257 UNIMPL NOHIDE nosys +258 UNIMPL NOHIDE nosys +259 UNIMPL NOHIDE nosys +260 UNIMPL NOHIDE nosys +261 UNIMPL NOHIDE nosys +262 UNIMPL NOHIDE nosys +263 UNIMPL NOHIDE nosys +264 UNIMPL NOHIDE nosys +265 UNIMPL NOHIDE nosys +266 UNIMPL NOHIDE nosys +267 UNIMPL NOHIDE nosys +268 UNIMPL NOHIDE nosys +269 UNIMPL NOHIDE nosys +270 UNIMPL NOHIDE nosys +271 UNIMPL NOHIDE nosys +272 NOPROTO BSD { int getdents(int fd, char *buf, size_t count); } +273 UNIMPL NOHIDE nosys +274 NOPROTO BSD { int lchmod(char *path, mode_t mode); } +275 NOPROTO BSD { int lchown(char *path, uid_t uid, gid_t gid); } netbsd_lchown lchown_args int +276 NOPROTO BSD { int lutimes(char *path, struct timeval *tptr); } +277 MNOPROTO BSD { int msync(void *addr, size_t len, int flags); } netbsd_msync msync_args int +278 NOPROTO BSD { int nstat(char *path, struct nstat *ub); } +279 MNOPROTO BSD { int nfstat(int fd, struct nstat *sb); } +280 NOPROTO BSD { int nlstat(char *path, struct nstat *ub); } +281 UNIMPL NOHIDE nosys +282 UNIMPL NOHIDE nosys +283 UNIMPL NOHIDE nosys +284 UNIMPL NOHIDE nosys +285 UNIMPL NOHIDE nosys +286 UNIMPL NOHIDE nosys +287 UNIMPL NOHIDE nosys +288 UNIMPL NOHIDE nosys +289 UNIMPL NOHIDE nosys +290 UNIMPL NOHIDE nosys +291 UNIMPL NOHIDE nosys +292 UNIMPL NOHIDE nosys +293 UNIMPL NOHIDE nosys +294 UNIMPL NOHIDE nosys +295 UNIMPL NOHIDE nosys +296 UNIMPL NOHIDE nosys +; XXX 297 is 300 in NetBSD +297 NOPROTO BSD { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } +298 NOPROTO BSD { int fhopen(const struct fhandle *u_fhp, int flags); } +299 NOPROTO BSD { int fhstat(const struct fhandle *u_fhp, struct stat *sb); } +; syscall numbers for FreeBSD +300 MNOPROTO BSD { int modnext(int modid); } +301 MNOPROTO BSD { int modstat(int modid, struct module_stat* stat); } +302 MNOPROTO BSD { int modfnext(int modid); } +303 MNOPROTO BSD { int modfind(const char *name); } +304 MNOPROTO BSD { int kldload(const char *file); } +305 MNOPROTO BSD { int kldunload(int fileid); } +306 MNOPROTO BSD { int kldfind(const char *file); } +307 MNOPROTO BSD { int kldnext(int fileid); } +308 MNOPROTO BSD { int kldstat(int fileid, struct kld_file_stat* stat); } +309 MNOPROTO BSD { int kldfirstmod(int fileid); } +310 MNOPROTO BSD { int getsid(pid_t pid); } +311 MNOPROTO BSD { int setresuid(uid_t ruid, uid_t euid, uid_t suid); } +312 MNOPROTO BSD { int setresgid(gid_t rgid, gid_t egid, gid_t sgid); } +313 OBSOL NOHIDE signanosleep +314 UNIMPL NOHIDE aio_return +315 UNIMPL NOHIDE aio_suspend +316 UNIMPL NOHIDE aio_cancel +317 UNIMPL NOHIDE aio_error +318 UNIMPL NOHIDE aio_read +319 UNIMPL NOHIDE aio_write +320 UNIMPL NOHIDE lio_listio +321 MNOPROTO BSD { int yield(void); } +322 OBSOL NOHIDE thr_sleep +323 OBSOL NOHIDE thr_wakeup +324 MNOPROTO BSD { int mlockall(int how); } +325 MNOPROTO BSD { int munlockall(void); } +326 NOPROTO BSD { int __getcwd(u_char *buf, u_int buflen); } + +327 MNOPROTO POSIX { int sched_setparam (pid_t pid, const struct sched_param *param); } +328 MNOPROTO POSIX { int sched_getparam (pid_t pid, struct sched_param *param); } + +329 MNOPROTO POSIX { int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param); } +330 MNOPROTO POSIX { int sched_getscheduler (pid_t pid); } + +331 MNOPROTO POSIX { int sched_yield (void); } +332 MNOPROTO POSIX { int sched_get_priority_max (int policy); } +333 MNOPROTO POSIX { int sched_get_priority_min (int policy); } +334 MNOPROTO POSIX { int sched_rr_get_interval (pid_t pid, struct timespec *interval); } +335 NOPROTO BSD { int utrace(const void *addr, size_t len); } +; XXX note - bigendian is different +336 MSTD BSD { int ia32_sendfile(int fd, int s, u_int32_t offsetlo, \ + u_int32_t offsethi, size_t nbytes, \ + struct sf_hdtr *hdtr, off_t *sbytes, int flags); } +337 NOPROTO BSD { int kldsym(int fileid, int cmd, void *data); } +338 MNOPROTO BSD { int jail(struct jail *jail); } +339 UNIMPL BSD pioctl +340 MNOPROTO POSIX { int sigprocmask(int how, const sigset_t *set, \ + sigset_t *oset); } +341 MNOPROTO POSIX { int sigsuspend(const sigset_t *sigmask); } +342 STD POSIX { int ia32_sigaction(int sig, \ + struct sigaction32 *act, \ + struct sigaction32 *oact); } +343 MNOPROTO POSIX { int sigpending(sigset_t *set); } +344 MNOPROTO BSD { int sigreturn(const struct __ucontext *sigcntxp); } +345 UNIMPL NOHIDE sigtimedwait +346 UNIMPL NOHIDE sigwaitinfo +347 MNOPROTO BSD { int __acl_get_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +348 MNOPROTO BSD { int __acl_set_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +349 MNOPROTO BSD { int __acl_get_fd(int filedes, acl_type_t type, \ + struct acl *aclp); } +350 MNOPROTO BSD { int __acl_set_fd(int filedes, acl_type_t type, \ + struct acl *aclp); } +351 MNOPROTO BSD { int __acl_delete_file(const char *path, \ + acl_type_t type); } +352 MNOPROTO BSD { int __acl_delete_fd(int filedes, acl_type_t type); } +353 MNOPROTO BSD { int __acl_aclcheck_file(const char *path, \ + acl_type_t type, struct acl *aclp); } +354 MNOPROTO BSD { int __acl_aclcheck_fd(int filedes, acl_type_t type, \ + struct acl *aclp); } +355 NOPROTO BSD { int extattrctl(const char *path, int cmd, \ + const char *filename, int attrnamespace, \ + const char *attrname); } +356 NOPROTO BSD { int extattr_set_file(const char *path, \ + int attrnamespace, const char *attrname, \ + void *data, size_t nbytes); } +357 NOPROTO BSD { ssize_t extattr_get_file(const char *path, \ + int attrnamespace, const char *attrname, \ + void *data, size_t nbytes); } +358 NOPROTO BSD { int extattr_delete_file(const char *path, \ + int attrnamespace, const char *attrname); } +359 UNIMPL NOHIDE aio_waitcomplete +360 MNOPROTO BSD { int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); } +361 MNOPROTO BSD { int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); } +362 MNOPROTO BSD { int kqueue(void); } +363 MNOPROTO BSD { int kevent(int fd, \ + const struct kevent *changelist, int nchanges, \ + struct kevent *eventlist, int nevents, \ + const struct timespec *timeout); } +364 UNIMPL NOHIDE __cap_get_proc +365 UNIMPL NOHIDE __cap_set_proc +366 UNIMPL NOHIDE __cap_get_fd +367 UNIMPL NOHIDE __cap_get_file +368 UNIMPL NOHIDE __cap_set_fd +369 UNIMPL NOHIDE __cap_set_file +370 UNIMPL NOHIDE lkmressys +371 NOPROTO BSD { int extattr_set_fd(int fd, int attrnamespace, \ + const char *attrname, void *data, \ + size_t nbytes); } +372 NOPROTO BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \ + const char *attrname, void *data, size_t nbytes); } +373 NOPROTO BSD { int extattr_delete_fd(int fd, int attrnamespace, \ + const char *attrname); } +374 MNOPROTO BSD { int __setugid(int flag); } +375 UNIMPL BSD nfsclnt +376 NOPROTO BSD { int eaccess(char *path, int flags); } +377 UNIMPL BSD afs_syscall +378 NOPROTO BSD { int nmount(struct iovec *iovp, unsigned int iovcnt, \ + int flags); } +379 NOPROTO BSD { int kse_exit(void); } +380 NOPROTO BSD { int kse_wakeup(void); } +381 NOPROTO BSD { int kse_new(struct kse_mailbox * mbx, \ + int new_grp_flag); } +382 NOPROTO BSD { int thread_wakeup(struct thread_mailbox *tmbx); } +383 NOPROTO BSD { int kse_yield(void); } +384 UNIMPL BSD __mac_get_proc +385 UNIMPL BSD __mac_set_proc +386 UNIMPL BSD __mac_get_fd +387 UNIMPL BSD __mac_get_file +388 UNIMPL BSD __mac_set_fd +389 UNIMPL BSD __mac_set_file +390 NOPROTO BSD { int kenv(int what, const char *name, char *value, \ + int len); } +391 NOPROTO BSD { int lchflags(const char *path, int flags); } +392 NOPROTO BSD { int uuidgen(struct uuid *store, int count); } diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c new file mode 100644 index 0000000..06e6505 --- /dev/null +++ b/sys/compat/ia32/ia32_sysvec.c @@ -0,0 +1,365 @@ +/*- + * Copyright (c) 2002 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define __ELF_WORD_SIZE 32 + +#include <sys/param.h> +#include <sys/exec.h> +#include <sys/fcntl.h> +#include <sys/imgact.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/mman.h> +#include <sys/namei.h> +#include <sys/pioctl.h> +#include <sys/proc.h> +#include <sys/procfs.h> +#include <sys/resourcevar.h> +#include <sys/systm.h> +#include <sys/signalvar.h> +#include <sys/stat.h> +#include <sys/sx.h> +#include <sys/syscall.h> +#include <sys/sysctl.h> +#include <sys/sysent.h> +#include <sys/vnode.h> +#include <sys/imgact_elf.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> + +#include <ia64/ia32/ia32_util.h> +#include <i386/include/psl.h> +#include <i386/include/segments.h> +#include <i386/include/specialreg.h> +#include <machine/frame.h> +#include <machine/md_var.h> + +static register_t *ia32_copyout_strings(struct image_params *imgp); +static void ia32_setregs(struct thread *td, u_long entry, u_long stack, + u_long ps_strings); + +extern struct sysent ia32_sysent[]; + +static char ia32_sigcode[] = { + 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ + 0x50, /* pushl %eax */ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne 9f */ + 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ + 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80, /* int $0x80 */ + 0xeb, 0xfe, /* 0: jmp 0b */ + 0, 0, 0, 0 +}; +static int ia32_szsigcode = sizeof(ia32_sigcode) & ~3; + +struct sysentvec ia32_freebsd_sysvec = { + SYS_MAXSYSCALL, + ia32_sysent, + 0, + 0, + 0, + 0, + 0, + 0, + elf32_freebsd_fixup, + sendsig, + ia32_sigcode, + &ia32_szsigcode, + 0, + "FreeBSD ELF", + elf32_coredump, + NULL, + MINSIGSTKSZ, + 4096, + IA32_USRSTACK, + IA32_USRSTACK, + ia32_copyout_strings, + ia32_setregs +}; + +static Elf32_Brandinfo ia32_brand_info = { + ELFOSABI_FREEBSD, + EM_386, + "FreeBSD", + "/compat/ia32", + "/usr/libexec/ld-elf.so.1", + &ia32_freebsd_sysvec + }; + +SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &ia32_brand_info); + +static register_t * +ia32_copyout_strings(struct image_params *imgp) +{ + int argc, envc; + u_int32_t *vectp; + char *stringp, *destp; + u_int32_t *stack_base; + struct ia32_ps_strings *arginfo; + int szsigcode; + + /* + * Calculate string base and vector table pointers. + * Also deal with signal trampoline code for this exec type. + */ + arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS; + szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); + destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - + roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); + + /* + * install sigcode + */ + if (szsigcode) + copyout(imgp->proc->p_sysent->sv_sigcode, + ((caddr_t)arginfo - szsigcode), szsigcode); + + /* + * If we have a valid auxargs ptr, prepare some room + * on the stack. + */ + if (imgp->auxargs) { + /* + * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for + * lower compatibility. + */ + imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size + : (AT_COUNT * 2); + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets,and imgp->auxarg_size is room + * for argument of Runtime loader. + */ + vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + + imgp->auxarg_size) * sizeof(u_int32_t)); + + } else + /* + * The '+ 2' is for the null pointers at the end of each of + * the arg and env vector sets + */ + vectp = (u_int32_t *) + (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); + + /* + * vectp also becomes our initial stack base + */ + stack_base = vectp; + + stringp = imgp->stringbase; + argc = imgp->argc; + envc = imgp->envc; + + /* + * Copy out strings - arguments and environment. + */ + copyout(stringp, destp, ARG_MAX - imgp->stringspace); + + /* + * Fill in "ps_strings" struct for ps, w, etc. + */ + suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nargvstr, argc); + + /* + * Fill in argument portion of vector table. + */ + for (; argc > 0; --argc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* a null vector table pointer separates the argp's from the envp's */ + suword32(vectp++, 0); + + suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); + suword32(&arginfo->ps_nenvstr, envc); + + /* + * Fill in environment portion of vector table. + */ + for (; envc > 0; --envc) { + suword32(vectp++, (u_int32_t)(intptr_t)destp); + while (*stringp++ != 0) + destp++; + destp++; + } + + /* end of vector table is a null pointer */ + suword32(vectp, 0); + + return ((register_t *)stack_base); +} + +static void +ia32_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *frame = td->td_frame; + vm_offset_t gdt, ldt; + u_int64_t codesel, datasel, ldtsel; + u_int64_t codeseg, dataseg, gdtseg, ldtseg; + struct segment_descriptor desc; + struct vmspace *vmspace = td->td_proc->p_vmspace; + + /* + * Make sure that we restore the entire trapframe after an + * execve. + */ + frame->tf_flags &= ~FRAME_SYSCALL; + + bzero(frame->tf_r, sizeof(frame->tf_r)); + bzero(frame->tf_f, sizeof(frame->tf_f)); + + frame->tf_cr_iip = entry; + frame->tf_cr_ipsr = (IA64_PSR_IC + | IA64_PSR_I + | IA64_PSR_IT + | IA64_PSR_DT + | IA64_PSR_RT + | IA64_PSR_DFH + | IA64_PSR_IS + | IA64_PSR_BN + | IA64_PSR_CPL_USER); + frame->tf_r[FRAME_R12] = stack; + + codesel = LSEL(LUCODE_SEL, SEL_UPL); + datasel = LSEL(LUDATA_SEL, SEL_UPL); + ldtsel = GSEL(GLDT_SEL, SEL_UPL); + +#if 1 + frame->tf_r[FRAME_R16] = (datasel << 48) | (datasel << 32) + | (datasel << 16) | datasel; + frame->tf_r[FRAME_R17] = (ldtsel << 32) | (datasel << 16) | codesel; +#else + frame->tf_r[FRAME_R16] = datasel; + frame->tf_r[FRAME_R17] = codesel; + frame->tf_r[FRAME_R18] = datasel; + frame->tf_r[FRAME_R19] = datasel; + frame->tf_r[FRAME_R20] = datasel; + frame->tf_r[FRAME_R21] = datasel; + frame->tf_r[FRAME_R22] = ldtsel; +#endif + + /* + * Build the GDT and LDT. + */ + gdt = IA32_USRSTACK; + vm_map_find(&vmspace->vm_map, 0, 0, + &gdt, PAGE_SIZE, 0, + VM_PROT_ALL, VM_PROT_ALL, 0); + ldt = gdt + 4096; + + desc.sd_lolimit = 8*NLDT-1; + desc.sd_lobase = ldt & 0xffffff; + desc.sd_type = SDT_SYSLDT; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = 0; + desc.sd_def32 = 0; + desc.sd_gran = 0; + desc.sd_hibase = ldt >> 24; + copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); + + desc.sd_lolimit = ((IA32_USRSTACK >> 12) - 1) & 0xffff; + desc.sd_lobase = 0; + desc.sd_type = SDT_MEMERA; + desc.sd_dpl = SEL_UPL; + desc.sd_p = 1; + desc.sd_hilimit = ((IA32_USRSTACK >> 12) - 1) >> 16; + desc.sd_def32 = 1; + desc.sd_gran = 1; + desc.sd_hibase = 0; + copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); + desc.sd_type = SDT_MEMRWA; + copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); + + codeseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMERA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + dataseg = 0 /* base */ + + (((IA32_USRSTACK >> 12) - 1) << 32) /* limit */ + + ((long)SDT_MEMRWA << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (1L << 62) /* 32 bits */ + + (1L << 63); /* page granularity */ + ia64_set_csd(codeseg); + ia64_set_ssd(dataseg); + frame->tf_r[FRAME_R24] = dataseg; /* ESD */ + frame->tf_r[FRAME_R27] = dataseg; /* DSD */ + frame->tf_r[FRAME_R28] = dataseg; /* FSD */ + frame->tf_r[FRAME_R29] = dataseg; /* GSD */ + + gdtseg = gdt /* base */ + + ((8L*NGDT - 1) << 32) /* limit */ + + ((long)SDT_SYSNULL << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + ldtseg = ldt /* base */ + + ((8L*NLDT - 1) << 32) /* limit */ + + ((long)SDT_SYSLDT << 52) + + ((long)SEL_UPL << 57) + + (1L << 59) /* present */ + + (0L << 62) /* 16 bits */ + + (0L << 63); /* byte granularity */ + frame->tf_r[FRAME_R30] = ldtseg; /* LDTD */ + frame->tf_r[FRAME_R31] = gdtseg; /* GDTD */ + + ia64_set_eflag(PSL_USER); + + /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ + frame->tf_r[FRAME_R11] = IA32_PS_STRINGS; + + /* + * XXX - Linux emulator + * Make sure sure edx is 0x0 on entry. Linux binaries depend + * on it. + */ + td->td_retval[1] = 0; +} diff --git a/sys/compat/ia32/ia32_util.h b/sys/compat/ia32/ia32_util.h new file mode 100644 index 0000000..b9e0a7c --- /dev/null +++ b/sys/compat/ia32/ia32_util.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 1998-1999 Andrew Gallatin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + + +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/cdefs.h> + + +#ifndef SCARG +#define SCARG(p, x) (p)->x +#endif + +struct ia32_ps_strings { + u_int32_t ps_argvstr; /* first of 0 or more argument strings */ + int ps_nargvstr; /* the number of argument strings */ + u_int32_t ps_envstr; /* first of 0 or more environment strings */ + int ps_nenvstr; /* the number of environment strings */ +}; + +#define IA32_USRSTACK (4L*1024*1024*1024 - PAGE_SIZE) +#define IA32_PS_STRINGS (IA32_USRSTACK - sizeof(struct ia32_ps_strings)) + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curproc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)IA32_PS_STRINGS) - szsigcode - SPARE_USRSPACE); +#undef szsigcode +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p; + + p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + + +extern const char ia32_emul_path[]; +int ia32_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = ia32_emul_find(p, sgp, ia32_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT((p), (sgp), (path), 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT((p), (sgp), (path), 1) diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c new file mode 100644 index 0000000..5129746 --- /dev/null +++ b/sys/compat/linprocfs/linprocfs.c @@ -0,0 +1,861 @@ +/* + * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav + * Copyright (c) 1999 Pierre Beyssac + * Copyright (c) 1993 Jan-Simon Pendry + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/blist.h> +#include <sys/conf.h> +#include <sys/dkstat.h> +#include <sys/exec.h> +#include <sys/jail.h> +#include <sys/kernel.h> +#include <sys/linker.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/resourcevar.h> +#include <sys/sbuf.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/tty.h> +#include <sys/user.h> +#include <sys/vmmeter.h> +#include <sys/vnode.h> + +#include <net/if.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_param.h> +#include <vm/vm_object.h> +#include <vm/swap_pager.h> + +#include <machine/clock.h> + +#ifdef __alpha__ +#include <machine/alpha_cpu.h> +#include <machine/cpuconf.h> +#include <machine/rpb.h> +extern int ncpus; +#endif /* __alpha__ */ + +#ifdef __i386__ +#include <machine/cputypes.h> +#include <machine/md_var.h> +#endif /* __i386__ */ + +#include <machine/../linux/linux.h> +#include <compat/linux/linux_ioctl.h> +#include <compat/linux/linux_mib.h> +#include <compat/linux/linux_util.h> +#include <fs/pseudofs/pseudofs.h> +#include <fs/procfs/procfs.h> + +/* + * Various conversion macros + */ +#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ +#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ +#define B2K(x) ((x) >> 10) /* bytes to kbytes */ +#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ +#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ +#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ + +/* + * Filler function for proc/meminfo + */ +static int +linprocfs_domeminfo(PFS_FILL_ARGS) +{ + unsigned long memtotal; /* total memory in bytes */ + unsigned long memused; /* used memory in bytes */ + unsigned long memfree; /* free memory in bytes */ + unsigned long memshared; /* shared memory ??? */ + unsigned long buffers, cached; /* buffer / cache memory ??? */ + u_quad_t swaptotal; /* total swap space in bytes */ + u_quad_t swapused; /* used swap space in bytes */ + u_quad_t swapfree; /* free swap space in bytes */ + vm_object_t object; + + memtotal = physmem * PAGE_SIZE; + /* + * The correct thing here would be: + * + memfree = cnt.v_free_count * PAGE_SIZE; + memused = memtotal - memfree; + * + * but it might mislead linux binaries into thinking there + * is very little memory left, so we cheat and tell them that + * all memory that isn't wired down is free. + */ + memused = cnt.v_wire_count * PAGE_SIZE; + memfree = memtotal - memused; + if (swapblist == NULL) { + swaptotal = 0; + swapfree = 0; + } else { + swaptotal = (u_quad_t)swapblist->bl_blocks * 1024; /* XXX why 1024? */ + swapfree = (u_quad_t)swapblist->bl_root->u.bmu_avail * PAGE_SIZE; + } + swapused = swaptotal - swapfree; + memshared = 0; + TAILQ_FOREACH(object, &vm_object_list, object_list) + if (object->shadow_count > 1) + memshared += object->resident_page_count; + memshared *= PAGE_SIZE; + /* + * We'd love to be able to write: + * + buffers = bufspace; + * + * but bufspace is internal to vfs_bio.c and we don't feel + * like unstaticizing it just for linprocfs's sake. + */ + buffers = 0; + cached = cnt.v_cache_count * PAGE_SIZE; + + sbuf_printf(sb, + " total: used: free: shared: buffers: cached:\n" + "Mem: %lu %lu %lu %lu %lu %lu\n" + "Swap: %llu %llu %llu\n" + "MemTotal: %9lu kB\n" + "MemFree: %9lu kB\n" + "MemShared:%9lu kB\n" + "Buffers: %9lu kB\n" + "Cached: %9lu kB\n" + "SwapTotal:%9llu kB\n" + "SwapFree: %9llu kB\n", + memtotal, memused, memfree, memshared, buffers, cached, + swaptotal, swapused, swapfree, + B2K(memtotal), B2K(memfree), + B2K(memshared), B2K(buffers), B2K(cached), + B2K(swaptotal), B2K(swapfree)); + + return (0); +} + +#ifdef __alpha__ +/* + * Filler function for proc/cpuinfo (Alpha version) + */ +static int +linprocfs_docpuinfo(PFS_FILL_ARGS) +{ + u_int64_t type, major; + struct pcs *pcsp; + const char *model, *sysname; + + static const char *cpuname[] = { + "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", + "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL" + }; + + pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); + type = pcsp->pcs_proc_type; + major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT; + if (major < sizeof(cpuname)/sizeof(char *)) { + model = cpuname[major - 1]; + } else { + model = "unknown"; + } + + sysname = alpha_dsr_sysname(); + + sbuf_printf(sb, + "cpu\t\t\t: Alpha\n" + "cpu model\t\t: %s\n" + "cpu variation\t\t: %ld\n" + "cpu revision\t\t: %ld\n" + "cpu serial number\t: %s\n" + "system type\t\t: %s\n" + "system variation\t: %s\n" + "system revision\t\t: %ld\n" + "system serial number\t: %s\n" + "cycle frequency [Hz]\t: %lu\n" + "timer frequency [Hz]\t: %lu\n" + "page size [bytes]\t: %ld\n" + "phys. address bits\t: %ld\n" + "max. addr. space #\t: %ld\n" + "BogoMIPS\t\t: %lu.%02lu\n" + "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n" + "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n" + "platform string\t\t: %s\n" + "cpus detected\t\t: %d\n" + , + model, + pcsp->pcs_proc_var, + *(int *)hwrpb->rpb_revision, + " ", + " ", + "0", + 0, + " ", + hwrpb->rpb_cc_freq, + hz, + hwrpb->rpb_page_size, + hwrpb->rpb_phys_addr_size, + hwrpb->rpb_max_asn, + 0, 0, + 0, 0, 0, + 0, 0, 0, + sysname, + ncpus); + return (0); +} +#endif /* __alpha__ */ + +#ifdef __i386__ +/* + * Filler function for proc/cpuinfo (i386 version) + */ +static int +linprocfs_docpuinfo(PFS_FILL_ARGS) +{ + int class, i, fqmhz, fqkhz; + + /* + * We default the flags to include all non-conflicting flags, + * and the Intel versions of conflicting flags. + */ + static char *flags[] = { + "fpu", "vme", "de", "pse", "tsc", + "msr", "pae", "mce", "cx8", "apic", + "sep", "sep", "mtrr", "pge", "mca", + "cmov", "pat", "pse36", "pn", "b19", + "b20", "b21", "mmxext", "mmx", "fxsr", + "xmm", "b26", "b27", "b28", "b29", + "3dnowext", "3dnow" + }; + + switch (cpu_class) { + case CPUCLASS_286: + class = 2; + break; + case CPUCLASS_386: + class = 3; + break; + case CPUCLASS_486: + class = 4; + break; + case CPUCLASS_586: + class = 5; + break; + case CPUCLASS_686: + class = 6; + break; + default: + class = 0; + break; + } + + sbuf_printf(sb, + "processor\t: %d\n" + "vendor_id\t: %.20s\n" + "cpu family\t: %d\n" + "model\t\t: %d\n" + "stepping\t: %d\n", + 0, cpu_vendor, class, cpu, cpu_id & 0xf); + + sbuf_cat(sb, + "flags\t\t:"); + + if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { + flags[16] = "fcmov"; + } else if (!strcmp(cpu_vendor, "CyrixInstead")) { + flags[24] = "cxmmx"; + } + + for (i = 0; i < 32; i++) + if (cpu_feature & (1 << i)) + sbuf_printf(sb, " %s", flags[i]); + sbuf_cat(sb, "\n"); + if (class >= 5) { + fqmhz = (tsc_freq + 4999) / 1000000; + fqkhz = ((tsc_freq + 4999) / 10000) % 100; + sbuf_printf(sb, + "cpu MHz\t\t: %d.%02d\n" + "bogomips\t: %d.%02d\n", + fqmhz, fqkhz, fqmhz, fqkhz); + } + + return (0); +} +#endif /* __i386__ */ + +/* + * Filler function for proc/mtab + * + * This file doesn't exist in Linux' procfs, but is included here so + * users can symlink /compat/linux/etc/mtab to /proc/mtab + */ +static int +linprocfs_domtab(PFS_FILL_ARGS) +{ + struct nameidata nd; + struct mount *mp; + const char *lep; + char *dlep, *flep, *mntto, *mntfrom, *fstype; + size_t lep_len; + int error; + + /* resolve symlinks etc. in the emulation tree prefix */ + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); + flep = NULL; + if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) == -1) + lep = linux_emul_path; + else + lep = dlep; + lep_len = strlen(lep); + + mtx_lock(&mountlist_mtx); + error = 0; + TAILQ_FOREACH(mp, &mountlist, mnt_list) { + error = VFS_STATFS(mp, &mp->mnt_stat, td); + if (error) + break; + + /* determine device name */ + mntfrom = mp->mnt_stat.f_mntfromname; + + /* determine mount point */ + mntto = mp->mnt_stat.f_mntonname; + if (strncmp(mntto, lep, lep_len) == 0 && + mntto[lep_len] == '/') + mntto += lep_len; + + /* determine fs type */ + fstype = mp->mnt_stat.f_fstypename; + if (strcmp(fstype, pn->pn_info->pi_name) == 0) + mntfrom = fstype = "proc"; + else if (strcmp(fstype, "procfs") == 0) + continue; + + sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, + mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); +#define ADD_OPTION(opt, name) \ + if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); + ADD_OPTION(MNT_SYNCHRONOUS, "sync"); + ADD_OPTION(MNT_NOEXEC, "noexec"); + ADD_OPTION(MNT_NOSUID, "nosuid"); + ADD_OPTION(MNT_NODEV, "nodev"); + ADD_OPTION(MNT_UNION, "union"); + ADD_OPTION(MNT_ASYNC, "async"); + ADD_OPTION(MNT_SUIDDIR, "suiddir"); + ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); + ADD_OPTION(MNT_NOATIME, "noatime"); +#undef ADD_OPTION + /* a real Linux mtab will also show NFS options */ + sbuf_printf(sb, " 0 0\n"); + } + mtx_unlock(&mountlist_mtx); + if (flep != NULL) + free(flep, M_TEMP); + return (error); +} + +/* + * Filler function for proc/stat + */ +static int +linprocfs_dostat(PFS_FILL_ARGS) +{ + sbuf_printf(sb, + "cpu %ld %ld %ld %ld\n" + "disk 0 0 0 0\n" + "page %u %u\n" + "swap %u %u\n" + "intr %u\n" + "ctxt %u\n" + "btime %lld\n", + T2J(cp_time[CP_USER]), + T2J(cp_time[CP_NICE]), + T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), + T2J(cp_time[CP_IDLE]), + cnt.v_vnodepgsin, + cnt.v_vnodepgsout, + cnt.v_swappgsin, + cnt.v_swappgsout, + cnt.v_intr, + cnt.v_swtch, + (quad_t)boottime.tv_sec); + return (0); +} + +/* + * Filler function for proc/uptime + */ +static int +linprocfs_douptime(PFS_FILL_ARGS) +{ + struct timeval tv; + + getmicrouptime(&tv); + sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", + (quad_t)tv.tv_sec, tv.tv_usec / 10000, + T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); + return (0); +} + +/* + * Filler function for proc/version + */ +static int +linprocfs_doversion(PFS_FILL_ARGS) +{ + char osname[LINUX_MAX_UTSNAME]; + char osrelease[LINUX_MAX_UTSNAME]; + + linux_get_osname(td->td_proc, osname); + linux_get_osrelease(td->td_proc, osrelease); + + sbuf_printf(sb, + "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" + " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); + return (0); +} + +/* + * Filler function for proc/loadavg + */ +static int +linprocfs_doloadavg(PFS_FILL_ARGS) +{ + sbuf_printf(sb, + "%d.%02d %d.%02d %d.%02d %d/%d %d\n", + (int)(averunnable.ldavg[0] / averunnable.fscale), + (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), + (int)(averunnable.ldavg[1] / averunnable.fscale), + (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), + (int)(averunnable.ldavg[2] / averunnable.fscale), + (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), + 1, /* number of running tasks */ + nprocs, /* number of tasks */ + lastpid /* the last pid */ + ); + + return (0); +} + +/* + * Filler function for proc/pid/stat + */ +static int +linprocfs_doprocstat(PFS_FILL_ARGS) +{ + struct kinfo_proc kp; + + PROC_LOCK(p); + fill_kinfo_proc(p, &kp); + sbuf_printf(sb, "%d", p->p_pid); +#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) + PS_ADD("comm", "(%s)", p->p_comm); + PS_ADD("statr", "%c", '0'); /* XXX */ + PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); + PS_ADD("pgrp", "%d", p->p_pgid); + PS_ADD("session", "%d", p->p_session->s_sid); + PROC_UNLOCK(p); + PS_ADD("tty", "%d", 0); /* XXX */ + PS_ADD("tpgid", "%d", 0); /* XXX */ + PS_ADD("flags", "%u", 0); /* XXX */ + PS_ADD("minflt", "%u", 0); /* XXX */ + PS_ADD("cminflt", "%u", 0); /* XXX */ + PS_ADD("majflt", "%u", 0); /* XXX */ + PS_ADD("cminflt", "%u", 0); /* XXX */ + PS_ADD("utime", "%d", 0); /* XXX */ + PS_ADD("stime", "%d", 0); /* XXX */ + PS_ADD("cutime", "%d", 0); /* XXX */ + PS_ADD("cstime", "%d", 0); /* XXX */ + PS_ADD("counter", "%d", 0); /* XXX */ + PS_ADD("priority", "%d", 0); /* XXX */ + PS_ADD("timeout", "%u", 0); /* XXX */ + PS_ADD("itrealvalue", "%u", 0); /* XXX */ + PS_ADD("starttime", "%d", 0); /* XXX */ + PS_ADD("vsize", "%u", kp.ki_size); + PS_ADD("rss", "%u", P2K(kp.ki_rssize)); + PS_ADD("rlim", "%u", 0); /* XXX */ + PS_ADD("startcode", "%u", (unsigned)0); + PS_ADD("endcode", "%u", 0); /* XXX */ + PS_ADD("startstack", "%u", 0); /* XXX */ + PS_ADD("esp", "%u", 0); /* XXX */ + PS_ADD("eip", "%u", 0); /* XXX */ + PS_ADD("signal", "%d", 0); /* XXX */ + PS_ADD("blocked", "%d", 0); /* XXX */ + PS_ADD("sigignore", "%d", 0); /* XXX */ + PS_ADD("sigcatch", "%d", 0); /* XXX */ + PS_ADD("wchan", "%u", 0); /* XXX */ + PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ + PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ + PS_ADD("exitsignal", "%d", 0); /* XXX */ + PS_ADD("processor", "%d", 0); /* XXX */ +#undef PS_ADD + sbuf_putc(sb, '\n'); + + return (0); +} + +/* + * Filler function for proc/pid/status + */ +static int +linprocfs_doprocstatus(PFS_FILL_ARGS) +{ + struct kinfo_proc kp; + char *state; + segsz_t lsize; + struct thread *td2; + int i; + + mtx_lock_spin(&sched_lock); + td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ + + if (P_SHOULDSTOP(p)) { + state = "T (stopped)"; + } else { + switch(p->p_state) { + case PRS_NEW: + state = "I (idle)"; + break; + case PRS_NORMAL: + if (p->p_flag & P_WEXIT) { + state = "X (exiting)"; + break; + } + switch(td2->td_state) { + case TDS_SLP: + case TDS_MTX: + state = "S (sleeping)"; + break; + case TDS_RUNQ: + case TDS_RUNNING: + state = "R (running)"; + break; + case TDS_NEW: + case TDS_UNQUEUED: + case TDS_IWAIT: + case TDS_SURPLUS: + default: + state = "? (unknown)"; + break; + } + break; + case PRS_WAIT: + state = "W (waiting)"; + break; + case PRS_ZOMBIE: + state = "Z (zombie)"; + break; + default: + state = "? (unknown)"; + break; + } + } + mtx_unlock_spin(&sched_lock); + + PROC_LOCK(p); + fill_kinfo_proc(p, &kp); + sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ + sbuf_printf(sb, "State:\t%s\n", state); + + /* + * Credentials + */ + sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); + sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? + p->p_pptr->p_pid : 0); + sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, + p->p_ucred->cr_uid, + p->p_ucred->cr_svuid, + /* FreeBSD doesn't have fsuid */ + p->p_ucred->cr_uid); + sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, + p->p_ucred->cr_gid, + p->p_ucred->cr_svgid, + /* FreeBSD doesn't have fsgid */ + p->p_ucred->cr_gid); + sbuf_cat(sb, "Groups:\t"); + for (i = 0; i < p->p_ucred->cr_ngroups; i++) + sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); + PROC_UNLOCK(p); + sbuf_putc(sb, '\n'); + + /* + * Memory + * + * While our approximation of VmLib may not be accurate (I + * don't know of a simple way to verify it, and I'm not sure + * it has much meaning anyway), I believe it's good enough. + * + * The same code that could (I think) accurately compute VmLib + * could also compute VmLck, but I don't really care enough to + * implement it. Submissions are welcome. + */ + sbuf_printf(sb, "VmSize:\t%8u kB\n", B2K(kp.ki_size)); + sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ + sbuf_printf(sb, "VmRss:\t%8u kB\n", P2K(kp.ki_rssize)); + sbuf_printf(sb, "VmData:\t%8u kB\n", P2K(kp.ki_dsize)); + sbuf_printf(sb, "VmStk:\t%8u kB\n", P2K(kp.ki_ssize)); + sbuf_printf(sb, "VmExe:\t%8u kB\n", P2K(kp.ki_tsize)); + lsize = B2P(kp.ki_size) - kp.ki_dsize - + kp.ki_ssize - kp.ki_tsize - 1; + sbuf_printf(sb, "VmLib:\t%8u kB\n", P2K(lsize)); + + /* + * Signal masks + * + * We support up to 128 signals, while Linux supports 32, + * but we only define 32 (the same 32 as Linux, to boot), so + * just show the lower 32 bits of each mask. XXX hack. + * + * NB: on certain platforms (Sparc at least) Linux actually + * supports 64 signals, but this code is a long way from + * running on anything but i386, so ignore that for now. + */ + PROC_LOCK(p); + sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); + /* + * I can't seem to find out where the signal mask is in + * relation to struct proc, so SigBlk is left unimplemented. + */ + sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ + sbuf_printf(sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]); + sbuf_printf(sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]); + PROC_UNLOCK(p); + + /* + * Linux also prints the capability masks, but we don't have + * capabilities yet, and when we do get them they're likely to + * be meaningless to Linux programs, so we lie. XXX + */ + sbuf_printf(sb, "CapInh:\t%016x\n", 0); + sbuf_printf(sb, "CapPrm:\t%016x\n", 0); + sbuf_printf(sb, "CapEff:\t%016x\n", 0); + + return (0); +} + +/* + * Filler function for proc/pid/cmdline + */ +static int +linprocfs_doproccmdline(PFS_FILL_ARGS) +{ + struct ps_strings pstr; + int error, i; + + /* + * If we are using the ps/cmdline caching, use that. Otherwise + * revert back to the old way which only implements full cmdline + * for the currept process and just p->p_comm for all other + * processes. + * Note that if the argv is no longer available, we deliberately + * don't fall back on p->p_comm or return an error: the authentic + * Linux behaviour is to return zero-length in this case. + */ + + PROC_LOCK(p); + if (p->p_args && (ps_argsopen || !p_cansee(td, p))) { + sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); + PROC_UNLOCK(p); + } else if (p != td->td_proc) { + PROC_UNLOCK(p); + sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); + } else { + PROC_UNLOCK(p); + error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr)); + if (error) + return (error); + for (i = 0; i < pstr.ps_nargvstr; i++) { + sbuf_copyin(sb, pstr.ps_argvstr[i], 0); + sbuf_printf(sb, "%c", '\0'); + } + } + + return (0); +} + +/* + * Filler function for proc/net/dev + */ +static int +linprocfs_donetdev(PFS_FILL_ARGS) +{ + char ifname[16]; /* XXX LINUX_IFNAMSIZ */ + struct ifnet *ifp; + + sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", + "Inter-", " Receive", " Transmit", " face", + "bytes packets errs drop fifo frame compressed", + "bytes packets errs drop fifo frame compressed"); + + TAILQ_FOREACH(ifp, &ifnet, if_link) { + linux_ifname(ifp, ifname, sizeof ifname); + sbuf_printf(sb, "%6.6s:", ifname); + sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", + 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); + sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", + 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); + } + + return (0); +} + +#if 0 +extern struct cdevsw *cdevsw[]; + +/* + * Filler function for proc/devices + */ +static int +linprocfs_dodevices(PFS_FILL_ARGS) +{ + int i; + + sbuf_printf(sb, "Character devices:\n"); + + for (i = 0; i < NUMCDEVSW; i++) + if (cdevsw[i] != NULL) + sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); + + sbuf_printf(sb, "\nBlock devices:\n"); + + return (0); +} +#endif + +/* + * Filler function for proc/cmdline + */ +static int +linprocfs_docmdline(PFS_FILL_ARGS) +{ + sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); + sbuf_printf(sb, " ro root=302\n"); + return (0); +} + +#if 0 +/* + * Filler function for proc/modules + */ +static int +linprocfs_domodules(PFS_FILL_ARGS) +{ + struct linker_file *lf; + + TAILQ_FOREACH(lf, &linker_files, link) { + sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, + (unsigned long)lf->size, lf->refs); + } + return (0); +} +#endif + +/* + * Constructor + */ +static int +linprocfs_init(PFS_INIT_ARGS) +{ + struct pfs_node *root; + struct pfs_node *dir; + + root = pi->pi_root; + +#define PFS_CREATE_FILE(name) \ + pfs_create_file(root, #name, &linprocfs_do##name, NULL, NULL, PFS_RD) + PFS_CREATE_FILE(cmdline); + PFS_CREATE_FILE(cpuinfo); +#if 0 + PFS_CREATE_FILE(devices); +#endif + PFS_CREATE_FILE(loadavg); + PFS_CREATE_FILE(meminfo); +#if 0 + PFS_CREATE_FILE(modules); +#endif + PFS_CREATE_FILE(mtab); + PFS_CREATE_FILE(stat); + PFS_CREATE_FILE(uptime); + PFS_CREATE_FILE(version); +#undef PFS_CREATE_FILE + pfs_create_link(root, "self", &procfs_docurproc, + NULL, NULL, 0); + + dir = pfs_create_dir(root, "net", NULL, NULL, 0); + pfs_create_file(dir, "dev", &linprocfs_donetdev, + NULL, NULL, PFS_RD); + + dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); + pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, + NULL, NULL, PFS_RD); + pfs_create_link(dir, "exe", &procfs_doprocfile, + NULL, &procfs_notsystem, 0); + pfs_create_file(dir, "mem", &procfs_doprocmem, + &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); + pfs_create_file(dir, "stat", &linprocfs_doprocstat, + NULL, NULL, PFS_RD); + pfs_create_file(dir, "status", &linprocfs_doprocstatus, + NULL, NULL, PFS_RD); + + return (0); +} + +/* + * Destructor + */ +static int +linprocfs_uninit(PFS_INIT_ARGS) +{ + + /* nothing to do, pseudofs will GC */ + return (0); +} + +PSEUDOFS(linprocfs, 1); +MODULE_DEPEND(linprocfs, linux, 1, 1, 1); +MODULE_DEPEND(linprocfs, procfs, 1, 1, 1); diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c new file mode 100644 index 0000000..3c459dd --- /dev/null +++ b/sys/compat/linux/linux_file.c @@ -0,0 +1,1197 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_compat.h" +#include "opt_mac.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/dirent.h> +#include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/lock.h> +#include <sys/mac.h> +#include <sys/malloc.h> +#include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sysproto.h> +#include <sys/tty.h> +#include <sys/vnode.h> + +#include <ufs/ufs/extattr.h> +#include <ufs/ufs/quota.h> +#include <ufs/ufs/ufsmount.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +#ifndef __alpha__ +int +linux_creat(struct thread *td, struct linux_creat_args *args) +{ + struct open_args /* { + char *path; + int flags; + int mode; + } */ bsd_open_args; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTCREAT(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(creat)) + printf(ARGS(creat, "%s, %d"), args->path, args->mode); +#endif + bsd_open_args.path = args->path; + bsd_open_args.mode = args->mode; + bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; + return open(td, &bsd_open_args); +} +#endif /*!__alpha__*/ + +int +linux_open(struct thread *td, struct linux_open_args *args) +{ + struct open_args /* { + char *path; + int flags; + int mode; + } */ bsd_open_args; + struct proc *p = td->td_proc; + int error; + caddr_t sg; + + sg = stackgap_init(); + + if (args->flags & LINUX_O_CREAT) + CHECKALTCREAT(td, &sg, args->path); + else + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(open)) + printf(ARGS(open, "%s, 0x%x, 0x%x"), + args->path, args->flags, args->mode); +#endif + bsd_open_args.flags = 0; + if (args->flags & LINUX_O_RDONLY) + bsd_open_args.flags |= O_RDONLY; + if (args->flags & LINUX_O_WRONLY) + bsd_open_args.flags |= O_WRONLY; + if (args->flags & LINUX_O_RDWR) + bsd_open_args.flags |= O_RDWR; + if (args->flags & LINUX_O_NDELAY) + bsd_open_args.flags |= O_NONBLOCK; + if (args->flags & LINUX_O_APPEND) + bsd_open_args.flags |= O_APPEND; + if (args->flags & LINUX_O_SYNC) + bsd_open_args.flags |= O_FSYNC; + if (args->flags & LINUX_O_NONBLOCK) + bsd_open_args.flags |= O_NONBLOCK; + if (args->flags & LINUX_FASYNC) + bsd_open_args.flags |= O_ASYNC; + if (args->flags & LINUX_O_CREAT) + bsd_open_args.flags |= O_CREAT; + if (args->flags & LINUX_O_TRUNC) + bsd_open_args.flags |= O_TRUNC; + if (args->flags & LINUX_O_EXCL) + bsd_open_args.flags |= O_EXCL; + if (args->flags & LINUX_O_NOCTTY) + bsd_open_args.flags |= O_NOCTTY; + bsd_open_args.path = args->path; + bsd_open_args.mode = args->mode; + + error = open(td, &bsd_open_args); + PROC_LOCK(p); + if (!error && !(bsd_open_args.flags & O_NOCTTY) && + SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { + struct file *fp; + + error = fget(td, td->td_retval[0], &fp); + PROC_UNLOCK(p); + if (!error) { + if (fp->f_type == DTYPE_VNODE) + fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td); + fdrop(fp, td); + } + } else { + PROC_UNLOCK(p); +#ifdef DEBUG + if (ldebug(open)) + printf(LMSG("open returns error %d"), error); +#endif + } + return error; +} + +int +linux_lseek(struct thread *td, struct linux_lseek_args *args) +{ + + struct lseek_args /* { + int fd; + int pad; + off_t offset; + int whence; + } */ tmp_args; + int error; + +#ifdef DEBUG + if (ldebug(lseek)) + printf(ARGS(lseek, "%d, %ld, %d"), + args->fdes, (long)args->off, args->whence); +#endif + tmp_args.fd = args->fdes; + tmp_args.offset = (off_t)args->off; + tmp_args.whence = args->whence; + error = lseek(td, &tmp_args); + return error; +} + +#ifndef __alpha__ +int +linux_llseek(struct thread *td, struct linux_llseek_args *args) +{ + struct lseek_args bsd_args; + int error; + off_t off; + +#ifdef DEBUG + if (ldebug(llseek)) + printf(ARGS(llseek, "%d, %d:%d, %d"), + args->fd, args->ohigh, args->olow, args->whence); +#endif + off = (args->olow) | (((off_t) args->ohigh) << 32); + + bsd_args.fd = args->fd; + bsd_args.offset = off; + bsd_args.whence = args->whence; + + if ((error = lseek(td, &bsd_args))) + return error; + + if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t)))) + return error; + + td->td_retval[0] = 0; + return 0; +} +#endif /*!__alpha__*/ + +#ifndef __alpha__ +int +linux_readdir(struct thread *td, struct linux_readdir_args *args) +{ + struct linux_getdents_args lda; + + lda.fd = args->fd; + lda.dent = args->dent; + lda.count = 1; + return linux_getdents(td, &lda); +} +#endif /*!__alpha__*/ + +/* + * Note that linux_getdents(2) and linux_getdents64(2) have the same + * arguments. They only differ in the definition of struct dirent they + * operate on. We use this to common the code, with the exception of + * accessing struct dirent. Note that linux_readdir(2) is implemented + * by means of linux_getdents(2). In this case we never operate on + * struct dirent64 and thus don't need to handle it... + */ + +struct l_dirent { + l_long d_ino; + l_off_t d_off; + l_ushort d_reclen; + char d_name[LINUX_NAME_MAX + 1]; +}; + +struct l_dirent64 { + uint64_t d_ino; + int64_t d_off; + l_ushort d_reclen; + u_char d_type; + char d_name[LINUX_NAME_MAX + 1]; +}; + +#define LINUX_RECLEN(de,namlen) \ + ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) + +#define LINUX_DIRBLKSIZ 512 + +static int +getdents_common(struct thread *td, struct linux_getdents64_args *args, + int is64bit) +{ + register struct dirent *bdp; + struct vnode *vp; + caddr_t inp, buf; /* BSD-format */ + int len, reclen; /* BSD-format */ + caddr_t outp; /* Linux-format */ + int resid, linuxreclen=0; /* Linux-format */ + struct file *fp; + struct uio auio; + struct iovec aiov; + struct vattr va; + off_t off; + struct l_dirent linux_dirent; + struct l_dirent64 linux_dirent64; + int buflen, error, eofflag, nbytes, justone; + u_long *cookies = NULL, *cookiep; + int ncookies; + + if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) + return (error); + + if ((fp->f_flag & FREAD) == 0) { + fdrop(fp, td); + return (EBADF); + } + + vp = (struct vnode *) fp->f_data; + if (vp->v_type != VDIR) { + fdrop(fp, td); + return (EINVAL); + } + + if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { + fdrop(fp, td); + return (error); + } + + nbytes = args->count; + if (nbytes == 1) { + /* readdir(2) case. Always struct dirent. */ + if (is64bit) { + fdrop(fp, td); + return (EINVAL); + } + nbytes = sizeof(linux_dirent); + justone = 1; + } else + justone = 0; + + off = fp->f_offset; + + buflen = max(LINUX_DIRBLKSIZ, nbytes); + buflen = min(buflen, MAXBSIZE); + buf = malloc(buflen, M_TEMP, M_WAITOK); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + +again: + aiov.iov_base = buf; + aiov.iov_len = buflen; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_td = td; + auio.uio_resid = buflen; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; + } + +#ifdef MAC + /* + * Do directory search MAC check using non-cached credentials. + */ + if ((error = mac_check_vnode_readdir(td->td_proc->p_ucred, vp)) + goto out; +#endif /* MAC */ + if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, + &cookies))) + goto out; + + inp = buf; + outp = (caddr_t)args->dirent; + resid = nbytes; + if ((len = buflen - auio.uio_resid) <= 0) + goto eof; + + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + bdp = (struct dirent *) inp; + len -= bdp->d_reclen; + inp += bdp->d_reclen; + cookiep++; + ncookies--; + } + } + + while (len > 0) { + if (cookiep && ncookies == 0) + break; + bdp = (struct dirent *) inp; + reclen = bdp->d_reclen; + if (reclen & 3) { + error = EFAULT; + goto out; + } + + if (bdp->d_fileno == 0) { + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + + len -= reclen; + continue; + } + + linuxreclen = (is64bit) + ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) + : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); + + if (reclen > len || resid < linuxreclen) { + outp++; + break; + } + + if (justone) { + /* readdir(2) case. */ + linux_dirent.d_ino = (l_long)bdp->d_fileno; + linux_dirent.d_off = (l_off_t)linuxreclen; + linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; + strcpy(linux_dirent.d_name, bdp->d_name); + error = copyout(&linux_dirent, outp, linuxreclen); + } else { + if (is64bit) { + linux_dirent64.d_ino = bdp->d_fileno; + linux_dirent64.d_off = (cookiep) + ? (l_off_t)*cookiep + : (l_off_t)(off + reclen); + linux_dirent64.d_reclen = + (l_ushort)linuxreclen; + linux_dirent64.d_type = bdp->d_type; + strcpy(linux_dirent64.d_name, bdp->d_name); + error = copyout(&linux_dirent64, outp, + linuxreclen); + } else { + linux_dirent.d_ino = bdp->d_fileno; + linux_dirent.d_off = (cookiep) + ? (l_off_t)*cookiep + : (l_off_t)(off + reclen); + linux_dirent.d_reclen = (l_ushort)linuxreclen; + strcpy(linux_dirent.d_name, bdp->d_name); + error = copyout(&linux_dirent, outp, + linuxreclen); + } + } + if (error) + goto out; + + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + + outp += linuxreclen; + resid -= linuxreclen; + len -= reclen; + if (justone) + break; + } + + if (outp == (caddr_t)args->dirent) + goto again; + + fp->f_offset = off; + if (justone) + nbytes = resid + linuxreclen; + +eof: + td->td_retval[0] = nbytes - resid; + +out: + if (cookies) + free(cookies, M_TEMP); + + VOP_UNLOCK(vp, 0, td); + fdrop(fp, td); + free(buf, M_TEMP); + return (error); +} + +int +linux_getdents(struct thread *td, struct linux_getdents_args *args) +{ + +#ifdef DEBUG + if (ldebug(getdents)) + printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); +#endif + + return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); +} + +int +linux_getdents64(struct thread *td, struct linux_getdents64_args *args) +{ + +#ifdef DEBUG + if (ldebug(getdents64)) + printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); +#endif + + return (getdents_common(td, args, 1)); +} + +/* + * These exist mainly for hooks for doing /compat/linux translation. + */ + +int +linux_access(struct thread *td, struct linux_access_args *args) +{ + struct access_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(access)) + printf(ARGS(access, "%s, %d"), args->path, args->flags); +#endif + bsd.path = args->path; + bsd.flags = args->flags; + + return access(td, &bsd); +} + +int +linux_unlink(struct thread *td, struct linux_unlink_args *args) +{ + struct unlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(unlink)) + printf(ARGS(unlink, "%s"), args->path); +#endif + bsd.path = args->path; + + return unlink(td, &bsd); +} + +int +linux_chdir(struct thread *td, struct linux_chdir_args *args) +{ + struct chdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(chdir)) + printf(ARGS(chdir, "%s"), args->path); +#endif + bsd.path = args->path; + + return chdir(td, &bsd); +} + +int +linux_chmod(struct thread *td, struct linux_chmod_args *args) +{ + struct chmod_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(chmod)) + printf(ARGS(chmod, "%s, %d"), args->path, args->mode); +#endif + bsd.path = args->path; + bsd.mode = args->mode; + + return chmod(td, &bsd); +} + +int +linux_mkdir(struct thread *td, struct linux_mkdir_args *args) +{ + struct mkdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTCREAT(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(mkdir)) + printf(ARGS(mkdir, "%s, %d"), args->path, args->mode); +#endif + bsd.path = args->path; + bsd.mode = args->mode; + + return mkdir(td, &bsd); +} + +int +linux_rmdir(struct thread *td, struct linux_rmdir_args *args) +{ + struct rmdir_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(rmdir)) + printf(ARGS(rmdir, "%s"), args->path); +#endif + bsd.path = args->path; + + return rmdir(td, &bsd); +} + +int +linux_rename(struct thread *td, struct linux_rename_args *args) +{ + struct rename_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->from); + CHECKALTCREAT(td, &sg, args->to); + +#ifdef DEBUG + if (ldebug(rename)) + printf(ARGS(rename, "%s, %s"), args->from, args->to); +#endif + bsd.from = args->from; + bsd.to = args->to; + + return rename(td, &bsd); +} + +int +linux_symlink(struct thread *td, struct linux_symlink_args *args) +{ + struct symlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + CHECKALTCREAT(td, &sg, args->to); + +#ifdef DEBUG + if (ldebug(symlink)) + printf(ARGS(symlink, "%s, %s"), args->path, args->to); +#endif + bsd.path = args->path; + bsd.link = args->to; + + return symlink(td, &bsd); +} + +int +linux_readlink(struct thread *td, struct linux_readlink_args *args) +{ + struct readlink_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->name); + +#ifdef DEBUG + if (ldebug(readlink)) + printf(ARGS(readlink, "%s, %p, %d"), + args->name, (void *)args->buf, args->count); +#endif + bsd.path = args->name; + bsd.buf = args->buf; + bsd.count = args->count; + + return readlink(td, &bsd); +} + +int +linux_truncate(struct thread *td, struct linux_truncate_args *args) +{ + struct truncate_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(truncate)) + printf(ARGS(truncate, "%s, %ld"), args->path, + (long)args->length); +#endif + bsd.path = args->path; + bsd.length = args->length; + + return truncate(td, &bsd); +} + +int +linux_link(struct thread *td, struct linux_link_args *args) +{ + struct link_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + CHECKALTCREAT(td, &sg, args->to); + +#ifdef DEBUG + if (ldebug(link)) + printf(ARGS(link, "%s, %s"), args->path, args->to); +#endif + + bsd.path = args->path; + bsd.link = args->to; + + return link(td, &bsd); +} + +#ifndef __alpha__ +int +linux_fdatasync(td, uap) + struct thread *td; + struct linux_fdatasync_args *uap; +{ + struct fsync_args bsd; + + bsd.fd = uap->fd; + return fsync(td, &bsd); +} +#endif /*!__alpha__*/ + +int +linux_pread(td, uap) + struct thread *td; + struct linux_pread_args *uap; +{ + struct pread_args bsd; + + bsd.fd = uap->fd; + bsd.buf = uap->buf; + bsd.nbyte = uap->nbyte; + bsd.offset = uap->offset; + return pread(td, &bsd); +} + +int +linux_pwrite(td, uap) + struct thread *td; + struct linux_pwrite_args *uap; +{ + struct pwrite_args bsd; + + bsd.fd = uap->fd; + bsd.buf = uap->buf; + bsd.nbyte = uap->nbyte; + bsd.offset = uap->offset; + return pwrite(td, &bsd); +} + +int +linux_mount(struct thread *td, struct linux_mount_args *args) +{ + struct ufs_args ufs; + char fstypename[MFSNAMELEN]; + char mntonname[MNAMELEN], mntfromname[MNAMELEN]; + int error; + int fsflags; + const char *fstype; + void *fsdata; + + error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, + NULL); + if (error) + return (error); + error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); + if (error) + return (error); + error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); + if (error) + return (error); + +#ifdef DEBUG + if (ldebug(mount)) + printf(ARGS(mount, "%s, %s, %s"), + fstypename, mntfromname, mntonname); +#endif + + if (strcmp(fstypename, "ext2") == 0) { + fstype = "ext2fs"; + fsdata = &ufs; + ufs.fspec = mntfromname; +#define DEFAULT_ROOTID -2 + ufs.export.ex_root = DEFAULT_ROOTID; + ufs.export.ex_flags = + args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; + } else if (strcmp(fstypename, "proc") == 0) { + fstype = "linprocfs"; + fsdata = NULL; + } else { + return (ENODEV); + } + + fsflags = 0; + + if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { + /* + * Linux SYNC flag is not included; the closest equivalent + * FreeBSD has is !ASYNC, which is our default. + */ + if (args->rwflag & LINUX_MS_RDONLY) + fsflags |= MNT_RDONLY; + if (args->rwflag & LINUX_MS_NOSUID) + fsflags |= MNT_NOSUID; + if (args->rwflag & LINUX_MS_NODEV) + fsflags |= MNT_NODEV; + if (args->rwflag & LINUX_MS_NOEXEC) + fsflags |= MNT_NOEXEC; + if (args->rwflag & LINUX_MS_REMOUNT) + fsflags |= MNT_UPDATE; + } + + return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); +} + +int +linux_oldumount(struct thread *td, struct linux_oldumount_args *args) +{ + struct linux_umount_args args2; + + args2.path = args->path; + args2.flags = 0; + return (linux_umount(td, &args2)); +} + +int +linux_umount(struct thread *td, struct linux_umount_args *args) +{ + struct unmount_args bsd; + + bsd.path = args->path; + bsd.flags = args->flags; /* XXX correct? */ + return (unmount(td, &bsd)); +} + +/* + * fcntl family of syscalls + */ + +struct l_flock { + l_short l_type; + l_short l_whence; + l_off_t l_start; + l_off_t l_len; + l_pid_t l_pid; +}; + +static void +linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) +{ + switch (linux_flock->l_type) { + case LINUX_F_RDLCK: + bsd_flock->l_type = F_RDLCK; + break; + case LINUX_F_WRLCK: + bsd_flock->l_type = F_WRLCK; + break; + case LINUX_F_UNLCK: + bsd_flock->l_type = F_UNLCK; + break; + default: + bsd_flock->l_type = -1; + break; + } + bsd_flock->l_whence = linux_flock->l_whence; + bsd_flock->l_start = (off_t)linux_flock->l_start; + bsd_flock->l_len = (off_t)linux_flock->l_len; + bsd_flock->l_pid = (pid_t)linux_flock->l_pid; +} + +static void +bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) +{ + switch (bsd_flock->l_type) { + case F_RDLCK: + linux_flock->l_type = LINUX_F_RDLCK; + break; + case F_WRLCK: + linux_flock->l_type = LINUX_F_WRLCK; + break; + case F_UNLCK: + linux_flock->l_type = LINUX_F_UNLCK; + break; + } + linux_flock->l_whence = bsd_flock->l_whence; + linux_flock->l_start = (l_off_t)bsd_flock->l_start; + linux_flock->l_len = (l_off_t)bsd_flock->l_len; + linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; +} + +#if defined(__i386__) +struct l_flock64 { + l_short l_type; + l_short l_whence; + l_loff_t l_start; + l_loff_t l_len; + l_pid_t l_pid; +}; + +static void +linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) +{ + switch (linux_flock->l_type) { + case LINUX_F_RDLCK: + bsd_flock->l_type = F_RDLCK; + break; + case LINUX_F_WRLCK: + bsd_flock->l_type = F_WRLCK; + break; + case LINUX_F_UNLCK: + bsd_flock->l_type = F_UNLCK; + break; + default: + bsd_flock->l_type = -1; + break; + } + bsd_flock->l_whence = linux_flock->l_whence; + bsd_flock->l_start = (off_t)linux_flock->l_start; + bsd_flock->l_len = (off_t)linux_flock->l_len; + bsd_flock->l_pid = (pid_t)linux_flock->l_pid; +} + +static void +bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) +{ + switch (bsd_flock->l_type) { + case F_RDLCK: + linux_flock->l_type = LINUX_F_RDLCK; + break; + case F_WRLCK: + linux_flock->l_type = LINUX_F_WRLCK; + break; + case F_UNLCK: + linux_flock->l_type = LINUX_F_UNLCK; + break; + } + linux_flock->l_whence = bsd_flock->l_whence; + linux_flock->l_start = (l_loff_t)bsd_flock->l_start; + linux_flock->l_len = (l_loff_t)bsd_flock->l_len; + linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; +} +#endif /* __i386__ */ + +#if defined(__alpha__) +#define linux_fcntl64_args linux_fcntl_args +#endif + +static int +fcntl_common(struct thread *td, struct linux_fcntl64_args *args) +{ + struct fcntl_args fcntl_args; + struct file *fp; + int error, result; + + fcntl_args.fd = args->fd; + + switch (args->cmd) { + case LINUX_F_DUPFD: + fcntl_args.cmd = F_DUPFD; + fcntl_args.arg = args->arg; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_GETFD: + fcntl_args.cmd = F_GETFD; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_SETFD: + fcntl_args.cmd = F_SETFD; + fcntl_args.arg = args->arg; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_GETFL: + fcntl_args.cmd = F_GETFL; + error = fcntl(td, &fcntl_args); + result = td->td_retval[0]; + td->td_retval[0] = 0; + if (result & O_RDONLY) + td->td_retval[0] |= LINUX_O_RDONLY; + if (result & O_WRONLY) + td->td_retval[0] |= LINUX_O_WRONLY; + if (result & O_RDWR) + td->td_retval[0] |= LINUX_O_RDWR; + if (result & O_NDELAY) + td->td_retval[0] |= LINUX_O_NONBLOCK; + if (result & O_APPEND) + td->td_retval[0] |= LINUX_O_APPEND; + if (result & O_FSYNC) + td->td_retval[0] |= LINUX_O_SYNC; + if (result & O_ASYNC) + td->td_retval[0] |= LINUX_FASYNC; + return (error); + + case LINUX_F_SETFL: + fcntl_args.arg = 0; + if (args->arg & LINUX_O_NDELAY) + fcntl_args.arg |= O_NONBLOCK; + if (args->arg & LINUX_O_APPEND) + fcntl_args.arg |= O_APPEND; + if (args->arg & LINUX_O_SYNC) + fcntl_args.arg |= O_FSYNC; + if (args->arg & LINUX_FASYNC) + fcntl_args.arg |= O_ASYNC; + fcntl_args.cmd = F_SETFL; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_GETOWN: + fcntl_args.cmd = F_GETOWN; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_SETOWN: + /* + * XXX some Linux applications depend on F_SETOWN having no + * significant effect for pipes (SIGIO is not delivered for + * pipes under Linux-2.2.35 at least). + */ + error = fget(td, args->fd, &fp); + if (error) + return (error); + if (fp->f_type == DTYPE_PIPE) { + fdrop(fp, td); + return (EINVAL); + } + fdrop(fp, td); + + fcntl_args.cmd = F_SETOWN; + fcntl_args.arg = args->arg; + return (fcntl(td, &fcntl_args)); + } + + return (EINVAL); +} + +int +linux_fcntl(struct thread *td, struct linux_fcntl_args *args) +{ + struct linux_fcntl64_args args64; + struct fcntl_args fcntl_args; + struct l_flock linux_flock; + struct flock *bsd_flock; + int error; + caddr_t sg; + + sg = stackgap_init(); + bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); + +#ifdef DEBUG + if (ldebug(fcntl)) + printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); +#endif + + switch (args->cmd) { + case LINUX_F_GETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_GETLK; + fcntl_args.arg = (long)bsd_flock; + error = fcntl(td, &fcntl_args); + if (error) + return (error); + bsd_to_linux_flock(bsd_flock, &linux_flock); + return (copyout(&linux_flock, (caddr_t)args->arg, + sizeof(linux_flock))); + + case LINUX_F_SETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLK; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_SETLKW: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLKW; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(td, &fcntl_args)); + } + + args64.fd = args->fd; + args64.cmd = args->cmd; + args64.arg = args->arg; + return (fcntl_common(td, &args64)); +} + +#if defined(__i386__) +int +linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) +{ + struct fcntl_args fcntl_args; + struct l_flock64 linux_flock; + struct flock *bsd_flock; + int error; + caddr_t sg; + + sg = stackgap_init(); + bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); + +#ifdef DEBUG + if (ldebug(fcntl64)) + printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); +#endif + + switch (args->cmd) { + case LINUX_F_GETLK: + case LINUX_F_GETLK64: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_GETLK; + fcntl_args.arg = (long)bsd_flock; + error = fcntl(td, &fcntl_args); + if (error) + return (error); + bsd_to_linux_flock64(bsd_flock, &linux_flock); + return (copyout(&linux_flock, (caddr_t)args->arg, + sizeof(linux_flock))); + + case LINUX_F_SETLK: + case LINUX_F_SETLK64: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLK; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(td, &fcntl_args)); + + case LINUX_F_SETLKW: + case LINUX_F_SETLKW64: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLKW; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(td, &fcntl_args)); + } + + return (fcntl_common(td, args)); +} +#endif /* __i386__ */ + +int +linux_chown(struct thread *td, struct linux_chown_args *args) +{ + struct chown_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(chown)) + printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid, + args->gid); +#endif + + bsd.path = args->path; + bsd.uid = args->uid; + bsd.gid = args->gid; + return (chown(td, &bsd)); +} + +int +linux_lchown(struct thread *td, struct linux_lchown_args *args) +{ + struct lchown_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(lchown)) + printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid, + args->gid); +#endif + + bsd.path = args->path; + bsd.uid = args->uid; + bsd.gid = args->gid; + return (lchown(td, &bsd)); +} diff --git a/sys/compat/linux/linux_getcwd.c b/sys/compat/linux/linux_getcwd.c new file mode 100644 index 0000000..2773562 --- /dev/null +++ b/sys/compat/linux/linux_getcwd.c @@ -0,0 +1,473 @@ +/* $FreeBSD$ */ +/* $OpenBSD: linux_getcwd.c,v 1.2 2001/05/16 12:50:21 ho Exp $ */ +/* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bill Sommerfeld. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "opt_compat.h" +#include "opt_mac.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/namei.h> +#include <sys/filedesc.h> +#include <sys/kernel.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/mac.h> +#include <sys/malloc.h> +#include <sys/dirent.h> +#include <ufs/ufs/dir.h> /* XXX only for DIRBLKSIZ */ + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +static int +linux_getcwd_scandir(struct vnode **, struct vnode **, + char **, char *, struct thread *); +static int +linux_getcwd_common(struct vnode *, struct vnode *, + char **, char *, int, int, struct thread *); + +#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) + +/* + * Vnode variable naming conventions in this file: + * + * rvp: the current root we're aiming towards. + * lvp, *lvpp: the "lower" vnode + * uvp, *uvpp: the "upper" vnode. + * + * Since all the vnodes we're dealing with are directories, and the + * lookups are going *up* in the filesystem rather than *down*, the + * usual "pvp" (parent) or "dvp" (directory) naming conventions are + * too confusing. + */ + +/* + * XXX Will infinite loop in certain cases if a directory read reliably + * returns EINVAL on last block. + * XXX is EINVAL the right thing to return if a directory is malformed? + */ + +/* + * XXX Untested vs. mount -o union; probably does the wrong thing. + */ + +/* + * Find parent vnode of *lvpp, return in *uvpp + * + * If we care about the name, scan it looking for name of directory + * entry pointing at lvp. + * + * Place the name in the buffer which starts at bufp, immediately + * before *bpp, and move bpp backwards to point at the start of it. + * + * On entry, *lvpp is a locked vnode reference; on exit, it is vput and NULL'ed + * On exit, *uvpp is either NULL or is a locked vnode reference. + */ +static int +linux_getcwd_scandir(lvpp, uvpp, bpp, bufp, td) + struct vnode **lvpp; + struct vnode **uvpp; + char **bpp; + char *bufp; + struct thread *td; +{ + int error = 0; + int eofflag; + off_t off; + int tries; + struct uio uio; + struct iovec iov; + char *dirbuf = NULL; + int dirbuflen; + ino_t fileno; + struct vattr va; + struct vnode *uvp = NULL; + struct vnode *lvp = *lvpp; + struct componentname cn; + int len, reclen; + tries = 0; + + /* + * If we want the filename, get some info we need while the + * current directory is still locked. + */ + if (bufp != NULL) { + error = VOP_GETATTR(lvp, &va, td->td_ucred, td); + if (error) { + vput(lvp); + *lvpp = NULL; + *uvpp = NULL; + return error; + } + } + + /* + * Ok, we have to do it the hard way.. + * Next, get parent vnode using lookup of .. + */ + cn.cn_nameiop = LOOKUP; + cn.cn_flags = ISLASTCN | ISDOTDOT | RDONLY; + cn.cn_thread = td; + cn.cn_cred = td->td_ucred; + cn.cn_pnbuf = NULL; + cn.cn_nameptr = ".."; + cn.cn_namelen = 2; + cn.cn_consume = 0; + + /* + * At this point, lvp is locked and will be unlocked by the lookup. + * On successful return, *uvpp will be locked + */ + error = VOP_LOOKUP(lvp, uvpp, &cn); + if (error) { + vput(lvp); + *lvpp = NULL; + *uvpp = NULL; + return error; + } + uvp = *uvpp; + + /* If we don't care about the pathname, we're done */ + if (bufp == NULL) { + vrele(lvp); + *lvpp = NULL; + return 0; + } + + fileno = va.va_fileid; + + dirbuflen = DIRBLKSIZ; + if (dirbuflen < va.va_blocksize) + dirbuflen = va.va_blocksize; + dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK); + +#if 0 +unionread: +#endif + off = 0; + do { + /* call VOP_READDIR of parent */ + iov.iov_base = dirbuf; + iov.iov_len = dirbuflen; + + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = off; + uio.uio_resid = dirbuflen; + uio.uio_segflg = UIO_SYSSPACE; + uio.uio_rw = UIO_READ; + uio.uio_td = td; + + eofflag = 0; + +#ifdef MAC + error = mac_check_vnode_readdir(td->td_ucred, uvp); + if (error == 0) +#endif /* MAC */ + error = VOP_READDIR(uvp, &uio, td->td_ucred, &eofflag, + 0, 0); + + off = uio.uio_offset; + + /* + * Try again if NFS tosses its cookies. + * XXX this can still loop forever if the directory is busted + * such that the second or subsequent page of it always + * returns EINVAL + */ + if ((error == EINVAL) && (tries < 3)) { + off = 0; + tries++; + continue; /* once more, with feeling */ + } + + if (!error) { + char *cpos; + struct dirent *dp; + + cpos = dirbuf; + tries = 0; + + /* scan directory page looking for matching vnode */ + for (len = (dirbuflen - uio.uio_resid); len > 0; len -= reclen) { + dp = (struct dirent *) cpos; + reclen = dp->d_reclen; + + /* check for malformed directory.. */ + if (reclen < DIRENT_MINSIZE) { + error = EINVAL; + goto out; + } + /* + * XXX should perhaps do VOP_LOOKUP to + * check that we got back to the right place, + * but getting the locking games for that + * right would be heinous. + */ + if ((dp->d_type != DT_WHT) && + (dp->d_fileno == fileno)) { + char *bp = *bpp; + bp -= dp->d_namlen; + + if (bp <= bufp) { + error = ERANGE; + goto out; + } + bcopy(dp->d_name, bp, dp->d_namlen); + error = 0; + *bpp = bp; + goto out; + } + cpos += reclen; + } + } + } while (!eofflag); + error = ENOENT; + +out: + vrele(lvp); + *lvpp = NULL; + free(dirbuf, M_TEMP); + return error; +} + + +/* + * common routine shared by sys___getcwd() and linux_vn_isunder() + */ + +#define GETCWD_CHECK_ACCESS 0x0001 + +static int +linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td) + struct vnode *lvp; + struct vnode *rvp; + char **bpp; + char *bufp; + int limit; + int flags; + struct thread *td; +{ + struct filedesc *fdp = td->td_proc->p_fd; + struct vnode *uvp = NULL; + char *bp = NULL; + int error; + int perms = VEXEC; + + if (rvp == NULL) { + rvp = fdp->fd_rdir; + if (rvp == NULL) + rvp = rootvnode; + } + + VREF(rvp); + VREF(lvp); + + /* + * Error handling invariant: + * Before a `goto out': + * lvp is either NULL, or locked and held. + * uvp is either NULL, or locked and held. + */ + + error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error) { + vrele(lvp); + lvp = NULL; + goto out; + } + if (bufp) + bp = *bpp; + /* + * this loop will terminate when one of the following happens: + * - we hit the root + * - getdirentries or lookup fails + * - we run out of space in the buffer. + */ + if (lvp == rvp) { + if (bp) + *(--bp) = '/'; + goto out; + } + do { + if (lvp->v_type != VDIR) { + error = ENOTDIR; + goto out; + } + + /* + * access check here is optional, depending on + * whether or not caller cares. + */ + if (flags & GETCWD_CHECK_ACCESS) { + error = VOP_ACCESS(lvp, perms, td->td_ucred, td); + if (error) + goto out; + perms = VEXEC|VREAD; + } + + /* + * step up if we're a covered vnode.. + */ + while (lvp->v_vflag & VV_ROOT) { + struct vnode *tvp; + + if (lvp == rvp) + goto out; + + tvp = lvp; + lvp = lvp->v_mount->mnt_vnodecovered; + vput(tvp); + /* + * hodie natus est radici frater + */ + if (lvp == NULL) { + error = ENOENT; + goto out; + } + VREF(lvp); + error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td); + if (error != 0) { + vrele(lvp); + lvp = NULL; + goto out; + } + } + error = linux_getcwd_scandir(&lvp, &uvp, &bp, bufp, td); + if (error) + goto out; +#if DIAGNOSTIC + if (lvp != NULL) + panic("getcwd: oops, forgot to null lvp"); + if (bufp && (bp <= bufp)) { + panic("getcwd: oops, went back too far"); + } +#endif + if (bp) + *(--bp) = '/'; + lvp = uvp; + uvp = NULL; + limit--; + } while ((lvp != rvp) && (limit > 0)); + +out: + if (bpp) + *bpp = bp; + if (uvp) + vput(uvp); + if (lvp) + vput(lvp); + vrele(rvp); + return error; +} + + +/* + * Find pathname of process's current directory. + * + * Use vfs vnode-to-name reverse cache; if that fails, fall back + * to reading directory contents. + */ + +int +linux_getcwd(struct thread *td, struct linux_getcwd_args *args) +{ + struct __getcwd_args bsd; + caddr_t sg, bp, bend, path; + int error, len, lenused; + +#ifdef DEBUG + printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)td->td_proc->p_pid, + args->buf, (long)args->bufsize); +#endif + + sg = stackgap_init(); + bsd.buf = stackgap_alloc(&sg, SPARE_USRSPACE); + bsd.buflen = SPARE_USRSPACE; + error = __getcwd(td, &bsd); + if (!error) { + lenused = strlen(bsd.buf) + 1; + if (lenused <= args->bufsize) { + td->td_retval[0] = lenused; + error = copyout(bsd.buf, args->buf, lenused); + } + else + error = ERANGE; + } else { + len = args->bufsize; + + if (len > MAXPATHLEN*4) + len = MAXPATHLEN*4; + else if (len < 2) + return ERANGE; + + path = (char *)malloc(len, M_TEMP, M_WAITOK); + + bp = &path[len]; + bend = bp; + *(--bp) = '\0'; + + /* + * 5th argument here is "max number of vnodes to traverse". + * Since each entry takes up at least 2 bytes in the output buffer, + * limit it to N/2 vnodes for an N byte buffer. + */ + + error = linux_getcwd_common (td->td_proc->p_fd->fd_cdir, NULL, + &bp, path, len/2, GETCWD_CHECK_ACCESS, td); + + if (error) + goto out; + lenused = bend - bp; + td->td_retval[0] = lenused; + /* put the result into user buffer */ + error = copyout(bp, args->buf, lenused); + +out: + free(path, M_TEMP); + } + return (error); +} + diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c new file mode 100644 index 0000000..77e2942 --- /dev/null +++ b/sys/compat/linux/linux_ioctl.c @@ -0,0 +1,2379 @@ +/* + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/cdio.h> +#include <sys/dvdio.h> +#include <sys/consio.h> +#include <sys/ctype.h> +#include <sys/disklabel.h> +#include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/filio.h> +#include <sys/kbio.h> +#include <sys/linker_set.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/socket.h> +#include <sys/sockio.h> +#include <sys/soundcard.h> +#include <sys/tty.h> +#include <sys/uio.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> + +#include <compat/linux/linux_ioctl.h> +#include <compat/linux/linux_mib.h> +#include <compat/linux/linux_util.h> + +static linux_ioctl_function_t linux_ioctl_cdrom; +static linux_ioctl_function_t linux_ioctl_console; +static linux_ioctl_function_t linux_ioctl_disk; +static linux_ioctl_function_t linux_ioctl_socket; +static linux_ioctl_function_t linux_ioctl_sound; +static linux_ioctl_function_t linux_ioctl_termio; +static linux_ioctl_function_t linux_ioctl_private; +static linux_ioctl_function_t linux_ioctl_special; + +static struct linux_ioctl_handler cdrom_handler = +{ linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; +static struct linux_ioctl_handler console_handler = +{ linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX }; +static struct linux_ioctl_handler disk_handler = +{ linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX }; +static struct linux_ioctl_handler socket_handler = +{ linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX }; +static struct linux_ioctl_handler sound_handler = +{ linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX }; +static struct linux_ioctl_handler termio_handler = +{ linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX }; +static struct linux_ioctl_handler private_handler = +{ linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX }; + +DATA_SET(linux_ioctl_handler_set, cdrom_handler); +DATA_SET(linux_ioctl_handler_set, console_handler); +DATA_SET(linux_ioctl_handler_set, disk_handler); +DATA_SET(linux_ioctl_handler_set, socket_handler); +DATA_SET(linux_ioctl_handler_set, sound_handler); +DATA_SET(linux_ioctl_handler_set, termio_handler); +DATA_SET(linux_ioctl_handler_set, private_handler); + +struct handler_element +{ + TAILQ_ENTRY(handler_element) list; + int (*func)(struct thread *, struct linux_ioctl_args *); + int low, high, span; +}; + +static TAILQ_HEAD(, handler_element) handlers = + TAILQ_HEAD_INITIALIZER(handlers); + +static int +linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + int error; + struct disklabel dl; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + switch (args->cmd & 0xffff) { + case LINUX_BLKGETSIZE: + error = fo_ioctl(fp, DIOCGDINFO, (caddr_t)&dl, td); + fdrop(fp, td); + if (error) + return (error); + return (copyout(&(dl.d_secperunit), (caddr_t)args->arg, + sizeof(dl.d_secperunit))); + } + fdrop(fp, td); + return (ENOIOCTL); +} + +/* + * termio related ioctls + */ + +struct linux_termio { + unsigned short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + unsigned char c_line; + unsigned char c_cc[LINUX_NCC]; +}; + +struct linux_termios { + unsigned int c_iflag; + unsigned int c_oflag; + unsigned int c_cflag; + unsigned int c_lflag; +#ifdef __alpha__ + unsigned char c_cc[LINUX_NCCS]; + unsigned char c_line; + unsigned int c_ispeed; + unsigned int c_ospeed; +#else + unsigned char c_line; + unsigned char c_cc[LINUX_NCCS]; +#endif +}; + +struct linux_winsize { + unsigned short ws_row, ws_col; + unsigned short ws_xpixel, ws_ypixel; +}; + +static struct speedtab sptab[] = { + { B0, LINUX_B0 }, { B50, LINUX_B50 }, + { B75, LINUX_B75 }, { B110, LINUX_B110 }, + { B134, LINUX_B134 }, { B150, LINUX_B150 }, + { B200, LINUX_B200 }, { B300, LINUX_B300 }, + { B600, LINUX_B600 }, { B1200, LINUX_B1200 }, + { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 }, + { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 }, + { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 }, + { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 }, + {-1, -1 } +}; + +struct linux_serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; + unsigned short closing_wait; + unsigned short closing_wait2; + int reserved[4]; +}; + +static int +linux_to_bsd_speed(int code, struct speedtab *table) +{ + for ( ; table->sp_code != -1; table++) + if (table->sp_code == code) + return (table->sp_speed); + return -1; +} + +static int +bsd_to_linux_speed(int speed, struct speedtab *table) +{ + for ( ; table->sp_speed != -1; table++) + if (table->sp_speed == speed) + return (table->sp_code); + return -1; +} + +static void +bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios) +{ + int i; + +#ifdef DEBUG + if (ldebug(ioctl)) { + printf("LINUX: BSD termios structure (input):\n"); + printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", + bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, + bios->c_ispeed, bios->c_ospeed); + printf("c_cc "); + for (i=0; i<NCCS; i++) + printf("%02x ", bios->c_cc[i]); + printf("\n"); + } +#endif + + lios->c_iflag = 0; + if (bios->c_iflag & IGNBRK) + lios->c_iflag |= LINUX_IGNBRK; + if (bios->c_iflag & BRKINT) + lios->c_iflag |= LINUX_BRKINT; + if (bios->c_iflag & IGNPAR) + lios->c_iflag |= LINUX_IGNPAR; + if (bios->c_iflag & PARMRK) + lios->c_iflag |= LINUX_PARMRK; + if (bios->c_iflag & INPCK) + lios->c_iflag |= LINUX_INPCK; + if (bios->c_iflag & ISTRIP) + lios->c_iflag |= LINUX_ISTRIP; + if (bios->c_iflag & INLCR) + lios->c_iflag |= LINUX_INLCR; + if (bios->c_iflag & IGNCR) + lios->c_iflag |= LINUX_IGNCR; + if (bios->c_iflag & ICRNL) + lios->c_iflag |= LINUX_ICRNL; + if (bios->c_iflag & IXON) + lios->c_iflag |= LINUX_IXON; + if (bios->c_iflag & IXANY) + lios->c_iflag |= LINUX_IXANY; + if (bios->c_iflag & IXOFF) + lios->c_iflag |= LINUX_IXOFF; + if (bios->c_iflag & IMAXBEL) + lios->c_iflag |= LINUX_IMAXBEL; + + lios->c_oflag = 0; + if (bios->c_oflag & OPOST) + lios->c_oflag |= LINUX_OPOST; + if (bios->c_oflag & ONLCR) + lios->c_oflag |= LINUX_ONLCR; + if (bios->c_oflag & OXTABS) + lios->c_oflag |= LINUX_XTABS; + + lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab); + lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4; + if (bios->c_cflag & CSTOPB) + lios->c_cflag |= LINUX_CSTOPB; + if (bios->c_cflag & CREAD) + lios->c_cflag |= LINUX_CREAD; + if (bios->c_cflag & PARENB) + lios->c_cflag |= LINUX_PARENB; + if (bios->c_cflag & PARODD) + lios->c_cflag |= LINUX_PARODD; + if (bios->c_cflag & HUPCL) + lios->c_cflag |= LINUX_HUPCL; + if (bios->c_cflag & CLOCAL) + lios->c_cflag |= LINUX_CLOCAL; + if (bios->c_cflag & CRTSCTS) + lios->c_cflag |= LINUX_CRTSCTS; + + lios->c_lflag = 0; + if (bios->c_lflag & ISIG) + lios->c_lflag |= LINUX_ISIG; + if (bios->c_lflag & ICANON) + lios->c_lflag |= LINUX_ICANON; + if (bios->c_lflag & ECHO) + lios->c_lflag |= LINUX_ECHO; + if (bios->c_lflag & ECHOE) + lios->c_lflag |= LINUX_ECHOE; + if (bios->c_lflag & ECHOK) + lios->c_lflag |= LINUX_ECHOK; + if (bios->c_lflag & ECHONL) + lios->c_lflag |= LINUX_ECHONL; + if (bios->c_lflag & NOFLSH) + lios->c_lflag |= LINUX_NOFLSH; + if (bios->c_lflag & TOSTOP) + lios->c_lflag |= LINUX_TOSTOP; + if (bios->c_lflag & ECHOCTL) + lios->c_lflag |= LINUX_ECHOCTL; + if (bios->c_lflag & ECHOPRT) + lios->c_lflag |= LINUX_ECHOPRT; + if (bios->c_lflag & ECHOKE) + lios->c_lflag |= LINUX_ECHOKE; + if (bios->c_lflag & FLUSHO) + lios->c_lflag |= LINUX_FLUSHO; + if (bios->c_lflag & PENDIN) + lios->c_lflag |= LINUX_PENDIN; + if (bios->c_lflag & IEXTEN) + lios->c_lflag |= LINUX_IEXTEN; + + for (i=0; i<LINUX_NCCS; i++) + lios->c_cc[i] = LINUX_POSIX_VDISABLE; + lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR]; + lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT]; + lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE]; + lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL]; + lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF]; + lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL]; + lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN]; + lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME]; + lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2]; + lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP]; + lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART]; + lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP]; + lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT]; + lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD]; + lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE]; + lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT]; + + for (i=0; i<LINUX_NCCS; i++) { + if (lios->c_cc[i] == _POSIX_VDISABLE) + lios->c_cc[i] = LINUX_POSIX_VDISABLE; + } + lios->c_line = 0; + +#ifdef DEBUG + if (ldebug(ioctl)) { + printf("LINUX: LINUX termios structure (output):\n"); + printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", + lios->c_iflag, lios->c_oflag, lios->c_cflag, + lios->c_lflag, (int)lios->c_line); + printf("c_cc "); + for (i=0; i<LINUX_NCCS; i++) + printf("%02x ", lios->c_cc[i]); + printf("\n"); + } +#endif +} + +static void +linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios) +{ + int i; + +#ifdef DEBUG + if (ldebug(ioctl)) { + printf("LINUX: LINUX termios structure (input):\n"); + printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", + lios->c_iflag, lios->c_oflag, lios->c_cflag, + lios->c_lflag, (int)lios->c_line); + printf("c_cc "); + for (i=0; i<LINUX_NCCS; i++) + printf("%02x ", lios->c_cc[i]); + printf("\n"); + } +#endif + + bios->c_iflag = 0; + if (lios->c_iflag & LINUX_IGNBRK) + bios->c_iflag |= IGNBRK; + if (lios->c_iflag & LINUX_BRKINT) + bios->c_iflag |= BRKINT; + if (lios->c_iflag & LINUX_IGNPAR) + bios->c_iflag |= IGNPAR; + if (lios->c_iflag & LINUX_PARMRK) + bios->c_iflag |= PARMRK; + if (lios->c_iflag & LINUX_INPCK) + bios->c_iflag |= INPCK; + if (lios->c_iflag & LINUX_ISTRIP) + bios->c_iflag |= ISTRIP; + if (lios->c_iflag & LINUX_INLCR) + bios->c_iflag |= INLCR; + if (lios->c_iflag & LINUX_IGNCR) + bios->c_iflag |= IGNCR; + if (lios->c_iflag & LINUX_ICRNL) + bios->c_iflag |= ICRNL; + if (lios->c_iflag & LINUX_IXON) + bios->c_iflag |= IXON; + if (lios->c_iflag & LINUX_IXANY) + bios->c_iflag |= IXANY; + if (lios->c_iflag & LINUX_IXOFF) + bios->c_iflag |= IXOFF; + if (lios->c_iflag & LINUX_IMAXBEL) + bios->c_iflag |= IMAXBEL; + + bios->c_oflag = 0; + if (lios->c_oflag & LINUX_OPOST) + bios->c_oflag |= OPOST; + if (lios->c_oflag & LINUX_ONLCR) + bios->c_oflag |= ONLCR; + if (lios->c_oflag & LINUX_XTABS) + bios->c_oflag |= OXTABS; + + bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4; + if (lios->c_cflag & LINUX_CSTOPB) + bios->c_cflag |= CSTOPB; + if (lios->c_cflag & LINUX_CREAD) + bios->c_cflag |= CREAD; + if (lios->c_cflag & LINUX_PARENB) + bios->c_cflag |= PARENB; + if (lios->c_cflag & LINUX_PARODD) + bios->c_cflag |= PARODD; + if (lios->c_cflag & LINUX_HUPCL) + bios->c_cflag |= HUPCL; + if (lios->c_cflag & LINUX_CLOCAL) + bios->c_cflag |= CLOCAL; + if (lios->c_cflag & LINUX_CRTSCTS) + bios->c_cflag |= CRTSCTS; + + bios->c_lflag = 0; + if (lios->c_lflag & LINUX_ISIG) + bios->c_lflag |= ISIG; + if (lios->c_lflag & LINUX_ICANON) + bios->c_lflag |= ICANON; + if (lios->c_lflag & LINUX_ECHO) + bios->c_lflag |= ECHO; + if (lios->c_lflag & LINUX_ECHOE) + bios->c_lflag |= ECHOE; + if (lios->c_lflag & LINUX_ECHOK) + bios->c_lflag |= ECHOK; + if (lios->c_lflag & LINUX_ECHONL) + bios->c_lflag |= ECHONL; + if (lios->c_lflag & LINUX_NOFLSH) + bios->c_lflag |= NOFLSH; + if (lios->c_lflag & LINUX_TOSTOP) + bios->c_lflag |= TOSTOP; + if (lios->c_lflag & LINUX_ECHOCTL) + bios->c_lflag |= ECHOCTL; + if (lios->c_lflag & LINUX_ECHOPRT) + bios->c_lflag |= ECHOPRT; + if (lios->c_lflag & LINUX_ECHOKE) + bios->c_lflag |= ECHOKE; + if (lios->c_lflag & LINUX_FLUSHO) + bios->c_lflag |= FLUSHO; + if (lios->c_lflag & LINUX_PENDIN) + bios->c_lflag |= PENDIN; + if (lios->c_lflag & LINUX_IEXTEN) + bios->c_lflag |= IEXTEN; + + for (i=0; i<NCCS; i++) + bios->c_cc[i] = _POSIX_VDISABLE; + bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR]; + bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT]; + bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE]; + bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL]; + bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF]; + bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL]; + bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN]; + bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME]; + bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2]; + bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP]; + bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART]; + bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP]; + bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT]; + bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD]; + bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE]; + bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT]; + + for (i=0; i<NCCS; i++) { + if (bios->c_cc[i] == LINUX_POSIX_VDISABLE) + bios->c_cc[i] = _POSIX_VDISABLE; + } + + bios->c_ispeed = bios->c_ospeed = + linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab); + +#ifdef DEBUG + if (ldebug(ioctl)) { + printf("LINUX: BSD termios structure (output):\n"); + printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", + bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, + bios->c_ispeed, bios->c_ospeed); + printf("c_cc "); + for (i=0; i<NCCS; i++) + printf("%02x ", bios->c_cc[i]); + printf("\n"); + } +#endif +} + +static void +bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio) +{ + struct linux_termios lios; + + bsd_to_linux_termios(bios, &lios); + lio->c_iflag = lios.c_iflag; + lio->c_oflag = lios.c_oflag; + lio->c_cflag = lios.c_cflag; + lio->c_lflag = lios.c_lflag; + lio->c_line = lios.c_line; +#ifdef __alpha__ + lio->c_cc[LINUX__VINTR] = lios.c_cc[LINUX_VINTR]; + lio->c_cc[LINUX__VQUIT] = lios.c_cc[LINUX_VQUIT]; + lio->c_cc[LINUX__VERASE] = lios.c_cc[LINUX_VERASE]; + lio->c_cc[LINUX__VKILL] = lios.c_cc[LINUX_VKILL]; + lio->c_cc[LINUX__VEOF] = + lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN]; + lio->c_cc[LINUX__VEOL] = + lios.c_cc[(lios.c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME]; + lio->c_cc[LINUX__VEOL2] = lios.c_cc[LINUX_VEOL2]; + lio->c_cc[LINUX__VSWTC] = lios.c_cc[LINUX_VSWTC]; +#else + memcpy(lio->c_cc, lios.c_cc, LINUX_NCC); +#endif +} + +static void +linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios) +{ + struct linux_termios lios; + int i; + + lios.c_iflag = lio->c_iflag; + lios.c_oflag = lio->c_oflag; + lios.c_cflag = lio->c_cflag; + lios.c_lflag = lio->c_lflag; +#ifdef __alpha__ + for (i=0; i<LINUX_NCCS; i++) + lios.c_cc[i] = LINUX_POSIX_VDISABLE; + lios.c_cc[LINUX_VINTR] = lio->c_cc[LINUX__VINTR]; + lios.c_cc[LINUX_VQUIT] = lio->c_cc[LINUX__VQUIT]; + lios.c_cc[LINUX_VERASE] = lio->c_cc[LINUX__VERASE]; + lios.c_cc[LINUX_VKILL] = lio->c_cc[LINUX__VKILL]; + lios.c_cc[LINUX_VEOL2] = lio->c_cc[LINUX__VEOL2]; + lios.c_cc[LINUX_VSWTC] = lio->c_cc[LINUX__VSWTC]; + lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOF : LINUX_VMIN] = + lio->c_cc[LINUX__VEOF]; + lios.c_cc[(lio->c_lflag & ICANON) ? LINUX_VEOL : LINUX_VTIME] = + lio->c_cc[LINUX__VEOL]; +#else + for (i=LINUX_NCC; i<LINUX_NCCS; i++) + lios.c_cc[i] = LINUX_POSIX_VDISABLE; + memcpy(lios.c_cc, lio->c_cc, LINUX_NCC); +#endif + linux_to_bsd_termios(&lios, bios); +} + +static int +linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) +{ + struct termios bios; + struct linux_termios lios; + struct linux_termio lio; + struct file *fp; + int error; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + + switch (args->cmd & 0xffff) { + + case LINUX_TCGETS: + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); + if (error) + break; + bsd_to_linux_termios(&bios, &lios); + error = copyout(&lios, (caddr_t)args->arg, sizeof(lios)); + break; + + case LINUX_TCSETS: + error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); + if (error) + break; + linux_to_bsd_termios(&lios, &bios); + error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); + break; + + case LINUX_TCSETSW: + error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); + if (error) + break; + linux_to_bsd_termios(&lios, &bios); + error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); + break; + + case LINUX_TCSETSF: + error = copyin((caddr_t)args->arg, &lios, sizeof(lios)); + if (error) + break; + linux_to_bsd_termios(&lios, &bios); + error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); + break; + + case LINUX_TCGETA: + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); + if (error) + break; + bsd_to_linux_termio(&bios, &lio); + error = (copyout(&lio, (caddr_t)args->arg, sizeof(lio))); + break; + + case LINUX_TCSETA: + error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); + if (error) + break; + linux_to_bsd_termio(&lio, &bios); + error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td)); + break; + + case LINUX_TCSETAW: + error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); + if (error) + break; + linux_to_bsd_termio(&lio, &bios); + error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td)); + break; + + case LINUX_TCSETAF: + error = copyin((caddr_t)args->arg, &lio, sizeof(lio)); + if (error) + break; + linux_to_bsd_termio(&lio, &bios); + error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td)); + break; + + /* LINUX_TCSBRK */ + + case LINUX_TCXONC: { + switch (args->arg) { + case LINUX_TCOOFF: + args->cmd = TIOCSTOP; + break; + case LINUX_TCOON: + args->cmd = TIOCSTART; + break; + case LINUX_TCIOFF: + case LINUX_TCION: { + int c; + struct write_args wr; + error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td); + if (error) + break; + fdrop(fp, td); + c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART; + c = bios.c_cc[c]; + if (c != _POSIX_VDISABLE) { + wr.fd = args->fd; + wr.buf = &c; + wr.nbyte = sizeof(c); + return (write(td, &wr)); + } else + return (0); + } + default: + fdrop(fp, td); + return (EINVAL); + } + args->arg = 0; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + } + + case LINUX_TCFLSH: { + args->cmd = TIOCFLUSH; + switch (args->arg) { + case LINUX_TCIFLUSH: + args->arg = FREAD; + break; + case LINUX_TCOFLUSH: + args->arg = FWRITE; + break; + case LINUX_TCIOFLUSH: + args->arg = FREAD | FWRITE; + break; + default: + fdrop(fp, td); + return (EINVAL); + } + error = (ioctl(td, (struct ioctl_args *)args)); + break; + } + + case LINUX_TIOCEXCL: + args->cmd = TIOCEXCL; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCNXCL: + args->cmd = TIOCNXCL; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_TIOCSCTTY */ + + case LINUX_TIOCGPGRP: + args->cmd = TIOCGPGRP; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCSPGRP: + args->cmd = TIOCSPGRP; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_TIOCOUTQ */ + /* LINUX_TIOCSTI */ + + case LINUX_TIOCGWINSZ: + args->cmd = TIOCGWINSZ; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCSWINSZ: + args->cmd = TIOCSWINSZ; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCMGET: + args->cmd = TIOCMGET; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCMBIS: + args->cmd = TIOCMBIS; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCMBIC: + args->cmd = TIOCMBIC; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCMSET: + args->cmd = TIOCMSET; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* TIOCGSOFTCAR */ + /* TIOCSSOFTCAR */ + + case LINUX_FIONREAD: /* LINUX_TIOCINQ */ + args->cmd = FIONREAD; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_TIOCLINUX */ + + case LINUX_TIOCCONS: + args->cmd = TIOCCONS; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCGSERIAL: { + struct linux_serial_struct lss; + lss.type = LINUX_PORT_16550A; + lss.flags = 0; + lss.close_delay = 0; + error = copyout(&lss, (caddr_t)args->arg, sizeof(lss)); + break; + } + + case LINUX_TIOCSSERIAL: { + struct linux_serial_struct lss; + error = copyin((caddr_t)args->arg, &lss, sizeof(lss)); + if (error) + break; + /* XXX - It really helps to have an implementation that + * does nothing. NOT! + */ + error = 0; + break; + } + + /* LINUX_TIOCPKT */ + + case LINUX_FIONBIO: + args->cmd = FIONBIO; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCNOTTY: + args->cmd = TIOCNOTTY; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_TIOCSETD: { + int line; + switch (args->arg) { + case LINUX_N_TTY: + line = TTYDISC; + break; + case LINUX_N_SLIP: + line = SLIPDISC; + break; + case LINUX_N_PPP: + line = PPPDISC; + break; + default: + fdrop(fp, td); + return (EINVAL); + } + error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td)); + break; + } + + case LINUX_TIOCGETD: { + int linux_line; + int bsd_line = TTYDISC; + error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, td); + if (error) + return (error); + switch (bsd_line) { + case TTYDISC: + linux_line = LINUX_N_TTY; + break; + case SLIPDISC: + linux_line = LINUX_N_SLIP; + break; + case PPPDISC: + linux_line = LINUX_N_PPP; + break; + default: + fdrop(fp, td); + return (EINVAL); + } + error = (copyout(&linux_line, (caddr_t)args->arg, sizeof(int))); + break; + } + + /* LINUX_TCSBRKP */ + /* LINUX_TIOCTTYGSTRUCT */ + + case LINUX_FIONCLEX: + args->cmd = FIONCLEX; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_FIOCLEX: + args->cmd = FIOCLEX; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_FIOASYNC: + args->cmd = FIOASYNC; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_TIOCSERCONFIG */ + /* LINUX_TIOCSERGWILD */ + /* LINUX_TIOCSERSWILD */ + /* LINUX_TIOCGLCKTRMIOS */ + /* LINUX_TIOCSLCKTRMIOS */ + + default: + error = ENOIOCTL; + break; + } + + fdrop(fp, td); + return (error); +} + +/* + * CDROM related ioctls + */ + +struct linux_cdrom_msf +{ + u_char cdmsf_min0; + u_char cdmsf_sec0; + u_char cdmsf_frame0; + u_char cdmsf_min1; + u_char cdmsf_sec1; + u_char cdmsf_frame1; +}; + +struct linux_cdrom_tochdr +{ + u_char cdth_trk0; + u_char cdth_trk1; +}; + +union linux_cdrom_addr +{ + struct { + u_char minute; + u_char second; + u_char frame; + } msf; + int lba; +}; + +struct linux_cdrom_tocentry +{ + u_char cdte_track; + u_char cdte_adr:4; + u_char cdte_ctrl:4; + u_char cdte_format; + union linux_cdrom_addr cdte_addr; + u_char cdte_datamode; +}; + +struct linux_cdrom_subchnl +{ + u_char cdsc_format; + u_char cdsc_audiostatus; + u_char cdsc_adr:4; + u_char cdsc_ctrl:4; + u_char cdsc_trk; + u_char cdsc_ind; + union linux_cdrom_addr cdsc_absaddr; + union linux_cdrom_addr cdsc_reladdr; +}; + +struct l_dvd_layer { + u_char book_version:4; + u_char book_type:4; + u_char min_rate:4; + u_char disc_size:4; + u_char layer_type:4; + u_char track_path:1; + u_char nlayers:2; + u_char track_density:4; + u_char linear_density:4; + u_char bca:1; + u_int32_t start_sector; + u_int32_t end_sector; + u_int32_t end_sector_l0; +}; + +struct l_dvd_physical { + u_char type; + u_char layer_num; + struct l_dvd_layer layer[4]; +}; + +struct l_dvd_copyright { + u_char type; + u_char layer_num; + u_char cpst; + u_char rmi; +}; + +struct l_dvd_disckey { + u_char type; + l_uint agid:2; + u_char value[2048]; +}; + +struct l_dvd_bca { + u_char type; + l_int len; + u_char value[188]; +}; + +struct l_dvd_manufact { + u_char type; + u_char layer_num; + l_int len; + u_char value[2048]; +}; + +typedef union { + u_char type; + struct l_dvd_physical physical; + struct l_dvd_copyright copyright; + struct l_dvd_disckey disckey; + struct l_dvd_bca bca; + struct l_dvd_manufact manufact; +} l_dvd_struct; + +typedef u_char l_dvd_key[5]; +typedef u_char l_dvd_challenge[10]; + +struct l_dvd_lu_send_agid { + u_char type; + l_uint agid:2; +}; + +struct l_dvd_host_send_challenge { + u_char type; + l_uint agid:2; + l_dvd_challenge chal; +}; + +struct l_dvd_send_key { + u_char type; + l_uint agid:2; + l_dvd_key key; +}; + +struct l_dvd_lu_send_challenge { + u_char type; + l_uint agid:2; + l_dvd_challenge chal; +}; + +struct l_dvd_lu_send_title_key { + u_char type; + l_uint agid:2; + l_dvd_key title_key; + l_int lba; + l_uint cpm:1; + l_uint cp_sec:1; + l_uint cgms:2; +}; + +struct l_dvd_lu_send_asf { + u_char type; + l_uint agid:2; + l_uint asf:1; +}; + +struct l_dvd_host_send_rpcstate { + u_char type; + u_char pdrc; +}; + +struct l_dvd_lu_send_rpcstate { + u_char type:2; + u_char vra:3; + u_char ucca:3; + u_char region_mask; + u_char rpc_scheme; +}; + +typedef union { + u_char type; + struct l_dvd_lu_send_agid lsa; + struct l_dvd_host_send_challenge hsc; + struct l_dvd_send_key lsk; + struct l_dvd_lu_send_challenge lsc; + struct l_dvd_send_key hsk; + struct l_dvd_lu_send_title_key lstk; + struct l_dvd_lu_send_asf lsasf; + struct l_dvd_host_send_rpcstate hrpcs; + struct l_dvd_lu_send_rpcstate lrpcs; +} l_dvd_authinfo; + +static void +bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp) +{ + if (af == CD_LBA_FORMAT) + lp->lba = bp->lba; + else { + lp->msf.minute = bp->msf.minute; + lp->msf.second = bp->msf.second; + lp->msf.frame = bp->msf.frame; + } +} + +static void +set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) +{ + if (format == LINUX_CDROM_MSF) { + addr->msf.frame = lba % 75; + lba /= 75; + lba += 2; + addr->msf.second = lba % 60; + addr->msf.minute = lba / 60; + } else + addr->lba = lba; +} + +static int +linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp) +{ + bp->format = lp->type; + switch (bp->format) { + case DVD_STRUCT_PHYSICAL: + if (bp->layer_num >= 4) + return (EINVAL); + bp->layer_num = lp->physical.layer_num; + break; + case DVD_STRUCT_COPYRIGHT: + bp->layer_num = lp->copyright.layer_num; + break; + case DVD_STRUCT_DISCKEY: + bp->agid = lp->disckey.agid; + break; + case DVD_STRUCT_BCA: + case DVD_STRUCT_MANUFACT: + break; + default: + return (EINVAL); + } + return (0); +} + +static int +bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp) +{ + switch (bp->format) { + case DVD_STRUCT_PHYSICAL: { + struct dvd_layer *blp = (struct dvd_layer *)bp->data; + struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num]; + memset(llp, 0, sizeof(*llp)); + llp->book_version = blp->book_version; + llp->book_type = blp->book_type; + llp->min_rate = blp->max_rate; + llp->disc_size = blp->disc_size; + llp->layer_type = blp->layer_type; + llp->track_path = blp->track_path; + llp->nlayers = blp->nlayers; + llp->track_density = blp->track_density; + llp->linear_density = blp->linear_density; + llp->bca = blp->bca; + llp->start_sector = blp->start_sector; + llp->end_sector = blp->end_sector; + llp->end_sector_l0 = blp->end_sector_l0; + break; + } + case DVD_STRUCT_COPYRIGHT: + lp->copyright.cpst = bp->cpst; + lp->copyright.rmi = bp->rmi; + break; + case DVD_STRUCT_DISCKEY: + memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value)); + break; + case DVD_STRUCT_BCA: + lp->bca.len = bp->length; + memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value)); + break; + case DVD_STRUCT_MANUFACT: + lp->manufact.len = bp->length; + memcpy(lp->manufact.value, bp->data, + sizeof(lp->manufact.value)); + /* lp->manufact.layer_num is unused in linux (redhat 7.0) */ + break; + default: + return (EINVAL); + } + return (0); +} + +static int +linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode, + struct dvd_authinfo *bp) +{ + switch (lp->type) { + case LINUX_DVD_LU_SEND_AGID: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_AGID; + bp->agid = lp->lsa.agid; + break; + case LINUX_DVD_HOST_SEND_CHALLENGE: + *bcode = DVDIOCSENDKEY; + bp->format = DVD_SEND_CHALLENGE; + bp->agid = lp->hsc.agid; + memcpy(bp->keychal, lp->hsc.chal, 10); + break; + case LINUX_DVD_LU_SEND_KEY1: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_KEY1; + bp->agid = lp->lsk.agid; + break; + case LINUX_DVD_LU_SEND_CHALLENGE: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_CHALLENGE; + bp->agid = lp->lsc.agid; + break; + case LINUX_DVD_HOST_SEND_KEY2: + *bcode = DVDIOCSENDKEY; + bp->format = DVD_SEND_KEY2; + bp->agid = lp->hsk.agid; + memcpy(bp->keychal, lp->hsk.key, 5); + break; + case LINUX_DVD_LU_SEND_TITLE_KEY: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_TITLE_KEY; + bp->agid = lp->lstk.agid; + bp->lba = lp->lstk.lba; + break; + case LINUX_DVD_LU_SEND_ASF: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_ASF; + bp->agid = lp->lsasf.agid; + break; + case LINUX_DVD_INVALIDATE_AGID: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_INVALIDATE_AGID; + bp->agid = lp->lsa.agid; + break; + case LINUX_DVD_LU_SEND_RPC_STATE: + *bcode = DVDIOCREPORTKEY; + bp->format = DVD_REPORT_RPC; + break; + case LINUX_DVD_HOST_SEND_RPC_STATE: + *bcode = DVDIOCSENDKEY; + bp->format = DVD_SEND_RPC; + bp->region = lp->hrpcs.pdrc; + break; + default: + return (EINVAL); + } + return (0); +} + +static int +bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp) +{ + switch (lp->type) { + case LINUX_DVD_LU_SEND_AGID: + lp->lsa.agid = bp->agid; + break; + case LINUX_DVD_HOST_SEND_CHALLENGE: + lp->type = LINUX_DVD_LU_SEND_KEY1; + break; + case LINUX_DVD_LU_SEND_KEY1: + memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key)); + break; + case LINUX_DVD_LU_SEND_CHALLENGE: + memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal)); + break; + case LINUX_DVD_HOST_SEND_KEY2: + lp->type = LINUX_DVD_AUTH_ESTABLISHED; + break; + case LINUX_DVD_LU_SEND_TITLE_KEY: + memcpy(lp->lstk.title_key, bp->keychal, + sizeof(lp->lstk.title_key)); + lp->lstk.cpm = bp->cpm; + lp->lstk.cp_sec = bp->cp_sec; + lp->lstk.cgms = bp->cgms; + break; + case LINUX_DVD_LU_SEND_ASF: + lp->lsasf.asf = bp->asf; + break; + case LINUX_DVD_INVALIDATE_AGID: + break; + case LINUX_DVD_LU_SEND_RPC_STATE: + lp->lrpcs.type = bp->reg_type; + lp->lrpcs.vra = bp->vend_rsts; + lp->lrpcs.ucca = bp->user_rsts; + lp->lrpcs.region_mask = bp->region; + lp->lrpcs.rpc_scheme = bp->rpc_scheme; + break; + case LINUX_DVD_HOST_SEND_RPC_STATE: + break; + default: + return (EINVAL); + } + return (0); +} + +static int +linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + int error; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + switch (args->cmd & 0xffff) { + + case LINUX_CDROMPAUSE: + args->cmd = CDIOCPAUSE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMRESUME: + args->cmd = CDIOCRESUME; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMPLAYMSF: + args->cmd = CDIOCPLAYMSF; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMPLAYTRKIND: + args->cmd = CDIOCPLAYTRACKS; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMREADTOCHDR: { + struct ioc_toc_header th; + struct linux_cdrom_tochdr lth; + error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, td); + if (!error) { + lth.cdth_trk0 = th.starting_track; + lth.cdth_trk1 = th.ending_track; + copyout(<h, (caddr_t)args->arg, sizeof(lth)); + } + break; + } + + case LINUX_CDROMREADTOCENTRY: { + struct linux_cdrom_tocentry lte, *ltep = + (struct linux_cdrom_tocentry *)args->arg; + struct ioc_read_toc_single_entry irtse; + irtse.address_format = ltep->cdte_format; + irtse.track = ltep->cdte_track; + error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, td); + if (!error) { + lte = *ltep; + lte.cdte_ctrl = irtse.entry.control; + lte.cdte_adr = irtse.entry.addr_type; + bsd_to_linux_msf_lba(irtse.address_format, + &irtse.entry.addr, <e.cdte_addr); + copyout(<e, (caddr_t)args->arg, sizeof(lte)); + } + break; + } + + case LINUX_CDROMSTOP: + args->cmd = CDIOCSTOP; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMSTART: + args->cmd = CDIOCSTART; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_CDROMEJECT: + args->cmd = CDIOCEJECT; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_CDROMVOLCTRL */ + + case LINUX_CDROMSUBCHNL: { + struct linux_cdrom_subchnl sc; + struct ioc_read_subchannel bsdsc; + struct cd_sub_channel_info *bsdinfo; + caddr_t sg = stackgap_init(); + bsdinfo = (struct cd_sub_channel_info*)stackgap_alloc(&sg, + sizeof(struct cd_sub_channel_info)); + bsdsc.address_format = CD_LBA_FORMAT; + bsdsc.data_format = CD_CURRENT_POSITION; + bsdsc.track = 0; + bsdsc.data_len = sizeof(struct cd_sub_channel_info); + bsdsc.data = bsdinfo; + error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, td); + if (error) + break; + error = copyin((caddr_t)args->arg, &sc, + sizeof(struct linux_cdrom_subchnl)); + if (error) + break; + sc.cdsc_audiostatus = bsdinfo->header.audio_status; + sc.cdsc_adr = bsdinfo->what.position.addr_type; + sc.cdsc_ctrl = bsdinfo->what.position.control; + sc.cdsc_trk = bsdinfo->what.position.track_number; + sc.cdsc_ind = bsdinfo->what.position.index_number; + set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, + bsdinfo->what.position.absaddr.lba); + set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, + bsdinfo->what.position.reladdr.lba); + error = copyout(&sc, (caddr_t)args->arg, + sizeof(struct linux_cdrom_subchnl)); + break; + } + + /* LINUX_CDROMREADMODE2 */ + /* LINUX_CDROMREADMODE1 */ + /* LINUX_CDROMREADAUDIO */ + /* LINUX_CDROMEJECT_SW */ + /* LINUX_CDROMMULTISESSION */ + /* LINUX_CDROM_GET_UPC */ + + case LINUX_CDROMRESET: + args->cmd = CDIOCRESET; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + /* LINUX_CDROMVOLREAD */ + /* LINUX_CDROMREADRAW */ + /* LINUX_CDROMREADCOOKED */ + /* LINUX_CDROMSEEK */ + /* LINUX_CDROMPLAYBLK */ + /* LINUX_CDROMREADALL */ + /* LINUX_CDROMCLOSETRAY */ + /* LINUX_CDROMLOADFROMSLOT */ + /* LINUX_CDROMGETSPINDOWN */ + /* LINUX_CDROMSETSPINDOWN */ + /* LINUX_CDROM_SET_OPTIONS */ + /* LINUX_CDROM_CLEAR_OPTIONS */ + /* LINUX_CDROM_SELECT_SPEED */ + /* LINUX_CDROM_SELECT_DISC */ + /* LINUX_CDROM_MEDIA_CHANGED */ + /* LINUX_CDROM_DRIVE_STATUS */ + /* LINUX_CDROM_DISC_STATUS */ + /* LINUX_CDROM_CHANGER_NSLOTS */ + /* LINUX_CDROM_LOCKDOOR */ + /* LINUX_CDROM_DEBUG */ + /* LINUX_CDROM_GET_CAPABILITY */ + /* LINUX_CDROMAUDIOBUFSIZ */ + + case LINUX_DVD_READ_STRUCT: { + l_dvd_struct lds; + struct dvd_struct bds; + + error = copyin((caddr_t)args->arg, &lds, sizeof(l_dvd_struct)); + if (error) + break; + error = linux_to_bsd_dvd_struct(&lds, &bds); + if (error) + break; + error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)&bds, td); + if (error) + break; + error = bsd_to_linux_dvd_struct(&bds, &lds); + if (error) + break; + error = copyout(&lds, (caddr_t)args->arg, + sizeof(l_dvd_struct)); + break; + } + + /* LINUX_DVD_WRITE_STRUCT */ + + case LINUX_DVD_AUTH: { + l_dvd_authinfo lda; + struct dvd_authinfo bda; + int bcode; + + error = copyin((caddr_t)args->arg, &lda, + sizeof(l_dvd_authinfo)); + if (error) + break; + error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda); + if (error) + break; + error = fo_ioctl(fp, bcode, (caddr_t)&bda, td); + if (error) { + if (lda.type == LINUX_DVD_HOST_SEND_KEY2) { + lda.type = LINUX_DVD_AUTH_FAILURE; + copyout(&lda, (caddr_t)args->arg, + sizeof(l_dvd_authinfo)); + } + break; + } + error = bsd_to_linux_dvd_authinfo(&bda, &lda); + if (error) + break; + error = copyout(&lda, (caddr_t)args->arg, + sizeof(l_dvd_authinfo)); + break; + } + + /* LINUX_CDROM_SEND_PACKET */ + /* LINUX_CDROM_NEXT_WRITABLE */ + /* LINUX_CDROM_LAST_WRITTEN */ + + default: + error = ENOIOCTL; + break; + } + + fdrop(fp, td); + return (error); +} + +/* + * Sound related ioctls + */ + +static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; + +#define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) + +static int +linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) +{ + + switch (args->cmd & 0xffff) { + + case LINUX_SOUND_MIXER_WRITE_VOLUME: + args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_BASS: + args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_TREBLE: + args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_SYNTH: + args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_PCM: + args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_SPEAKER: + args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_LINE: + args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_MIC: + args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_CD: + args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_IMIX: + args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_ALTPCM: + args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_RECLEV: + args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_IGAIN: + args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_OGAIN: + args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_LINE1: + args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_LINE2: + args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_LINE3: + args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_OSS_GETVERSION: { + int version = linux_get_oss_version(td->td_proc); + return (copyout(&version, (caddr_t)args->arg, sizeof(int))); + } + + case LINUX_SOUND_MIXER_READ_DEVMASK: + args->cmd = SOUND_MIXER_READ_DEVMASK; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_MIXER_WRITE_RECSRC: + args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC); + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_RESET: + args->cmd = SNDCTL_DSP_RESET; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SYNC: + args->cmd = SNDCTL_DSP_SYNC; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SPEED: + args->cmd = SNDCTL_DSP_SPEED; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_STEREO: + args->cmd = SNDCTL_DSP_STEREO; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ + args->cmd = SNDCTL_DSP_GETBLKSIZE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SETFMT: + args->cmd = SNDCTL_DSP_SETFMT; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_PCM_WRITE_CHANNELS: + args->cmd = SOUND_PCM_WRITE_CHANNELS; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SOUND_PCM_WRITE_FILTER: + args->cmd = SOUND_PCM_WRITE_FILTER; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_POST: + args->cmd = SNDCTL_DSP_POST; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SUBDIVIDE: + args->cmd = SNDCTL_DSP_SUBDIVIDE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SETFRAGMENT: + args->cmd = SNDCTL_DSP_SETFRAGMENT; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETFMTS: + args->cmd = SNDCTL_DSP_GETFMTS; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETOSPACE: + args->cmd = SNDCTL_DSP_GETOSPACE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETISPACE: + args->cmd = SNDCTL_DSP_GETISPACE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_NONBLOCK: + args->cmd = SNDCTL_DSP_NONBLOCK; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETCAPS: + args->cmd = SNDCTL_DSP_GETCAPS; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */ + args->cmd = SNDCTL_DSP_SETTRIGGER; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETIPTR: + args->cmd = SNDCTL_DSP_GETIPTR; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETOPTR: + args->cmd = SNDCTL_DSP_GETOPTR; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_DSP_GETODELAY: + args->cmd = SNDCTL_DSP_GETODELAY; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_RESET: + args->cmd = SNDCTL_SEQ_RESET; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_SYNC: + args->cmd = SNDCTL_SEQ_SYNC; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SYNTH_INFO: + args->cmd = SNDCTL_SYNTH_INFO; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_CTRLRATE: + args->cmd = SNDCTL_SEQ_CTRLRATE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_GETOUTCOUNT: + args->cmd = SNDCTL_SEQ_GETOUTCOUNT; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_GETINCOUNT: + args->cmd = SNDCTL_SEQ_GETINCOUNT; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_PERCMODE: + args->cmd = SNDCTL_SEQ_PERCMODE; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_FM_LOAD_INSTR: + args->cmd = SNDCTL_FM_LOAD_INSTR; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_TESTMIDI: + args->cmd = SNDCTL_SEQ_TESTMIDI; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_RESETSAMPLES: + args->cmd = SNDCTL_SEQ_RESETSAMPLES; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_NRSYNTHS: + args->cmd = SNDCTL_SEQ_NRSYNTHS; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_NRMIDIS: + args->cmd = SNDCTL_SEQ_NRMIDIS; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_MIDI_INFO: + args->cmd = SNDCTL_MIDI_INFO; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SEQ_TRESHOLD: + args->cmd = SNDCTL_SEQ_TRESHOLD; + return (ioctl(td, (struct ioctl_args *)args)); + + case LINUX_SNDCTL_SYNTH_MEMAVL: + args->cmd = SNDCTL_SYNTH_MEMAVL; + return (ioctl(td, (struct ioctl_args *)args)); + + } + + return (ENOIOCTL); +} + +/* + * Console related ioctls + */ + +#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) + +static int +linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + int error; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + switch (args->cmd & 0xffff) { + + case LINUX_KIOCSOUND: + args->cmd = KIOCSOUND; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDMKTONE: + args->cmd = KDMKTONE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDGETLED: + args->cmd = KDGETLED; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDSETLED: + args->cmd = KDSETLED; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDSETMODE: + args->cmd = KDSETMODE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDGETMODE: + args->cmd = KDGETMODE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDGKBMODE: + args->cmd = KDGKBMODE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_KDSKBMODE: { + int kbdmode; + switch (args->arg) { + case LINUX_KBD_RAW: + kbdmode = K_RAW; + break; + case LINUX_KBD_XLATE: + kbdmode = K_XLATE; + break; + case LINUX_KBD_MEDIUMRAW: + kbdmode = K_RAW; + break; + default: + fdrop(fp, td); + return (EINVAL); + } + error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, td)); + break; + } + + case LINUX_VT_OPENQRY: + args->cmd = VT_OPENQRY; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_VT_GETMODE: + args->cmd = VT_GETMODE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_VT_SETMODE: { + struct vt_mode *mode; + args->cmd = VT_SETMODE; + mode = (struct vt_mode *)args->arg; + if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig)) + mode->frsig = mode->acqsig; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + } + + case LINUX_VT_GETSTATE: + args->cmd = VT_GETACTIVE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_VT_RELDISP: + args->cmd = VT_RELDISP; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_VT_ACTIVATE: + args->cmd = VT_ACTIVATE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + case LINUX_VT_WAITACTIVE: + args->cmd = VT_WAITACTIVE; + error = (ioctl(td, (struct ioctl_args *)args)); + break; + + default: + error = ENOIOCTL; + break; + } + + fdrop(fp, td); + return (error); +} + +/* + * Criteria for interface name translation + */ +#define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER) + +/* + * Interface function used by linprocfs (at the time of writing). It's not + * used by the Linuxulator itself. + */ +int +linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen) +{ + struct ifnet *ifscan; + int ethno; + + /* Short-circuit non ethernet interfaces */ + if (!IFP_IS_ETH(ifp)) + return (snprintf(buffer, buflen, "%s%d", ifp->if_name, + ifp->if_unit)); + + /* Determine the (relative) unit number for ethernet interfaces */ + ethno = 0; + TAILQ_FOREACH(ifscan, &ifnet, if_link) { + if (ifscan == ifp) + return (snprintf(buffer, buflen, "eth%d", ethno)); + if (IFP_IS_ETH(ifscan)) + ethno++; + } + + return (0); +} + +/* + * Translate a Linux interface name to a FreeBSD interface name, + * and return the associated ifnet structure + * bsdname and lxname need to be least IFNAMSIZ bytes long, but + * can point to the same buffer. + */ + +static struct ifnet * +ifname_linux_to_bsd(const char *lxname, char *bsdname) +{ + struct ifnet *ifp; + int len, unit; + char *ep; + int is_eth, index; + + for (len = 0; len < LINUX_IFNAMSIZ; ++len) + if (!isalpha(lxname[len])) + break; + if (len == 0 || len == LINUX_IFNAMSIZ) + return (NULL); + unit = (int)strtoul(lxname + len, &ep, 10); + if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) + return (NULL); + index = 0; + is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0; + TAILQ_FOREACH(ifp, &ifnet, if_link) { + /* + * Allow Linux programs to use FreeBSD names. Don't presume + * we never have an interface named "eth", so don't make + * the test optional based on is_eth. + */ + if (ifp->if_unit == unit && ifp->if_name[len] == '\0' && + strncmp(ifp->if_name, lxname, len) == 0) + break; + if (is_eth && IFP_IS_ETH(ifp) && unit == index++) + break; + } + if (ifp != NULL) + snprintf(bsdname, IFNAMSIZ, "%s%d", ifp->if_name, ifp->if_unit); + return (ifp); +} + +/* + * Implement the SIOCGIFCONF ioctl + */ + +static int +linux_ifconf(struct thread *td, struct ifconf *uifc) +{ + struct ifconf ifc; + struct l_ifreq ifr; + struct ifnet *ifp; + struct ifaddr *ifa; + struct iovec iov; + struct uio uio; + int error, ethno; + + error = copyin(uifc, &ifc, sizeof ifc); + if (error != 0) + return (error); + + /* much easier to use uiomove than keep track ourselves */ + iov.iov_base = ifc.ifc_buf; + iov.iov_len = ifc.ifc_len; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + uio.uio_offset = 0; + uio.uio_resid = ifc.ifc_len; + uio.uio_segflg = UIO_USERSPACE; + uio.uio_rw = UIO_READ; + uio.uio_td = td; + + /* Keep track of eth interfaces */ + ethno = 0; + + /* Return all AF_INET addresses of all interfaces */ + TAILQ_FOREACH(ifp, &ifnet, if_link) { + if (uio.uio_resid <= 0) + break; + + bzero(&ifr, sizeof ifr); + if (IFP_IS_ETH(ifp)) + snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d", + ethno++); + else + snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "%s%d", + ifp->if_name, ifp->if_unit); + + /* Walk the address list */ + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + struct sockaddr *sa = ifa->ifa_addr; + + if (uio.uio_resid <= 0) + break; + + if (sa->sa_family == AF_INET) { + ifr.ifr_addr.sa_family = LINUX_AF_INET; + memcpy(ifr.ifr_addr.sa_data, sa->sa_data, + sizeof(ifr.ifr_addr.sa_data)); + + error = uiomove((caddr_t)&ifr, sizeof ifr, + &uio); + if (error != 0) + return (error); + } + } + } + + ifc.ifc_len -= uio.uio_resid; + error = copyout(&ifc, uifc, sizeof ifc); + + return (error); +} + +static int +linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr) +{ + l_short flags; + + flags = ifp->if_flags; + /* these flags have no Linux equivalent */ + flags &= ~(IFF_SMART|IFF_OACTIVE|IFF_SIMPLEX| + IFF_LINK0|IFF_LINK1|IFF_LINK2); + /* Linux' multicast flag is in a different bit */ + if (flags & IFF_MULTICAST) { + flags &= ~IFF_MULTICAST; + flags |= 0x1000; + } + + return (copyout(&flags, &ifr->ifr_flags, sizeof flags)); +} + +#define ARPHRD_ETHER 1 +#define ARPHRD_LOOPBACK 772 + +static int +linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr) +{ + struct ifaddr *ifa; + struct sockaddr_dl *sdl; + struct l_sockaddr lsa; + + if (ifp->if_type == IFT_LOOP) { + bzero(&lsa, sizeof lsa); + lsa.sa_family = ARPHRD_LOOPBACK; + return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); + } + + if (ifp->if_type != IFT_ETHER) + return (ENOENT); + + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + sdl = (struct sockaddr_dl*)ifa->ifa_addr; + if (sdl != NULL && (sdl->sdl_family == AF_LINK) && + (sdl->sdl_type == IFT_ETHER)) { + bzero(&lsa, sizeof lsa); + lsa.sa_family = ARPHRD_ETHER; + bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN); + return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof lsa)); + } + } + + return (ENOENT); +} + +/* + * Socket related ioctls + */ + +static int +linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) +{ + char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; + struct ifnet *ifp; + struct file *fp; + int error, type; + + KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ, + ("%s(): LINUX_IFNAMSIZ != IFNAMSIZ", __func__)); + + ifp = NULL; + error = 0; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + type = fp->f_type; + fdrop(fp, td); + if (type != DTYPE_SOCKET) { + /* not a socket - probably a tap / vmnet device */ + switch (args->cmd) { + case LINUX_SIOCGIFADDR: + case LINUX_SIOCSIFADDR: + case LINUX_SIOCGIFFLAGS: + return (linux_ioctl_special(td, args)); + default: + return (ENOIOCTL); + } + } + + switch (args->cmd & 0xffff) { + + case LINUX_FIOGETOWN: + case LINUX_FIOSETOWN: + case LINUX_SIOCADDMULTI: + case LINUX_SIOCATMARK: + case LINUX_SIOCDELMULTI: + case LINUX_SIOCGIFCONF: + case LINUX_SIOCGPGRP: + case LINUX_SIOCSPGRP: + /* these ioctls don't take an interface name */ +#ifdef DEBUG + printf("%s(): ioctl %d\n", __func__, + args->cmd & 0xffff); +#endif + break; + + case LINUX_SIOCGIFFLAGS: + case LINUX_SIOCGIFADDR: + case LINUX_SIOCSIFADDR: + case LINUX_SIOCGIFDSTADDR: + case LINUX_SIOCGIFBRDADDR: + case LINUX_SIOCGIFNETMASK: + case LINUX_SIOCSIFNETMASK: + case LINUX_SIOCGIFMTU: + case LINUX_SIOCSIFMTU: + case LINUX_SIOCSIFNAME: + case LINUX_SIOCGIFHWADDR: + case LINUX_SIOCSIFHWADDR: + case LINUX_SIOCDEVPRIVATE: + case LINUX_SIOCDEVPRIVATE+1: + /* copy in the interface name and translate it. */ + error = copyin((char *)args->arg, lifname, LINUX_IFNAMSIZ); + if (error != 0) + return (error); +#ifdef DEBUG + printf("%s(): ioctl %d on %.*s\n", __func__, + args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname); +#endif + ifp = ifname_linux_to_bsd(lifname, ifname); + if (ifp == NULL) + return (EINVAL); + /* + * We need to copy it back out in case we pass the + * request on to our native ioctl(), which will expect + * the ifreq to be in user space and have the correct + * interface name. + */ + error = copyout(ifname, (char *)args->arg, IFNAMSIZ); + if (error != 0) + return (error); +#ifdef DEBUG + printf("%s(): %s translated to %s\n", __func__, + lifname, ifname); +#endif + break; + + default: + return (ENOIOCTL); + } + + switch (args->cmd & 0xffff) { + + case LINUX_FIOSETOWN: + args->cmd = FIOSETOWN; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCSPGRP: + args->cmd = SIOCSPGRP; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_FIOGETOWN: + args->cmd = FIOGETOWN; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCGPGRP: + args->cmd = SIOCGPGRP; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCATMARK: + args->cmd = SIOCATMARK; + error = ioctl(td, (struct ioctl_args *)args); + break; + + /* LINUX_SIOCGSTAMP */ + + case LINUX_SIOCGIFCONF: + error = linux_ifconf(td, (struct ifconf *)args->arg); + break; + + case LINUX_SIOCGIFFLAGS: + args->cmd = SIOCGIFFLAGS; + error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg); + break; + + case LINUX_SIOCGIFADDR: + args->cmd = OSIOCGIFADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCSIFADDR: + /* XXX probably doesn't work, included for completeness */ + args->cmd = SIOCSIFADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCGIFDSTADDR: + args->cmd = OSIOCGIFDSTADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCGIFBRDADDR: + args->cmd = OSIOCGIFBRDADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCGIFNETMASK: + args->cmd = OSIOCGIFNETMASK; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCSIFNETMASK: + error = ENOIOCTL; + break; + + case LINUX_SIOCGIFMTU: + args->cmd = SIOCGIFMTU; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCSIFMTU: + args->cmd = SIOCSIFMTU; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCSIFNAME: + error = ENOIOCTL; + break; + + case LINUX_SIOCGIFHWADDR: + error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg); + break; + + case LINUX_SIOCSIFHWADDR: + error = ENOIOCTL; + break; + + case LINUX_SIOCADDMULTI: + args->cmd = SIOCADDMULTI; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCDELMULTI: + args->cmd = SIOCDELMULTI; + error = ioctl(td, (struct ioctl_args *)args); + break; + + /* + * XXX This is slightly bogus, but these ioctls are currently + * XXX only used by the aironet (if_an) network driver. + */ + case LINUX_SIOCDEVPRIVATE: + args->cmd = SIOCGPRIVATE_0; + error = ioctl(td, (struct ioctl_args *)args); + break; + + case LINUX_SIOCDEVPRIVATE+1: + args->cmd = SIOCGPRIVATE_1; + error = ioctl(td, (struct ioctl_args *)args); + break; + } + + if (ifp != NULL) + /* restore the original interface name */ + copyout(lifname, (char *)args->arg, LINUX_IFNAMSIZ); + +#ifdef DEBUG + printf("%s(): returning %d\n", __func__, error); +#endif + return (error); +} + +/* + * Device private ioctl handler + */ +static int +linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + int error, type; + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + type = fp->f_type; + fdrop(fp, td); + if (type == DTYPE_SOCKET) + return (linux_ioctl_socket(td, args)); + return (ENOIOCTL); +} + +/* + * Special ioctl handler + */ +static int +linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args) +{ + int error; + + switch (args->cmd) { + case LINUX_SIOCGIFADDR: + args->cmd = SIOCGIFADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + case LINUX_SIOCSIFADDR: + args->cmd = SIOCSIFADDR; + error = ioctl(td, (struct ioctl_args *)args); + break; + case LINUX_SIOCGIFFLAGS: + args->cmd = SIOCGIFFLAGS; + error = ioctl(td, (struct ioctl_args *)args); + break; + default: + error = ENOIOCTL; + } + + return (error); +} + +/* + * main ioctl syscall function + */ + +int +linux_ioctl(struct thread *td, struct linux_ioctl_args *args) +{ + struct file *fp; + struct handler_element *he; + int error, cmd; + +#ifdef DEBUG + if (ldebug(ioctl)) + printf(ARGS(ioctl, "%d, %04lx, *"), args->fd, + (unsigned long)args->cmd); +#endif + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + if ((fp->f_flag & (FREAD|FWRITE)) == 0) { + fdrop(fp, td); + return (EBADF); + } + + /* Iterate over the ioctl handlers */ + cmd = args->cmd & 0xffff; + TAILQ_FOREACH(he, &handlers, list) { + if (cmd >= he->low && cmd <= he->high) { + error = (*he->func)(td, args); + if (error != ENOIOCTL) { + fdrop(fp, td); + return (error); + } + } + } + fdrop(fp, td); + + printf("linux: 'ioctl' fd=%d, cmd=0x%x ('%c',%d) not implemented\n", + args->fd, (int)(args->cmd & 0xffff), + (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff)); + + return (EINVAL); +} + +int +linux_ioctl_register_handler(struct linux_ioctl_handler *h) +{ + struct handler_element *he, *cur; + + if (h == NULL || h->func == NULL) + return (EINVAL); + + /* + * Reuse the element if the handler is already on the list, otherwise + * create a new element. + */ + TAILQ_FOREACH(he, &handlers, list) { + if (he->func == h->func) + break; + } + if (he == NULL) { + MALLOC(he, struct handler_element *, sizeof(*he), + M_LINUX, M_WAITOK); + he->func = h->func; + } else + TAILQ_REMOVE(&handlers, he, list); + + /* Initialize range information. */ + he->low = h->low; + he->high = h->high; + he->span = h->high - h->low + 1; + + /* Add the element to the list, sorted on span. */ + TAILQ_FOREACH(cur, &handlers, list) { + if (cur->span > he->span) { + TAILQ_INSERT_BEFORE(cur, he, list); + return (0); + } + } + TAILQ_INSERT_TAIL(&handlers, he, list); + + return (0); +} + +int +linux_ioctl_unregister_handler(struct linux_ioctl_handler *h) +{ + struct handler_element *he; + + if (h == NULL || h->func == NULL) + return (EINVAL); + + TAILQ_FOREACH(he, &handlers, list) { + if (he->func == h->func) { + TAILQ_REMOVE(&handlers, he, list); + FREE(he, M_LINUX); + return (0); + } + } + + return (EINVAL); +} diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h new file mode 100644 index 0000000..0d77e0d --- /dev/null +++ b/sys/compat/linux/linux_ioctl.h @@ -0,0 +1,668 @@ +/* + * Copyright (c) 1999 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_IOCTL_H_ +#define _LINUX_IOCTL_H_ + +/* + * disk + */ +#define LINUX_BLKROSET 0x125d +#define LINUX_BLKROGET 0x125e +#define LINUX_BLKRRPART 0x125f +#define LINUX_BLKGETSIZE 0x1260 +#define LINUX_BLKFLSBUF 0x1261 +#define LINUX_BLKRASET 0x1262 +#define LINUX_BLKRAGET 0x1263 +#define LINUX_BLKFRASET 0x1264 +#define LINUX_BLKFRAGET 0x1265 +#define LINUX_BLKSECTSET 0x1266 +#define LINUX_BLKSECTGET 0x1267 +#define LINUX_BLKSSZGET 0x1268 + +#define LINUX_IOCTL_DISK_MIN LINUX_BLKROSET +#define LINUX_IOCTL_DISK_MAX LINUX_BLKSSZGET + +/* + * cdrom + */ +#define LINUX_CDROMPAUSE 0x5301 +#define LINUX_CDROMRESUME 0x5302 +#define LINUX_CDROMPLAYMSF 0x5303 +#define LINUX_CDROMPLAYTRKIND 0x5304 +#define LINUX_CDROMREADTOCHDR 0x5305 +#define LINUX_CDROMREADTOCENTRY 0x5306 +#define LINUX_CDROMSTOP 0x5307 +#define LINUX_CDROMSTART 0x5308 +#define LINUX_CDROMEJECT 0x5309 +#define LINUX_CDROMVOLCTRL 0x530a +#define LINUX_CDROMSUBCHNL 0x530b +#define LINUX_CDROMREADMODE2 0x530c +#define LINUX_CDROMREADMODE1 0x530d +#define LINUX_CDROMREADAUDIO 0x530e +#define LINUX_CDROMEJECT_SW 0x530f +#define LINUX_CDROMMULTISESSION 0x5310 +#define LINUX_CDROM_GET_UPC 0x5311 +#define LINUX_CDROMRESET 0x5312 +#define LINUX_CDROMVOLREAD 0x5313 +#define LINUX_CDROMREADRAW 0x5314 +#define LINUX_CDROMREADCOOKED 0x5315 +#define LINUX_CDROMSEEK 0x5316 +#define LINUX_CDROMPLAYBLK 0x5317 +#define LINUX_CDROMREADALL 0x5318 +#define LINUX_CDROMCLOSETRAY 0x5319 +#define LINUX_CDROMLOADFROMSLOT 0x531a +#define LINUX_CDROMGETSPINDOWN 0x531d +#define LINUX_CDROMSETSPINDOWN 0x531e +#define LINUX_CDROM_SET_OPTIONS 0x5320 +#define LINUX_CDROM_CLEAR_OPTIONS 0x5321 +#define LINUX_CDROM_SELECT_SPEED 0x5322 +#define LINUX_CDROM_SELECT_DISC 0x5323 +#define LINUX_CDROM_MEDIA_CHANGED 0x5325 +#define LINUX_CDROM_DRIVE_STATUS 0x5326 +#define LINUX_CDROM_DISC_STATUS 0x5327 +#define LINUX_CDROM_CHANGER_NSLOTS 0x5328 +#define LINUX_CDROM_LOCKDOOR 0x5329 +#define LINUX_CDROM_DEBUG 0x5330 +#define LINUX_CDROM_GET_CAPABILITY 0x5331 +#define LINUX_CDROMAUDIOBUFSIZ 0x5382 +#define LINUX_DVD_READ_STRUCT 0x5390 +#define LINUX_DVD_WRITE_STRUCT 0x5391 +#define LINUX_DVD_AUTH 0x5392 +#define LINUX_CDROM_SEND_PACKET 0x5393 +#define LINUX_CDROM_NEXT_WRITABLE 0x5394 +#define LINUX_CDROM_LAST_WRITTEN 0x5395 + +#define LINUX_IOCTL_CDROM_MIN LINUX_CDROMPAUSE +#define LINUX_IOCTL_CDROM_MAX LINUX_CDROM_LAST_WRITTEN + +#define LINUX_CDROM_LBA 0x01 +#define LINUX_CDROM_MSF 0x02 + +#define LINUX_DVD_LU_SEND_AGID 0 +#define LINUX_DVD_HOST_SEND_CHALLENGE 1 +#define LINUX_DVD_LU_SEND_KEY1 2 +#define LINUX_DVD_LU_SEND_CHALLENGE 3 +#define LINUX_DVD_HOST_SEND_KEY2 4 +#define LINUX_DVD_AUTH_ESTABLISHED 5 +#define LINUX_DVD_AUTH_FAILURE 6 +#define LINUX_DVD_LU_SEND_TITLE_KEY 7 +#define LINUX_DVD_LU_SEND_ASF 8 +#define LINUX_DVD_INVALIDATE_AGID 9 +#define LINUX_DVD_LU_SEND_RPC_STATE 10 +#define LINUX_DVD_HOST_SEND_RPC_STATE 11 + +/* + * console + */ +#define LINUX_KIOCSOUND 0x4B2F +#define LINUX_KDMKTONE 0x4B30 +#define LINUX_KDGETLED 0x4B31 +#define LINUX_KDSETLED 0x4B32 +#define LINUX_KDSETMODE 0x4B3A +#define LINUX_KDGETMODE 0x4B3B +#define LINUX_KDGKBMODE 0x4B44 +#define LINUX_KDSKBMODE 0x4B45 +#define LINUX_VT_OPENQRY 0x5600 +#define LINUX_VT_GETMODE 0x5601 +#define LINUX_VT_SETMODE 0x5602 +#define LINUX_VT_GETSTATE 0x5603 +#define LINUX_VT_RELDISP 0x5605 +#define LINUX_VT_ACTIVATE 0x5606 +#define LINUX_VT_WAITACTIVE 0x5607 + +#define LINUX_IOCTL_CONSOLE_MIN LINUX_KIOCSOUND +#define LINUX_IOCTL_CONSOLE_MAX LINUX_VT_WAITACTIVE + +#define LINUX_LED_SCR 0x01 +#define LINUX_LED_NUM 0x02 +#define LINUX_LED_CAP 0x04 + +#define LINUX_KD_TEXT 0x0 +#define LINUX_KD_GRAPHICS 0x1 +#define LINUX_KD_TEXT0 0x2 +#define LINUX_KD_TEXT1 0x3 + +#define LINUX_KBD_RAW 0 +#define LINUX_KBD_XLATE 1 +#define LINUX_KBD_MEDIUMRAW 2 + +/* + * socket + */ +#define LINUX_FIOSETOWN 0x8901 +#define LINUX_SIOCSPGRP 0x8902 +#define LINUX_FIOGETOWN 0x8903 +#define LINUX_SIOCGPGRP 0x8904 +#define LINUX_SIOCATMARK 0x8905 +#define LINUX_SIOCGSTAMP 0x8906 +#define LINUX_SIOCGIFCONF 0x8912 +#define LINUX_SIOCGIFFLAGS 0x8913 +#define LINUX_SIOCGIFADDR 0x8915 +#define LINUX_SIOCSIFADDR 0x8916 +#define LINUX_SIOCGIFDSTADDR 0x8917 +#define LINUX_SIOCGIFBRDADDR 0x8919 +#define LINUX_SIOCGIFNETMASK 0x891b +#define LINUX_SIOCSIFNETMASK 0x891c +#define LINUX_SIOCGIFMTU 0x8921 +#define LINUX_SIOCSIFMTU 0x8922 +#define LINUX_SIOCSIFNAME 0x8923 +#define LINUX_SIOCSIFHWADDR 0x8924 +#define LINUX_SIOCGIFHWADDR 0x8927 +#define LINUX_SIOCADDMULTI 0x8931 +#define LINUX_SIOCDELMULTI 0x8932 + +#define LINUX_IOCTL_SOCKET_MIN LINUX_FIOSETOWN +#define LINUX_IOCTL_SOCKET_MAX LINUX_SIOCDELMULTI + +/* + * Device private ioctl calls + */ +#define LINUX_SIOCDEVPRIVATE 0x89F0 /* to 89FF */ +#define LINUX_IOCTL_PRIVATE_MIN LINUX_SIOCDEVPRIVATE +#define LINUX_IOCTL_PRIVATE_MAX LINUX_SIOCDEVPRIVATE+0xf + +/* + * sound + */ +#define LINUX_SOUND_MIXER_WRITE_VOLUME 0x4d00 +#define LINUX_SOUND_MIXER_WRITE_BASS 0x4d01 +#define LINUX_SOUND_MIXER_WRITE_TREBLE 0x4d02 +#define LINUX_SOUND_MIXER_WRITE_SYNTH 0x4d03 +#define LINUX_SOUND_MIXER_WRITE_PCM 0x4d04 +#define LINUX_SOUND_MIXER_WRITE_SPEAKER 0x4d05 +#define LINUX_SOUND_MIXER_WRITE_LINE 0x4d06 +#define LINUX_SOUND_MIXER_WRITE_MIC 0x4d07 +#define LINUX_SOUND_MIXER_WRITE_CD 0x4d08 +#define LINUX_SOUND_MIXER_WRITE_IMIX 0x4d09 +#define LINUX_SOUND_MIXER_WRITE_ALTPCM 0x4d0A +#define LINUX_SOUND_MIXER_WRITE_RECLEV 0x4d0B +#define LINUX_SOUND_MIXER_WRITE_IGAIN 0x4d0C +#define LINUX_SOUND_MIXER_WRITE_OGAIN 0x4d0D +#define LINUX_SOUND_MIXER_WRITE_LINE1 0x4d0E +#define LINUX_SOUND_MIXER_WRITE_LINE2 0x4d0F +#define LINUX_SOUND_MIXER_WRITE_LINE3 0x4d10 +#define LINUX_OSS_GETVERSION 0x4d76 +#define LINUX_SOUND_MIXER_READ_DEVMASK 0x4dfe +#define LINUX_SOUND_MIXER_WRITE_RECSRC 0x4dff +#define LINUX_SNDCTL_DSP_RESET 0x5000 +#define LINUX_SNDCTL_DSP_SYNC 0x5001 +#define LINUX_SNDCTL_DSP_SPEED 0x5002 +#define LINUX_SNDCTL_DSP_STEREO 0x5003 +#define LINUX_SNDCTL_DSP_GETBLKSIZE 0x5004 +#define LINUX_SNDCTL_DSP_SETBLKSIZE LINUX_SNDCTL_DSP_GETBLKSIZE +#define LINUX_SNDCTL_DSP_SETFMT 0x5005 +#define LINUX_SOUND_PCM_WRITE_CHANNELS 0x5006 +#define LINUX_SOUND_PCM_WRITE_FILTER 0x5007 +#define LINUX_SNDCTL_DSP_POST 0x5008 +#define LINUX_SNDCTL_DSP_SUBDIVIDE 0x5009 +#define LINUX_SNDCTL_DSP_SETFRAGMENT 0x500A +#define LINUX_SNDCTL_DSP_GETFMTS 0x500B +#define LINUX_SNDCTL_DSP_GETOSPACE 0x500C +#define LINUX_SNDCTL_DSP_GETISPACE 0x500D +#define LINUX_SNDCTL_DSP_NONBLOCK 0x500E +#define LINUX_SNDCTL_DSP_GETCAPS 0x500F +#define LINUX_SNDCTL_DSP_GETTRIGGER 0x5010 +#define LINUX_SNDCTL_DSP_SETTRIGGER LINUX_SNDCTL_DSP_GETTRIGGER +#define LINUX_SNDCTL_DSP_GETIPTR 0x5011 +#define LINUX_SNDCTL_DSP_GETOPTR 0x5012 +#define LINUX_SNDCTL_DSP_GETODELAY 0x5017 +#define LINUX_SNDCTL_SEQ_RESET 0x5100 +#define LINUX_SNDCTL_SEQ_SYNC 0x5101 +#define LINUX_SNDCTL_SYNTH_INFO 0x5102 +#define LINUX_SNDCTL_SEQ_CTRLRATE 0x5103 +#define LINUX_SNDCTL_SEQ_GETOUTCOUNT 0x5104 +#define LINUX_SNDCTL_SEQ_GETINCOUNT 0x5105 +#define LINUX_SNDCTL_SEQ_PERCMODE 0x5106 +#define LINUX_SNDCTL_FM_LOAD_INSTR 0x5107 +#define LINUX_SNDCTL_SEQ_TESTMIDI 0x5108 +#define LINUX_SNDCTL_SEQ_RESETSAMPLES 0x5109 +#define LINUX_SNDCTL_SEQ_NRSYNTHS 0x510A +#define LINUX_SNDCTL_SEQ_NRMIDIS 0x510B +#define LINUX_SNDCTL_MIDI_INFO 0x510C +#define LINUX_SNDCTL_SEQ_TRESHOLD 0x510D +#define LINUX_SNDCTL_SYNTH_MEMAVL 0x510E + +#define LINUX_IOCTL_SOUND_MIN LINUX_SOUND_MIXER_WRITE_VOLUME +#define LINUX_IOCTL_SOUND_MAX LINUX_SNDCTL_SYNTH_MEMAVL + +/* + * termio + */ +#ifdef __alpha__ +#define LINUX_TCGETS 0x7413 +#define LINUX_TCSETS 0x7414 +#define LINUX_TCSETSW 0x7415 +#define LINUX_TCSETSF 0x7416 +#define LINUX_TCGETA 0x7417 +#define LINUX_TCSETA 0x7418 +#define LINUX_TCSETAW 0x7419 +#define LINUX_TCSETAF 0x741c +#define LINUX_TCSBRK 0x741d +#define LINUX_TCXONC 0x741e +#define LINUX_TCFLSH 0x741f +#else +#define LINUX_TCGETS 0x5401 +#define LINUX_TCSETS 0x5402 +#define LINUX_TCSETSW 0x5403 +#define LINUX_TCSETSF 0x5404 +#define LINUX_TCGETA 0x5405 +#define LINUX_TCSETA 0x5406 +#define LINUX_TCSETAW 0x5407 +#define LINUX_TCSETAF 0x5408 +#define LINUX_TCSBRK 0x5409 +#define LINUX_TCXONC 0x540A +#define LINUX_TCFLSH 0x540B +#endif + +#define LINUX_TIOCEXCL 0x540C +#define LINUX_TIOCNXCL 0x540D +#define LINUX_TIOCSCTTY 0x540E + +#ifdef __alpha__ +#define LINUX_TIOCSPGRP 0x7476 +#define LINUX_TIOCGPGRP 0x7477 +#else +#define LINUX_TIOCGPGRP 0x540F +#define LINUX_TIOCSPGRP 0x5410 +#endif + +#define LINUX_TIOCOUTQ 0x5411 +#define LINUX_TIOCSTI 0x5412 + +#ifdef __alpha__ +#define LINUX_TIOCSWINSZ 0x7467 +#define LINUX_TIOCGWINSZ 0x7468 +#else +#define LINUX_TIOCGWINSZ 0x5413 +#define LINUX_TIOCSWINSZ 0x5414 +#endif + +#define LINUX_TIOCMGET 0x5415 +#define LINUX_TIOCMBIS 0x5416 +#define LINUX_TIOCMBIC 0x5417 +#define LINUX_TIOCMSET 0x5418 +#define LINUX_TIOCGSOFTCAR 0x5419 +#define LINUX_TIOCSSOFTCAR 0x541A + +#ifdef __alpha__ +#define LINUX_FIONREAD 0x667f +#else +#define LINUX_FIONREAD 0x541B +#endif + +#define LINUX_TIOCINQ FIONREAD +#define LINUX_TIOCLINUX 0x541C +#define LINUX_TIOCCONS 0x541D +#define LINUX_TIOCGSERIAL 0x541E +#define LINUX_TIOCSSERIAL 0x541F +#define LINUX_TIOCPKT 0x5420 + +#ifdef __alpha__ +#define LINUX_FIONBIO 0x667e +#else +#define LINUX_FIONBIO 0x5421 +#endif + +#define LINUX_TIOCNOTTY 0x5422 +#define LINUX_TIOCSETD 0x5423 +#define LINUX_TIOCGETD 0x5424 +#define LINUX_TCSBRKP 0x5425 +#define LINUX_TIOCTTYGSTRUCT 0x5426 + +#ifdef __alpha__ +#define LINUX_FIOCLEX 0x6601 +#define LINUX_FIONCLEX 0x6602 +#define LINUX_FIOASYNC 0x667d +#else +#define LINUX_FIONCLEX 0x5450 +#define LINUX_FIOCLEX 0x5451 +#define LINUX_FIOASYNC 0x5452 +#endif + +#define LINUX_TIOCSERCONFIG 0x5453 +#define LINUX_TIOCSERGWILD 0x5454 +#define LINUX_TIOCSERSWILD 0x5455 +#define LINUX_TIOCGLCKTRMIOS 0x5456 +#define LINUX_TIOCSLCKTRMIOS 0x5457 + +#ifdef __alpha__ +#define LINUX_IOCTL_TERMIO_MIN LINUX_TIOCEXCL +#define LINUX_IOCTL_TERMIO_MAX LINUX_TIOCGPGRP +#else +#define LINUX_IOCTL_TERMIO_MIN LINUX_TCGETS +#define LINUX_IOCTL_TERMIO_MAX LINUX_TIOCSLCKTRMIOS +#endif + +/* arguments for tcflow() and LINUX_TCXONC */ +#define LINUX_TCOOFF 0 +#define LINUX_TCOON 1 +#define LINUX_TCIOFF 2 +#define LINUX_TCION 3 + +/* arguments for tcflush() and LINUX_TCFLSH */ +#define LINUX_TCIFLUSH 0 +#define LINUX_TCOFLUSH 1 +#define LINUX_TCIOFLUSH 2 + +/* line disciplines */ +#define LINUX_N_TTY 0 +#define LINUX_N_SLIP 1 +#define LINUX_N_MOUSE 2 +#define LINUX_N_PPP 3 + +/* Linux termio c_cc values */ +#ifdef __alpha__ +#define LINUX__VINTR 0 +#define LINUX__VQUIT 1 +#define LINUX__VERASE 2 +#define LINUX__VKILL 3 +#define LINUX__VEOF 4 +#define LINUX__VMIN 4 +#define LINUX__VEOL 5 +#define LINUX__VTIME 5 +#define LINUX__VEOL2 6 +#define LINUX__VSWTC 7 +#else +#define LINUX_VINTR 0 +#define LINUX_VQUIT 1 +#define LINUX_VERASE 2 +#define LINUX_VKILL 3 +#define LINUX_VEOF 4 +#define LINUX_VTIME 5 +#define LINUX_VMIN 6 +#define LINUX_VSWTC 7 +#endif +#define LINUX_NCC 8 + +/* Linux termios c_cc values */ +#ifdef __alpha__ +#define LINUX_VEOF 0 +#define LINUX_VEOL 1 +#define LINUX_VEOL2 2 +#define LINUX_VERASE 3 +#define LINUX_VWERASE 4 +#define LINUX_VKILL 5 +#define LINUX_VREPRINT 6 +#define LINUX_VSWTC 7 +#define LINUX_VINTR 8 +#define LINUX_VQUIT 9 +#define LINUX_VSUSP 10 +#define LINUX_VSTART 12 +#define LINUX_VSTOP 13 +#define LINUX_VLNEXT 14 +#define LINUX_VDISCARD 15 +#define LINUX_VMIN 16 +#define LINUX_VTIME 17 +#else +/* In addition to the termio values */ +#define LINUX_VSTART 8 +#define LINUX_VSTOP 9 +#define LINUX_VSUSP 10 +#define LINUX_VEOL 11 +#define LINUX_VREPRINT 12 +#define LINUX_VDISCARD 13 +#define LINUX_VWERASE 14 +#define LINUX_VLNEXT 15 +#define LINUX_VEOL2 16 +#endif +#define LINUX_NCCS 19 + +#define LINUX_POSIX_VDISABLE '\0' + +/* Linux c_iflag masks */ +#define LINUX_IGNBRK 0x0000001 +#define LINUX_BRKINT 0x0000002 +#define LINUX_IGNPAR 0x0000004 +#define LINUX_PARMRK 0x0000008 +#define LINUX_INPCK 0x0000010 +#define LINUX_ISTRIP 0x0000020 +#define LINUX_INLCR 0x0000040 +#define LINUX_IGNCR 0x0000080 +#define LINUX_ICRNL 0x0000100 + +#ifdef __alpha__ +#define LINUX_IXON 0x0000200 +#define LINUX_IXOFF 0x0000400 +#define LINUX_IXANY 0x0000800 +#define LINUX_IUCLC 0x0001000 +#else +#define LINUX_IUCLC 0x0000200 +#define LINUX_IXON 0x0000400 +#define LINUX_IXANY 0x0000800 +#define LINUX_IXOFF 0x0001000 +#endif + +#define LINUX_IMAXBEL 0x0002000 + +/* Linux c_oflag masks */ +#define LINUX_OPOST 0x0000001 + +#ifdef __alpha__ +#define LINUX_ONLCR 0x0000002 +#define LINUX_OLCUC 0x0000004 +#else +#define LINUX_OLCUC 0x0000002 +#define LINUX_ONLCR 0x0000004 +#endif + +#define LINUX_OCRNL 0x0000008 +#define LINUX_ONOCR 0x0000010 +#define LINUX_ONLRET 0x0000020 +#define LINUX_OFILL 0x0000040 +#define LINUX_OFDEL 0x0000080 + +#ifdef __alpha__ +#define LINUX_NLDLY 0x0000300 +#define LINUX_NL0 0x0000000 +#define LINUX_NL1 0x0000100 +#define LINUX_NL2 0x0000200 +#define LINUX_NL3 0x0000300 +#define LINUX_TABDLY 0x000C000 +#define LINUX_TAB0 0x0000000 +#define LINUX_TAB1 0x0004000 +#define LINUX_TAB2 0x0008000 +#define LINUX_TAB3 0x000C000 +#define LINUX_CRDLY 0x0030000 +#define LINUX_CR0 0x0000000 +#define LINUX_CR1 0x0010000 +#define LINUX_CR2 0x0020000 +#define LINUX_CR3 0x0030000 +#define LINUX_FFDLY 0x0040000 +#define LINUX_FF0 0x0000000 +#define LINUX_FF1 0x0040000 +#define LINUX_BSDLY 0x0080000 +#define LINUX_BS0 0x0000000 +#define LINUX_BS1 0x0080000 +#define LINUX_VTDLY 0x0100000 +#define LINUX_VT0 0x0000000 +#define LINUX_VT1 0x0100000 +#define LINUX_XTABS 0x0200000 +#else +#define LINUX_NLDLY 0x0000100 +#define LINUX_NL0 0x0000000 +#define LINUX_NL1 0x0000100 +#define LINUX_CRDLY 0x0000600 +#define LINUX_CR0 0x0000000 +#define LINUX_CR1 0x0000200 +#define LINUX_CR2 0x0000400 +#define LINUX_CR3 0x0000600 +#define LINUX_TABDLY 0x0001800 +#define LINUX_TAB0 0x0000000 +#define LINUX_TAB1 0x0000800 +#define LINUX_TAB2 0x0001000 +#define LINUX_TAB3 0x0001800 +#define LINUX_XTABS 0x0001800 +#define LINUX_BSDLY 0x0002000 +#define LINUX_BS0 0x0000000 +#define LINUX_BS1 0x0002000 +#define LINUX_VTDLY 0x0004000 +#define LINUX_VT0 0x0000000 +#define LINUX_VT1 0x0004000 +#define LINUX_FFDLY 0x0008000 +#define LINUX_FF0 0x0000000 +#define LINUX_FF1 0x0008000 +#endif + +#ifdef __alpha__ +#define LINUX_CBAUD 0x0000001f +#else +#define LINUX_CBAUD 0x0000100f +#endif + +#define LINUX_B0 0x00000000 +#define LINUX_B50 0x00000001 +#define LINUX_B75 0x00000002 +#define LINUX_B110 0x00000003 +#define LINUX_B134 0x00000004 +#define LINUX_B150 0x00000005 +#define LINUX_B200 0x00000006 +#define LINUX_B300 0x00000007 +#define LINUX_B600 0x00000008 +#define LINUX_B1200 0x00000009 +#define LINUX_B1800 0x0000000a +#define LINUX_B2400 0x0000000b +#define LINUX_B4800 0x0000000c +#define LINUX_B9600 0x0000000d +#define LINUX_B19200 0x0000000e +#define LINUX_B38400 0x0000000f +#define LINUX_EXTA LINUX_B19200 +#define LINUX_EXTB LINUX_B38400 + +#ifdef __alpha__ +#define LINUX_CBAUDEX 0x00000000 +#define LINUX_B57600 0x00000010 +#define LINUX_B115200 0x00000011 +#else +#define LINUX_CBAUDEX 0x00001000 +#define LINUX_B57600 0x00001001 +#define LINUX_B115200 0x00001002 +#endif + +#ifdef __alpha__ +#define LINUX_CSIZE 0x00000300 +#define LINUX_CS5 0x00000000 +#define LINUX_CS6 0x00000100 +#define LINUX_CS7 0x00000200 +#define LINUX_CS8 0x00000300 +#define LINUX_CSTOPB 0x00000400 +#define LINUX_CREAD 0x00000800 +#define LINUX_PARENB 0x00001000 +#define LINUX_PARODD 0x00002000 +#define LINUX_HUPCL 0x00004000 +#define LINUX_CLOCAL 0x00008000 +#else +#define LINUX_CSIZE 0x00000030 +#define LINUX_CS5 0x00000000 +#define LINUX_CS6 0x00000010 +#define LINUX_CS7 0x00000020 +#define LINUX_CS8 0x00000030 +#define LINUX_CSTOPB 0x00000040 +#define LINUX_CREAD 0x00000080 +#define LINUX_PARENB 0x00000100 +#define LINUX_PARODD 0x00000200 +#define LINUX_HUPCL 0x00000400 +#define LINUX_CLOCAL 0x00000800 +#endif + +#define LINUX_CRTSCTS 0x80000000 + +/* Linux c_lflag masks */ +#ifdef __alpha__ +#define LINUX_ECHOKE 0x00000001 +#define LINUX_ECHOE 0x00000002 +#define LINUX_ECHOK 0x00000004 +#define LINUX_ECHO 0x00000008 +#define LINUX_ECHONL 0x00000010 +#define LINUX_ECHOPRT 0x00000020 +#define LINUX_ECHOCTL 0x00000040 +#define LINUX_ISIG 0x00000080 +#define LINUX_ICANON 0x00000100 +#define LINUX_IEXTEN 0x00000400 +#define LINUX_XCASE 0x00004000 +#define LINUX_TOSTOP 0x00400000 +#define LINUX_FLUSHO 0x00800000 +#define LINUX_PENDIN 0x20000000 +#define LINUX_NOFLSH 0x80000000 +#else +#define LINUX_ISIG 0x00000001 +#define LINUX_ICANON 0x00000002 +#define LINUX_XCASE 0x00000004 +#define LINUX_ECHO 0x00000008 +#define LINUX_ECHOE 0x00000010 +#define LINUX_ECHOK 0x00000020 +#define LINUX_ECHONL 0x00000040 +#define LINUX_NOFLSH 0x00000080 +#define LINUX_TOSTOP 0x00000100 +#define LINUX_ECHOCTL 0x00000200 +#define LINUX_ECHOPRT 0x00000400 +#define LINUX_ECHOKE 0x00000800 +#define LINUX_FLUSHO 0x00001000 +#define LINUX_PENDIN 0x00002000 +#define LINUX_IEXTEN 0x00008000 +#endif + +/* serial_struct values for TIOC[GS]SERIAL ioctls */ +#define LINUX_ASYNC_CLOSING_WAIT_INF 0 +#define LINUX_ASYNC_CLOSING_WAIT_NONE 65535 + +#define LINUX_PORT_UNKNOWN 0 +#define LINUX_PORT_8250 1 +#define LINUX_PORT_16450 2 +#define LINUX_PORT_16550 3 +#define LINUX_PORT_16550A 4 +#define LINUX_PORT_CIRRUS 5 +#define LINUX_PORT_16650 6 + +#define LINUX_PORT_MAX 6 + +#define LINUX_ASYNC_HUP_NOTIFY 0x0001 +#define LINUX_ASYNC_FOURPORT 0x0002 +#define LINUX_ASYNC_SAK 0x0004 +#define LINUX_ASYNC_SPLIT_TERMIOS 0x0008 +#define LINUX_ASYNC_SPD_MASK 0x0030 +#define LINUX_ASYNC_SPD_HI 0x0010 +#define LINUX_ASYNC_SPD_VHI 0x0020 +#define LINUX_ASYNC_SPD_CUST 0x0030 +#define LINUX_ASYNC_SKIP_TEST 0x0040 +#define LINUX_ASYNC_AUTO_IRQ 0x0080 +#define LINUX_ASYNC_SESSION_LOCKOUT 0x0100 +#define LINUX_ASYNC_PGRP_LOCKOUT 0x0200 +#define LINUX_ASYNC_CALLOUT_NOHUP 0x0400 +#define LINUX_ASYNC_FLAGS 0x0FFF + +/* + * This doesn't really belong here, but I can't think of a better + * place to put it. + */ +struct ifnet; +int linux_ifname(struct ifnet *, char *, size_t); + +#endif /* !_LINUX_IOCTL_H_ */ diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c new file mode 100644 index 0000000..cf3bf61 --- /dev/null +++ b/sys/compat/linux/linux_ipc.c @@ -0,0 +1,528 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/proc.h> +#include <sys/sem.h> +#include <sys/shm.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_ipc.h> +#include <compat/linux/linux_util.h> + +struct l_seminfo { + l_int semmap; + l_int semmni; + l_int semmns; + l_int semmnu; + l_int semmsl; + l_int semopm; + l_int semume; + l_int semusz; + l_int semvmx; + l_int semaem; +}; + +struct l_shminfo { + l_int shmmax; + l_int shmmin; + l_int shmmni; + l_int shmseg; + l_int shmall; +}; + +struct l_shm_info { + l_int used_ids; + l_ulong shm_tot; /* total allocated shm */ + l_ulong shm_rss; /* total resident shm */ + l_ulong shm_swp; /* total swapped shm */ + l_ulong swap_attempts; + l_ulong swap_successes; +}; + +static void +bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp) +{ + lpp->shmmax = bpp->shmmax; + lpp->shmmin = bpp->shmmin; + lpp->shmmni = bpp->shmmni; + lpp->shmseg = bpp->shmseg; + lpp->shmall = bpp->shmall; +} + +static void +bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp) +{ + lpp->used_ids = bpp->used_ids ; + lpp->shm_tot = bpp->shm_tot ; + lpp->shm_rss = bpp->shm_rss ; + lpp->shm_swp = bpp->shm_swp ; + lpp->swap_attempts = bpp->swap_attempts ; + lpp->swap_successes = bpp->swap_successes ; +} + +struct l_ipc_perm { + l_key_t key; + l_uid16_t uid; + l_gid16_t gid; + l_uid16_t cuid; + l_gid16_t cgid; + l_ushort mode; + l_ushort seq; +}; + +static void +linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) +{ + bpp->key = lpp->key; + bpp->uid = lpp->uid; + bpp->gid = lpp->gid; + bpp->cuid = lpp->cuid; + bpp->cgid = lpp->cgid; + bpp->mode = lpp->mode; + bpp->seq = lpp->seq; +} + + +static void +bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) +{ + lpp->key = bpp->key; + lpp->uid = bpp->uid; + lpp->gid = bpp->gid; + lpp->cuid = bpp->cuid; + lpp->cgid = bpp->cgid; + lpp->mode = bpp->mode; + lpp->seq = bpp->seq; +} + +struct l_semid_ds { + struct l_ipc_perm sem_perm; + l_time_t sem_otime; + l_time_t sem_ctime; + void *sem_base; + void *sem_pending; + void *sem_pending_last; + void *undo; + l_ushort sem_nsems; +}; + +struct l_shmid_ds { + struct l_ipc_perm shm_perm; + l_int shm_segsz; + l_time_t shm_atime; + l_time_t shm_dtime; + l_time_t shm_ctime; + l_ushort shm_cpid; + l_ushort shm_lpid; + l_short shm_nattch; + l_ushort private1; + void *private2; + void *private3; +}; + +static void +linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) +{ + linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); + bsp->sem_otime = lsp->sem_otime; + bsp->sem_ctime = lsp->sem_ctime; + bsp->sem_nsems = lsp->sem_nsems; + bsp->sem_base = lsp->sem_base; +} + +static void +bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) +{ + bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); + lsp->sem_otime = bsp->sem_otime; + lsp->sem_ctime = bsp->sem_ctime; + lsp->sem_nsems = bsp->sem_nsems; + lsp->sem_base = bsp->sem_base; +} + +static void +linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) +{ + linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); + bsp->shm_segsz = lsp->shm_segsz; + bsp->shm_lpid = lsp->shm_lpid; + bsp->shm_cpid = lsp->shm_cpid; + bsp->shm_nattch = lsp->shm_nattch; + bsp->shm_atime = lsp->shm_atime; + bsp->shm_dtime = lsp->shm_dtime; + bsp->shm_ctime = lsp->shm_ctime; + bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ +} + +static void +bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) +{ + bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); + lsp->shm_segsz = bsp->shm_segsz; + lsp->shm_lpid = bsp->shm_lpid; + lsp->shm_cpid = bsp->shm_cpid; + lsp->shm_nattch = bsp->shm_nattch; + lsp->shm_atime = bsp->shm_atime; + lsp->shm_dtime = bsp->shm_dtime; + lsp->shm_ctime = bsp->shm_ctime; + lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ +} + +int +linux_semop(struct thread *td, struct linux_semop_args *args) +{ + struct semop_args /* { + int semid; + struct sembuf *sops; + int nsops; + } */ bsd_args; + + bsd_args.semid = args->semid; + bsd_args.sops = (struct sembuf *)args->tsops; + bsd_args.nsops = args->nsops; + return semop(td, &bsd_args); +} + +int +linux_semget(struct thread *td, struct linux_semget_args *args) +{ + struct semget_args /* { + key_t key; + int nsems; + int semflg; + } */ bsd_args; + + bsd_args.key = args->key; + bsd_args.nsems = args->nsems; + bsd_args.semflg = args->semflg; + return semget(td, &bsd_args); +} + +int +linux_semctl(struct thread *td, struct linux_semctl_args *args) +{ + struct l_semid_ds linux_semid; + struct __semctl_args /* { + int semid; + int semnum; + int cmd; + union semun *arg; + } */ bsd_args; + struct l_seminfo linux_seminfo; + int error; + union semun *unptr; + caddr_t sg; + + sg = stackgap_init(); + + /* Make sure the arg parameter can be copied in. */ + unptr = stackgap_alloc(&sg, sizeof(union semun)); + bcopy(&args->arg, unptr, sizeof(union semun)); + + bsd_args.semid = args->semid; + bsd_args.semnum = args->semnum; + bsd_args.arg = unptr; + + switch (args->cmd) { + case LINUX_IPC_RMID: + bsd_args.cmd = IPC_RMID; + break; + case LINUX_GETNCNT: + bsd_args.cmd = GETNCNT; + break; + case LINUX_GETPID: + bsd_args.cmd = GETPID; + break; + case LINUX_GETVAL: + bsd_args.cmd = GETVAL; + break; + case LINUX_GETZCNT: + bsd_args.cmd = GETZCNT; + break; + case LINUX_SETVAL: + bsd_args.cmd = SETVAL; + break; + case LINUX_IPC_SET: + bsd_args.cmd = IPC_SET; + error = copyin((caddr_t)args->arg.buf, &linux_semid, + sizeof(linux_semid)); + if (error) + return (error); + unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds)); + linux_to_bsd_semid_ds(&linux_semid, unptr->buf); + return __semctl(td, &bsd_args); + case LINUX_IPC_STAT: + case LINUX_SEM_STAT: + if( args->cmd == LINUX_IPC_STAT ) + bsd_args.cmd = IPC_STAT; + else + bsd_args.cmd = SEM_STAT; + unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds)); + error = __semctl(td, &bsd_args); + if (error) + return error; + td->td_retval[0] = IXSEQ_TO_IPCID(bsd_args.semid, + unptr->buf->sem_perm); + bsd_to_linux_semid_ds(unptr->buf, &linux_semid); + return copyout(&linux_semid, (caddr_t)args->arg.buf, + sizeof(linux_semid)); + case LINUX_IPC_INFO: + case LINUX_SEM_INFO: + error = copyin((caddr_t)args->arg.buf, &linux_seminfo, + sizeof(linux_seminfo) ); + if (error) + return error; + bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) ); +/* XXX BSD equivalent? +#define used_semids 10 +#define used_sems 10 + linux_seminfo.semusz = used_semids; + linux_seminfo.semaem = used_sems; +*/ + error = copyout((caddr_t)&linux_seminfo, (caddr_t)args->arg.buf, + sizeof(linux_seminfo) ); + if (error) + return error; + td->td_retval[0] = seminfo.semmni; + return 0; /* No need for __semctl call */ + case LINUX_GETALL: + /* FALLTHROUGH */ + case LINUX_SETALL: + /* FALLTHROUGH */ + default: + uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd); + return EINVAL; + } + return __semctl(td, &bsd_args); +} + +int +linux_msgsnd(struct thread *td, struct linux_msgsnd_args *args) +{ + struct msgsnd_args /* { + int msqid; + void *msgp; + size_t msgsz; + int msgflg; + } */ bsd_args; + + bsd_args.msqid = args->msqid; + bsd_args.msgp = args->msgp; + bsd_args.msgsz = args->msgsz; + bsd_args.msgflg = args->msgflg; + return msgsnd(td, &bsd_args); +} + +int +linux_msgrcv(struct thread *td, struct linux_msgrcv_args *args) +{ + struct msgrcv_args /* { + int msqid; + void *msgp; + size_t msgsz; + long msgtyp; + int msgflg; + } */ bsd_args; + + bsd_args.msqid = args->msqid; + bsd_args.msgp = args->msgp; + bsd_args.msgsz = args->msgsz; + bsd_args.msgtyp = args->msgtyp; + bsd_args.msgflg = args->msgflg; + return msgrcv(td, &bsd_args); +} + +int +linux_msgget(struct thread *td, struct linux_msgget_args *args) +{ + struct msgget_args /* { + key_t key; + int msgflg; + } */ bsd_args; + + bsd_args.key = args->key; + bsd_args.msgflg = args->msgflg; + return msgget(td, &bsd_args); +} + +int +linux_msgctl(struct thread *td, struct linux_msgctl_args *args) +{ + struct msgctl_args /* { + int msqid; + int cmd; + struct msqid_ds *buf; + } */ bsd_args; + int error; + + bsd_args.msqid = args->msqid; + bsd_args.cmd = args->cmd; + bsd_args.buf = (struct msqid_ds *)args->buf; + error = msgctl(td, &bsd_args); + return ((args->cmd == LINUX_IPC_RMID && error == EINVAL) ? 0 : error); +} + +int +linux_shmat(struct thread *td, struct linux_shmat_args *args) +{ + struct shmat_args /* { + int shmid; + void *shmaddr; + int shmflg; + } */ bsd_args; + int error; + + bsd_args.shmid = args->shmid; + bsd_args.shmaddr = args->shmaddr; + bsd_args.shmflg = args->shmflg; + if ((error = shmat(td, &bsd_args))) + return error; +#ifdef __i386__ + if ((error = copyout(td->td_retval, (caddr_t)args->raddr, sizeof(l_ulong)))) + return error; + td->td_retval[0] = 0; +#endif + return 0; +} + +int +linux_shmdt(struct thread *td, struct linux_shmdt_args *args) +{ + struct shmdt_args /* { + void *shmaddr; + } */ bsd_args; + + bsd_args.shmaddr = args->shmaddr; + return shmdt(td, &bsd_args); +} + +int +linux_shmget(struct thread *td, struct linux_shmget_args *args) +{ + struct shmget_args /* { + key_t key; + int size; + int shmflg; + } */ bsd_args; + + bsd_args.key = args->key; + bsd_args.size = args->size; + bsd_args.shmflg = args->shmflg; + return shmget(td, &bsd_args); +} + +int +linux_shmctl(struct thread *td, struct linux_shmctl_args *args) +{ + struct l_shmid_ds linux_shmid; + struct l_shminfo linux_shminfo; + struct l_shm_info linux_shm_info; + struct shmctl_args /* { + int shmid; + int cmd; + struct shmid_ds *buf; + } */ bsd_args; + int error; + caddr_t sg = stackgap_init(); + + switch (args->cmd) { + + case LINUX_IPC_INFO: + bsd_args.shmid = args->shmid; + bsd_args.cmd = IPC_INFO; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shminfo)); + if ((error = shmctl(td, &bsd_args))) + return error; + bsd_to_linux_shminfo( (struct shminfo *)bsd_args.buf, &linux_shminfo ); + return copyout(&linux_shminfo, (caddr_t)args->buf, sizeof(shminfo)); + + case LINUX_SHM_INFO: + bsd_args.shmid = args->shmid; + bsd_args.cmd = SHM_INFO; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shm_info)); + if ((error = shmctl(td, &bsd_args))) + return error; + bsd_to_linux_shm_info( (struct shm_info *)bsd_args.buf, &linux_shm_info ); + return copyout(&linux_shm_info, (caddr_t)args->buf, sizeof(struct shm_info)); + + case LINUX_IPC_STAT: + bsd_args.shmid = args->shmid; + bsd_args.cmd = IPC_STAT; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); + if ((error = shmctl(td, &bsd_args))) + return error; + bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid); + return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid)); + + case LINUX_SHM_STAT: + bsd_args.shmid = args->shmid; + bsd_args.cmd = SHM_STAT; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); + if ((error = shmctl(td, &bsd_args))) { + return error; + } + bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid); + return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid)); + + case LINUX_IPC_SET: + if ((error = copyin((caddr_t)args->buf, &linux_shmid, + sizeof(linux_shmid)))) + return error; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); + linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf); + bsd_args.shmid = args->shmid; + bsd_args.cmd = IPC_SET; + return shmctl(td, &bsd_args); + + case LINUX_IPC_RMID: + bsd_args.shmid = args->shmid; + bsd_args.cmd = IPC_RMID; + if (args->buf == NULL) + bsd_args.buf = NULL; + else { + if ((error = copyin((caddr_t)args->buf, &linux_shmid, + sizeof(linux_shmid)))) + return error; + bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); + linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf); + } + return shmctl(td, &bsd_args); + + case LINUX_SHM_LOCK: + case LINUX_SHM_UNLOCK: + default: + uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd); + return EINVAL; + } +} diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h new file mode 100644 index 0000000..183afe1 --- /dev/null +++ b/sys/compat/linux/linux_ipc.h @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2000 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_IPC_H_ +#define _LINUX_IPC_H_ + +#ifdef __i386__ + +struct linux_msgctl_args +{ + l_int msqid; + l_int cmd; + struct l_msqid_ds *buf; +}; + +struct linux_msgget_args +{ + l_key_t key; + l_int msgflg; +}; + +struct linux_msgrcv_args +{ + l_int msqid; + struct l_msgbuf *msgp; + l_size_t msgsz; + l_long msgtyp; + l_int msgflg; +}; + +struct linux_msgsnd_args +{ + l_int msqid; + struct l_msgbuf *msgp; + l_size_t msgsz; + l_int msgflg; +}; + +struct linux_semctl_args +{ + l_int semid; + l_int semnum; + l_int cmd; + union l_semun arg; +}; + +struct linux_semget_args +{ + l_key_t key; + l_int nsems; + l_int semflg; +}; + +struct linux_semop_args +{ + l_int semid; + struct l_sembuf *tsops; + l_uint nsops; +}; + +struct linux_shmat_args +{ + l_int shmid; + char *shmaddr; + l_int shmflg; + l_ulong *raddr; +}; + +struct linux_shmctl_args +{ + l_int shmid; + l_int cmd; + struct l_shmid_ds *buf; +}; + +struct linux_shmdt_args +{ + char *shmaddr; +}; + +struct linux_shmget_args +{ + l_key_t key; + l_size_t size; + l_int shmflg; +}; + +int linux_msgctl(struct thread *, struct linux_msgctl_args *); +int linux_msgget(struct thread *, struct linux_msgget_args *); +int linux_msgrcv(struct thread *, struct linux_msgrcv_args *); +int linux_msgsnd(struct thread *, struct linux_msgsnd_args *); + +int linux_semctl(struct thread *, struct linux_semctl_args *); +int linux_semget(struct thread *, struct linux_semget_args *); +int linux_semop(struct thread *, struct linux_semop_args *); + +int linux_shmat(struct thread *, struct linux_shmat_args *); +int linux_shmctl(struct thread *, struct linux_shmctl_args *); +int linux_shmdt(struct thread *, struct linux_shmdt_args *); +int linux_shmget(struct thread *, struct linux_shmget_args *); + +#endif /* __i386__ */ + +#endif /* _LINUX_IPC_H_ */ diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c new file mode 100644 index 0000000..d9cdd07 --- /dev/null +++ b/sys/compat/linux/linux_mib.c @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1999 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/jail.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <machine/../linux/linux.h> +#include <compat/linux/linux_mib.h> + +struct linux_prison { + char pr_osname[LINUX_MAX_UTSNAME]; + char pr_osrelease[LINUX_MAX_UTSNAME]; + int pr_oss_version; +}; + +SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, + "Linux mode"); + +static char linux_osname[LINUX_MAX_UTSNAME] = "Linux"; + +static int +linux_sysctl_osname(SYSCTL_HANDLER_ARGS) +{ + char osname[LINUX_MAX_UTSNAME]; + int error; + + linux_get_osname(req->td->td_proc, osname); + error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); + if (error || req->newptr == NULL) + return (error); + error = linux_set_osname(req->td->td_proc, osname); + return (error); +} + +SYSCTL_PROC(_compat_linux, OID_AUTO, osname, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON, + 0, 0, linux_sysctl_osname, "A", + "Linux kernel OS name"); + +static char linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2"; + +static int +linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) +{ + char osrelease[LINUX_MAX_UTSNAME]; + int error; + + linux_get_osrelease(req->td->td_proc, osrelease); + error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); + if (error || req->newptr == NULL) + return (error); + error = linux_set_osrelease(req->td->td_proc, osrelease); + return (error); +} + +SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON, + 0, 0, linux_sysctl_osrelease, "A", + "Linux kernel OS release"); + +static int linux_oss_version = 0x030600; + +static int +linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) +{ + int oss_version; + int error; + + oss_version = linux_get_oss_version(req->td->td_proc); + error = sysctl_handle_int(oidp, &oss_version, 0, req); + if (error || req->newptr == NULL) + return (error); + error = linux_set_oss_version(req->td->td_proc, oss_version); + return (error); +} + +SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON, + 0, 0, linux_sysctl_oss_version, "I", + "Linux OSS version"); + +/* + * Returns holding the prison mutex if return non-NULL. + */ +static struct linux_prison * +linux_get_prison(struct proc *p) +{ + register struct prison *pr; + register struct linux_prison *lpr; + + if (!jailed(p->p_ucred)) + return (NULL); + + pr = p->p_ucred->cr_prison; + + /* + * Rather than hold the prison mutex during allocation, check to + * see if we need to allocate while holding the mutex, release it, + * allocate, then once we've allocated the memory, check again to + * see if it's still needed, and set if appropriate. If it's not, + * we release the mutex again to FREE(), and grab it again so as + * to release holding the lock. + */ + mtx_lock(&pr->pr_mtx); + if (pr->pr_linux == NULL) { + mtx_unlock(&pr->pr_mtx); + MALLOC(lpr, struct linux_prison *, sizeof *lpr, + M_PRISON, M_WAITOK|M_ZERO); + mtx_lock(&pr->pr_mtx); + if (pr->pr_linux == NULL) { + pr->pr_linux = lpr; + } else { + mtx_unlock(&pr->pr_mtx); + FREE(lpr, M_PRISON); + mtx_lock(&pr->pr_mtx); + } + } + + return (pr->pr_linux); +} + +void +linux_get_osname(p, dst) + struct proc *p; + char *dst; +{ + register struct prison *pr; + register struct linux_prison *lpr; + + if (p->p_ucred->cr_prison == NULL) { + bcopy(linux_osname, dst, LINUX_MAX_UTSNAME); + return; + } + + pr = p->p_ucred->cr_prison; + + mtx_lock(&pr->pr_mtx); + if (pr->pr_linux != NULL) { + lpr = (struct linux_prison *)pr->pr_linux; + if (lpr->pr_osname[0]) { + bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); + mtx_unlock(&pr->pr_mtx); + return; + } + } + mtx_unlock(&pr->pr_mtx); + bcopy(linux_osname, dst, LINUX_MAX_UTSNAME); +} + +int +linux_set_osname(p, osname) + struct proc *p; + char *osname; +{ + register struct linux_prison *lpr; + + lpr = linux_get_prison(p); + if (lpr != NULL) { + strcpy(lpr->pr_osname, osname); + mtx_unlock(&p->p_ucred->cr_prison->pr_mtx); + } else { + strcpy(linux_osname, osname); + } + + return (0); +} + +void +linux_get_osrelease(p, dst) + struct proc *p; + char *dst; +{ + register struct prison *pr; + struct linux_prison *lpr; + + if (p->p_ucred->cr_prison == NULL) { + bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME); + return; + } + + pr = p->p_ucred->cr_prison; + + mtx_lock(&pr->pr_mtx); + if (pr->pr_linux != NULL) { + lpr = (struct linux_prison *) pr->pr_linux; + if (lpr->pr_osrelease[0]) { + bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); + mtx_unlock(&pr->pr_mtx); + return; + } + } + mtx_unlock(&pr->pr_mtx); + bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME); +} + +int +linux_set_osrelease(p, osrelease) + struct proc *p; + char *osrelease; +{ + register struct linux_prison *lpr; + + lpr = linux_get_prison(p); + if (lpr != NULL) { + strcpy(lpr->pr_osrelease, osrelease); + mtx_unlock(&p->p_ucred->cr_prison->pr_mtx); + } else { + strcpy(linux_osrelease, osrelease); + } + + return (0); +} + +int +linux_get_oss_version(p) + struct proc *p; +{ + register struct prison *pr; + register struct linux_prison *lpr; + int version; + + if (p->p_ucred->cr_prison == NULL) + return (linux_oss_version); + + pr = p->p_ucred->cr_prison; + + mtx_lock(&pr->pr_mtx); + if (pr->pr_linux != NULL) { + lpr = (struct linux_prison *) pr->pr_linux; + if (lpr->pr_oss_version) { + version = lpr->pr_oss_version; + } else { + version = linux_oss_version; + } + } else { + version = linux_oss_version; + } + mtx_unlock(&pr->pr_mtx); + + return (version); +} + +int +linux_set_oss_version(p, oss_version) + struct proc *p; + int oss_version; +{ + register struct linux_prison *lpr; + + lpr = linux_get_prison(p); + if (lpr != NULL) { + lpr->pr_oss_version = oss_version; + mtx_unlock(&p->p_ucred->cr_prison->pr_mtx); + } else { + linux_oss_version = oss_version; + } + + return (0); +} + +#ifdef DEBUG + +u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))]; + +static int +linux_debug(int syscall, int toggle, int global) +{ + + if (global) { + char c = toggle ? 0 : 0xff; + + memset(linux_debug_map, c, sizeof(linux_debug_map)); + return (0); + } + if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL) + return (EINVAL); + if (toggle) + clrbit(linux_debug_map, syscall); + else + setbit(linux_debug_map, syscall); + return (0); +} + +/* + * Usage: sysctl linux.debug=<syscall_nr>.<0/1> + * + * E.g.: sysctl linux.debug=21.0 + * + * As a special case, syscall "all" will apply to all syscalls globally. + */ +#define LINUX_MAX_DEBUGSTR 16 +static int +linux_sysctl_debug(SYSCTL_HANDLER_ARGS) +{ + char value[LINUX_MAX_DEBUGSTR], *p; + int error, sysc, toggle; + int global = 0; + + value[0] = '\0'; + error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req); + if (error || req->newptr == NULL) + return (error); + for (p = value; *p != '\0' && *p != '.'; p++); + if (*p == '\0') + return (EINVAL); + *p++ = '\0'; + sysc = strtol(value, NULL, 0); + toggle = strtol(p, NULL, 0); + if (strcmp(value, "all") == 0) + global = 1; + error = linux_debug(sysc, toggle, global); + return (error); +} + +SYSCTL_PROC(_compat_linux, OID_AUTO, debug, + CTLTYPE_STRING | CTLFLAG_RW, + 0, 0, linux_sysctl_debug, "A", + "Linux debugging control"); + +#endif /* DEBUG */ diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h new file mode 100644 index 0000000..9e122ec --- /dev/null +++ b/sys/compat/linux/linux_mib.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 1999 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_MIB_H_ +#define _LINUX_MIB_H_ + +void linux_get_osname(struct proc *p, char *dst); +int linux_set_osname(struct proc *p, char *osname); + +void linux_get_osrelease(struct proc *p, char *dst); +int linux_set_osrelease(struct proc *p, char *osrelease); + +int linux_get_oss_version(struct proc *p); +int linux_set_oss_version(struct proc *p, int oss_version); + +#endif /* _LINUX_MIB_H_ */ diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c new file mode 100644 index 0000000..d6259bc --- /dev/null +++ b/sys/compat/linux/linux_misc.c @@ -0,0 +1,1349 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_compat.h" +#include "opt_mac.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/fcntl.h> +#include <sys/imgact_aout.h> +#include <sys/jail.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mac.h> +#include <sys/mman.h> +#include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/poll.h> +#include <sys/proc.h> +#include <sys/blist.h> +#include <sys/reboot.h> +#include <sys/resourcevar.h> +#include <sys/signalvar.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/sysproto.h> +#include <sys/time.h> +#include <sys/unistd.h> +#include <sys/vmmeter.h> +#include <sys/vnode.h> +#include <sys/wait.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_kern.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> +#include <vm/vm_object.h> +#include <vm/swap_pager.h> + +#include <machine/limits.h> + +#include <posix4/sched.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_mib.h> +#include <compat/linux/linux_util.h> + +#ifdef __alpha__ +#define BSD_TO_LINUX_SIGNAL(sig) (sig) +#else +#define BSD_TO_LINUX_SIGNAL(sig) \ + (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) +#endif + +#ifndef __alpha__ +static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { + RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, + RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, + RLIMIT_MEMLOCK, -1 +}; +#endif /*!__alpha__*/ + +struct l_sysinfo { + l_long uptime; /* Seconds since boot */ + l_ulong loads[3]; /* 1, 5, and 15 minute load averages */ + l_ulong totalram; /* Total usable main memory size */ + l_ulong freeram; /* Available memory size */ + l_ulong sharedram; /* Amount of shared memory */ + l_ulong bufferram; /* Memory used by buffers */ + l_ulong totalswap; /* Total swap space size */ + l_ulong freeswap; /* swap space still available */ + l_ushort procs; /* Number of current processes */ + char _f[22]; /* Pads structure to 64 bytes */ +}; +#ifndef __alpha__ +int +linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args) +{ + struct l_sysinfo sysinfo; + vm_object_t object; + int i; + struct timespec ts; + + /* Uptime is copied out of print_uptime() in kern_shutdown.c */ + getnanouptime(&ts); + i = 0; + if (ts.tv_sec >= 86400) { + ts.tv_sec %= 86400; + i = 1; + } + if (i || ts.tv_sec >= 3600) { + ts.tv_sec %= 3600; + i = 1; + } + if (i || ts.tv_sec >= 60) { + ts.tv_sec %= 60; + i = 1; + } + sysinfo.uptime=ts.tv_sec; + + /* Use the information from the mib to get our load averages */ + for (i = 0; i < 3; i++) + sysinfo.loads[i] = averunnable.ldavg[i]; + + sysinfo.totalram = physmem * PAGE_SIZE; + sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE; + + sysinfo.sharedram = 0; + for (object = TAILQ_FIRST(&vm_object_list); object != NULL; + object = TAILQ_NEXT(object, object_list)) + if (object->shadow_count > 1) + sysinfo.sharedram += object->resident_page_count; + + sysinfo.sharedram *= PAGE_SIZE; + sysinfo.bufferram = 0; + + if (swapblist == NULL) { + sysinfo.totalswap= 0; + sysinfo.freeswap = 0; + } else { + sysinfo.totalswap = swapblist->bl_blocks * 1024; + sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE; + } + + sysinfo.procs = 20; /* Hack */ + + return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo)); +} +#endif /*!__alpha__*/ + +#ifndef __alpha__ +int +linux_alarm(struct thread *td, struct linux_alarm_args *args) +{ + struct itimerval it, old_it; + struct timeval tv; + int s; + +#ifdef DEBUG + if (ldebug(alarm)) + printf(ARGS(alarm, "%u"), args->secs); +#endif + + if (args->secs > 100000000) + return EINVAL; + + it.it_value.tv_sec = (long)args->secs; + it.it_value.tv_usec = 0; + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + s = splsoftclock(); + old_it = td->td_proc->p_realtimer; + getmicrouptime(&tv); + if (timevalisset(&old_it.it_value)) + callout_stop(&td->td_proc->p_itcallout); + if (it.it_value.tv_sec != 0) { + callout_reset(&td->td_proc->p_itcallout, tvtohz(&it.it_value), + realitexpire, td->td_proc); + timevaladd(&it.it_value, &tv); + } + td->td_proc->p_realtimer = it; + splx(s); + if (timevalcmp(&old_it.it_value, &tv, >)) { + timevalsub(&old_it.it_value, &tv); + if (old_it.it_value.tv_usec != 0) + old_it.it_value.tv_sec++; + td->td_retval[0] = old_it.it_value.tv_sec; + } + return 0; +} +#endif /*!__alpha__*/ + +int +linux_brk(struct thread *td, struct linux_brk_args *args) +{ + struct vmspace *vm = td->td_proc->p_vmspace; + vm_offset_t new, old; + struct obreak_args /* { + char * nsize; + } */ tmp; + +#ifdef DEBUG + if (ldebug(brk)) + printf(ARGS(brk, "%p"), (void *)args->dsend); +#endif + old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); + new = (vm_offset_t)args->dsend; + tmp.nsize = (char *) new; + if (((caddr_t)new > vm->vm_daddr) && !obreak(td, &tmp)) + td->td_retval[0] = (long)new; + else + td->td_retval[0] = (long)old; + + return 0; +} + +int +linux_uselib(struct thread *td, struct linux_uselib_args *args) +{ + struct nameidata ni; + struct vnode *vp; + struct exec *a_out; + struct vattr attr; + vm_offset_t vmaddr; + unsigned long file_offset; + vm_offset_t buffer; + unsigned long bss_size; + int error; + caddr_t sg; + int locked; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->library); + +#ifdef DEBUG + if (ldebug(uselib)) + printf(ARGS(uselib, "%s"), args->library); +#endif + + a_out = NULL; + locked = 0; + vp = NULL; + + /* + * XXX: This code should make use of vn_open(), rather than doing + * all this stuff itself. + */ + NDINIT(&ni, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, args->library, td); + error = namei(&ni); + if (error) + goto cleanup; + + vp = ni.ni_vp; + /* + * XXX - This looks like a bogus check. A LOCKLEAF namei should not + * succeed without returning a vnode. + */ + if (vp == NULL) { + error = ENOEXEC; /* ?? */ + goto cleanup; + } + NDFREE(&ni, NDF_ONLY_PNBUF); + + /* + * From here on down, we have a locked vnode that must be unlocked. + */ + locked++; + + /* Writable? */ + if (vp->v_writecount) { + error = ETXTBSY; + goto cleanup; + } + + /* Executable? */ + error = VOP_GETATTR(vp, &attr, td->td_ucred, td); + if (error) + goto cleanup; + + if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || + ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { + error = ENOEXEC; + goto cleanup; + } + + /* Sensible size? */ + if (attr.va_size == 0) { + error = ENOEXEC; + goto cleanup; + } + + /* Can we access it? */ + error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + if (error) + goto cleanup; + + /* + * XXX: This should use vn_open() so that it is properly authorized, + * and to reduce code redundancy all over the place here. + */ +#ifdef MAC + error = mac_check_vnode_open(td->td_ucred, vp, FREAD); + if (error) + goto cleanup; +#endif + error = VOP_OPEN(vp, FREAD, td->td_ucred, td); + if (error) + goto cleanup; + + /* + * Lock no longer needed + */ + VOP_UNLOCK(vp, 0, td); + locked = 0; + + /* Pull in executable header into kernel_map */ + error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, + VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); + if (error) + goto cleanup; + + /* Is it a Linux binary ? */ + if (((a_out->a_magic >> 16) & 0xff) != 0x64) { + error = ENOEXEC; + goto cleanup; + } + + /* + * While we are here, we should REALLY do some more checks + */ + + /* Set file/virtual offset based on a.out variant. */ + switch ((int)(a_out->a_magic & 0xffff)) { + case 0413: /* ZMAGIC */ + file_offset = 1024; + break; + case 0314: /* QMAGIC */ + file_offset = 0; + break; + default: + error = ENOEXEC; + goto cleanup; + } + + bss_size = round_page(a_out->a_bss); + + /* Check various fields in header for validity/bounds. */ + if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { + error = ENOEXEC; + goto cleanup; + } + + /* text + data can't exceed file size */ + if (a_out->a_data + a_out->a_text > attr.va_size) { + error = EFAULT; + goto cleanup; + } + + /* To protect td->td_proc->p_rlimit in the if condition. */ + mtx_assert(&Giant, MA_OWNED); + + /* + * text/data/bss must not exceed limits + * XXX - this is not complete. it should check current usage PLUS + * the resources needed by this library. + */ + if (a_out->a_text > maxtsiz || + a_out->a_data + bss_size > + td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur) { + error = ENOMEM; + goto cleanup; + } + + mp_fixme("Unlocked vflags access."); + /* prevent more writers */ + vp->v_vflag |= VV_TEXT; + + /* + * Check if file_offset page aligned. Currently we cannot handle + * misalinged file offsets, and so we read in the entire image + * (what a waste). + */ + if (file_offset & PAGE_MASK) { +#ifdef DEBUG + printf("uselib: Non page aligned binary %lu\n", file_offset); +#endif + /* Map text+data read/write/execute */ + + /* a_entry is the load address and is page aligned */ + vmaddr = trunc_page(a_out->a_entry); + + /* get anon user mapping, read+write+execute */ + error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, + &vmaddr, a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, + VM_PROT_ALL, 0); + if (error) + goto cleanup; + + /* map file into kernel_map */ + error = vm_mmap(kernel_map, &buffer, + round_page(a_out->a_text + a_out->a_data + file_offset), + VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, + trunc_page(file_offset)); + if (error) + goto cleanup; + + /* copy from kernel VM space to user space */ + error = copyout((caddr_t)(uintptr_t)(buffer + file_offset), + (caddr_t)vmaddr, a_out->a_text + a_out->a_data); + + /* release temporary kernel space */ + vm_map_remove(kernel_map, buffer, buffer + + round_page(a_out->a_text + a_out->a_data + file_offset)); + + if (error) + goto cleanup; + } else { +#ifdef DEBUG + printf("uselib: Page aligned binary %lu\n", file_offset); +#endif + /* + * for QMAGIC, a_entry is 20 bytes beyond the load address + * to skip the executable header + */ + vmaddr = trunc_page(a_out->a_entry); + + /* + * Map it all into the process's space as a single + * copy-on-write "data" segment. + */ + error = vm_mmap(&td->td_proc->p_vmspace->vm_map, &vmaddr, + a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, + MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset); + if (error) + goto cleanup; + } +#ifdef DEBUG + printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0], + ((long*)vmaddr)[1]); +#endif + if (bss_size != 0) { + /* Calculate BSS start address */ + vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + + a_out->a_data; + + /* allocate some 'anon' space */ + error = vm_map_find(&td->td_proc->p_vmspace->vm_map, NULL, 0, + &vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) + goto cleanup; + } + +cleanup: + /* Unlock vnode if needed */ + if (locked) + VOP_UNLOCK(vp, 0, td); + + /* Release the kernel mapping. */ + if (a_out) + vm_map_remove(kernel_map, (vm_offset_t)a_out, + (vm_offset_t)a_out + PAGE_SIZE); + + return error; +} + +int +linux_select(struct thread *td, struct linux_select_args *args) +{ + struct select_args bsa; + struct timeval tv0, tv1, utv, *tvp; + caddr_t sg; + int error; + +#ifdef DEBUG + if (ldebug(select)) + printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, + (void *)args->readfds, (void *)args->writefds, + (void *)args->exceptfds, (void *)args->timeout); +#endif + + error = 0; + bsa.nd = args->nfds; + bsa.in = args->readfds; + bsa.ou = args->writefds; + bsa.ex = args->exceptfds; + bsa.tv = (struct timeval *)args->timeout; + + /* + * Store current time for computation of the amount of + * time left. + */ + if (args->timeout) { + if ((error = copyin((caddr_t)args->timeout, &utv, + sizeof(utv)))) + goto select_out; +#ifdef DEBUG + if (ldebug(select)) + printf(LMSG("incoming timeout (%ld/%ld)"), + utv.tv_sec, utv.tv_usec); +#endif + + if (itimerfix(&utv)) { + /* + * The timeval was invalid. Convert it to something + * valid that will act as it does under Linux. + */ + sg = stackgap_init(); + tvp = stackgap_alloc(&sg, sizeof(utv)); + utv.tv_sec += utv.tv_usec / 1000000; + utv.tv_usec %= 1000000; + if (utv.tv_usec < 0) { + utv.tv_sec -= 1; + utv.tv_usec += 1000000; + } + if (utv.tv_sec < 0) + timevalclear(&utv); + if ((error = copyout(&utv, tvp, sizeof(utv)))) + goto select_out; + bsa.tv = tvp; + } + microtime(&tv0); + } + + error = select(td, &bsa); +#ifdef DEBUG + if (ldebug(select)) + printf(LMSG("real select returns %d"), error); +#endif + if (error) { + /* + * See fs/select.c in the Linux kernel. Without this, + * Maelstrom doesn't work. + */ + if (error == ERESTART) + error = EINTR; + goto select_out; + } + + if (args->timeout) { + if (td->td_retval[0]) { + /* + * Compute how much time was left of the timeout, + * by subtracting the current time and the time + * before we started the call, and subtracting + * that result from the user-supplied value. + */ + microtime(&tv1); + timevalsub(&tv1, &tv0); + timevalsub(&utv, &tv1); + if (utv.tv_sec < 0) + timevalclear(&utv); + } else + timevalclear(&utv); +#ifdef DEBUG + if (ldebug(select)) + printf(LMSG("outgoing timeout (%ld/%ld)"), + utv.tv_sec, utv.tv_usec); +#endif + if ((error = copyout(&utv, (caddr_t)args->timeout, + sizeof(utv)))) + goto select_out; + } + +select_out: +#ifdef DEBUG + if (ldebug(select)) + printf(LMSG("select_out -> %d"), error); +#endif + return error; +} + +int +linux_mremap(struct thread *td, struct linux_mremap_args *args) +{ + struct munmap_args /* { + void *addr; + size_t len; + } */ bsd_args; + int error = 0; + +#ifdef DEBUG + if (ldebug(mremap)) + printf(ARGS(mremap, "%p, %08lx, %08lx, %08lx"), + (void *)args->addr, + (unsigned long)args->old_len, + (unsigned long)args->new_len, + (unsigned long)args->flags); +#endif + args->new_len = round_page(args->new_len); + args->old_len = round_page(args->old_len); + + if (args->new_len > args->old_len) { + td->td_retval[0] = 0; + return ENOMEM; + } + + if (args->new_len < args->old_len) { + bsd_args.addr = (caddr_t)(args->addr + args->new_len); + bsd_args.len = args->old_len - args->new_len; + error = munmap(td, &bsd_args); + } + + td->td_retval[0] = error ? 0 : (u_long)args->addr; + return error; +} + +int +linux_msync(struct thread *td, struct linux_msync_args *args) +{ + struct msync_args bsd_args; + + bsd_args.addr = (caddr_t)args->addr; + bsd_args.len = args->len; + bsd_args.flags = 0; /* XXX ignore */ + + return msync(td, &bsd_args); +} + +#ifndef __alpha__ +int +linux_time(struct thread *td, struct linux_time_args *args) +{ + struct timeval tv; + l_time_t tm; + int error; + +#ifdef DEBUG + if (ldebug(time)) + printf(ARGS(time, "*")); +#endif + + microtime(&tv); + tm = tv.tv_sec; + if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm)))) + return error; + td->td_retval[0] = tm; + return 0; +} +#endif /*!__alpha__*/ + +struct l_times_argv { + l_long tms_utime; + l_long tms_stime; + l_long tms_cutime; + l_long tms_cstime; +}; + +#ifdef __alpha__ +#define CLK_TCK 1024 /* Linux uses 1024 on alpha */ +#else +#define CLK_TCK 100 /* Linux uses 100 */ +#endif + +#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) + +int +linux_times(struct thread *td, struct linux_times_args *args) +{ + struct timeval tv; + struct l_times_argv tms; + struct rusage ru; + int error; + +#ifdef DEBUG + if (ldebug(times)) + printf(ARGS(times, "*")); +#endif + + mtx_lock_spin(&sched_lock); + calcru(td->td_proc, &ru.ru_utime, &ru.ru_stime, NULL); + mtx_unlock_spin(&sched_lock); + + tms.tms_utime = CONVTCK(ru.ru_utime); + tms.tms_stime = CONVTCK(ru.ru_stime); + + tms.tms_cutime = CONVTCK(td->td_proc->p_stats->p_cru.ru_utime); + tms.tms_cstime = CONVTCK(td->td_proc->p_stats->p_cru.ru_stime); + + if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms)))) + return error; + + microuptime(&tv); + td->td_retval[0] = (int)CONVTCK(tv); + return 0; +} + +int +linux_newuname(struct thread *td, struct linux_newuname_args *args) +{ + struct l_new_utsname utsname; + char osname[LINUX_MAX_UTSNAME]; + char osrelease[LINUX_MAX_UTSNAME]; + +#ifdef DEBUG + if (ldebug(newuname)) + printf(ARGS(newuname, "*")); +#endif + + linux_get_osname(td->td_proc, osname); + linux_get_osrelease(td->td_proc, osrelease); + + bzero(&utsname, sizeof(utsname)); + strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1); + getcredhostname(td->td_ucred, utsname.nodename, LINUX_MAX_UTSNAME-1); + strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1); + strncpy(utsname.version, version, LINUX_MAX_UTSNAME-1); + strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1); + strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1); + + return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname))); +} + +#if defined(__i386__) +struct l_utimbuf { + l_time_t l_actime; + l_time_t l_modtime; +}; + +int +linux_utime(struct thread *td, struct linux_utime_args *args) +{ + struct utimes_args /* { + char *path; + struct timeval *tptr; + } */ bsdutimes; + struct timeval tv[2], *tvp; + struct l_utimbuf lut; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->fname); + +#ifdef DEBUG + if (ldebug(utime)) + printf(ARGS(utime, "%s, *"), args->fname); +#endif + + if (args->times) { + if ((error = copyin((caddr_t)args->times, &lut, sizeof lut))) + return error; + tv[0].tv_sec = lut.l_actime; + tv[0].tv_usec = 0; + tv[1].tv_sec = lut.l_modtime; + tv[1].tv_usec = 0; + /* so that utimes can copyin */ + tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); + if (tvp == NULL) + return (ENAMETOOLONG); + if ((error = copyout(tv, tvp, sizeof(tv)))) + return error; + bsdutimes.tptr = tvp; + } else + bsdutimes.tptr = NULL; + + bsdutimes.path = args->fname; + return utimes(td, &bsdutimes); +} +#endif /* __i386__ */ + +#define __WCLONE 0x80000000 + +#ifndef __alpha__ +int +linux_waitpid(struct thread *td, struct linux_waitpid_args *args) +{ + struct wait_args /* { + int pid; + int *status; + int options; + struct rusage *rusage; + } */ tmp; + int error, tmpstat; + +#ifdef DEBUG + if (ldebug(waitpid)) + printf(ARGS(waitpid, "%d, %p, %d"), + args->pid, (void *)args->status, args->options); +#endif + + tmp.pid = args->pid; + tmp.status = args->status; + tmp.options = (args->options & (WNOHANG | WUNTRACED)); + /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ + if (args->options & __WCLONE) + tmp.options |= WLINUXCLONE; + tmp.rusage = NULL; + + if ((error = wait4(td, &tmp)) != 0) + return error; + + if (args->status) { + if ((error = copyin((caddr_t)args->status, &tmpstat, + sizeof(int))) != 0) + return error; + tmpstat &= 0xffff; + if (WIFSIGNALED(tmpstat)) + tmpstat = (tmpstat & 0xffffff80) | + BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); + else if (WIFSTOPPED(tmpstat)) + tmpstat = (tmpstat & 0xffff00ff) | + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); + return copyout(&tmpstat, (caddr_t)args->status, sizeof(int)); + } + + return 0; +} +#endif /*!__alpha__*/ + +int +linux_wait4(struct thread *td, struct linux_wait4_args *args) +{ + struct wait_args /* { + int pid; + int *status; + int options; + struct rusage *rusage; + } */ tmp; + int error, tmpstat; + +#ifdef DEBUG + if (ldebug(wait4)) + printf(ARGS(wait4, "%d, %p, %d, %p"), + args->pid, (void *)args->status, args->options, + (void *)args->rusage); +#endif + + tmp.pid = args->pid; + tmp.status = args->status; + tmp.options = (args->options & (WNOHANG | WUNTRACED)); + /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ + if (args->options & __WCLONE) + tmp.options |= WLINUXCLONE; + tmp.rusage = (struct rusage *)args->rusage; + + if ((error = wait4(td, &tmp)) != 0) + return error; + + SIGDELSET(td->td_proc->p_siglist, SIGCHLD); + + if (args->status) { + if ((error = copyin((caddr_t)args->status, &tmpstat, + sizeof(int))) != 0) + return error; + tmpstat &= 0xffff; + if (WIFSIGNALED(tmpstat)) + tmpstat = (tmpstat & 0xffffff80) | + BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); + else if (WIFSTOPPED(tmpstat)) + tmpstat = (tmpstat & 0xffff00ff) | + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); + return copyout(&tmpstat, (caddr_t)args->status, sizeof(int)); + } + + return 0; +} + +int +linux_mknod(struct thread *td, struct linux_mknod_args *args) +{ + caddr_t sg; + struct mknod_args bsd_mknod; + struct mkfifo_args bsd_mkfifo; + + sg = stackgap_init(); + + CHECKALTCREAT(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(mknod)) + printf(ARGS(mknod, "%s, %d, %d"), + args->path, args->mode, args->dev); +#endif + + if (args->mode & S_IFIFO) { + bsd_mkfifo.path = args->path; + bsd_mkfifo.mode = args->mode; + return mkfifo(td, &bsd_mkfifo); + } else { + bsd_mknod.path = args->path; + bsd_mknod.mode = args->mode; + bsd_mknod.dev = args->dev; + return mknod(td, &bsd_mknod); + } +} + +/* + * UGH! This is just about the dumbest idea I've ever heard!! + */ +int +linux_personality(struct thread *td, struct linux_personality_args *args) +{ +#ifdef DEBUG + if (ldebug(personality)) + printf(ARGS(personality, "%d"), args->per); +#endif +#ifndef __alpha__ + if (args->per != 0) + return EINVAL; +#endif + + /* Yes Jim, it's still a Linux... */ + td->td_retval[0] = 0; + return 0; +} + +/* + * Wrappers for get/setitimer for debugging.. + */ +int +linux_setitimer(struct thread *td, struct linux_setitimer_args *args) +{ + struct setitimer_args bsa; + struct itimerval foo; + int error; + +#ifdef DEBUG + if (ldebug(setitimer)) + printf(ARGS(setitimer, "%p, %p"), + (void *)args->itv, (void *)args->oitv); +#endif + bsa.which = args->which; + bsa.itv = (struct itimerval *)args->itv; + bsa.oitv = (struct itimerval *)args->oitv; + if (args->itv) { + if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo)))) + return error; +#ifdef DEBUG + if (ldebug(setitimer)) { + printf("setitimer: value: sec: %ld, usec: %ld\n", + foo.it_value.tv_sec, foo.it_value.tv_usec); + printf("setitimer: interval: sec: %ld, usec: %ld\n", + foo.it_interval.tv_sec, foo.it_interval.tv_usec); + } +#endif + } + return setitimer(td, &bsa); +} + +int +linux_getitimer(struct thread *td, struct linux_getitimer_args *args) +{ + struct getitimer_args bsa; +#ifdef DEBUG + if (ldebug(getitimer)) + printf(ARGS(getitimer, "%p"), (void *)args->itv); +#endif + bsa.which = args->which; + bsa.itv = (struct itimerval *)args->itv; + return getitimer(td, &bsa); +} + +#ifndef __alpha__ +int +linux_nice(struct thread *td, struct linux_nice_args *args) +{ + struct setpriority_args bsd_args; + + bsd_args.which = PRIO_PROCESS; + bsd_args.who = 0; /* current process */ + bsd_args.prio = args->inc; + return setpriority(td, &bsd_args); +} +#endif /*!__alpha__*/ + +int +linux_setgroups(struct thread *td, struct linux_setgroups_args *args) +{ + struct ucred *newcred, *oldcred; + l_gid_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int ngrp, error; + struct proc *p; + + ngrp = args->gidsetsize; + if (ngrp >= NGROUPS) + return (EINVAL); + error = copyin((caddr_t)args->grouplist, linux_gidset, + ngrp * sizeof(l_gid_t)); + if (error) + return (error); + newcred = crget(); + p = td->td_proc; + PROC_LOCK(p); + oldcred = p->p_ucred; + + /* + * cr_groups[0] holds egid. Setting the whole set from + * the supplied set will cause egid to be changed too. + * Keep cr_groups[0] unchanged to prevent that. + */ + + if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) { + PROC_UNLOCK(p); + crfree(newcred); + return (error); + } + + crcopy(newcred, oldcred); + if (ngrp > 0) { + newcred->cr_ngroups = ngrp + 1; + + bsd_gidset = newcred->cr_groups; + ngrp--; + while (ngrp >= 0) { + bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; + ngrp--; + } + } + else + newcred->cr_ngroups = 1; + + setsugid(p); + p->p_ucred = newcred; + PROC_UNLOCK(p); + crfree(oldcred); + return (0); +} + +int +linux_getgroups(struct thread *td, struct linux_getgroups_args *args) +{ + struct ucred *cred; + l_gid_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int bsd_gidsetsz, ngrp, error; + + cred = td->td_ucred; + bsd_gidset = cred->cr_groups; + bsd_gidsetsz = cred->cr_ngroups - 1; + + /* + * cr_groups[0] holds egid. Returning the whole set + * here will cause a duplicate. Exclude cr_groups[0] + * to prevent that. + */ + + if ((ngrp = args->gidsetsize) == 0) { + td->td_retval[0] = bsd_gidsetsz; + return (0); + } + + if (ngrp < bsd_gidsetsz) + return (EINVAL); + + ngrp = 0; + while (ngrp < bsd_gidsetsz) { + linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; + ngrp++; + } + + if ((error = copyout(linux_gidset, (caddr_t)args->grouplist, + ngrp * sizeof(l_gid_t)))) + return (error); + + td->td_retval[0] = ngrp; + return (0); +} + +#ifndef __alpha__ +int +linux_setrlimit(struct thread *td, struct linux_setrlimit_args *args) +{ + struct __setrlimit_args bsd; + struct l_rlimit rlim; + int error; + caddr_t sg = stackgap_init(); + +#ifdef DEBUG + if (ldebug(setrlimit)) + printf(ARGS(setrlimit, "%d, %p"), + args->resource, (void *)args->rlim); +#endif + + if (args->resource >= LINUX_RLIM_NLIMITS) + return (EINVAL); + + bsd.which = linux_to_bsd_resource[args->resource]; + if (bsd.which == -1) + return (EINVAL); + + error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim)); + if (error) + return (error); + + bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); + bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur; + bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max; + return (setrlimit(td, &bsd)); +} + +int +linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) +{ + struct __getrlimit_args bsd; + struct l_rlimit rlim; + int error; + caddr_t sg = stackgap_init(); + +#ifdef DEBUG + if (ldebug(old_getrlimit)) + printf(ARGS(old_getrlimit, "%d, %p"), + args->resource, (void *)args->rlim); +#endif + + if (args->resource >= LINUX_RLIM_NLIMITS) + return (EINVAL); + + bsd.which = linux_to_bsd_resource[args->resource]; + if (bsd.which == -1) + return (EINVAL); + + bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); + error = getrlimit(td, &bsd); + if (error) + return (error); + + rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur; + if (rlim.rlim_cur == ULONG_MAX) + rlim.rlim_cur = LONG_MAX; + rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max; + if (rlim.rlim_max == ULONG_MAX) + rlim.rlim_max = LONG_MAX; + return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); +} + +int +linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) +{ + struct __getrlimit_args bsd; + struct l_rlimit rlim; + int error; + caddr_t sg = stackgap_init(); + +#ifdef DEBUG + if (ldebug(getrlimit)) + printf(ARGS(getrlimit, "%d, %p"), + args->resource, (void *)args->rlim); +#endif + + if (args->resource >= LINUX_RLIM_NLIMITS) + return (EINVAL); + + bsd.which = linux_to_bsd_resource[args->resource]; + if (bsd.which == -1) + return (EINVAL); + + bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); + error = getrlimit(td, &bsd); + if (error) + return (error); + + rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur; + rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max; + return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); +} +#endif /*!__alpha__*/ + +int +linux_sched_setscheduler(struct thread *td, + struct linux_sched_setscheduler_args *args) +{ + struct sched_setscheduler_args bsd; + +#ifdef DEBUG + if (ldebug(sched_setscheduler)) + printf(ARGS(sched_setscheduler, "%d, %d, %p"), + args->pid, args->policy, (const void *)args->param); +#endif + + switch (args->policy) { + case LINUX_SCHED_OTHER: + bsd.policy = SCHED_OTHER; + break; + case LINUX_SCHED_FIFO: + bsd.policy = SCHED_FIFO; + break; + case LINUX_SCHED_RR: + bsd.policy = SCHED_RR; + break; + default: + return EINVAL; + } + + bsd.pid = args->pid; + bsd.param = (struct sched_param *)args->param; + return sched_setscheduler(td, &bsd); +} + +int +linux_sched_getscheduler(struct thread *td, + struct linux_sched_getscheduler_args *args) +{ + struct sched_getscheduler_args bsd; + int error; + +#ifdef DEBUG + if (ldebug(sched_getscheduler)) + printf(ARGS(sched_getscheduler, "%d"), args->pid); +#endif + + bsd.pid = args->pid; + error = sched_getscheduler(td, &bsd); + + switch (td->td_retval[0]) { + case SCHED_OTHER: + td->td_retval[0] = LINUX_SCHED_OTHER; + break; + case SCHED_FIFO: + td->td_retval[0] = LINUX_SCHED_FIFO; + break; + case SCHED_RR: + td->td_retval[0] = LINUX_SCHED_RR; + break; + } + + return error; +} + +int +linux_sched_get_priority_max(struct thread *td, + struct linux_sched_get_priority_max_args *args) +{ + struct sched_get_priority_max_args bsd; + +#ifdef DEBUG + if (ldebug(sched_get_priority_max)) + printf(ARGS(sched_get_priority_max, "%d"), args->policy); +#endif + + switch (args->policy) { + case LINUX_SCHED_OTHER: + bsd.policy = SCHED_OTHER; + break; + case LINUX_SCHED_FIFO: + bsd.policy = SCHED_FIFO; + break; + case LINUX_SCHED_RR: + bsd.policy = SCHED_RR; + break; + default: + return EINVAL; + } + return sched_get_priority_max(td, &bsd); +} + +int +linux_sched_get_priority_min(struct thread *td, + struct linux_sched_get_priority_min_args *args) +{ + struct sched_get_priority_min_args bsd; + +#ifdef DEBUG + if (ldebug(sched_get_priority_min)) + printf(ARGS(sched_get_priority_min, "%d"), args->policy); +#endif + + switch (args->policy) { + case LINUX_SCHED_OTHER: + bsd.policy = SCHED_OTHER; + break; + case LINUX_SCHED_FIFO: + bsd.policy = SCHED_FIFO; + break; + case LINUX_SCHED_RR: + bsd.policy = SCHED_RR; + break; + default: + return EINVAL; + } + return sched_get_priority_min(td, &bsd); +} + +#define REBOOT_CAD_ON 0x89abcdef +#define REBOOT_CAD_OFF 0 +#define REBOOT_HALT 0xcdef0123 + +int +linux_reboot(struct thread *td, struct linux_reboot_args *args) +{ + struct reboot_args bsd_args; + +#ifdef DEBUG + if (ldebug(reboot)) + printf(ARGS(reboot, "0x%x"), args->cmd); +#endif + if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF) + return (0); + bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0; + return (reboot(td, &bsd_args)); +} + +#ifndef __alpha__ + +/* + * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify + * td->td_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This + * globbers registers that are assumed to be preserved. The following + * lightweight syscalls fixes this. See also linux_getgid16() and + * linux_getuid16() in linux_uid16.c. + * + * linux_getpid() - MP SAFE + * linux_getgid() - MP SAFE + * linux_getuid() - MP SAFE + */ + +int +linux_getpid(struct thread *td, struct linux_getpid_args *args) +{ + + td->td_retval[0] = td->td_proc->p_pid; + return (0); +} + +int +linux_getgid(struct thread *td, struct linux_getgid_args *args) +{ + + td->td_retval[0] = td->td_ucred->cr_rgid; + return (0); +} + +int +linux_getuid(struct thread *td, struct linux_getuid_args *args) +{ + + td->td_retval[0] = td->td_ucred->cr_ruid; + return (0); +} + +#endif /*!__alpha__*/ + +int +linux_getsid(struct thread *td, struct linux_getsid_args *args) +{ + struct getsid_args bsd; + bsd.pid = args->pid; + return getsid(td, &bsd); +} diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c new file mode 100644 index 0000000..61fc98c --- /dev/null +++ b/sys/compat/linux/linux_signal.c @@ -0,0 +1,438 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/sysproto.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_signal.h> +#include <compat/linux/linux_util.h> + +void +linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) +{ + int b, l; + + SIGEMPTYSET(*bss); + bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); + bss->__bits[1] = lss->__bits[1]; + for (l = 1; l <= LINUX_SIGTBLSZ; l++) { + if (LINUX_SIGISMEMBER(*lss, l)) { +#ifdef __alpha__ + b = _SIG_IDX(l); +#else + b = linux_to_bsd_signal[_SIG_IDX(l)]; +#endif + if (b) + SIGADDSET(*bss, b); + } + } +} + +void +bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) +{ + int b, l; + + LINUX_SIGEMPTYSET(*lss); + lss->__bits[0] = bss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1); + lss->__bits[1] = bss->__bits[1]; + for (b = 1; b <= LINUX_SIGTBLSZ; b++) { + if (SIGISMEMBER(*bss, b)) { +#if __alpha__ + l = _SIG_IDX(b); +#else + l = bsd_to_linux_signal[_SIG_IDX(b)]; +#endif + if (l) + LINUX_SIGADDSET(*lss, l); + } + } +} + +static void +linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa) +{ + + linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); + bsa->sa_handler = lsa->lsa_handler; + bsa->sa_flags = 0; + if (lsa->lsa_flags & LINUX_SA_NOCLDSTOP) + bsa->sa_flags |= SA_NOCLDSTOP; + if (lsa->lsa_flags & LINUX_SA_NOCLDWAIT) + bsa->sa_flags |= SA_NOCLDWAIT; + if (lsa->lsa_flags & LINUX_SA_SIGINFO) + bsa->sa_flags |= SA_SIGINFO; + if (lsa->lsa_flags & LINUX_SA_ONSTACK) + bsa->sa_flags |= SA_ONSTACK; + if (lsa->lsa_flags & LINUX_SA_RESTART) + bsa->sa_flags |= SA_RESTART; + if (lsa->lsa_flags & LINUX_SA_ONESHOT) + bsa->sa_flags |= SA_RESETHAND; + if (lsa->lsa_flags & LINUX_SA_NOMASK) + bsa->sa_flags |= SA_NODEFER; +} + +static void +bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa) +{ + + bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); + lsa->lsa_handler = bsa->sa_handler; + lsa->lsa_restorer = NULL; /* unsupported */ + lsa->lsa_flags = 0; + if (bsa->sa_flags & SA_NOCLDSTOP) + lsa->lsa_flags |= LINUX_SA_NOCLDSTOP; + if (bsa->sa_flags & SA_NOCLDWAIT) + lsa->lsa_flags |= LINUX_SA_NOCLDWAIT; + if (bsa->sa_flags & SA_SIGINFO) + lsa->lsa_flags |= LINUX_SA_SIGINFO; + if (bsa->sa_flags & SA_ONSTACK) + lsa->lsa_flags |= LINUX_SA_ONSTACK; + if (bsa->sa_flags & SA_RESTART) + lsa->lsa_flags |= LINUX_SA_RESTART; + if (bsa->sa_flags & SA_RESETHAND) + lsa->lsa_flags |= LINUX_SA_ONESHOT; + if (bsa->sa_flags & SA_NODEFER) + lsa->lsa_flags |= LINUX_SA_NOMASK; +} + +int +linux_do_sigaction(struct thread *td, int linux_sig, l_sigaction_t *linux_nsa, + l_sigaction_t *linux_osa) +{ + struct sigaction *nsa, *osa; + struct sigaction_args sa_args; + int error; + caddr_t sg = stackgap_init(); + + if (linux_sig <= 0 || linux_sig > LINUX_NSIG) + return (EINVAL); + + if (linux_osa != NULL) + osa = stackgap_alloc(&sg, sizeof(struct sigaction)); + else + osa = NULL; + + if (linux_nsa != NULL) { + nsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + linux_to_bsd_sigaction(linux_nsa, nsa); + } + else + nsa = NULL; + +#ifndef __alpha__ + if (linux_sig <= LINUX_SIGTBLSZ) + sa_args.sig = linux_to_bsd_signal[_SIG_IDX(linux_sig)]; + else +#endif + sa_args.sig = linux_sig; + + sa_args.act = nsa; + sa_args.oact = osa; + error = sigaction(td, &sa_args); + if (error) + return (error); + + if (linux_osa != NULL) + bsd_to_linux_sigaction(osa, linux_osa); + + return (0); +} + + +#ifndef __alpha__ +int +linux_signal(struct thread *td, struct linux_signal_args *args) +{ + l_sigaction_t nsa, osa; + int error; + +#ifdef DEBUG + if (ldebug(signal)) + printf(ARGS(signal, "%d, %p"), + args->sig, (void *)args->handler); +#endif + + nsa.lsa_handler = args->handler; + nsa.lsa_flags = LINUX_SA_ONESHOT | LINUX_SA_NOMASK; + LINUX_SIGEMPTYSET(nsa.lsa_mask); + + error = linux_do_sigaction(td, args->sig, &nsa, &osa); + td->td_retval[0] = (int)osa.lsa_handler; + + return (error); +} +#endif /*!__alpha__*/ + +int +linux_rt_sigaction(struct thread *td, struct linux_rt_sigaction_args *args) +{ + l_sigaction_t nsa, osa; + int error; + +#ifdef DEBUG + if (ldebug(rt_sigaction)) + printf(ARGS(rt_sigaction, "%ld, %p, %p, %ld"), + (long)args->sig, (void *)args->act, + (void *)args->oact, (long)args->sigsetsize); +#endif + + if (args->sigsetsize != sizeof(l_sigset_t)) + return (EINVAL); + + if (args->act != NULL) { + error = copyin(args->act, &nsa, sizeof(l_sigaction_t)); + if (error) + return (error); + } + + error = linux_do_sigaction(td, args->sig, + args->act ? &nsa : NULL, + args->oact ? &osa : NULL); + + if (args->oact != NULL && !error) { + error = copyout(&osa, args->oact, sizeof(l_sigaction_t)); + } + + return (error); +} + +static int +linux_do_sigprocmask(struct thread *td, int how, l_sigset_t *new, + l_sigset_t *old) +{ + int error; + sigset_t mask; + struct proc *p = td->td_proc; + + error = 0; + td->td_retval[0] = 0; + + PROC_LOCK(p); + if (old != NULL) + bsd_to_linux_sigset(&p->p_sigmask, old); + + if (new != NULL) { + linux_to_bsd_sigset(new, &mask); + + switch (how) { + case LINUX_SIG_BLOCK: + SIGSETOR(p->p_sigmask, mask); + SIG_CANTMASK(p->p_sigmask); + break; + case LINUX_SIG_UNBLOCK: + SIGSETNAND(p->p_sigmask, mask); + signotify(p); + break; + case LINUX_SIG_SETMASK: + p->p_sigmask = mask; + SIG_CANTMASK(p->p_sigmask); + signotify(p); + break; + default: + error = EINVAL; + break; + } + } + PROC_UNLOCK(p); + + return (error); +} + +#ifndef __alpha__ +int +linux_sigprocmask(struct thread *td, struct linux_sigprocmask_args *args) +{ + l_osigset_t mask; + l_sigset_t set, oset; + int error; + +#ifdef DEBUG + if (ldebug(sigprocmask)) + printf(ARGS(sigprocmask, "%d, *, *"), args->how); +#endif + + if (args->mask != NULL) { + error = copyin(args->mask, &mask, sizeof(l_osigset_t)); + if (error) + return (error); + LINUX_SIGEMPTYSET(set); + set.__bits[0] = mask; + } + + error = linux_do_sigprocmask(td, args->how, + args->mask ? &set : NULL, + args->omask ? &oset : NULL); + + if (args->omask != NULL && !error) { + mask = oset.__bits[0]; + error = copyout(&mask, args->omask, sizeof(l_osigset_t)); + } + + return (error); +} +#endif /*!__alpha__*/ + +int +linux_rt_sigprocmask(struct thread *td, struct linux_rt_sigprocmask_args *args) +{ + l_sigset_t set, oset; + int error; + +#ifdef DEBUG + if (ldebug(rt_sigprocmask)) + printf(ARGS(rt_sigprocmask, "%d, %p, %p, %ld"), + args->how, (void *)args->mask, + (void *)args->omask, (long)args->sigsetsize); +#endif + + if (args->sigsetsize != sizeof(l_sigset_t)) + return EINVAL; + + if (args->mask != NULL) { + error = copyin(args->mask, &set, sizeof(l_sigset_t)); + if (error) + return (error); + } + + error = linux_do_sigprocmask(td, args->how, + args->mask ? &set : NULL, + args->omask ? &oset : NULL); + + if (args->omask != NULL && !error) { + error = copyout(&oset, args->omask, sizeof(l_sigset_t)); + } + + return (error); +} + +#ifndef __alpha__ +int +linux_sgetmask(struct thread *td, struct linux_sgetmask_args *args) +{ + struct proc *p = td->td_proc; + l_sigset_t mask; + +#ifdef DEBUG + if (ldebug(sgetmask)) + printf(ARGS(sgetmask, "")); +#endif + + PROC_LOCK(p); + bsd_to_linux_sigset(&p->p_sigmask, &mask); + PROC_UNLOCK(p); + td->td_retval[0] = mask.__bits[0]; + return (0); +} + +int +linux_ssetmask(struct thread *td, struct linux_ssetmask_args *args) +{ + struct proc *p = td->td_proc; + l_sigset_t lset; + sigset_t bset; + +#ifdef DEBUG + if (ldebug(ssetmask)) + printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); +#endif + + PROC_LOCK(p); + bsd_to_linux_sigset(&p->p_sigmask, &lset); + td->td_retval[0] = lset.__bits[0]; + LINUX_SIGEMPTYSET(lset); + lset.__bits[0] = args->mask; + linux_to_bsd_sigset(&lset, &bset); + p->p_sigmask = bset; + SIG_CANTMASK(p->p_sigmask); + signotify(p); + PROC_UNLOCK(p); + return (0); +} + +int +linux_sigpending(struct thread *td, struct linux_sigpending_args *args) +{ + struct proc *p = td->td_proc; + sigset_t bset; + l_sigset_t lset; + l_osigset_t mask; + +#ifdef DEBUG + if (ldebug(sigpending)) + printf(ARGS(sigpending, "*")); +#endif + + PROC_LOCK(p); + bset = p->p_siglist; + SIGSETAND(bset, p->p_sigmask); + bsd_to_linux_sigset(&bset, &lset); + PROC_UNLOCK(p); + mask = lset.__bits[0]; + return (copyout(&mask, args->mask, sizeof(mask))); +} +#endif /*!__alpha__*/ + +int +linux_kill(struct thread *td, struct linux_kill_args *args) +{ + struct kill_args /* { + int pid; + int signum; + } */ tmp; + +#ifdef DEBUG + if (ldebug(kill)) + printf(ARGS(kill, "%d, %d"), args->pid, args->signum); +#endif + + /* + * Allow signal 0 as a means to check for privileges + */ + if (args->signum < 0 || args->signum > LINUX_NSIG) + return EINVAL; + +#ifndef __alpha__ + if (args->signum > 0 && args->signum <= LINUX_SIGTBLSZ) + tmp.signum = linux_to_bsd_signal[_SIG_IDX(args->signum)]; + else +#endif + tmp.signum = args->signum; + + tmp.pid = args->pid; + return (kill(td, &tmp)); +} diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h new file mode 100644 index 0000000..edb7c66 --- /dev/null +++ b/sys/compat/linux/linux_signal.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2000 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_SIGNAL_H_ +#define _LINUX_SIGNAL_H_ + +void linux_to_bsd_sigset(l_sigset_t *, sigset_t *); +void bsd_to_linux_sigset(sigset_t *, l_sigset_t *); +int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *); + +#endif /* _LINUX_SIGNAL_H_ */ diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c new file mode 100644 index 0000000..a3af70f --- /dev/null +++ b/sys/compat/linux/linux_socket.c @@ -0,0 +1,971 @@ +/*- + * Copyright (c) 1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* XXX we use functions that might not exist. */ +#include "opt_compat.h" + +#ifndef COMPAT_43 +#error "Unable to compile Linux-emulator due to missing COMPAT_43 option!" +#endif + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/sysproto.h> +#include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_socket.h> +#include <compat/linux/linux_util.h> + +/* + * FreeBSD's socket calls require the sockaddr struct length to agree + * with the address family. Linux does not, so we must force it. + */ +static int +linux_to_bsd_namelen(caddr_t name, int namelen) +{ + uint16_t family; /* XXX must match Linux sockaddr */ + + if (copyin(name, &family, sizeof(family))) + return namelen; + + switch (family) { + case AF_INET: + return sizeof(struct sockaddr_in); + case AF_INET6: + return sizeof(struct sockaddr_in6); + } + return namelen; +} + +#ifndef __alpha__ +static int +linux_to_bsd_domain(int domain) +{ + + switch (domain) { + case LINUX_AF_UNSPEC: + return (AF_UNSPEC); + case LINUX_AF_UNIX: + return (AF_LOCAL); + case LINUX_AF_INET: + return (AF_INET); + case LINUX_AF_AX25: + return (AF_CCITT); + case LINUX_AF_IPX: + return (AF_IPX); + case LINUX_AF_APPLETALK: + return (AF_APPLETALK); + } + return (-1); +} + +static int +linux_to_bsd_sockopt_level(int level) +{ + + switch (level) { + case LINUX_SOL_SOCKET: + return (SOL_SOCKET); + } + return (level); +} + +static int +linux_to_bsd_ip_sockopt(int opt) +{ + + switch (opt) { + case LINUX_IP_TOS: + return (IP_TOS); + case LINUX_IP_TTL: + return (IP_TTL); + case LINUX_IP_OPTIONS: + return (IP_OPTIONS); + case LINUX_IP_MULTICAST_IF: + return (IP_MULTICAST_IF); + case LINUX_IP_MULTICAST_TTL: + return (IP_MULTICAST_TTL); + case LINUX_IP_MULTICAST_LOOP: + return (IP_MULTICAST_LOOP); + case LINUX_IP_ADD_MEMBERSHIP: + return (IP_ADD_MEMBERSHIP); + case LINUX_IP_DROP_MEMBERSHIP: + return (IP_DROP_MEMBERSHIP); + case LINUX_IP_HDRINCL: + return (IP_HDRINCL); + } + return (-1); +} + +static int +linux_to_bsd_so_sockopt(int opt) +{ + + switch (opt) { + case LINUX_SO_DEBUG: + return (SO_DEBUG); + case LINUX_SO_REUSEADDR: + return (SO_REUSEADDR); + case LINUX_SO_TYPE: + return (SO_TYPE); + case LINUX_SO_ERROR: + return (SO_ERROR); + case LINUX_SO_DONTROUTE: + return (SO_DONTROUTE); + case LINUX_SO_BROADCAST: + return (SO_BROADCAST); + case LINUX_SO_SNDBUF: + return (SO_SNDBUF); + case LINUX_SO_RCVBUF: + return (SO_RCVBUF); + case LINUX_SO_KEEPALIVE: + return (SO_KEEPALIVE); + case LINUX_SO_OOBINLINE: + return (SO_OOBINLINE); + case LINUX_SO_LINGER: + return (SO_LINGER); + } + return (-1); +} + +static int +linux_to_bsd_msg_flags(int flags) +{ + int ret_flags = 0; + + if (flags & LINUX_MSG_OOB) + ret_flags |= MSG_OOB; + if (flags & LINUX_MSG_PEEK) + ret_flags |= MSG_PEEK; + if (flags & LINUX_MSG_DONTROUTE) + ret_flags |= MSG_DONTROUTE; + if (flags & LINUX_MSG_CTRUNC) + ret_flags |= MSG_CTRUNC; + if (flags & LINUX_MSG_TRUNC) + ret_flags |= MSG_TRUNC; + if (flags & LINUX_MSG_DONTWAIT) + ret_flags |= MSG_DONTWAIT; + if (flags & LINUX_MSG_EOR) + ret_flags |= MSG_EOR; + if (flags & LINUX_MSG_WAITALL) + ret_flags |= MSG_WAITALL; +#if 0 /* not handled */ + if (flags & LINUX_MSG_PROXY) + ; + if (flags & LINUX_MSG_FIN) + ; + if (flags & LINUX_MSG_SYN) + ; + if (flags & LINUX_MSG_CONFIRM) + ; + if (flags & LINUX_MSG_RST) + ; + if (flags & LINUX_MSG_ERRQUEUE) + ; + if (flags & LINUX_MSG_NOSIGNAL) + ; +#endif + return ret_flags; +} + +/* Return 0 if IP_HDRINCL is set for the given socket. */ +static int +linux_check_hdrincl(struct thread *td, int s) +{ + struct getsockopt_args /* { + int s; + int level; + int name; + caddr_t val; + int *avalsize; + } */ bsd_args; + int error; + caddr_t sg, val, valsize; + int size_val = sizeof val; + int optval; + + sg = stackgap_init(); + val = stackgap_alloc(&sg, sizeof(int)); + valsize = stackgap_alloc(&sg, sizeof(int)); + + if ((error = copyout(&size_val, valsize, sizeof(size_val)))) + return (error); + + bsd_args.s = s; + bsd_args.level = IPPROTO_IP; + bsd_args.name = IP_HDRINCL; + bsd_args.val = val; + bsd_args.avalsize = (int *)valsize; + if ((error = getsockopt(td, &bsd_args))) + return (error); + + if ((error = copyin(val, &optval, sizeof(optval)))) + return (error); + + return (optval == 0); +} + +/* + * Updated sendto() when IP_HDRINCL is set: + * tweak endian-dependent fields in the IP packet. + */ +static int +linux_sendto_hdrincl(struct thread *td, struct sendto_args *bsd_args) +{ +/* + * linux_ip_copysize defines how many bytes we should copy + * from the beginning of the IP packet before we customize it for BSD. + * It should include all the fields we modify (ip_len and ip_off) + * and be as small as possible to minimize copying overhead. + */ +#define linux_ip_copysize 8 + + caddr_t sg; + struct ip *packet; + struct msghdr *msg; + struct iovec *iov; + + int error; + struct sendmsg_args /* { + int s; + caddr_t msg; + int flags; + } */ sendmsg_args; + + /* Check the packet isn't too small before we mess with it */ + if (bsd_args->len < linux_ip_copysize) + return (EINVAL); + + /* + * Tweaking the user buffer in place would be bad manners. + * We create a corrected IP header with just the needed length, + * then use an iovec to glue it to the rest of the user packet + * when calling sendmsg(). + */ + sg = stackgap_init(); + packet = (struct ip *)stackgap_alloc(&sg, linux_ip_copysize); + msg = (struct msghdr *)stackgap_alloc(&sg, sizeof(*msg)); + iov = (struct iovec *)stackgap_alloc(&sg, sizeof(*iov)*2); + + /* Make a copy of the beginning of the packet to be sent */ + if ((error = copyin(bsd_args->buf, packet, linux_ip_copysize))) + return (error); + + /* Convert fields from Linux to BSD raw IP socket format */ + packet->ip_len = bsd_args->len; + packet->ip_off = ntohs(packet->ip_off); + + /* Prepare the msghdr and iovec structures describing the new packet */ + msg->msg_name = bsd_args->to; + msg->msg_namelen = bsd_args->tolen; + msg->msg_iov = iov; + msg->msg_iovlen = 2; + msg->msg_control = NULL; + msg->msg_controllen = 0; + msg->msg_flags = 0; + iov[0].iov_base = (char *)packet; + iov[0].iov_len = linux_ip_copysize; + iov[1].iov_base = (char *)(bsd_args->buf) + linux_ip_copysize; + iov[1].iov_len = bsd_args->len - linux_ip_copysize; + + sendmsg_args.s = bsd_args->s; + sendmsg_args.msg = (caddr_t)msg; + sendmsg_args.flags = bsd_args->flags; + return (sendmsg(td, &sendmsg_args)); +} + +struct linux_socket_args { + int domain; + int type; + int protocol; +}; + +static int +linux_socket(struct thread *td, struct linux_socket_args *args) +{ + struct linux_socket_args linux_args; + struct socket_args /* { + int domain; + int type; + int protocol; + } */ bsd_args; + int error; + int retval_socket; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.protocol = linux_args.protocol; + bsd_args.type = linux_args.type; + bsd_args.domain = linux_to_bsd_domain(linux_args.domain); + if (bsd_args.domain == -1) + return (EINVAL); + + retval_socket = socket(td, &bsd_args); + if (bsd_args.type == SOCK_RAW + && (bsd_args.protocol == IPPROTO_RAW || bsd_args.protocol == 0) + && bsd_args.domain == AF_INET + && retval_socket >= 0) { + /* It's a raw IP socket: set the IP_HDRINCL option. */ + struct setsockopt_args /* { + int s; + int level; + int name; + caddr_t val; + int valsize; + } */ bsd_setsockopt_args; + caddr_t sg; + int *hdrincl; + + sg = stackgap_init(); + hdrincl = (int *)stackgap_alloc(&sg, sizeof(*hdrincl)); + *hdrincl = 1; + bsd_setsockopt_args.s = td->td_retval[0]; + bsd_setsockopt_args.level = IPPROTO_IP; + bsd_setsockopt_args.name = IP_HDRINCL; + bsd_setsockopt_args.val = (caddr_t)hdrincl; + bsd_setsockopt_args.valsize = sizeof(*hdrincl); + /* We ignore any error returned by setsockopt() */ + setsockopt(td, &bsd_setsockopt_args); + /* Copy back the return value from socket() */ + td->td_retval[0] = bsd_setsockopt_args.s; + } + + return (retval_socket); +} + +struct linux_bind_args { + int s; + struct sockaddr *name; + int namelen; +}; + +static int +linux_bind(struct thread *td, struct linux_bind_args *args) +{ + struct linux_bind_args linux_args; + struct bind_args /* { + int s; + caddr_t name; + int namelen; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.name = (caddr_t)linux_args.name; + bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen); + return (bind(td, &bsd_args)); +} + +struct linux_connect_args { + int s; + struct sockaddr * name; + int namelen; +}; +int linux_connect(struct thread *, struct linux_connect_args *); +#endif /* !__alpha__*/ + +int +linux_connect(struct thread *td, struct linux_connect_args *args) +{ + struct linux_connect_args linux_args; + struct connect_args /* { + int s; + caddr_t name; + int namelen; + } */ bsd_args; + struct socket *so; + u_int fflag; + int error; + +#ifdef __alpha__ + bcopy(args, &linux_args, sizeof(linux_args)); +#else + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); +#endif /* __alpha__ */ + + bsd_args.s = linux_args.s; + bsd_args.name = (caddr_t)linux_args.name; + bsd_args.namelen = linux_to_bsd_namelen(bsd_args.name, linux_args.namelen); + error = connect(td, &bsd_args); + if (error != EISCONN) + return (error); + + /* + * Linux doesn't return EISCONN the first time it occurs, + * when on a non-blocking socket. Instead it returns the + * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. + */ + if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) + return(error); + error = EISCONN; + if (fflag & FNONBLOCK) { + if (so->so_emuldata == 0) + error = so->so_error; + so->so_emuldata = (void *)1; + } + fputsock(so); + return (error); +} + +#ifndef __alpha__ + +struct linux_listen_args { + int s; + int backlog; +}; + +static int +linux_listen(struct thread *td, struct linux_listen_args *args) +{ + struct linux_listen_args linux_args; + struct listen_args /* { + int s; + int backlog; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.backlog = linux_args.backlog; + return (listen(td, &bsd_args)); +} + +struct linux_accept_args { + int s; + struct sockaddr *addr; + int *namelen; +}; + +static int +linux_accept(struct thread *td, struct linux_accept_args *args) +{ + struct linux_accept_args linux_args; + struct accept_args /* { + int s; + caddr_t name; + int *anamelen; + } */ bsd_args; + struct fcntl_args /* { + int fd; + int cmd; + long arg; + } */ f_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.name = (caddr_t)linux_args.addr; + bsd_args.anamelen = linux_args.namelen; + error = oaccept(td, &bsd_args); + if (error) + return (error); + + /* + * linux appears not to copy flags from the parent socket to the + * accepted one, so we must clear the flags in the new descriptor. + * Ignore any errors, because we already have an open fd. + */ + f_args.fd = td->td_retval[0]; + f_args.cmd = F_SETFL; + f_args.arg = 0; + (void)fcntl(td, &f_args); + td->td_retval[0] = f_args.fd; + return (0); +} + +struct linux_getsockname_args { + int s; + struct sockaddr *addr; + int *namelen; +}; + +static int +linux_getsockname(struct thread *td, struct linux_getsockname_args *args) +{ + struct linux_getsockname_args linux_args; + struct getsockname_args /* { + int fdes; + caddr_t asa; + int *alen; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.fdes = linux_args.s; + bsd_args.asa = (caddr_t) linux_args.addr; + bsd_args.alen = linux_args.namelen; + return (ogetsockname(td, &bsd_args)); +} + +struct linux_getpeername_args { + int s; + struct sockaddr *addr; + int *namelen; +}; + +static int +linux_getpeername(struct thread *td, struct linux_getpeername_args *args) +{ + struct linux_getpeername_args linux_args; + struct ogetpeername_args /* { + int fdes; + caddr_t asa; + int *alen; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.fdes = linux_args.s; + bsd_args.asa = (caddr_t) linux_args.addr; + bsd_args.alen = linux_args.namelen; + return (ogetpeername(td, &bsd_args)); +} + +struct linux_socketpair_args { + int domain; + int type; + int protocol; + int *rsv; +}; + +static int +linux_socketpair(struct thread *td, struct linux_socketpair_args *args) +{ + struct linux_socketpair_args linux_args; + struct socketpair_args /* { + int domain; + int type; + int protocol; + int *rsv; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.domain = linux_to_bsd_domain(linux_args.domain); + if (bsd_args.domain == -1) + return (EINVAL); + + bsd_args.type = linux_args.type; + bsd_args.protocol = linux_args.protocol; + bsd_args.rsv = linux_args.rsv; + return (socketpair(td, &bsd_args)); +} + +struct linux_send_args { + int s; + void *msg; + int len; + int flags; +}; + +static int +linux_send(struct thread *td, struct linux_send_args *args) +{ + struct linux_send_args linux_args; + struct osend_args /* { + int s; + caddr_t buf; + int len; + int flags; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.buf = linux_args.msg; + bsd_args.len = linux_args.len; + bsd_args.flags = linux_args.flags; + return (osend(td, &bsd_args)); +} + +struct linux_recv_args { + int s; + void *msg; + int len; + int flags; +}; + +static int +linux_recv(struct thread *td, struct linux_recv_args *args) +{ + struct linux_recv_args linux_args; + struct orecv_args /* { + int s; + caddr_t buf; + int len; + int flags; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.buf = linux_args.msg; + bsd_args.len = linux_args.len; + bsd_args.flags = linux_args.flags; + return (orecv(td, &bsd_args)); +} + +struct linux_sendto_args { + int s; + void *msg; + int len; + int flags; + caddr_t to; + int tolen; +}; + +static int +linux_sendto(struct thread *td, struct linux_sendto_args *args) +{ + struct linux_sendto_args linux_args; + struct sendto_args /* { + int s; + caddr_t buf; + size_t len; + int flags; + caddr_t to; + int tolen; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.buf = linux_args.msg; + bsd_args.len = linux_args.len; + bsd_args.flags = linux_args.flags; + bsd_args.to = linux_args.to; + bsd_args.tolen = linux_args.tolen; + + if (linux_check_hdrincl(td, linux_args.s) == 0) + /* IP_HDRINCL set, tweak the packet before sending */ + return (linux_sendto_hdrincl(td, &bsd_args)); + + return (sendto(td, &bsd_args)); +} + +struct linux_recvfrom_args { + int s; + void *buf; + int len; + int flags; + caddr_t from; + int *fromlen; +}; + +static int +linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args) +{ + struct linux_recvfrom_args linux_args; + struct recvfrom_args /* { + int s; + caddr_t buf; + size_t len; + int flags; + caddr_t from; + int *fromlenaddr; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.buf = linux_args.buf; + bsd_args.len = linux_args.len; + bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); + bsd_args.from = linux_args.from; + bsd_args.fromlenaddr = linux_args.fromlen; + return (orecvfrom(td, &bsd_args)); +} + +struct linux_recvmsg_args { + int s; + struct msghdr *msg; + int flags; +}; + +static int +linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) +{ + struct linux_recvmsg_args linux_args; + struct recvmsg_args /* { + int s; + struct msghdr *msg; + int flags; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.msg = linux_args.msg; + bsd_args.flags = linux_to_bsd_msg_flags(linux_args.flags); + return (recvmsg(td, &bsd_args)); +} + +struct linux_shutdown_args { + int s; + int how; +}; + +static int +linux_shutdown(struct thread *td, struct linux_shutdown_args *args) +{ + struct linux_shutdown_args linux_args; + struct shutdown_args /* { + int s; + int how; + } */ bsd_args; + int error; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.how = linux_args.how; + return (shutdown(td, &bsd_args)); +} + +struct linux_setsockopt_args { + int s; + int level; + int optname; + void *optval; + int optlen; +}; + +static int +linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) +{ + struct linux_setsockopt_args linux_args; + struct setsockopt_args /* { + int s; + int level; + int name; + caddr_t val; + int valsize; + } */ bsd_args; + int error, name; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); + switch (bsd_args.level) { + case SOL_SOCKET: + name = linux_to_bsd_so_sockopt(linux_args.optname); + break; + case IPPROTO_IP: + name = linux_to_bsd_ip_sockopt(linux_args.optname); + break; + case IPPROTO_TCP: + /* Linux TCP option values match BSD's */ + name = linux_args.optname; + break; + default: + name = -1; + break; + } + if (name == -1) + return (EINVAL); + + bsd_args.name = name; + bsd_args.val = linux_args.optval; + bsd_args.valsize = linux_args.optlen; + return (setsockopt(td, &bsd_args)); +} + +struct linux_getsockopt_args { + int s; + int level; + int optname; + void *optval; + int *optlen; +}; + +static int +linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args) +{ + struct linux_getsockopt_args linux_args; + struct getsockopt_args /* { + int s; + int level; + int name; + caddr_t val; + int *avalsize; + } */ bsd_args; + int error, name; + + if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + return (error); + + bsd_args.s = linux_args.s; + bsd_args.level = linux_to_bsd_sockopt_level(linux_args.level); + switch (bsd_args.level) { + case SOL_SOCKET: + name = linux_to_bsd_so_sockopt(linux_args.optname); + break; + case IPPROTO_IP: + name = linux_to_bsd_ip_sockopt(linux_args.optname); + break; + case IPPROTO_TCP: + /* Linux TCP option values match BSD's */ + name = linux_args.optname; + break; + default: + name = -1; + break; + } + if (name == -1) + return (EINVAL); + + bsd_args.name = name; + bsd_args.val = linux_args.optval; + bsd_args.avalsize = linux_args.optlen; + return (getsockopt(td, &bsd_args)); +} + +int +linux_socketcall(struct thread *td, struct linux_socketcall_args *args) +{ + void *arg = (void *)args->args; + + switch (args->what) { + case LINUX_SOCKET: + return (linux_socket(td, arg)); + case LINUX_BIND: + return (linux_bind(td, arg)); + case LINUX_CONNECT: + return (linux_connect(td, arg)); + case LINUX_LISTEN: + return (linux_listen(td, arg)); + case LINUX_ACCEPT: + return (linux_accept(td, arg)); + case LINUX_GETSOCKNAME: + return (linux_getsockname(td, arg)); + case LINUX_GETPEERNAME: + return (linux_getpeername(td, arg)); + case LINUX_SOCKETPAIR: + return (linux_socketpair(td, arg)); + case LINUX_SEND: + return (linux_send(td, arg)); + case LINUX_RECV: + return (linux_recv(td, arg)); + case LINUX_SENDTO: + return (linux_sendto(td, arg)); + case LINUX_RECVFROM: + return (linux_recvfrom(td, arg)); + case LINUX_SHUTDOWN: + return (linux_shutdown(td, arg)); + case LINUX_SETSOCKOPT: + return (linux_setsockopt(td, arg)); + case LINUX_GETSOCKOPT: + return (linux_getsockopt(td, arg)); + case LINUX_SENDMSG: + do { + int error; + int level; + caddr_t control; + struct { + int s; + const struct msghdr *msg; + int flags; + } *uap = arg; + + error = copyin(&uap->msg->msg_control, &control, + sizeof(caddr_t)); + if (error) + return (error); + + if (control == NULL) + goto done; + + error = copyin(&((struct cmsghdr*)control)->cmsg_level, + &level, sizeof(int)); + if (error) + return (error); + + if (level == 1) { + /* + * Linux thinks that SOL_SOCKET is 1; we know + * that it's really 0xffff, of course. + */ + level = SOL_SOCKET; + error = copyout(&level, + &((struct cmsghdr *)control)->cmsg_level, + sizeof(int)); + if (error) + return (error); + } + done: + return (sendmsg(td, arg)); + } while (0); + case LINUX_RECVMSG: + return (linux_recvmsg(td, arg)); + } + + uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); + return (ENOSYS); +} +#endif /*!__alpha__*/ diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h new file mode 100644 index 0000000..b6b9841 --- /dev/null +++ b/sys/compat/linux/linux_socket.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2000 Assar Westerlund + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LINUX_SOCKET_H_ +#define _LINUX_SOCKET_H_ + +/* msg flags in recvfrom/recvmsg */ + +#define LINUX_MSG_OOB 0x01 +#define LINUX_MSG_PEEK 0x02 +#define LINUX_MSG_DONTROUTE 0x04 +#define LINUX_MSG_CTRUNC 0x08 +#define LINUX_MSG_PROXY 0x10 +#define LINUX_MSG_TRUNC 0x20 +#define LINUX_MSG_DONTWAIT 0x40 +#define LINUX_MSG_EOR 0x80 +#define LINUX_MSG_WAITALL 0x100 +#define LINUX_MSG_FIN 0x200 +#define LINUX_MSG_SYN 0x400 +#define LINUX_MSG_CONFIRM 0x800 +#define LINUX_MSG_RST 0x1000 +#define LINUX_MSG_ERRQUEUE 0x2000 +#define LINUX_MSG_NOSIGNAL 0x4000 + +#endif /* _LINUX_SOCKET_H_ */ diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c new file mode 100644 index 0000000..5ceb22a --- /dev/null +++ b/sys/compat/linux/linux_stats.c @@ -0,0 +1,499 @@ +/*- + * Copyright (c) 1994-1995 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_mac.h" + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/dirent.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/proc.h> +#include <sys/mac.h> +#include <sys/mount.h> +#include <sys/namei.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/vnode.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +static int +newstat_copyout(struct stat *buf, void *ubuf) +{ + struct l_newstat tbuf; + struct cdevsw *cdevsw; + dev_t dev; + + tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8); + tbuf.st_ino = buf->st_ino; + tbuf.st_mode = buf->st_mode; + tbuf.st_nlink = buf->st_nlink; + tbuf.st_uid = buf->st_uid; + tbuf.st_gid = buf->st_gid; + tbuf.st_rdev = buf->st_rdev; + tbuf.st_size = buf->st_size; + tbuf.st_atime = buf->st_atime; + tbuf.st_mtime = buf->st_mtime; + tbuf.st_ctime = buf->st_ctime; + tbuf.st_blksize = buf->st_blksize; + tbuf.st_blocks = buf->st_blocks; + + /* Lie about disk drives which are character devices + * in FreeBSD but block devices under Linux. + */ + if (S_ISCHR(tbuf.st_mode) && + (dev = udev2dev(buf->st_rdev, 0)) != NODEV) { + cdevsw = devsw(dev); + if (cdevsw != NULL && (cdevsw->d_flags & D_DISK)) { + tbuf.st_mode &= ~S_IFMT; + tbuf.st_mode |= S_IFBLK; + + /* XXX this may not be quite right */ + /* Map major number to 0 */ + tbuf.st_dev = uminor(buf->st_dev) & 0xf; + tbuf.st_rdev = buf->st_rdev & 0xff; + } + } + + return (copyout(&tbuf, ubuf, sizeof(tbuf))); +} + +int +linux_newstat(struct thread *td, struct linux_newstat_args *args) +{ + struct stat buf; + struct nameidata nd; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(newstat)) + printf(ARGS(newstat, "%s, *"), args->path); +#endif + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &buf, td); + vput(nd.ni_vp); + if (error) + return (error); + + return (newstat_copyout(&buf, args->buf)); +} + +int +linux_newlstat(struct thread *td, struct linux_newlstat_args *args) +{ + int error; + struct stat sb; + struct nameidata nd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(newlstat)) + printf(ARGS(newlstat, "%s, *"), args->path); +#endif + + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &sb, td); + vput(nd.ni_vp); + if (error) + return (error); + + return (newstat_copyout(&sb, args->buf)); +} + +int +linux_newfstat(struct thread *td, struct linux_newfstat_args *args) +{ + struct file *fp; + struct stat buf; + int error; + +#ifdef DEBUG + if (ldebug(newfstat)) + printf(ARGS(newfstat, "%d, *"), args->fd); +#endif + + if ((error = fget(td, args->fd, &fp)) != 0) + return (error); + + error = fo_stat(fp, &buf, td); + fdrop(fp, td); + if (!error) + error = newstat_copyout(&buf, args->buf); + + return (error); +} + +/* XXX - All fields of type l_int are defined as l_long on i386 */ +struct l_statfs { + l_int f_type; + l_int f_bsize; + l_int f_blocks; + l_int f_bfree; + l_int f_bavail; + l_int f_files; + l_int f_ffree; + l_fsid_t f_fsid; + l_int f_namelen; + l_int f_spare[6]; +}; + +#define LINUX_CODA_SUPER_MAGIC 0x73757245L +#define LINUX_EXT2_SUPER_MAGIC 0xEF53L +#define LINUX_HPFS_SUPER_MAGIC 0xf995e849L +#define LINUX_ISOFS_SUPER_MAGIC 0x9660L +#define LINUX_MSDOS_SUPER_MAGIC 0x4d44L +#define LINUX_NCP_SUPER_MAGIC 0x564cL +#define LINUX_NFS_SUPER_MAGIC 0x6969L +#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL +#define LINUX_PROC_SUPER_MAGIC 0x9fa0L +#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */ + +static long +bsd_to_linux_ftype(const char *fstypename) +{ + int i; + static struct {const char *bsd_name; long linux_type;} b2l_tbl[] = { + {"ufs", LINUX_UFS_SUPER_MAGIC}, + {"cd9660", LINUX_ISOFS_SUPER_MAGIC}, + {"nfs", LINUX_NFS_SUPER_MAGIC}, + {"ext2fs", LINUX_EXT2_SUPER_MAGIC}, + {"procfs", LINUX_PROC_SUPER_MAGIC}, + {"msdosfs", LINUX_MSDOS_SUPER_MAGIC}, + {"ntfs", LINUX_NTFS_SUPER_MAGIC}, + {"nwfs", LINUX_NCP_SUPER_MAGIC}, + {"hpfs", LINUX_HPFS_SUPER_MAGIC}, + {"coda", LINUX_CODA_SUPER_MAGIC}, + {NULL, 0L}}; + + for (i = 0; b2l_tbl[i].bsd_name != NULL; i++) + if (strcmp(b2l_tbl[i].bsd_name, fstypename) == 0) + return (b2l_tbl[i].linux_type); + + return (0L); +} + +int +linux_statfs(struct thread *td, struct linux_statfs_args *args) +{ + struct mount *mp; + struct nameidata *ndp; + struct statfs *bsd_statfs; + struct nameidata nd; + struct l_statfs linux_statfs; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(statfs)) + printf(ARGS(statfs, "%s, *"), args->path); +#endif + ndp = &nd; + NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args->path, curthread); + error = namei(ndp); + if (error) + return error; + NDFREE(ndp, NDF_ONLY_PNBUF); + mp = ndp->ni_vp->v_mount; + bsd_statfs = &mp->mnt_stat; + vrele(ndp->ni_vp); +#ifdef MAC + error = mac_check_mount_stat(td->td_proc->p_ucred, mp); + if (error) + return (error); +#endif + error = VFS_STATFS(mp, bsd_statfs, td); + if (error) + return error; + bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename); + linux_statfs.f_bsize = bsd_statfs->f_bsize; + linux_statfs.f_blocks = bsd_statfs->f_blocks; + linux_statfs.f_bfree = bsd_statfs->f_bfree; + linux_statfs.f_bavail = bsd_statfs->f_bavail; + linux_statfs.f_ffree = bsd_statfs->f_ffree; + linux_statfs.f_files = bsd_statfs->f_files; + linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs.f_namelen = MAXNAMLEN; + return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, + sizeof(linux_statfs)); +} + +int +linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args) +{ + struct file *fp; + struct mount *mp; + struct statfs *bsd_statfs; + struct l_statfs linux_statfs; + int error; + +#ifdef DEBUG + if (ldebug(fstatfs)) + printf(ARGS(fstatfs, "%d, *"), args->fd); +#endif + error = getvnode(td->td_proc->p_fd, args->fd, &fp); + if (error) + return error; + mp = ((struct vnode *)fp->f_data)->v_mount; +#ifdef MAC + error = mac_check_mount_stat(td->td_proc->p_ucred, mp); + if (error) { + fdrop(fp, td); + return (error); + } +#endif + bsd_statfs = &mp->mnt_stat; + error = VFS_STATFS(mp, bsd_statfs, td); + if (error) { + fdrop(fp, td); + return error; + } + bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename); + linux_statfs.f_bsize = bsd_statfs->f_bsize; + linux_statfs.f_blocks = bsd_statfs->f_blocks; + linux_statfs.f_bfree = bsd_statfs->f_bfree; + linux_statfs.f_bavail = bsd_statfs->f_bavail; + linux_statfs.f_ffree = bsd_statfs->f_ffree; + linux_statfs.f_files = bsd_statfs->f_files; + linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs.f_namelen = MAXNAMLEN; + error = copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, + sizeof(linux_statfs)); + fdrop(fp, td); + return error; +} + +struct l_ustat +{ + l_daddr_t f_tfree; + l_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +int +linux_ustat(struct thread *td, struct linux_ustat_args *args) +{ + struct l_ustat lu; + dev_t dev; + struct vnode *vp; + struct statfs *stat; + int error; + +#ifdef DEBUG + if (ldebug(ustat)) + printf(ARGS(ustat, "%d, *"), args->dev); +#endif + + /* + * lu.f_fname and lu.f_fpack are not used. They are always zeroed. + * lu.f_tinode and lu.f_tfree are set from the device's super block. + */ + bzero(&lu, sizeof(lu)); + + /* + * XXX - Don't return an error if we can't find a vnode for the + * device. Our dev_t is 32-bits whereas Linux only has a 16-bits + * dev_t. The dev_t that is used now may as well be a truncated + * dev_t returned from previous syscalls. Just return a bzeroed + * ustat in that case. + */ + dev = makedev(args->dev >> 8, args->dev & 0xFF); + if (vfinddev(dev, VCHR, &vp)) { + if (vp->v_mount == NULL) + return (EINVAL); +#ifdef MAC + error = mac_check_mount_stat(td->td_proc->p_ucred, mp); + if (error) + return (error); +#endif + stat = &(vp->v_mount->mnt_stat); + error = VFS_STATFS(vp->v_mount, stat, td); + if (error) + return (error); + + lu.f_tfree = stat->f_bfree; + lu.f_tinode = stat->f_ffree; + } + + return (copyout(&lu, args->ubuf, sizeof(lu))); +} + +#if defined(__i386__) + +static int +stat64_copyout(struct stat *buf, void *ubuf) +{ + struct l_stat64 lbuf; + + bzero(&lbuf, sizeof(lbuf)); + lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8); + lbuf.st_ino = buf->st_ino; + lbuf.st_mode = buf->st_mode; + lbuf.st_nlink = buf->st_nlink; + lbuf.st_uid = buf->st_uid; + lbuf.st_gid = buf->st_gid; + lbuf.st_rdev = buf->st_rdev; + lbuf.st_size = buf->st_size; + lbuf.st_atime = buf->st_atime; + lbuf.st_mtime = buf->st_mtime; + lbuf.st_ctime = buf->st_ctime; + lbuf.st_blksize = buf->st_blksize; + lbuf.st_blocks = buf->st_blocks; + + /* + * The __st_ino field makes all the difference. In the Linux kernel + * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO, + * but without the assignment to __st_ino the runtime linker refuses + * to mmap(2) any shared libraries. I guess it's broken alright :-) + */ + lbuf.__st_ino = buf->st_ino; + + return (copyout(&lbuf, ubuf, sizeof(lbuf))); +} + +int +linux_stat64(struct thread *td, struct linux_stat64_args *args) +{ + struct stat buf; + struct nameidata nd; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->filename); + +#ifdef DEBUG + if (ldebug(stat64)) + printf(ARGS(stat64, "%s, *"), args->filename); +#endif + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->filename, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &buf, td); + vput(nd.ni_vp); + if (error) + return (error); + + return (stat64_copyout(&buf, args->statbuf)); +} + +int +linux_lstat64(struct thread *td, struct linux_lstat64_args *args) +{ + int error; + struct stat sb; + struct nameidata nd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->filename); + +#ifdef DEBUG + if (ldebug(lstat64)) + printf(ARGS(lstat64, "%s, *"), args->filename); +#endif + + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->filename, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &sb, td); + vput(nd.ni_vp); + if (error) + return (error); + + return (stat64_copyout(&sb, args->statbuf)); +} + +int +linux_fstat64(struct thread *td, struct linux_fstat64_args *args) +{ + struct filedesc *fdp; + struct file *fp; + struct stat buf; + int error; + +#ifdef DEBUG + if (ldebug(fstat64)) + printf(ARGS(fstat64, "%d, *"), args->fd); +#endif + + fdp = td->td_proc->p_fd; + if ((unsigned)args->fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[args->fd]) == NULL) + return (EBADF); + + error = fo_stat(fp, &buf, td); + if (!error) + error = stat64_copyout(&buf, args->statbuf); + + return (error); +} + +#endif /* __i386__ */ diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c new file mode 100644 index 0000000..98dab20 --- /dev/null +++ b/sys/compat/linux/linux_sysctl.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2001 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_compat.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/sysproto.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +#define LINUX_CTL_KERN 1 +#define LINUX_CTL_VM 2 +#define LINUX_CTL_NET 3 +#define LINUX_CTL_PROC 4 +#define LINUX_CTL_FS 5 +#define LINUX_CTL_DEBUG 6 +#define LINUX_CTL_DEV 7 +#define LINUX_CTL_BUS 8 + +/* CTL_KERN names */ +#define LINUX_KERN_OSTYPE 1 +#define LINUX_KERN_OSRELEASE 2 +#define LINUX_KERN_OSREV 3 +#define LINUX_KERN_VERSION 4 + +static int +handle_string(struct l___sysctl_args *la, char *value) +{ + int error; + + if (la->oldval != NULL) { + l_int len = strlen(value); + error = copyout(value, la->oldval, len + 1); + if (!error && la->oldlenp != NULL) + error = copyout(&len, la->oldlenp, sizeof(len)); + if (error) + return (error); + } + + if (la->newval != NULL) + return (ENOTDIR); + + return (0); +} + +int +linux_sysctl(struct thread *td, struct linux_sysctl_args *args) +{ + struct l___sysctl_args la; + l_int *mib; + int error, i; + caddr_t sg; + + error = copyin((caddr_t)args->args, &la, sizeof(la)); + if (error) + return (error); + + if (la.nlen == 0 || la.nlen > LINUX_CTL_MAXNAME) + return (ENOTDIR); + + sg = stackgap_init(); + mib = stackgap_alloc(&sg, la.nlen * sizeof(l_int)); + error = copyin(la.name, mib, la.nlen * sizeof(l_int)); + if (error) + return (error); + + switch (mib[0]) { + case LINUX_CTL_KERN: + if (la.nlen < 2) + break; + + switch (mib[1]) { + case LINUX_KERN_VERSION: + return (handle_string(&la, version)); + default: + break; + } + break; + default: + break; + } + + printf("linux: sysctl: unhandled name="); + for (i = 0; i < la.nlen; i++) + printf("%c%d", (i) ? ',' : '{', mib[i]); + printf("}\n"); + + return (ENOTDIR); +} diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c new file mode 100644 index 0000000..ee39025 --- /dev/null +++ b/sys/compat/linux/linux_uid16.c @@ -0,0 +1,297 @@ +/*- + * Copyright (c) 2001 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_compat.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sysproto.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +DUMMY(setfsuid16); +DUMMY(setfsgid16); +DUMMY(getresuid16); +DUMMY(getresgid16); + +#define CAST_NOCHG(x) (x == 0xFFFF) ? -1 : x; + +int +linux_chown16(struct thread *td, struct linux_chown16_args *args) +{ + struct chown_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(chown16)) + printf(ARGS(chown16, "%s, %d, %d"), args->path, args->uid, + args->gid); +#endif + + bsd.path = args->path; + bsd.uid = CAST_NOCHG(args->uid); + bsd.gid = CAST_NOCHG(args->gid); + return (chown(td, &bsd)); +} + +int +linux_lchown16(struct thread *td, struct linux_lchown16_args *args) +{ + struct lchown_args bsd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, args->path); + +#ifdef DEBUG + if (ldebug(lchown16)) + printf(ARGS(lchown16, "%s, %d, %d"), args->path, args->uid, + args->gid); +#endif + + bsd.path = args->path; + bsd.uid = CAST_NOCHG(args->uid); + bsd.gid = CAST_NOCHG(args->gid); + return (lchown(td, &bsd)); +} + +int +linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) +{ + struct ucred *newcred, *oldcred; + l_gid16_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int ngrp, error; + struct proc *p; + +#ifdef DEBUG + if (ldebug(setgroups16)) + printf(ARGS(setgroups16, "%d, *"), args->gidsetsize); +#endif + + ngrp = args->gidsetsize; + if (ngrp >= NGROUPS) + return (EINVAL); + error = copyin((caddr_t)args->gidset, linux_gidset, + ngrp * sizeof(l_gid16_t)); + if (error) + return (error); + newcred = crget(); + p = td->td_proc; + PROC_LOCK(p); + oldcred = p->p_ucred; + + /* + * cr_groups[0] holds egid. Setting the whole set from + * the supplied set will cause egid to be changed too. + * Keep cr_groups[0] unchanged to prevent that. + */ + + if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) { + PROC_UNLOCK(p); + crfree(newcred); + return (error); + } + + crcopy(newcred, oldcred); + if (ngrp > 0) { + newcred->cr_ngroups = ngrp + 1; + + bsd_gidset = newcred->cr_groups; + ngrp--; + while (ngrp >= 0) { + bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; + ngrp--; + } + } + else + newcred->cr_ngroups = 1; + + setsugid(td->td_proc); + p->p_ucred = newcred; + PROC_UNLOCK(p); + crfree(oldcred); + return (0); +} + +int +linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) +{ + struct ucred *cred; + l_gid16_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int bsd_gidsetsz, ngrp, error; + +#ifdef DEBUG + if (ldebug(getgroups16)) + printf(ARGS(getgroups16, "%d, *"), args->gidsetsize); +#endif + + cred = td->td_ucred; + bsd_gidset = cred->cr_groups; + bsd_gidsetsz = cred->cr_ngroups - 1; + + /* + * cr_groups[0] holds egid. Returning the whole set + * here will cause a duplicate. Exclude cr_groups[0] + * to prevent that. + */ + + if ((ngrp = args->gidsetsize) == 0) { + td->td_retval[0] = bsd_gidsetsz; + return (0); + } + + if (ngrp < bsd_gidsetsz) + return (EINVAL); + + ngrp = 0; + while (ngrp < bsd_gidsetsz) { + linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; + ngrp++; + } + + error = copyout(linux_gidset, (caddr_t)args->gidset, + ngrp * sizeof(l_gid16_t)); + if (error) + return (error); + + td->td_retval[0] = ngrp; + return (0); +} + +/* + * The FreeBSD native getgid(2) and getuid(2) also modify td->td_retval[1] + * when COMPAT_43 or COMPAT_SUNOS is defined. This globbers registers that + * are assumed to be preserved. The following lightweight syscalls fixes + * this. See also linux_getpid(2), linux_getgid(2) and linux_getuid(2) in + * linux_misc.c + * + * linux_getgid16() - MP SAFE + * linux_getuid16() - MP SAFE + */ + +int +linux_getgid16(struct thread *td, struct linux_getgid16_args *args) +{ + + td->td_retval[0] = td->td_ucred->cr_rgid; + return (0); +} + +int +linux_getuid16(struct thread *td, struct linux_getuid16_args *args) +{ + + td->td_retval[0] = td->td_ucred->cr_ruid; + return (0); +} + +int +linux_getegid16(struct thread *td, struct linux_getegid16_args *args) +{ + struct getegid_args bsd; + + return (getegid(td, &bsd)); +} + +int +linux_geteuid16(struct thread *td, struct linux_geteuid16_args *args) +{ + struct geteuid_args bsd; + + return (geteuid(td, &bsd)); +} + +int +linux_setgid16(struct thread *td, struct linux_setgid16_args *args) +{ + struct setgid_args bsd; + + bsd.gid = args->gid; + return (setgid(td, &bsd)); +} + +int +linux_setuid16(struct thread *td, struct linux_setuid16_args *args) +{ + struct setuid_args bsd; + + bsd.uid = args->uid; + return (setuid(td, &bsd)); +} + +int +linux_setregid16(struct thread *td, struct linux_setregid16_args *args) +{ + struct setregid_args bsd; + + bsd.rgid = CAST_NOCHG(args->rgid); + bsd.egid = CAST_NOCHG(args->egid); + return (setregid(td, &bsd)); +} + +int +linux_setreuid16(struct thread *td, struct linux_setreuid16_args *args) +{ + struct setreuid_args bsd; + + bsd.ruid = CAST_NOCHG(args->ruid); + bsd.euid = CAST_NOCHG(args->euid); + return (setreuid(td, &bsd)); +} + +int +linux_setresgid16(struct thread *td, struct linux_setresgid16_args *args) +{ + struct setresgid_args bsd; + + bsd.rgid = CAST_NOCHG(args->rgid); + bsd.egid = CAST_NOCHG(args->egid); + bsd.sgid = CAST_NOCHG(args->sgid); + return (setresgid(td, &bsd)); +} + +int +linux_setresuid16(struct thread *td, struct linux_setresuid16_args *args) +{ + struct setresuid_args bsd; + + bsd.ruid = CAST_NOCHG(args->ruid); + bsd.euid = CAST_NOCHG(args->euid); + bsd.suid = CAST_NOCHG(args->suid); + return (setresuid(td, &bsd)); +} diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c new file mode 100644 index 0000000..4949a45 --- /dev/null +++ b/sys/compat/linux/linux_util.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 1994 Christos Zoulas + * Copyright (c) 1995 Frank van der Linden + * Copyright (c) 1995 Scott Bartram + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/vnode.h> + +#include <compat/linux/linux_util.h> + +const char linux_emul_path[] = "/compat/linux"; + +/* + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + */ +int +linux_emul_find(td, sgp, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + char *path; + char **pbuf; + int cflag; +{ + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + int error; + const char *prefix; + char *ptr, *buf, *cp; + size_t sz, len; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + prefix = linux_emul_path; + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--); + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + *cp = '/'; + } + else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + + /* + * We now compare the vnode of the linux_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + NDFREE(&nd, NDF_ONLY_PNBUF); + vrele(nd.ni_vp); + return error; + } + + if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { + goto bad; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) + != 0) { + goto bad; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto bad; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + if (*pbuf != NULL) + error = copyout(buf, *pbuf, sz); + else + error = ENAMETOOLONG; + free(buf, M_TEMP); + } + + NDFREE(&nd, NDF_ONLY_PNBUF); + vrele(nd.ni_vp); + if (!cflag) { + NDFREE(&ndroot, NDF_ONLY_PNBUF); + vrele(ndroot.ni_vp); + } + return error; + +bad: + NDFREE(&ndroot, NDF_ONLY_PNBUF); + vrele(ndroot.ni_vp); + NDFREE(&nd, NDF_ONLY_PNBUF); + vrele(nd.ni_vp); + free(buf, M_TEMP); + return error; +} diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h new file mode 100644 index 0000000..ee421a2 --- /dev/null +++ b/sys/compat/linux/linux_util.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1994 Christos Zoulas + * Copyright (c) 1995 Frank van der Linden + * Copyright (c) 1995 Scott Bartram + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp + * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp + * $FreeBSD$ + */ + +/* + * This file is pretty much the same as Christos' svr4_util.h + * (for now). + */ + +#ifndef _LINUX_UTIL_H_ +#define _LINUX_UTIL_H_ + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <machine/vmparam.h> +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/cdefs.h> + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode)) + +static __inline caddr_t +stackgap_init() +{ + return (caddr_t)(PS_STRINGS - szsigcode - SPARE_USRSPACE); +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p = (void *) *sgp; + + sz = ALIGN(sz); + if (*sgp + sz > (caddr_t)(PS_STRINGS - szsigcode)) + return NULL; + *sgp += sz; + return p; +} + +extern const char linux_emul_path[]; + +int linux_emul_find(struct thread *, caddr_t *, char *, char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = linux_emul_find(p, sgp, path, &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT(p, sgp, path, 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT(p, sgp, path, 1) + +#define DUMMY(s) \ +int \ +linux_ ## s(struct thread *p, struct linux_ ## s ## _args *args) \ +{ \ + return (unsupported_msg(p, #s)); \ +} \ +struct __hack + +static __inline int +unsupported_msg(struct thread *td, const char *fname) +{ + + printf("linux: syscall %s is obsoleted or not implemented (pid=%ld)\n", + fname, (long)td->td_proc->p_pid); + return (ENOSYS); +} + +#endif /* !_LINUX_UTIL_H_ */ diff --git a/sys/compat/netbsd/dvcfg.h b/sys/compat/netbsd/dvcfg.h new file mode 100644 index 0000000..5485f89 --- /dev/null +++ b/sys/compat/netbsd/dvcfg.h @@ -0,0 +1,65 @@ +/* $FreeBSD$ */ +/* $NetBSD$ */ +/* + * [NetBSD for NEC PC98 series] + * Copyright (c) 1996 NetBSD/pc98 porting staff. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1996 Naofumi HONDA. All rights reserved. + */ + +#ifndef _I386_DVCFG_H_ +#define _I386_DVCFG_H_ + +typedef void *dvcfg_hw_t; + +struct dvcfg_hwsel { + int cfg_max; + + dvcfg_hw_t *cfg_sel; +}; + +#define DVCFG_MAJOR(dvcfg) (((u_int)(dvcfg)) >> 16) +#define DVCFG_MINOR(dvcfg) (((u_int)(dvcfg)) & 0xffff) + +#define DVCFG_MKCFG(major, minor) ((((u_int)(major)) << 16) | ((minor) & 0xffff)) + +#define DVCFG_HWSEL_SZ(array) (sizeof(array) / sizeof(dvcfg_hw_t)) + +static __inline dvcfg_hw_t dvcfg_hw(struct dvcfg_hwsel *, u_int); + +static __inline dvcfg_hw_t +dvcfg_hw(selp, num) + struct dvcfg_hwsel *selp; + u_int num; +{ + + return ((num >= selp->cfg_max) ? 0 : selp->cfg_sel[num]); +} + +#define DVCFG_HW(SELP, NUM) dvcfg_hw((SELP), (NUM)) +#endif /* _I386_DVCFG_H_ */ diff --git a/sys/compat/netbsd/physio_proc.h b/sys/compat/netbsd/physio_proc.h new file mode 100644 index 0000000..74848a4 --- /dev/null +++ b/sys/compat/netbsd/physio_proc.h @@ -0,0 +1,56 @@ +/* $FreeBSD$ */ +/* $NecBSD: physio_proc.h,v 3.4 1999/07/23 20:47:03 honda Exp $ */ +/* $NetBSD$ */ + +/* + * [NetBSD for NEC PC-98 series] + * Copyright (c) 1998 + * NetBSD/pc98 porting staff. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _I386_PHYSIO_PROC_H_ +#define _I386_PHYSIO_PROC_H_ +#include <sys/buf.h> +#include <sys/queue.h> + +struct physio_proc { +}; + +static __inline struct physio_proc *physio_proc_enter(struct buf *); +static __inline void physio_proc_leave(struct physio_proc *); + +static __inline struct physio_proc * +physio_proc_enter(bp) + struct buf *bp; +{ + return NULL; +} + +static __inline void +physio_proc_leave(pp) + struct physio_proc *pp; +{ +} +#endif /* _I386_PHYSIO_PROC_H_ */ diff --git a/sys/compat/pecoff/imgact_pecoff.c b/sys/compat/pecoff/imgact_pecoff.c new file mode 100644 index 0000000..175b021 --- /dev/null +++ b/sys/compat/pecoff/imgact_pecoff.c @@ -0,0 +1,650 @@ +/* $NetBSD$ */ +/* $FreeBSD$ */ + +/* + * Copyright (c) 2000 Masaru OKI + * Copyright (c) 1994, 1995, 1998 Scott Bartram + * Copyright (c) 1994 Adam Glass + * Copyright (c) 1993, 1994 Christopher G. Demetriou + * + * originally from NetBSD kern/exec_ecoff.c + * + * Copyright (c) 2000 Takanori Watanabe + * Copyright (c) 2000 KUROSAWA Takahiro + * Copyright (c) 1995-1996 Sen Schmidt + * Copyright (c) 1996 Peter Wemm + * All rights reserved. + * + * originally from FreeBSD kern/imgact_elf.c + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Masaru OKI. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/imgact.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mman.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/sysent.h> +#include <sys/vnode.h> + +#include <machine/reg.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> + +#include <sys/user.h> +#include <sys/exec.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/cpu.h> +#include <sys/syscall.h> +#include <sys/sysent.h> +#include <machine/md_var.h> +#include <machine/pecoff_machdep.h> +#include <compat/pecoff/imgact_pecoff.h> + +#include "opt_pecoff.h" + +#define PECOFF_PE_SIGNATURE "PE\0\0" +static int pecoff_fixup(register_t **, struct image_params *); +static int +pecoff_coredump(register struct thread *, register struct vnode *, + off_t); +#ifndef PECOFF_DEBUG +#define DPRINTF(a) +#else +#define DPRINTF(a) printf a +#endif +static struct sysentvec pecoff_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + 0, + 0, + 0, + 0, + pecoff_fixup, + sendsig, + sigcode, + &szsigcode, + 0, + "FreeBSD PECoff", + pecoff_coredump, + NULL, + MINSIGSTKSZ + +}; + +static const char signature[] = PECOFF_PE_SIGNATURE; + +static int +exec_pecoff_coff_prep_omagic(struct image_params *, + struct coff_filehdr *, + struct coff_aouthdr *, int peoffs); +static int +exec_pecoff_coff_prep_nmagic(struct image_params *, + struct coff_filehdr *, + struct coff_aouthdr *, int peoffs); +static int +exec_pecoff_coff_prep_zmagic(struct image_params *, + struct coff_filehdr *, + struct coff_aouthdr *, int peoffs); + +static int +exec_pecoff_coff_makecmds(struct image_params *, + struct coff_filehdr *, int); + +static int pecoff_signature(struct thread *, struct vnode *, const struct pecoff_dos_filehdr *); +static int pecoff_read_from(struct thread *, struct vnode *, int, caddr_t, int); +static int +pecoff_load_section(struct thread * td, + struct vmspace * vmspace, struct vnode * vp, + vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, + vm_prot_t prot); + +static int +pecoff_fixup(register_t ** stack_base, struct image_params * imgp) +{ + int len = sizeof(struct pecoff_args); + struct pecoff_imghdr *ap; + register_t *pos; + + pos = *stack_base + (imgp->argc + imgp->envc + 2); + ap = (struct pecoff_imghdr *) imgp->auxargs; + if (copyout(ap, pos, len)) { + return NULL; + } + free(ap, M_TEMP); + imgp->auxargs = NULL; + (*stack_base)--; + suword(*stack_base, (long) imgp->argc); + return 0; +} + + +static int +pecoff_coredump(register struct thread * td, register struct vnode * vp, + off_t limit) +{ + register struct ucred *cred = td->td_ucred; + struct proc *p = td->td_proc; + register struct vmspace *vm = p->p_vmspace; + int error; +#ifdef PECOFF_DEBUG + struct vm_map *map; + struct vm_map_entry *ent; + struct reg regs; + +#endif + if (ctob((UAREA_PAGES+KSTACK_PAGES) + vm->vm_dsize + vm->vm_ssize) >= limit) + return (EFAULT); + PROC_LOCK(p); + fill_kinfo_proc(p, &p->p_uarea->u_kproc); + PROC_UNLOCK(p); + +#if PECOFF_DEBUG + fill_regs(td, ®s); + printf("EIP%x\n", regs.r_eip); + printf("EAX%x EBX%x ECX%x EDI%x\n", + regs.r_eax, regs.r_ebx, regs.r_ecx, regs.r_edi); + map = &vm->vm_map; + ent = &map->header; + printf("%p %p %p\n", ent, ent->prev, ent->next); +#endif + error = cpu_coredump(td, vp, cred); + if (error == 0) + error = vn_rdwr_inchunks(UIO_WRITE, vp, vm->vm_daddr, + (int)ctob(vm->vm_dsize), + (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)), + UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td); + if (error == 0) + error = vn_rdwr_inchunks(UIO_WRITE, vp, + (caddr_t)trunc_page(USRSTACK - ctob(vm->vm_ssize)), + round_page(ctob(vm->vm_ssize)), + (off_t)ctob((UAREA_PAGES+KSTACK_PAGES)) + + ctob(vm->vm_dsize), + UIO_USERSPACE, IO_UNIT, cred, (int *)NULL, td); + return (error); + +} + +static int +pecoff_load_section(struct thread * td, struct vmspace * vmspace, struct vnode * vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) +{ + size_t map_len; + vm_offset_t map_addr; + int error, rv; + size_t copy_len; + size_t copy_map_len; + size_t copy_start; + vm_object_t object; + vm_offset_t copy_map_offset; + vm_offset_t file_addr; + vm_offset_t data_buf = 0; + + object = vp->v_object; + error = 0; + + map_addr = trunc_page((vm_offset_t) vmaddr); + file_addr = trunc_page(offset); + DPRINTF(("SECARG:%x %p %x %x\n", offset, vmaddr, memsz, filsz)); + if (file_addr != offset) { + /* + * The section is not on page boundary. We can't use + * vm_map_insert(). Use copyin instead. + */ + map_len = round_page(memsz); + copy_len = filsz; + copy_map_offset = file_addr; + copy_map_len = round_page(offset + filsz) - file_addr; + copy_start = offset - file_addr; + + DPRINTF(("offset=%x vmaddr=%lx filsz=%x memsz=%x\n", + offset, (long)vmaddr, filsz, memsz)); + DPRINTF(("map_len=%x copy_len=%x copy_map_offset=%x" + " copy_map_len=%x copy_start=%x\n", + map_len, copy_len, copy_map_offset, + copy_map_len, copy_start)); + } else { + + map_len = trunc_page(filsz); + + if (map_len != 0) { + vm_object_reference(object); + vm_map_lock(&vmspace->vm_map); + rv = vm_map_insert(&vmspace->vm_map, + object, + file_addr, /* file offset */ + map_addr, /* virtual start */ + map_addr + map_len, /* virtual end */ + prot, + VM_PROT_ALL, + MAP_COPY_ON_WRITE | MAP_PREFAULT); + + vm_map_unlock(&vmspace->vm_map); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return EINVAL; + } + /* we can stop now if we've covered it all */ + if (memsz == filsz) + return 0; + + } + copy_map_offset = trunc_page(offset + filsz); + copy_map_len = PAGE_SIZE; + copy_start = 0; + copy_len = (offset + filsz) - trunc_page(offset + filsz); + map_addr = trunc_page((vm_offset_t) vmaddr + filsz); + map_len = round_page((vm_offset_t) vmaddr + memsz) - map_addr; + + } + + if (map_len != 0) { + vm_map_lock(&vmspace->vm_map); + rv = vm_map_insert(&vmspace->vm_map, NULL, 0, + map_addr, map_addr + map_len, + VM_PROT_ALL, VM_PROT_ALL, 0); + vm_map_unlock(&vmspace->vm_map); + DPRINTF(("EMP-rv:%d,%x %x\n", rv, map_addr, map_addr + map_len)); + if (rv != KERN_SUCCESS) { + return EINVAL; + } + } + DPRINTF(("COPYARG %x %x\n", map_addr, copy_len)); + if (copy_len != 0) { + vm_object_reference(object); + rv = vm_map_find(exec_map, + object, + copy_map_offset, + &data_buf, + copy_map_len, + TRUE, + VM_PROT_READ, + VM_PROT_ALL, + MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); + if (rv != KERN_SUCCESS) { + vm_object_deallocate(object); + return EINVAL; + } + /* send the page fragment to user space */ + + error = copyout((caddr_t) data_buf + copy_start, + (caddr_t) map_addr, copy_len); + vm_map_remove(exec_map, data_buf, data_buf + copy_map_len); + DPRINTF(("%d\n", error)); + if (error) + return (error); + } + /* + * set it to the specified protection + */ + vm_map_protect(&vmspace->vm_map, map_addr, + map_addr + map_len, prot, + FALSE); + return error; + +} +static int +pecoff_load_file(struct thread * td, const char *file, u_long * addr, u_long * entry, u_long * ldexport) +{ + + struct nameidata nd; + struct pecoff_dos_filehdr dh; + struct coff_filehdr *fp = 0; + struct coff_aouthdr *ap; + struct pecoff_opthdr *wp; + struct coff_scnhdr *sh = 0; + struct vmspace *vmspace = td->td_proc->p_vmspace; + struct vattr attr; + struct image_params image_params, *imgp; + int peofs; + int error, i, scnsiz; + + imgp = &image_params; + /* + * Initialize part of the common data + */ + imgp->proc = td->td_proc; + imgp->uap = NULL; + imgp->attr = &attr; + imgp->firstpage = NULL; + + NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_SYSSPACE, file, td); + + if ((error = namei(&nd)) != 0) { + nd.ni_vp = NULL; + goto fail; + } + NDFREE(&nd, NDF_ONLY_PNBUF); + imgp->vp = nd.ni_vp; + + /* + * Check permissions, modes, uid, etc on the file, and "open" it. + */ + error = exec_check_permissions(imgp); + if (error) { + VOP_UNLOCK(nd.ni_vp, 0, td); + goto fail; + } + VOP_UNLOCK(nd.ni_vp, 0, td); + if (error) + goto fail; + if ((error = pecoff_read_from(td, imgp->vp, 0, (caddr_t) & dh, sizeof(dh))) != 0) + goto fail; + if ((error = pecoff_signature(td, imgp->vp, &dh) != 0)) + goto fail; + fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK); + peofs = dh.d_peofs + sizeof(signature) - 1; + if ((error = pecoff_read_from(td, imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE) != 0)) + goto fail; + if (COFF_BADMAG(fp)) { + error = ENOEXEC; + goto fail; + } + ap = (void *) ((char *) fp + sizeof(struct coff_filehdr)); + wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr)); + /* read section header */ + scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns; + sh = malloc(scnsiz, M_TEMP, M_WAITOK); + if ((error = pecoff_read_from(td, imgp->vp, peofs + PECOFF_HDR_SIZE, + (caddr_t) sh, scnsiz)) != 0) + goto fail; + + /* + * Read Section infomation and map sections. + */ + + for (i = 0; i < fp->f_nscns; i++) { + int prot = 0; + + if (sh[i].s_flags & COFF_STYP_DISCARD) + continue; + /* XXX ? */ + if ((sh[i].s_flags & COFF_STYP_TEXT) && + (sh[i].s_flags & COFF_STYP_EXEC) == 0) + continue; + if ((sh[i].s_flags & (COFF_STYP_TEXT | COFF_STYP_DATA | COFF_STYP_BSS)) == 0) + continue; + + prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0; + prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0; + prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0; + + sh[i].s_vaddr += wp->w_base; /* RVA --> VA */ + if ((error = pecoff_load_section(td, vmspace, imgp->vp, sh[i].s_scnptr + ,(caddr_t) sh[i].s_vaddr, + sh[i].s_paddr, sh[i].s_size + ,prot)) != 0) + goto fail; + + } + *entry = wp->w_base + ap->a_entry; + *addr = wp->w_base; + *ldexport = wp->w_imghdr[0].i_vaddr + wp->w_base; +fail: + if (fp) + free(fp, M_TEMP); + if (sh) + free(sh, M_TEMP); + if (nd.ni_vp) + vrele(nd.ni_vp); + + return error; +} +static int +exec_pecoff_coff_prep_omagic(struct image_params * imgp, + struct coff_filehdr * fp, + struct coff_aouthdr * ap, int peofs) +{ + return ENOEXEC; +} +static int +exec_pecoff_coff_prep_nmagic(struct image_params * imgp, + struct coff_filehdr * fp, + struct coff_aouthdr * ap, int peofs) +{ + return ENOEXEC; +} +static int +exec_pecoff_coff_prep_zmagic(struct image_params * imgp, + struct coff_filehdr * fp, + struct coff_aouthdr * ap, int peofs) +{ + int scnsiz = sizeof(struct coff_scnhdr) * fp->f_nscns; + int error = ENOEXEC, i; + int prot; + u_long text_size = 0, data_size = 0, dsize; + u_long text_addr = 0, data_addr = VM_MAXUSER_ADDRESS; + u_long ldexport, ldbase; + struct pecoff_opthdr *wp; + struct coff_scnhdr *sh; + struct vmspace *vmspace; + struct pecoff_args *argp = NULL; + + sh = malloc(scnsiz, M_TEMP, M_WAITOK); + + wp = (void *) ((char *) ap + sizeof(struct coff_aouthdr)); + error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), imgp->vp, + peofs + PECOFF_HDR_SIZE, (caddr_t) sh, scnsiz); + if ((error = exec_extract_strings(imgp)) != 0) + goto fail; + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); + vmspace = imgp->proc->p_vmspace; + for (i = 0; i < fp->f_nscns; i++) { + prot = VM_PROT_WRITE; /* XXX for relocation? */ + prot |= (sh[i].s_flags & COFF_STYP_READ) ? VM_PROT_READ : 0; + prot |= (sh[i].s_flags & COFF_STYP_WRITE) ? VM_PROT_WRITE : 0; + prot |= (sh[i].s_flags & COFF_STYP_EXEC) ? VM_PROT_EXECUTE : 0; + sh[i].s_vaddr += wp->w_base; + if (sh[i].s_flags & COFF_STYP_DISCARD) + continue; + if ((sh[i].s_flags & COFF_STYP_TEXT) != 0) { + + error = pecoff_load_section( + FIRST_THREAD_IN_PROC(imgp->proc), + vmspace, imgp->vp, sh[i].s_scnptr, + (caddr_t) sh[i].s_vaddr, sh[i].s_paddr, + sh[i].s_size ,prot); + DPRINTF(("ERROR%d\n", error)); + if (error) + goto fail; + text_addr = trunc_page(sh[i].s_vaddr); + text_size = trunc_page(sh[i].s_size + sh[i].s_vaddr - text_addr); + + } + if ((sh[i].s_flags & (COFF_STYP_DATA|COFF_STYP_BSS)) != 0) { + if (pecoff_load_section( + FIRST_THREAD_IN_PROC(imgp->proc), vmspace, + imgp->vp, sh[i].s_scnptr, (caddr_t) sh[i].s_vaddr, + sh[i].s_paddr, sh[i].s_size, prot) != 0) + goto fail; + data_addr = min(trunc_page(sh[i].s_vaddr), data_addr); + dsize = round_page(sh[i].s_vaddr + sh[i].s_paddr) + - data_addr; + data_size = max(dsize, data_size); + + } + } + vmspace->vm_tsize = text_size >> PAGE_SHIFT; + vmspace->vm_taddr = (caddr_t) (uintptr_t) text_addr; + vmspace->vm_dsize = data_size >> PAGE_SHIFT; + vmspace->vm_daddr = (caddr_t) (uintptr_t) data_addr; + argp = malloc(sizeof(struct pecoff_args), M_TEMP, M_WAITOK); + if (argp == NULL) { + error = ENOMEM; + goto fail; + } + argp->a_base = wp->w_base; + argp->a_entry = wp->w_base + ap->a_entry; + argp->a_end = data_addr + data_size; + argp->a_subsystem = wp->w_subvers; + error = pecoff_load_file(FIRST_THREAD_IN_PROC(imgp->proc), + "/usr/libexec/ld.so.dll", &ldbase, &imgp->entry_addr, &ldexport); + if (error) + goto fail; + + argp->a_ldbase = ldbase; + argp->a_ldexport = ldexport; + memcpy(argp->a_imghdr, wp->w_imghdr, sizeof(struct pecoff_imghdr) * 16); + for (i = 0; i < 16; i++) { + argp->a_imghdr[i].i_vaddr += wp->w_base; + } + imgp->proc->p_sysent = &pecoff_sysvec; + if (error) + goto fail; + imgp->auxargs = argp; + imgp->auxarg_size = sizeof(struct pecoff_args); + imgp->interpreted = 0; + + mp_fixme("Unlocked vflag access."); + imgp->vp->v_vflag |= VV_TEXT; + if (sh != NULL) + free(sh, M_TEMP); + return 0; +fail: + error = (error) ? error : ENOEXEC; + if (sh != NULL) + free(sh, M_TEMP); + if (argp != NULL) + free(argp, M_TEMP); + + return error; +} + +int +exec_pecoff_coff_makecmds(struct image_params * imgp, + struct coff_filehdr * fp, int peofs) +{ + struct coff_aouthdr *ap; + int error; + + if (COFF_BADMAG(fp)) { + return ENOEXEC; + } + ap = (void *) ((char *) fp + sizeof(struct coff_filehdr)); + switch (ap->a_magic) { + case COFF_OMAGIC: + error = exec_pecoff_coff_prep_omagic(imgp, fp, ap, peofs); + break; + case COFF_NMAGIC: + error = exec_pecoff_coff_prep_nmagic(imgp, fp, ap, peofs); + break; + case COFF_ZMAGIC: + error = exec_pecoff_coff_prep_zmagic(imgp, fp, ap, peofs); + break; + default: + return ENOEXEC; + } + + return error; +} + +static int +pecoff_signature(td, vp, dp) + struct thread *td; + struct vnode *vp; + const struct pecoff_dos_filehdr *dp; +{ + int error; + char buf[512]; + char *pesig; + if (DOS_BADMAG(dp)) { + return ENOEXEC; + } + error = pecoff_read_from(td, vp, dp->d_peofs, buf, sizeof(buf)); + if (error) { + return error; + } + pesig = buf; + if (memcmp(pesig, signature, sizeof(signature) - 1) == 0) { + return 0; + } + return EFTYPE; +} +int +pecoff_read_from(td, vp, pos, buf, siz) + struct thread *td; + struct vnode *vp; + int pos; + caddr_t buf; + int siz; +{ + int error; + size_t resid; + + error = vn_rdwr(UIO_READ, vp, buf, siz, pos, + UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, + &resid, td); + if (error) + return error; + + if (resid != 0) { + return ENOEXEC; + } + return 0; +} + +static int +imgact_pecoff(struct image_params * imgp) +{ + const struct pecoff_dos_filehdr *dp = (const struct pecoff_dos_filehdr *) + imgp->image_header; + struct coff_filehdr *fp; + int error, peofs; + error = pecoff_signature(FIRST_THREAD_IN_PROC(imgp->proc), + imgp->vp, dp); + if (error) { + return -1; + } + peofs = dp->d_peofs + sizeof(signature) - 1; + fp = malloc(PECOFF_HDR_SIZE, M_TEMP, M_WAITOK); + error = pecoff_read_from(FIRST_THREAD_IN_PROC(imgp->proc), + imgp->vp, peofs, (caddr_t) fp, PECOFF_HDR_SIZE); + if (error) { + free(fp, M_TEMP); + return error; + } + error = exec_pecoff_coff_makecmds(imgp, fp, peofs); + free(fp, M_TEMP); + return error; +} + +static struct execsw pecoff_execsw = {imgact_pecoff, "FreeBSD PEcoff"}; +EXEC_SET(pecoff, pecoff_execsw); diff --git a/sys/compat/pecoff/imgact_pecoff.h b/sys/compat/pecoff/imgact_pecoff.h new file mode 100644 index 0000000..0da3a56 --- /dev/null +++ b/sys/compat/pecoff/imgact_pecoff.h @@ -0,0 +1,142 @@ +/* $NetBSD$ */ +/* $FreeBSD$ */ +/* + * Copyright (c) 2000 Masaru OKI + */ + +#ifndef _PECOFF_EXEC_H_ +#define _PECOFF_EXEC_H_ + +struct pecoff_dos_filehdr { + u_int16_t d_magic;/* +0x00 'MZ' */ + u_int8_t d_stub[0x3a]; + u_int32_t d_peofs;/* +0x3c */ +}; + +#define PECOFF_DOS_MAGIC 0x5a4d +#define PECOFF_DOS_HDR_SIZE (sizeof(struct pecoff_dos_filehdr)) + +#define DOS_BADMAG(dp) ((dp)->d_magic != PECOFF_DOS_MAGIC) + +/* + * COFF file header + */ + +struct coff_filehdr { + u_short f_magic;/* magic number */ + u_short f_nscns;/* # of sections */ + long f_timdat; /* timestamp */ + long f_symptr; /* file offset of symbol table */ + long f_nsyms;/* # of symbol table entries */ + u_short f_opthdr; /* size of optional header */ + u_short f_flags;/* flags */ +}; + +/* + * COFF system header + */ + +struct coff_aouthdr { + short a_magic; + short a_vstamp; + long a_tsize; + long a_dsize; + long a_bsize; + long a_entry; + long a_tstart; + long a_dstart; +}; + +/* magic */ +#define COFF_OMAGIC 0407 /* text not write-protected; data seg is + * contiguous with text */ +#define COFF_NMAGIC 0410 /* text is write-protected; data starts at + * next seg following text */ +#define COFF_ZMAGIC 0413 /* text and data segs are aligned for direct + * paging */ +#define COFF_SMAGIC 0443 /* shared lib */ + +struct pecoff_imghdr { + long i_vaddr; + long i_size; +}; + +struct pecoff_opthdr { + long w_base; + long w_salign; + long w_falign; + long w_osvers; + long w_imgvers; + long w_subvers; + long w_rsvd; + long w_imgsize; + long w_hdrsize; + long w_chksum; + u_short w_subsys; + u_short w_dllflags; + long w_ssize; + long w_cssize; + long w_hsize; + long w_chsize; + long w_lflag; + long w_nimghdr; + struct pecoff_imghdr w_imghdr[16]; +}; + +/* + * COFF section header + */ + +struct coff_scnhdr { + char s_name[8]; + long s_paddr; + long s_vaddr; + long s_size; + long s_scnptr; + long s_relptr; + long s_lnnoptr; + u_short s_nreloc; + u_short s_nlnno; + long s_flags; +}; + +/* s_flags */ +#define COFF_STYP_REG 0x00 +#define COFF_STYP_DSECT 0x01 +#define COFF_STYP_NOLOAD 0x02 +#define COFF_STYP_GROUP 0x04 +#define COFF_STYP_PAD 0x08 +#define COFF_STYP_COPY 0x10 +#define COFF_STYP_TEXT 0x20 +#define COFF_STYP_DATA 0x40 +#define COFF_STYP_BSS 0x80 +#define COFF_STYP_INFO 0x200 +#define COFF_STYP_OVER 0x400 +#define COFF_STYP_SHLIB 0x800 +/* s_flags for PE */ +#define COFF_STYP_DISCARD 0x2000000 +#define COFF_STYP_EXEC 0x20000000 +#define COFF_STYP_READ 0x40000000 +#define COFF_STYP_WRITE 0x80000000 + +struct pecoff_args { + u_long a_base; + u_long a_entry; + u_long a_end; + u_long a_subsystem; + struct pecoff_imghdr a_imghdr[16]; + u_long a_ldbase; + u_long a_ldexport; +}; + +#define COFF_LDPGSZ 4096 +#define COFF_ALIGN(a) ((a) & ~(COFF_LDPGSZ - 1)) +#define COFF_ROUND(a) COFF_ALIGN((a) + COFF_LDPGSZ - 1) + +#define COFF_HDR_SIZE \ + (sizeof(struct coff_filehdr) + sizeof(struct coff_aouthdr)) + +#define PECOFF_HDR_SIZE (COFF_HDR_SIZE + sizeof(struct pecoff_opthdr)) + + +#endif diff --git a/sys/compat/svr4/Makefile b/sys/compat/svr4/Makefile new file mode 100644 index 0000000..7da356e --- /dev/null +++ b/sys/compat/svr4/Makefile @@ -0,0 +1,19 @@ +# Makefile for syscall tables +# +# $FreeBSD$ + +MAINTAINER= newton@freebsd.org + +all: + @echo "make sysent only" + +sysent: svr4_sysent.c svr4_syscall.h svr4_proto.h + +svr4_syscallnames.c svr4_sysent.c svr4_syscall.h svr4_proto.h: \ + ../../kern/makesyscalls.sh syscalls.master syscalls.conf + -mv -f svr4_syscallnames.c svr4_syscallnames.c.bak + -mv -f svr4_sysent.c svr4_sysent.c.bak + -mv -f svr4_syscall.h svr4_syscall.h.bak + -mv -f svr4_proto.h svr4_proto.h.bak + sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf + diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c new file mode 100644 index 0000000..c8b0e1f8 --- /dev/null +++ b/sys/compat/svr4/imgact_svr4.c @@ -0,0 +1,241 @@ +/*- + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994-1996 Søren Schmidt + * All rights reserved. + * + * Based heavily on /sys/kern/imgact_aout.c which is: + * Copyright (c) 1993, David Greenman + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/exec.h> +#include <sys/imgact.h> +#include <sys/imgact_aout.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mman.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/resourcevar.h> +#include <sys/vnode.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +#include <compat/svr4/svr4.h> + +static int exec_svr4_imgact(struct image_params *iparams); + +static int +exec_svr4_imgact(imgp) + struct image_params *imgp; +{ + const struct exec *a_out = (const struct exec *) imgp->image_header; + struct vmspace *vmspace; + vm_offset_t vmaddr; + unsigned long virtual_offset, file_offset; + vm_offset_t buffer; + unsigned long bss_size; + int error; + + if (((a_out->a_magic >> 16) & 0xff) != 0x64) + return -1; + + /* + * Set file/virtual offset based on a.out variant. + */ + switch ((int)(a_out->a_magic & 0xffff)) { + case 0413: + virtual_offset = 0; + file_offset = 1024; + break; + case 0314: + virtual_offset = 4096; + file_offset = 0; + break; + default: + return (-1); + } + bss_size = round_page(a_out->a_bss); +#ifdef DEBUG + printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", a_out->a_text, a_out->a_data, bss_size); +#endif + + /* + * Check various fields in header for validity/bounds. + */ + if (a_out->a_entry < virtual_offset || + a_out->a_entry >= virtual_offset + a_out->a_text || + a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) + return (-1); + + /* text + data can't exceed file size */ + if (a_out->a_data + a_out->a_text > imgp->attr->va_size) + return (EFAULT); + /* For p_rlimit below. */ + mtx_assert(&Giant, MA_OWNED); + /* + * text/data/bss must not exceed limits + */ + if (a_out->a_text > maxtsiz || + a_out->a_data + bss_size > imgp->proc->p_rlimit[RLIMIT_DATA].rlim_cur) + return (ENOMEM); + + /* copy in arguments and/or environment from old process */ + error = exec_extract_strings(imgp); + if (error) + return (error); + + /* + * Destroy old process VM and create a new one (with a new stack) + */ + exec_new_vmspace(imgp, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS, USRSTACK); + vmspace = imgp->proc->p_vmspace; + + /* + * Check if file_offset page aligned,. + * Currently we cannot handle misalinged file offsets, + * and so we read in the entire image (what a waste). + */ + if (file_offset & PAGE_MASK) { +#ifdef DEBUG + printf("imgact: Non page aligned binary %lu\n", file_offset); +#endif + /* + * Map text+data+bss read/write/execute + */ + vmaddr = virtual_offset; + error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, + a_out->a_text + a_out->a_data + bss_size, FALSE, + VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) + return error; + + error = vm_mmap(kernel_map, &buffer, + round_page(a_out->a_text + a_out->a_data + file_offset), + VM_PROT_READ, VM_PROT_READ, 0, + (caddr_t) imgp->vp, trunc_page(file_offset)); + if (error) + return error; + + error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, + a_out->a_text + a_out->a_data); + + vm_map_remove(kernel_map, buffer, + buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); + + if (error) + return error; + + /* + * remove write enable on the 'text' part + */ + error = vm_map_protect(&vmspace->vm_map, + vmaddr, + vmaddr + a_out->a_text, + VM_PROT_EXECUTE|VM_PROT_READ, + TRUE); + if (error) + return error; + } + else { +#ifdef DEBUG + printf("imgact: Page aligned binary %lu\n", file_offset); +#endif + /* + * Map text+data read/execute + */ + vmaddr = virtual_offset; + error = vm_mmap(&vmspace->vm_map, &vmaddr, + a_out->a_text + a_out->a_data, + VM_PROT_READ | VM_PROT_EXECUTE, + VM_PROT_ALL, + MAP_PRIVATE | MAP_FIXED, + (caddr_t)imgp->vp, file_offset); + if (error) + return (error); + +#ifdef DEBUG + printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr, + a_out->a_text + a_out->a_data); +#endif + /* + * allow read/write of data + */ + error = vm_map_protect(&vmspace->vm_map, + vmaddr + a_out->a_text, + vmaddr + a_out->a_text + a_out->a_data, + VM_PROT_ALL, + FALSE); + if (error) + return (error); + + /* + * Allocate anon demand-zeroed area for uninitialized data + */ + if (bss_size != 0) { + vmaddr = virtual_offset + a_out->a_text + a_out->a_data; + error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr, + bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) + return (error); +#ifdef DEBUG + printf("imgact: bssaddr=%08lx, length=%08lx\n", + (u_long)vmaddr, bss_size); +#endif + + } + /* Indicate that this file should not be modified */ + mp_fixme("Unlocked vflag access."); + imgp->vp->v_vflag |= VV_TEXT; + } + /* Fill in process VM information */ + vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT; + vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT; + vmspace->vm_taddr = (caddr_t)virtual_offset; + vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text; + + /* Fill in image_params */ + imgp->interpreted = 0; + imgp->entry_addr = a_out->a_entry; + + imgp->proc->p_sysent = &svr4_sysvec; + return (0); +} + +/* + * Tell kern_execve.c about it, with a little help from the linker. + */ +struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" }; +EXEC_SET(execsw_set, svr4_execsw); + diff --git a/sys/compat/svr4/svr4.h b/sys/compat/svr4/svr4.h new file mode 100644 index 0000000..4fbace6 --- /dev/null +++ b/sys/compat/svr4/svr4.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_svr4.h" + +#if !defined(_SVR4_H) +#define _SVR4_H + +extern struct sysentvec svr4_sysvec; + +#define memset(x,y,z) bzero(x,z) + +#define COMPAT_SVR4_SOLARIS2 +#define KTRACE + +/* These are currently unimplemented (see svr4_ipc.c) */ +#if defined(SYSVMSG) +# undef SYSVMSG +#endif +#if defined(SYSVSHM) +# undef SYSVSHM +#endif +#if defined(SYSVSEM) +# undef SYSVSEM +#endif + +#endif diff --git a/sys/compat/svr4/svr4_acl.h b/sys/compat/svr4/svr4_acl.h new file mode 100644 index 0000000..6d9454f --- /dev/null +++ b/sys/compat/svr4/svr4_acl.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1996 Christos Zoulas. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _SVR4_ACL_H_ +#define _SVR4_ACL_H_ + +typedef struct svr4_aclent { + int a_type; + svr4_uid_t a_id; + svr4_o_mode_t a_perm; +} svr4_aclent_t; + +#define SVR4_SYS_GETACL 1 +#define SVR4_SYS_SETACL 2 +#define SVR4_SYS_GETACLCNT 3 + +#endif /* !_SVR4_ACL_H_ */ diff --git a/sys/compat/svr4/svr4_dirent.h b/sys/compat/svr4/svr4_dirent.h new file mode 100644 index 0000000..2440782 --- /dev/null +++ b/sys/compat/svr4/svr4_dirent.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_DIRENT_H_ +#define _SVR4_DIRENT_H_ + +#define SVR4_MAXNAMLEN 512 + +struct svr4_dirent { + svr4_ino_t d_ino; + svr4_off_t d_off; + u_short d_reclen; + char d_name[SVR4_MAXNAMLEN + 1]; +}; + +struct svr4_dirent64 { + svr4_ino64_t d_ino; + svr4_off64_t d_off; + u_short d_reclen; + char d_name[SVR4_MAXNAMLEN + 1]; +}; + +#define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp) +#define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1)) + +#endif /* !_SVR4_DIRENT_H_ */ diff --git a/sys/compat/svr4/svr4_errno.h b/sys/compat/svr4/svr4_errno.h new file mode 100644 index 0000000..cc39929 --- /dev/null +++ b/sys/compat/svr4/svr4_errno.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_ERRNO_H_ +#define _SVR4_ERRNO_H_ + +#define SVR4_EPERM 1 +#define SVR4_ENOENT 2 +#define SVR4_ESRCH 3 +#define SVR4_EINTR 4 +#define SVR4_EIO 5 +#define SVR4_ENXIO 6 +#define SVR4_E2BIG 7 +#define SVR4_ENOEXEC 8 +#define SVR4_EBADF 9 +#define SVR4_ECHILD 10 +#define SVR4_EAGAIN 11 +#define SVR4_ENOMEM 12 +#define SVR4_EACCES 13 +#define SVR4_EFAULT 14 +#define SVR4_ENOTBLK 15 +#define SVR4_EBUSY 16 +#define SVR4_EEXIST 17 +#define SVR4_EXDEV 18 +#define SVR4_ENODEV 19 +#define SVR4_ENOTDIR 20 +#define SVR4_EISDIR 21 +#define SVR4_EINVAL 22 +#define SVR4_ENFILE 23 +#define SVR4_EMFILE 24 +#define SVR4_ENOTTY 25 +#define SVR4_ETXTBSY 26 +#define SVR4_EFBIG 27 +#define SVR4_ENOSPC 28 +#define SVR4_ESPIPE 29 +#define SVR4_EROFS 30 +#define SVR4_EMLINK 31 +#define SVR4_EPIPE 32 +#define SVR4_EDOM 33 +#define SVR4_ERANGE 34 +#define SVR4_ENOMSG 35 +#define SVR4_EIDRM 36 +#define SVR4_ECHRNG 37 +#define SVR4_EL2NSYNC 38 +#define SVR4_EL3HLT 39 +#define SVR4_EL3RST 40 +#define SVR4_ELNRNG 41 +#define SVR4_EUNATCH 42 +#define SVR4_ENOCSI 43 +#define SVR4_EL2HLT 44 +#define SVR4_EDEADLK 45 +#define SVR4_ENOLCK 46 +#define SVR4_EBADE 50 +#define SVR4_EBADR 51 +#define SVR4_EXFULL 52 +#define SVR4_ENOANO 53 +#define SVR4_EBADRQC 54 +#define SVR4_EBADSLT 55 +#define SVR4_EDEADLOCK 56 +#define SVR4_EBFONT 57 +#define SVR4_ENOSTR 60 +#define SVR4_ENODATA 61 +#define SVR4_ETIME 62 +#define SVR4_ENOSR 63 +#define SVR4_ENONET 64 +#define SVR4_ENOPKG 65 +#define SVR4_EREMOTE 66 +#define SVR4_ENOLINK 67 +#define SVR4_EADV 68 +#define SVR4_ESRMNT 69 +#define SVR4_ECOMM 70 +#define SVR4_EPROTO 71 +#define SVR4_EMULTIHOP 74 +#define SVR4_EBADMSG 77 +#define SVR4_ENAMETOOLONG 78 +#define SVR4_EOVERFLOW 79 +#define SVR4_ENOTUNIQ 80 +#define SVR4_EBADFD 81 +#define SVR4_EREMCHG 82 +#define SVR4_ELIBACC 83 +#define SVR4_ELIBBAD 84 +#define SVR4_ELIBSCN 85 +#define SVR4_ELIBMAX 86 +#define SVR4_ELIBEXEC 87 +#define SVR4_EILSEQ 88 +#define SVR4_ENOSYS 89 +#define SVR4_ELOOP 90 +#define SVR4_ERESTART 91 +#define SVR4_ESTRPIPE 92 +#define SVR4_ENOTEMPTY 93 +#define SVR4_EUSERS 94 +#define SVR4_ENOTSOCK 95 +#define SVR4_EDESTADDRREQ 96 +#define SVR4_EMSGSIZE 97 +#define SVR4_EPROTOTYPE 98 +#define SVR4_ENOPROTOOPT 99 +#define SVR4_EPROTONOSUPPORT 120 +#define SVR4_ESOCKTNOSUPPORT 121 +#define SVR4_EOPNOTSUPP 122 +#define SVR4_EPFNOSUPPORT 123 +#define SVR4_EAFNOSUPPORT 124 +#define SVR4_EADDRINUSE 125 +#define SVR4_EADDRNOTAVAIL 126 +#define SVR4_ENETDOWN 127 +#define SVR4_ENETUNREACH 128 +#define SVR4_ENETRESET 129 +#define SVR4_ECONNABORTED 130 +#define SVR4_ECONNRESET 131 +#define SVR4_ENOBUFS 132 +#define SVR4_EISCONN 133 +#define SVR4_ENOTCONN 134 +#define SVR4_EUCLEAN 135 +#define SVR4_ENOTNAM 137 +#define SVR4_ENAVAIL 138 +#define SVR4_EISNAM 139 +#define SVR4_EREMOTEIO 140 +#define SVR4_EINIT 141 +#define SVR4_EREMDEV 142 +#define SVR4_ESHUTDOWN 143 +#define SVR4_ETOOMANYREFS 144 +#define SVR4_ETIMEDOUT 145 +#define SVR4_ECONNREFUSED 146 +#define SVR4_EHOSTDOWN 147 +#define SVR4_EHOSTUNREACH 148 +#define SVR4_EWOULDBLOCK SVR4_EAGAIN +#define SVR4_EALREADY 149 +#define SVR4_EINPROGRESS 150 +#define SVR4_ESTALE 151 +#define SVR4_EIORESID 500 + +/* + * These ones are not translated... + */ +#define SVR4_EPROCLIM SVR4_ENOSYS +#define SVR4_EDQUOT SVR4_ENOSYS +#define SVR4_EBADRPC SVR4_ENOSYS +#define SVR4_ERPCMISMATCH SVR4_ENOSYS +#define SVR4_EPROGUNAVAIL SVR4_ENOSYS +#define SVR4_EPROGMISMATCH SVR4_ENOSYS +#define SVR4_EPROCUNAVAIL SVR4_ENOSYS +#define SVR4_EFTYPE SVR4_ENOSYS +#define SVR4_EAUTH SVR4_ENOSYS +#define SVR4_ENEEDAUTH SVR4_ENOSYS + +#endif /* !_SVR4_ERRNO_H_ */ diff --git a/sys/compat/svr4/svr4_exec.h b/sys/compat/svr4/svr4_exec.h new file mode 100644 index 0000000..672a360 --- /dev/null +++ b/sys/compat/svr4/svr4_exec.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_EXEC_H_ +#define _SVR4_EXEC_H_ + +#ifdef SVR4_COMPAT_SOLARIS2 +# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 12 / sizeof(char *)) +#else +# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *)) +#endif + +#if 0 +/* Don't think we need all this NetBSD stuff */ +/* + * The following is horrible; there must be a better way. I need to + * play with brk(2) a bit more. + */ +#ifdef __i386__ +/* + * I cannot load the interpreter after the data segment because brk(2) + * breaks. I have to load it somewhere before. Programs start at + * 0x08000000 so I load the interpreter far before. + */ +#define SVR4_INTERP_ADDR 0x01000000 +#endif + +#ifdef sparc +/* + * Here programs load at 0x00010000, so I load the interpreter far after + * the end of the data segment. + */ +#define SVR4_INTERP_ADDR 0x10000000 +#endif + +#ifndef SVR4_INTERP_ADDR +# define SVR4_INTERP_ADDR 0 +#endif +#endif + +/*void svr4_setregs(struct thread *, struct exec_package *, u_long);*/ + +#endif /* !_SVR4_EXEC_H_ */ diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c new file mode 100644 index 0000000..cf2fa0a --- /dev/null +++ b/sys/compat/svr4/svr4_fcntl.c @@ -0,0 +1,736 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994, 1997 Christos Zoulas. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/filedesc.h> +/*#include <sys/ioctl.h>*/ +#include <sys/lock.h> +#include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <sys/unistd.h> +#include <sys/vnode.h> + +#include <sys/sysproto.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_fcntl.h> + +static int svr4_to_bsd_flags(int); +static u_long svr4_to_bsd_cmd(u_long); +static int fd_revoke(struct thread *, int); +static int fd_truncate(struct thread *, int, struct flock *); +static int bsd_to_svr4_flags(int); +static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *); +static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *); +static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *); +static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *); + +static u_long +svr4_to_bsd_cmd(cmd) + u_long cmd; +{ + switch (cmd) { + case SVR4_F_DUPFD: + return F_DUPFD; + case SVR4_F_GETFD: + return F_GETFD; + case SVR4_F_SETFD: + return F_SETFD; + case SVR4_F_GETFL: + return F_GETFL; + case SVR4_F_SETFL: + return F_SETFL; + case SVR4_F_GETLK: + return F_GETLK; + case SVR4_F_SETLK: + return F_SETLK; + case SVR4_F_SETLKW: + return F_SETLKW; + default: + return -1; + } +} + +static int +svr4_to_bsd_flags(l) + int l; +{ + int r = 0; + r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0; + r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0; + r |= (l & SVR4_O_RDWR) ? O_RDWR : 0; + r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0; + r |= (l & SVR4_O_APPEND) ? O_APPEND : 0; + r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0; + r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0; + r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0; + r |= (l & SVR4_O_CREAT) ? O_CREAT : 0; + r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0; + r |= (l & SVR4_O_EXCL) ? O_EXCL : 0; + r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0; + return r; +} + +static int +bsd_to_svr4_flags(l) + int l; +{ + int r = 0; + r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0; + r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0; + r |= (l & O_RDWR) ? SVR4_O_RDWR : 0; + r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0; + r |= (l & O_APPEND) ? SVR4_O_APPEND : 0; + r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0; + r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0; + r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0; + r |= (l & O_CREAT) ? SVR4_O_CREAT : 0; + r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0; + r |= (l & O_EXCL) ? SVR4_O_EXCL : 0; + r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0; + return r; +} + + +static void +bsd_to_svr4_flock(iflp, oflp) + struct flock *iflp; + struct svr4_flock *oflp; +{ + switch (iflp->l_type) { + case F_RDLCK: + oflp->l_type = SVR4_F_RDLCK; + break; + case F_WRLCK: + oflp->l_type = SVR4_F_WRLCK; + break; + case F_UNLCK: + oflp->l_type = SVR4_F_UNLCK; + break; + default: + oflp->l_type = -1; + break; + } + + oflp->l_whence = (short) iflp->l_whence; + oflp->l_start = (svr4_off_t) iflp->l_start; + oflp->l_len = (svr4_off_t) iflp->l_len; + oflp->l_sysid = 0; + oflp->l_pid = (svr4_pid_t) iflp->l_pid; +} + + +static void +svr4_to_bsd_flock(iflp, oflp) + struct svr4_flock *iflp; + struct flock *oflp; +{ + switch (iflp->l_type) { + case SVR4_F_RDLCK: + oflp->l_type = F_RDLCK; + break; + case SVR4_F_WRLCK: + oflp->l_type = F_WRLCK; + break; + case SVR4_F_UNLCK: + oflp->l_type = F_UNLCK; + break; + default: + oflp->l_type = -1; + break; + } + + oflp->l_whence = iflp->l_whence; + oflp->l_start = (off_t) iflp->l_start; + oflp->l_len = (off_t) iflp->l_len; + oflp->l_pid = (pid_t) iflp->l_pid; + +} + +static void +bsd_to_svr4_flock64(iflp, oflp) + struct flock *iflp; + struct svr4_flock64 *oflp; +{ + switch (iflp->l_type) { + case F_RDLCK: + oflp->l_type = SVR4_F_RDLCK; + break; + case F_WRLCK: + oflp->l_type = SVR4_F_WRLCK; + break; + case F_UNLCK: + oflp->l_type = SVR4_F_UNLCK; + break; + default: + oflp->l_type = -1; + break; + } + + oflp->l_whence = (short) iflp->l_whence; + oflp->l_start = (svr4_off64_t) iflp->l_start; + oflp->l_len = (svr4_off64_t) iflp->l_len; + oflp->l_sysid = 0; + oflp->l_pid = (svr4_pid_t) iflp->l_pid; +} + + +static void +svr4_to_bsd_flock64(iflp, oflp) + struct svr4_flock64 *iflp; + struct flock *oflp; +{ + switch (iflp->l_type) { + case SVR4_F_RDLCK: + oflp->l_type = F_RDLCK; + break; + case SVR4_F_WRLCK: + oflp->l_type = F_WRLCK; + break; + case SVR4_F_UNLCK: + oflp->l_type = F_UNLCK; + break; + default: + oflp->l_type = -1; + break; + } + + oflp->l_whence = iflp->l_whence; + oflp->l_start = (off_t) iflp->l_start; + oflp->l_len = (off_t) iflp->l_len; + oflp->l_pid = (pid_t) iflp->l_pid; + +} + + +static int +fd_revoke(td, fd) + struct thread *td; + int fd; +{ + struct vnode *vp; + struct mount *mp; + struct vattr vattr; + int error, *retval; + + retval = td->td_retval; + if ((error = fgetvp(td, fd, &vp)) != 0) + return (error); + + if (vp->v_type != VCHR && vp->v_type != VBLK) { + error = EINVAL; + goto out; + } + + if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) + goto out; + + if (td->td_ucred->cr_uid != vattr.va_uid && + (error = suser(td)) != 0) + goto out; + + if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) + goto out; + if (vcount(vp) > 1) + VOP_REVOKE(vp, REVOKEALL); + vn_finished_write(mp); +out: + vrele(vp); + return error; +} + + +static int +fd_truncate(td, fd, flp) + struct thread *td; + int fd; + struct flock *flp; +{ + off_t start, length; + struct file *fp; + struct vnode *vp; + struct vattr vattr; + int error, *retval; + struct ftruncate_args ft; + + retval = td->td_retval; + + /* + * We only support truncating the file. + */ + if ((error = fget(td, fd, &fp)) != 0) + return (error); + + vp = (struct vnode *) fp->f_data; + + if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { + fdrop(fp, td); + return ESPIPE; + } + + if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred, td)) != 0) { + fdrop(fp, td); + return error; + } + + length = vattr.va_size; + + switch (flp->l_whence) { + case SEEK_CUR: + start = fp->f_offset + flp->l_start; + break; + + case SEEK_END: + start = flp->l_start + length; + break; + + case SEEK_SET: + start = flp->l_start; + break; + + default: + fdrop(fp, td); + return EINVAL; + } + + if (start + flp->l_len < length) { + /* We don't support free'ing in the middle of the file */ + fdrop(fp, td); + return EINVAL; + } + + SCARG(&ft, fd) = fd; + SCARG(&ft, length) = start; + + error = ftruncate(td, &ft); + + fdrop(fp, td); + return (error); +} + +int +svr4_sys_open(td, uap) + register struct thread *td; + struct svr4_sys_open_args *uap; +{ + struct proc *p = td->td_proc; + int error, retval; + struct open_args cup; + + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + (&cup)->path = uap->path; + (&cup)->flags = svr4_to_bsd_flags(uap->flags); + (&cup)->mode = uap->mode; + error = open(td, &cup); + + if (error) { + /* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path, + uap->flags, uap->mode, error);*/ + return error; + } + + retval = td->td_retval[0]; + + PROC_LOCK(p); + if (!(SCARG(&cup, flags) & O_NOCTTY) && SESS_LEADER(p) && + !(td->td_proc->p_flag & P_CONTROLT)) { +#if defined(NOTYET) + struct file *fp; + + error = fget(td, retval, &fp); + PROC_UNLOCK(p); + /* + * we may have lost a race the above open() and + * another thread issuing a close() + */ + if (error) + return (EBADF); /* XXX: correct errno? */ + /* ignore any error, just give it a try */ + if (fp->f_type == DTYPE_VNODE) + fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td); + fdrop(fp, td); + } else { + PROC_UNLOCK(p); + } +#else + } + PROC_UNLOCK(p); +#endif + return error; +} + +int +svr4_sys_open64(td, uap) + register struct thread *td; + struct svr4_sys_open64_args *uap; +{ + return svr4_sys_open(td, (struct svr4_sys_open_args *)uap); +} + +int +svr4_sys_creat(td, uap) + register struct thread *td; + struct svr4_sys_creat_args *uap; +{ + struct open_args cup; + + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, mode) = SCARG(uap, mode); + SCARG(&cup, flags) = O_WRONLY | O_CREAT | O_TRUNC; + + return open(td, &cup); +} + +int +svr4_sys_creat64(td, uap) + register struct thread *td; + struct svr4_sys_creat64_args *uap; +{ + return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap); +} + +int +svr4_sys_llseek(td, uap) + register struct thread *td; + struct svr4_sys_llseek_args *uap; +{ + struct lseek_args ap; + + SCARG(&ap, fd) = SCARG(uap, fd); + +#if BYTE_ORDER == BIG_ENDIAN + SCARG(&ap, offset) = (((u_int64_t) SCARG(uap, offset1)) << 32) | + SCARG(uap, offset2); +#else + SCARG(&ap, offset) = (((u_int64_t) SCARG(uap, offset2)) << 32) | + SCARG(uap, offset1); +#endif + SCARG(&ap, whence) = SCARG(uap, whence); + + return lseek(td, &ap); +} + +int +svr4_sys_access(td, uap) + register struct thread *td; + struct svr4_sys_access_args *uap; +{ + struct access_args cup; + int *retval; + + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + retval = td->td_retval; + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, flags) = SCARG(uap, flags); + + return access(td, &cup); +} + +#if defined(NOTYET) +int +svr4_sys_pread(td, uap) + register struct thread *td; + struct svr4_sys_pread_args *uap; +{ + struct pread_args pra; + + /* + * Just translate the args structure and call the NetBSD + * pread(2) system call (offset type is 64-bit in NetBSD). + */ + SCARG(&pra, fd) = SCARG(uap, fd); + SCARG(&pra, buf) = SCARG(uap, buf); + SCARG(&pra, nbyte) = SCARG(uap, nbyte); + SCARG(&pra, offset) = SCARG(uap, off); + + return pread(td, &pra); +} +#endif + +#if defined(NOTYET) +int +svr4_sys_pread64(td, v, retval) + register struct thread *td; + void *v; + register_t *retval; +{ + + struct svr4_sys_pread64_args *uap = v; + struct sys_pread_args pra; + + /* + * Just translate the args structure and call the NetBSD + * pread(2) system call (offset type is 64-bit in NetBSD). + */ + SCARG(&pra, fd) = SCARG(uap, fd); + SCARG(&pra, buf) = SCARG(uap, buf); + SCARG(&pra, nbyte) = SCARG(uap, nbyte); + SCARG(&pra, offset) = SCARG(uap, off); + + return (sys_pread(td, &pra, retval)); +} +#endif /* NOTYET */ + +#if defined(NOTYET) +int +svr4_sys_pwrite(td, uap) + register struct thread *td; + struct svr4_sys_pwrite_args *uap; +{ + struct pwrite_args pwa; + + /* + * Just translate the args structure and call the NetBSD + * pwrite(2) system call (offset type is 64-bit in NetBSD). + */ + SCARG(&pwa, fd) = SCARG(uap, fd); + SCARG(&pwa, buf) = SCARG(uap, buf); + SCARG(&pwa, nbyte) = SCARG(uap, nbyte); + SCARG(&pwa, offset) = SCARG(uap, off); + + return pwrite(td, &pwa); +} +#endif + +#if defined(NOTYET) +int +svr4_sys_pwrite64(td, v, retval) + register struct thread *td; + void *v; + register_t *retval; +{ + struct svr4_sys_pwrite64_args *uap = v; + struct sys_pwrite_args pwa; + + /* + * Just translate the args structure and call the NetBSD + * pwrite(2) system call (offset type is 64-bit in NetBSD). + */ + SCARG(&pwa, fd) = SCARG(uap, fd); + SCARG(&pwa, buf) = SCARG(uap, buf); + SCARG(&pwa, nbyte) = SCARG(uap, nbyte); + SCARG(&pwa, offset) = SCARG(uap, off); + + return (sys_pwrite(td, &pwa, retval)); +} +#endif /* NOTYET */ + +int +svr4_sys_fcntl(td, uap) + register struct thread *td; + struct svr4_sys_fcntl_args *uap; +{ + int error; + struct fcntl_args fa; + int *retval; + + retval = td->td_retval; + + SCARG(&fa, fd) = SCARG(uap, fd); + SCARG(&fa, cmd) = svr4_to_bsd_cmd(SCARG(uap, cmd)); + + switch (SCARG(&fa, cmd)) { + case F_DUPFD: + case F_GETFD: + case F_SETFD: + SCARG(&fa, arg) = (long) SCARG(uap, arg); + return fcntl(td, &fa); + + case F_GETFL: + SCARG(&fa, arg) = (long) SCARG(uap, arg); + error = fcntl(td, &fa); + if (error) + return error; + *retval = bsd_to_svr4_flags(*retval); + return error; + + case F_SETFL: + { + /* + * we must save the O_ASYNC flag, as that is + * handled by ioctl(_, I_SETSIG, _) emulation. + */ + long cmd; + int flags; + + DPRINTF(("Setting flags %p\n", SCARG(uap, arg))); + cmd = SCARG(&fa, cmd); /* save it for a while */ + + SCARG(&fa, cmd) = F_GETFL; + if ((error = fcntl(td, &fa)) != 0) + return error; + flags = *retval; + flags &= O_ASYNC; + flags |= svr4_to_bsd_flags((u_long) SCARG(uap, arg)); + SCARG(&fa, cmd) = cmd; + SCARG(&fa, arg) = (long) flags; + return fcntl(td, &fa); + } + + case F_GETLK: + case F_SETLK: + case F_SETLKW: + { + struct svr4_flock ifl; + struct flock *flp, fl; + caddr_t sg = stackgap_init(); + + flp = stackgap_alloc(&sg, sizeof(struct flock)); + SCARG(&fa, arg) = (long) flp; + + error = copyin(SCARG(uap, arg), &ifl, sizeof ifl); + if (error) + return error; + + svr4_to_bsd_flock(&ifl, &fl); + + error = copyout(&fl, flp, sizeof fl); + if (error) + return error; + + error = fcntl(td, &fa); + if (error || SCARG(&fa, cmd) != F_GETLK) + return error; + + error = copyin(flp, &fl, sizeof fl); + if (error) + return error; + + bsd_to_svr4_flock(&fl, &ifl); + + return copyout(&ifl, SCARG(uap, arg), sizeof ifl); + } + case -1: + switch (SCARG(uap, cmd)) { + case SVR4_F_DUP2FD: + { + struct dup2_args du; + + SCARG(&du, from) = SCARG(uap, fd); + SCARG(&du, to) = (int)SCARG(uap, arg); + error = dup2(td, &du); + if (error) + return error; + *retval = SCARG(&du, to); + return 0; + } + + case SVR4_F_FREESP: + { + struct svr4_flock ifl; + struct flock fl; + + error = copyin(SCARG(uap, arg), &ifl, + sizeof ifl); + if (error) + return error; + svr4_to_bsd_flock(&ifl, &fl); + return fd_truncate(td, SCARG(uap, fd), &fl); + } + + case SVR4_F_GETLK64: + case SVR4_F_SETLK64: + case SVR4_F_SETLKW64: + { + struct svr4_flock64 ifl; + struct flock *flp, fl; + caddr_t sg = stackgap_init(); + + flp = stackgap_alloc(&sg, sizeof(struct flock)); + SCARG(&fa, arg) = (long) flp; + + error = copyin(SCARG(uap, arg), &ifl, + sizeof ifl); + if (error) + return error; + + svr4_to_bsd_flock64(&ifl, &fl); + + error = copyout(&fl, flp, sizeof fl); + if (error) + return error; + + error = fcntl(td, &fa); + if (error || SCARG(&fa, cmd) != F_GETLK) + return error; + + error = copyin(flp, &fl, sizeof fl); + if (error) + return error; + + bsd_to_svr4_flock64(&fl, &ifl); + + return copyout(&ifl, SCARG(uap, arg), + sizeof ifl); + } + + case SVR4_F_FREESP64: + { + struct svr4_flock64 ifl; + struct flock fl; + + error = copyin(SCARG(uap, arg), &ifl, + sizeof ifl); + if (error) + return error; + svr4_to_bsd_flock64(&ifl, &fl); + return fd_truncate(td, SCARG(uap, fd), &fl); + } + + case SVR4_F_REVOKE: + return fd_revoke(td, SCARG(uap, fd)); + + default: + return ENOSYS; + } + + default: + return ENOSYS; + } +} diff --git a/sys/compat/svr4/svr4_fcntl.h b/sys/compat/svr4/svr4_fcntl.h new file mode 100644 index 0000000..3309a4f --- /dev/null +++ b/sys/compat/svr4/svr4_fcntl.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_FCNTL_H_ +#define _SVR4_FCNTL_H_ + +#include <compat/svr4/svr4_types.h> +#include <sys/fcntl.h> + +#define SVR4_O_RDONLY 0x0000 +#define SVR4_O_WRONLY 0x0001 +#define SVR4_O_RDWR 0x0002 +#define SVR4_O_ACCMODE 0x0003 +#define SVR4_O_NDELAY 0x0004 +#define SVR4_O_APPEND 0x0008 +#define SVR4_O_SYNC 0x0010 +#define SVR4_O_NONBLOCK 0x0080 +#define SVR4_O_CREAT 0x0100 +#define SVR4_O_TRUNC 0x0200 +#define SVR4_O_EXCL 0x0400 +#define SVR4_O_NOCTTY 0x0800 +#define SVR4_O_PRIV 0x1000 + + +#define SVR4_FD_CLOEXEC 1 + +#define SVR4_F_DUPFD 0 +#define SVR4_F_GETFD 1 +#define SVR4_F_SETFD 2 +#define SVR4_F_GETFL 3 +#define SVR4_F_SETFL 4 +#define SVR4_F_GETLK_SVR3 5 +#define SVR4_F_SETLK 6 +#define SVR4_F_SETLKW 7 +#define SVR4_F_CHKFL 8 +#define SVR4_F_DUP2FD 9 +#define SVR4_F_ALLOCSP 10 +#define SVR4_F_FREESP 11 + +#define SVR4_F_ISSTREAM 13 +#define SVR4_F_GETLK 14 +#define SVR4_F_PRIV 15 +#define SVR4_F_NPRIV 16 +#define SVR4_F_QUOTACTL 17 +#define SVR4_F_BLOCKS 18 +#define SVR4_F_BLKSIZE 19 +#define SVR4_F_RSETLK 20 +#define SVR4_F_RGETLK 21 +#define SVR4_F_RSETLKW 22 +#define SVR4_F_GETOWN 23 +#define SVR4_F_SETOWN 24 +#define SVR4_F_REVOKE 25 +#define SVR4_F_HASREMOTELOCKS 26 +#define SVR4_F_FREESP64 27 + +#define SVR4_F_GETLK64 33 +#define SVR4_F_SETLK64 34 +#define SVR4_F_SETLKW64 35 + +#define SVR4_F_SHARE 40 +#define SVR4_F_UNSHARE 41 + +#define SVR4_F_CHSIZE_XENIX 0x6000 +#define SVR4_F_RDCHK_XENIX 0x6001 +#define SVR4_F_LK_UNLCK_XENIX 0x6300 +#define SVR4_F_LK_LOCK_XENIX 0x7200 +#define SVR4_F_LK_NBLCK_XENIX 0x6200 +#define SVR4_F_LK_RLCK_XENIX 0x7100 +#define SVR4_F_LK_NBRLCK_XENIX 0x6100 + +#define SVR4_LK_CMDTYPE(x) (((x) >> 12) & 0x7) +#define SVR4_LK_LCKTYPE(x) (((x) >> 8) & 0x7) + +#define SVR4_F_RDLCK 1 +#define SVR4_F_WRLCK 2 +#define SVR4_F_UNLCK 3 + +struct svr4_flock_svr3 { + short l_type; + short l_whence; + svr4_off_t l_start; + svr4_off_t l_len; + short l_sysid; + svr4_o_pid_t l_pid; +}; + + +struct svr4_flock { + short l_type; + short l_whence; + svr4_off_t l_start; + svr4_off_t l_len; + long l_sysid; + svr4_pid_t l_pid; + long pad[4]; +}; + +struct svr4_flock64 { + short l_type; + short l_whence; + svr4_off64_t l_start; + svr4_off64_t l_len; + long l_sysid; + svr4_pid_t l_pid; + long pad[4]; +}; +#endif /* !_SVR4_FCNTL_H_ */ diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c new file mode 100644 index 0000000..ef9b8b6 --- /dev/null +++ b/sys/compat/svr4/svr4_filio.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/filio.h> +#include <sys/lock.h> +#include <sys/signal.h> +#include <sys/filedesc.h> +#include <sys/poll.h> +#include <sys/malloc.h> +#include <sys/mutex.h> + +#include <sys/sysproto.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_ioctl.h> +#include <compat/svr4/svr4_filio.h> + +/*#define GROTTY_READ_HACK*/ + +int +svr4_sys_poll(td, uap) + struct thread *td; + struct svr4_sys_poll_args *uap; +{ + int error; + struct poll_args pa; + struct pollfd *pfd; + int idx = 0, cerr; + u_long siz; + + SCARG(&pa, fds) = SCARG(uap, fds); + SCARG(&pa, nfds) = SCARG(uap, nfds); + SCARG(&pa, timeout) = SCARG(uap, timeout); + + siz = SCARG(uap, nfds) * sizeof(struct pollfd); + pfd = (struct pollfd *)malloc(siz, M_TEMP, M_WAITOK); + + error = poll(td, (struct poll_args *)uap); + + if ((cerr = copyin(SCARG(uap, fds), pfd, siz)) != 0) { + error = cerr; + goto done; + } + + for (idx = 0; idx < SCARG(uap, nfds); idx++) { + /* POLLWRNORM already equals POLLOUT, so we don't worry about that */ + if (pfd[idx].revents & (POLLOUT | POLLWRNORM | POLLWRBAND)) + pfd[idx].revents |= (POLLOUT | POLLWRNORM | POLLWRBAND); + } + if ((cerr = copyout(pfd, SCARG(uap, fds), siz)) != 0) { + error = cerr; + goto done; /* yeah, I know it's the next line, but this way I won't + forget to update it if I add more code */ + } +done: + free(pfd, M_TEMP); + return error; +} + +#if defined(READ_TEST) +int +svr4_sys_read(td, uap) + struct thread *td; + struct svr4_sys_read_args *uap; +{ + struct read_args ra; + struct file *fp; + struct socket *so = NULL; + int so_state; + sigset_t sigmask; + int rv; + + SCARG(&ra, fd) = SCARG(uap, fd); + SCARG(&ra, buf) = SCARG(uap, buf); + SCARG(&ra, nbyte) = SCARG(uap, nbyte); + + if (fget(td, uap->fd, &fp) != 0) { + DPRINTF(("Something fishy with the user-supplied file descriptor...\n")); + return EBADF; + } + + if (fp->f_type == DTYPE_SOCKET) { + so = (struct socket *)fp->f_data; + DPRINTF(("fd %d is a socket\n", SCARG(uap, fd))); + if (so->so_state & SS_ASYNC) { + DPRINTF(("fd %d is an ASYNC socket!\n", SCARG(uap, fd))); + } + DPRINTF(("Here are its flags: 0x%x\n", so->so_state)); +#if defined(GROTTY_READ_HACK) + so_state = so->so_state; + so->so_state &= ~SS_NBIO; +#endif + } + + rv = read(td, &ra); + + DPRINTF(("svr4_read(%d, 0x%0x, %d) = %d\n", + SCARG(uap, fd), SCARG(uap, buf), SCARG(uap, nbyte), rv)); + if (rv == EAGAIN) { + DPRINTF(("sigmask = 0x%x\n", td->td_proc->p_sigmask)); + DPRINTF(("sigignore = 0x%x\n", td->td_proc->p_sigignore)); + DPRINTF(("sigcaught = 0x%x\n", td->td_proc->p_sigcatch)); + DPRINTF(("siglist = 0x%x\n", td->td_proc->p_siglist)); + } + +#if defined(GROTTY_READ_HACK) + if (so) { /* We've already checked to see if this is a socket */ + so->so_state = so_state; + } +#endif + fdrop(fp, td); + + return(rv); +} +#endif /* READ_TEST */ + +#if defined(BOGUS) +int +svr4_sys_write(td, uap) + struct thread *td; + struct svr4_sys_write_args *uap; +{ + struct write_args wa; + struct file *fp; + int rv; + + SCARG(&wa, fd) = SCARG(uap, fd); + SCARG(&wa, buf) = SCARG(uap, buf); + SCARG(&wa, nbyte) = SCARG(uap, nbyte); + + rv = write(td, &wa); + + DPRINTF(("svr4_write(%d, 0x%0x, %d) = %d\n", + SCARG(uap, fd), SCARG(uap, buf), SCARG(uap, nbyte), rv)); + + return(rv); +} +#endif /* BOGUS */ + +int +svr4_fil_ioctl(fp, td, retval, fd, cmd, data) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t data; +{ + int error; + int num; + struct filedesc *fdp = td->td_proc->p_fd; + + *retval = 0; + + FILEDESC_LOCK(fdp); + switch (cmd) { + case SVR4_FIOCLEX: + fdp->fd_ofileflags[fd] |= UF_EXCLOSE; + FILEDESC_UNLOCK(fdp); + return 0; + + case SVR4_FIONCLEX: + fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE; + FILEDESC_UNLOCK(fdp); + return 0; + + case SVR4_FIOGETOWN: + case SVR4_FIOSETOWN: + case SVR4_FIOASYNC: + case SVR4_FIONBIO: + case SVR4_FIONREAD: + FILEDESC_UNLOCK(fdp); + if ((error = copyin(data, &num, sizeof(num))) != 0) + return error; + + switch (cmd) { + case SVR4_FIOGETOWN: cmd = FIOGETOWN; break; + case SVR4_FIOSETOWN: cmd = FIOSETOWN; break; + case SVR4_FIOASYNC: cmd = FIOASYNC; break; + case SVR4_FIONBIO: cmd = FIONBIO; break; + case SVR4_FIONREAD: cmd = FIONREAD; break; + } + +#ifdef SVR4_DEBUG + if (cmd == FIOASYNC) DPRINTF(("FIOASYNC\n")); +#endif + error = fo_ioctl(fp, cmd, (caddr_t) &num, td); + + if (error) + return error; + + return copyout(&num, data, sizeof(num)); + + default: + FILEDESC_UNLOCK(fdp); + DPRINTF(("Unknown svr4 filio %lx\n", cmd)); + return 0; /* ENOSYS really */ + } +} diff --git a/sys/compat/svr4/svr4_filio.h b/sys/compat/svr4/svr4_filio.h new file mode 100644 index 0000000..37184cb --- /dev/null +++ b/sys/compat/svr4/svr4_filio.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_FILIO_H_ +#define _SVR4_FILIO_H_ + +#define SVR4_FIOC ('f' << 8) + +#define SVR4_FIOCLEX SVR4_IO('f', 1) +#define SVR4_FIONCLEX SVR4_IO('f', 2) + +#define SVR4_FIOGETOWN SVR4_IOR('f', 123, int) +#define SVR4_FIOSETOWN SVR4_IOW('f', 124, int) +#define SVR4_FIOASYNC SVR4_IOW('f', 125, int) +#define SVR4_FIONBIO SVR4_IOW('f', 126, int) +#define SVR4_FIONREAD SVR4_IOR('f', 127, int) + +#endif /* !_SVR4_FILIO_H_ */ diff --git a/sys/compat/svr4/svr4_fuser.h b/sys/compat/svr4/svr4_fuser.h new file mode 100644 index 0000000..f828c84 --- /dev/null +++ b/sys/compat/svr4/svr4_fuser.h @@ -0,0 +1,97 @@ +/* + * $FreeBSD$ + * Derived from: + * $NetBSD: svr4_fuser.h,v 1.4 1998/09/04 19:54:38 christos Exp $ */ + +/*- + * Original Copyright: + * + * Copyright (c) 1994 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Portions of this code have been derived from code contributed to the + * FreeBSD Project by Mark Newton. + * + * Copyright (c) 1999 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SVR4_FUSER_H_ +#define _SVR4_FUSER_H_ + +#include <compat/svr4/svr4_types.h> + +struct svr4_f_user { + svr4_pid_t fu_pid; + int fu_flags; + uid_t fu_uid; +}; + + +#define SVR4_F_FILE_ONLY 1 +#define SVR4_F_CONTAINED 2 + +#define SVR4_F_CDIR 0x01 +#define SVR4_F_RDIR 0x02 +#define SVR4_F_TEXT 0x04 +#define SVR4_F_MAP 0x08 +#define SVR4_F_OPEN 0x10 +#define SVR4_F_TRACE 0x20 +#define SVR4_F_TTY 0x40 + +#endif /* !_SVR4_FUSER_H_ */ diff --git a/sys/compat/svr4/svr4_hrt.h b/sys/compat/svr4/svr4_hrt.h new file mode 100644 index 0000000..c160b8e --- /dev/null +++ b/sys/compat/svr4/svr4_hrt.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_HRT_H_ +#define _SVR4_HRT_H_ + +#define SVR4_HRT_CNTL 0 +#define SVR4_HRT_CNTL_RES 0 +#define SVR4_HRT_CNTL_TOFD 1 +#define SVR4_HRT_CNTL_START 2 +#define SVR4_HRT_CNTL_GET 3 + +#define SVR4_HRT_ALRM 1 +#define SVR4_HRT_ALRM_DO 4 +#define SVR4_HRT_ALRM_REP 5 +#define SVR4_HRT_ALRM_TOD 6 +#define SVR4_HRT_ALRM_FUTREP 7 +#define SVR4_HRT_ALRM_TODREP 8 +#define SVR4_HRT_ALRM_PEND 9 + +#define SVR4_HRT_SLP 2 +#define SVR4_HRT_SLP_INT 10 +#define SVR4_HRT_SLP_TOD 11 + +#define SVR4_HRT_BSD 12 +#define SVR4_HRT_BSD_PEND 13 +#define SVR4_HRT_BSD_REP1 14 +#define SVR4_HRT_BSD_REP2 15 +#define SVR4_HRT_BSD_CANCEL 16 + +#define SVR4_HRT_CAN 3 + +#define SVR4_HRT_SEC 1 +#define SVR4_HRT_MSEC 1000 +#define SVR4_HRT_USEC 1000000 +#define SVR4_HRT_NSEC 1000000000 + +#define SVR4_HRT_TRUNC 0 +#define SVR4_HRT_RND 1 + +typedef struct { + u_long i_word1; + u_long i_word2; + int i_clock; +} svr4_hrt_interval_t; + +typedef struct { + u_long h_sec; + long h_rem; + u_long h_res; +} svr4_hrt_time_t; + +#define SVR4_HRT_DONE 1 +#define SVR4_HRT_ERROR 2 + +#define SVR4_HRT_CLK_STD 1 +#define SVR4_HRT_CLK_USERVIRT 2 +#define SVR4_HRT_CLK_PROCVIRT 4 + +#endif /* !_SVR4_HRT_H_ */ diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c new file mode 100644 index 0000000..50d28ee --- /dev/null +++ b/sys/compat/svr4/svr4_ioctl.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_stropts.h> +#include <compat/svr4/svr4_ioctl.h> +#include <compat/svr4/svr4_termios.h> +#include <compat/svr4/svr4_ttold.h> +#include <compat/svr4/svr4_filio.h> +#include <compat/svr4/svr4_sockio.h> + +#ifdef DEBUG_SVR4 +static void svr4_decode_cmd(u_long, char *, char *, int *, int *); +/* + * Decode an ioctl command symbolically + */ +static void +svr4_decode_cmd(cmd, dir, c, num, argsiz) + u_long cmd; + char *dir, *c; + int *num, *argsiz; +{ + if (cmd & SVR4_IOC_VOID) + *dir++ = 'V'; + if (cmd & SVR4_IOC_IN) + *dir++ = 'R'; + if (cmd & SVR4_IOC_OUT) + *dir++ = 'W'; + *dir = '\0'; + if (cmd & SVR4_IOC_INOUT) + *argsiz = (cmd >> 16) & 0xff; + else + *argsiz = -1; + + *c = (cmd >> 8) & 0xff; + *num = cmd & 0xff; +} +#endif + +int +svr4_sys_ioctl(td, uap) + register struct thread *td; + struct svr4_sys_ioctl_args *uap; +{ + int *retval; + struct file *fp; + u_long cmd; + int (*fun)(struct file *, struct thread *, register_t *, + int, u_long, caddr_t); + int error; +#ifdef DEBUG_SVR4 + char dir[4]; + char c; + int num; + int argsiz; + + svr4_decode_cmd(SCARG(uap, com), dir, &c, &num, &argsiz); + + DPRINTF(("svr4_ioctl[%lx](%d, _IO%s(%c, %d, %d), %p);\n", SCARG(uap, com), SCARG(uap, fd), + dir, c, num, argsiz, SCARG(uap, data))); +#endif + retval = td->td_retval; + cmd = SCARG(uap, com); + + if ((error = fget(td, uap->fd, &fp)) != 0) + return (error); + + if ((fp->f_flag & (FREAD | FWRITE)) == 0) { + fdrop(fp, td); + return EBADF; + } + +#if defined(DEBUG_SVR4) + if (fp->f_type == DTYPE_SOCKET) { + struct socket *so = (struct socket *)fp->f_data; + DPRINTF(("<<< IN: so_state = 0x%x\n", so->so_state)); + } +#endif + + switch (cmd & 0xff00) { + case SVR4_tIOC: + DPRINTF(("ttold\n")); + fun = svr4_ttold_ioctl; + break; + + case SVR4_TIOC: + DPRINTF(("term\n")); + fun = svr4_term_ioctl; + break; + + case SVR4_STR: + DPRINTF(("stream\n")); + fun = svr4_stream_ioctl; + break; + + case SVR4_FIOC: + DPRINTF(("file\n")); + fun = svr4_fil_ioctl; + break; + + case SVR4_SIOC: + DPRINTF(("socket\n")); + fun = svr4_sock_ioctl; + break; + + case SVR4_XIOC: + /* We do not support those */ + fdrop(fp, td); + return EINVAL; + + default: + fdrop(fp, td); + DPRINTF(("Unimplemented ioctl %lx\n", cmd)); + return 0; /* XXX: really ENOSYS */ + } +#if defined(DEBUG_SVR4) + if (fp->f_type == DTYPE_SOCKET) { + struct socket *so; + + so = (struct socket *)fp->f_data; + DPRINTF((">>> OUT: so_state = 0x%x\n", so->so_state)); + } +#endif + error = (*fun)(fp, td, retval, SCARG(uap, fd), cmd, SCARG(uap, data)); + fdrop(fp, td); + return (error); +} diff --git a/sys/compat/svr4/svr4_ioctl.h b/sys/compat/svr4/svr4_ioctl.h new file mode 100644 index 0000000..54811b9 --- /dev/null +++ b/sys/compat/svr4/svr4_ioctl.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_IOCTL_H_ +#define _SVR4_IOCTL_H_ + +#define SVR4_IOC_VOID 0x20000000 +#define SVR4_IOC_OUT 0x40000000 +#define SVR4_IOC_IN 0x80000000 +#define SVR4_IOC_INOUT (SVR4_IOC_IN|SVR4_IOC_OUT) + +#define SVR4_IOC(inout,group,num,len) \ + (inout | ((len & 0xff) << 16) | ((group) << 8) | (num)) + +#define SVR4_XIOC ('X' << 8) + +#define SVR4_IO(g,n) SVR4_IOC(SVR4_IOC_VOID, (g), (n), 0) +#define SVR4_IOR(g,n,t) SVR4_IOC(SVR4_IOC_OUT, (g), (n), sizeof(t)) +#define SVR4_IOW(g,n,t) SVR4_IOC(SVR4_IOC_IN, (g), (n), sizeof(t)) +#define SVR4_IOWR(g,n,t) SVR4_IOC(SVR4_IOC_INOUT,(g), (n), sizeof(t)) + +int svr4_stream_ti_ioctl(struct file *, struct thread *, register_t *, + int, u_long, caddr_t); +int svr4_stream_ioctl(struct file *, struct thread *, register_t *, + int, u_long, caddr_t); +int svr4_term_ioctl(struct file *, struct thread *, register_t *, + int, u_long, caddr_t); +int svr4_ttold_ioctl(struct file *, struct thread *, register_t *, + int, u_long, caddr_t); +int svr4_fil_ioctl (struct file *, struct thread *, register_t *, + int, u_long, caddr_t); +int svr4_sock_ioctl (struct file *, struct thread *, register_t *, + int, u_long, caddr_t); + +#endif /* !_SVR4_IOCTL_H_ */ diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c new file mode 100644 index 0000000..17caaa5 --- /dev/null +++ b/sys/compat/svr4/svr4_ipc.c @@ -0,0 +1,821 @@ +/* + * $FreeBSD$ + * Derived from: + * $NetBSD: svr4_ipc.c,v 1.7 1998/10/19 22:43:00 tron Exp $ */ + +/*- + * Original copyright: + * + * Copyright (c) 1995 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Portions of this code have been derived from software contributed + * to the FreeBSD Project by Mark Newton. + * + * Copyright (c) 1999 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * XXX- This code is presently a no-op on FreeBSD (and isn't compiled due + * to preprocessor conditionals). A nice project for a kernel hacking + * novice might be to MakeItGo, but I have more important fish to fry + * at present. + * + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/time.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_ipc.h> + +#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM) +static void svr4_to_bsd_ipc_perm(const struct svr4_ipc_perm *, + struct ipc_perm *); +static void bsd_to_svr4_ipc_perm(const struct ipc_perm *, + struct svr4_ipc_perm *); +#endif + +#ifdef SYSVSEM +static void bsd_to_svr4_semid_ds(const struct semid_ds *, + struct svr4_semid_ds *); +static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *, + struct semid_ds *); +static int svr4_setsemun(caddr_t *sgp, union semun **argp, + union semun *usp); +static int svr4_semop(struct proc *, void *, register_t *); +static int svr4_semget(struct proc *, void *, register_t *); +static int svr4_semctl(struct proc *, void *, register_t *); +#endif + +#ifdef SYSVMSG +static void bsd_to_svr4_msqid_ds(const struct msqid_ds *, + struct svr4_msqid_ds *); +static void svr4_to_bsd_msqid_ds(const struct svr4_msqid_ds *, + struct msqid_ds *); +static int svr4_msgsnd(struct proc *, void *, register_t *); +static int svr4_msgrcv(struct proc *, void *, register_t *); +static int svr4_msgget(struct proc *, void *, register_t *); +static int svr4_msgctl(struct proc *, void *, register_t *); +#endif + +#ifdef SYSVSHM +static void bsd_to_svr4_shmid_ds(const struct shmid_ds *, + struct svr4_shmid_ds *); +static void svr4_to_bsd_shmid_ds(const struct svr4_shmid_ds *, + struct shmid_ds *); +static int svr4_shmat(struct proc *, void *, register_t *); +static int svr4_shmdt(struct proc *, void *, register_t *); +static int svr4_shmget(struct proc *, void *, register_t *); +static int svr4_shmctl(struct proc *, void *, register_t *); +#endif + +#if defined(SYSVMSG) || defined(SYSVSHM) || defined(SYSVSEM) + +static void +svr4_to_bsd_ipc_perm(spp, bpp) + const struct svr4_ipc_perm *spp; + struct ipc_perm *bpp; +{ + bpp->key = spp->key; + bpp->uid = spp->uid; + bpp->gid = spp->gid; + bpp->cuid = spp->cuid; + bpp->cgid = spp->cgid; + bpp->mode = spp->mode; + bpp->seq = spp->seq; +} + +static void +bsd_to_svr4_ipc_perm(bpp, spp) + const struct ipc_perm *bpp; + struct svr4_ipc_perm *spp; +{ + spp->key = bpp->key; + spp->uid = bpp->uid; + spp->gid = bpp->gid; + spp->cuid = bpp->cuid; + spp->cgid = bpp->cgid; + spp->mode = bpp->mode; + spp->seq = bpp->seq; +} +#endif + +#ifdef SYSVSEM +static void +bsd_to_svr4_semid_ds(bds, sds) + const struct semid_ds *bds; + struct svr4_semid_ds *sds; +{ + bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm); + sds->sem_base = (struct svr4_sem *) bds->sem_base; + sds->sem_nsems = bds->sem_nsems; + sds->sem_otime = bds->sem_otime; + sds->sem_pad1 = bds->sem_pad1; + sds->sem_ctime = bds->sem_ctime; + sds->sem_pad2 = bds->sem_pad2; +} + +static void +svr4_to_bsd_semid_ds(sds, bds) + const struct svr4_semid_ds *sds; + struct semid_ds *bds; +{ + svr4_to_bsd_ipc_perm(&sds->sem_perm, &bds->sem_perm); + bds->sem_base = (struct sem *) bds->sem_base; + bds->sem_nsems = sds->sem_nsems; + bds->sem_otime = sds->sem_otime; + bds->sem_pad1 = sds->sem_pad1; + bds->sem_ctime = sds->sem_ctime; + bds->sem_pad2 = sds->sem_pad2; +} + +static int +svr4_setsemun(sgp, argp, usp) + caddr_t *sgp; + union semun **argp; + union semun *usp; +{ + *argp = stackgap_alloc(sgp, sizeof(union semun)); + return copyout((caddr_t)usp, *argp, sizeof(union semun)); +} + +struct svr4_sys_semctl_args { + syscallarg(int) what; + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun) arg; +}; + +static int +svr4_semctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + int error; + struct svr4_sys_semctl_args *uap = v; + struct sys___semctl_args ap; + struct svr4_semid_ds ss; + struct semid_ds bs, *bsp; + caddr_t sg = stackgap_init(); + + SCARG(&ap, semid) = SCARG(uap, semid); + SCARG(&ap, semnum) = SCARG(uap, semnum); + + switch (SCARG(uap, cmd)) { + case SVR4_SEM_GETZCNT: + case SVR4_SEM_GETNCNT: + case SVR4_SEM_GETPID: + case SVR4_SEM_GETVAL: + switch (SCARG(uap, cmd)) { + case SVR4_SEM_GETZCNT: + SCARG(&ap, cmd) = GETZCNT; + break; + case SVR4_SEM_GETNCNT: + SCARG(&ap, cmd) = GETNCNT; + break; + case SVR4_SEM_GETPID: + SCARG(&ap, cmd) = GETPID; + break; + case SVR4_SEM_GETVAL: + SCARG(&ap, cmd) = GETVAL; + break; + } + return sys___semctl(p, &ap, retval); + + case SVR4_SEM_SETVAL: + error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg)); + if (error) + return error; + SCARG(&ap, cmd) = SETVAL; + return sys___semctl(p, &ap, retval); + + case SVR4_SEM_GETALL: + error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg)); + if (error) + return error; + SCARG(&ap, cmd) = GETVAL; + return sys___semctl(p, &ap, retval); + + case SVR4_SEM_SETALL: + error = svr4_setsemun(&sg, &SCARG(&ap, arg), &SCARG(uap, arg)); + if (error) + return error; + SCARG(&ap, cmd) = SETVAL; + return sys___semctl(p, &ap, retval); + + case SVR4_IPC_STAT: + SCARG(&ap, cmd) = IPC_STAT; + bsp = stackgap_alloc(&sg, sizeof(bs)); + error = svr4_setsemun(&sg, &SCARG(&ap, arg), + (union semun *)&bsp); + if (error) + return error; + if ((error = sys___semctl(p, &ap, retval)) != 0) + return error; + error = copyin((caddr_t)bsp, (caddr_t)&bs, sizeof(bs)); + if (error) + return error; + bsd_to_svr4_semid_ds(&bs, &ss); + return copyout(&ss, SCARG(uap, arg).buf, sizeof(ss)); + + case SVR4_IPC_SET: + SCARG(&ap, cmd) = IPC_SET; + bsp = stackgap_alloc(&sg, sizeof(bs)); + error = svr4_setsemun(&sg, &SCARG(&ap, arg), + (union semun *)&bsp); + if (error) + return error; + error = copyin(SCARG(uap, arg).buf, (caddr_t) &ss, sizeof ss); + if (error) + return error; + svr4_to_bsd_semid_ds(&ss, &bs); + error = copyout(&bs, bsp, sizeof(bs)); + if (error) + return error; + return sys___semctl(p, &ap, retval); + + case SVR4_IPC_RMID: + SCARG(&ap, cmd) = IPC_RMID; + bsp = stackgap_alloc(&sg, sizeof(bs)); + error = svr4_setsemun(&sg, &SCARG(&ap, arg), + (union semun *)&bsp); + if (error) + return error; + error = copyin(SCARG(uap, arg).buf, &ss, sizeof ss); + if (error) + return error; + svr4_to_bsd_semid_ds(&ss, &bs); + error = copyout(&bs, bsp, sizeof(bs)); + if (error) + return error; + return sys___semctl(p, &ap, retval); + + default: + return EINVAL; + } +} + +struct svr4_sys_semget_args { + syscallarg(int) what; + syscallarg(svr4_key_t) key; + syscallarg(int) nsems; + syscallarg(int) semflg; +}; + +static int +svr4_semget(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_semget_args *uap = v; + struct sys_semget_args ap; + + SCARG(&ap, key) = SCARG(uap, key); + SCARG(&ap, nsems) = SCARG(uap, nsems); + SCARG(&ap, semflg) = SCARG(uap, semflg); + + return sys_semget(p, &ap, retval); +} + +struct svr4_sys_semop_args { + syscallarg(int) what; + syscallarg(int) semid; + syscallarg(struct svr4_sembuf *) sops; + syscallarg(u_int) nsops; +}; + +static int +svr4_semop(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_semop_args *uap = v; + struct sys_semop_args ap; + + SCARG(&ap, semid) = SCARG(uap, semid); + /* These are the same */ + SCARG(&ap, sops) = (struct sembuf *) SCARG(uap, sops); + SCARG(&ap, nsops) = SCARG(uap, nsops); + + return sys_semop(p, &ap, retval); +} + +int +svr4_sys_semsys(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_semsys_args *uap = v; + + DPRINTF(("svr4_semsys(%d)\n", SCARG(uap, what))); + + switch (SCARG(uap, what)) { + case SVR4_semctl: + return svr4_semctl(p, v, retval); + case SVR4_semget: + return svr4_semget(p, v, retval); + case SVR4_semop: + return svr4_semop(p, v, retval); + default: + return EINVAL; + } +} +#endif + +#ifdef SYSVMSG +static void +bsd_to_svr4_msqid_ds(bds, sds) + const struct msqid_ds *bds; + struct svr4_msqid_ds *sds; +{ + bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm); + sds->msg_first = (struct svr4_msg *) bds->msg_first; + sds->msg_last = (struct svr4_msg *) bds->msg_last; + sds->msg_cbytes = bds->msg_cbytes; + sds->msg_qnum = bds->msg_qnum; + sds->msg_qbytes = bds->msg_qbytes; + sds->msg_lspid = bds->msg_lspid; + sds->msg_lrpid = bds->msg_lrpid; + sds->msg_stime = bds->msg_stime; + sds->msg_pad1 = bds->msg_pad1; + sds->msg_rtime = bds->msg_rtime; + sds->msg_pad2 = bds->msg_pad2; + sds->msg_ctime = bds->msg_ctime; + sds->msg_pad3 = bds->msg_pad3; + + /* use the padding for the rest of the fields */ + { + const short *pad = (const short *) bds->msg_pad4; + sds->msg_cv = pad[0]; + sds->msg_qnum_cv = pad[1]; + } +} + +static void +svr4_to_bsd_msqid_ds(sds, bds) + const struct svr4_msqid_ds *sds; + struct msqid_ds *bds; +{ + svr4_to_bsd_ipc_perm(&sds->msg_perm, &bds->msg_perm); + bds->msg_first = (struct msg *) sds->msg_first; + bds->msg_last = (struct msg *) sds->msg_last; + bds->msg_cbytes = sds->msg_cbytes; + bds->msg_qnum = sds->msg_qnum; + bds->msg_qbytes = sds->msg_qbytes; + bds->msg_lspid = sds->msg_lspid; + bds->msg_lrpid = sds->msg_lrpid; + bds->msg_stime = sds->msg_stime; + bds->msg_pad1 = sds->msg_pad1; + bds->msg_rtime = sds->msg_rtime; + bds->msg_pad2 = sds->msg_pad2; + bds->msg_ctime = sds->msg_ctime; + bds->msg_pad3 = sds->msg_pad3; + + /* use the padding for the rest of the fields */ + { + short *pad = (short *) bds->msg_pad4; + pad[0] = sds->msg_cv; + pad[1] = sds->msg_qnum_cv; + } +} + +struct svr4_sys_msgsnd_args { + syscallarg(int) what; + syscallarg(int) msqid; + syscallarg(void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(int) msgflg; +}; + +static int +svr4_msgsnd(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_msgsnd_args *uap = v; + struct sys_msgsnd_args ap; + + SCARG(&ap, msqid) = SCARG(uap, msqid); + SCARG(&ap, msgp) = SCARG(uap, msgp); + SCARG(&ap, msgsz) = SCARG(uap, msgsz); + SCARG(&ap, msgflg) = SCARG(uap, msgflg); + + return sys_msgsnd(p, &ap, retval); +} + +struct svr4_sys_msgrcv_args { + syscallarg(int) what; + syscallarg(int) msqid; + syscallarg(void *) msgp; + syscallarg(size_t) msgsz; + syscallarg(long) msgtyp; + syscallarg(int) msgflg; +}; + +static int +svr4_msgrcv(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_msgrcv_args *uap = v; + struct sys_msgrcv_args ap; + + SCARG(&ap, msqid) = SCARG(uap, msqid); + SCARG(&ap, msgp) = SCARG(uap, msgp); + SCARG(&ap, msgsz) = SCARG(uap, msgsz); + SCARG(&ap, msgtyp) = SCARG(uap, msgtyp); + SCARG(&ap, msgflg) = SCARG(uap, msgflg); + + return sys_msgrcv(p, &ap, retval); +} + +struct svr4_sys_msgget_args { + syscallarg(int) what; + syscallarg(svr4_key_t) key; + syscallarg(int) msgflg; +}; + +static int +svr4_msgget(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_msgget_args *uap = v; + struct sys_msgget_args ap; + + SCARG(&ap, key) = SCARG(uap, key); + SCARG(&ap, msgflg) = SCARG(uap, msgflg); + + return sys_msgget(p, &ap, retval); +} + +struct svr4_sys_msgctl_args { + syscallarg(int) what; + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct svr4_msqid_ds *) buf; +}; + +static int +svr4_msgctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + int error; + struct svr4_sys_msgctl_args *uap = v; + struct sys_msgctl_args ap; + struct svr4_msqid_ds ss; + struct msqid_ds bs; + caddr_t sg = stackgap_init(); + + SCARG(&ap, msqid) = SCARG(uap, msqid); + SCARG(&ap, cmd) = SCARG(uap, cmd); + SCARG(&ap, buf) = stackgap_alloc(&sg, sizeof(bs)); + + switch (SCARG(uap, cmd)) { + case SVR4_IPC_STAT: + SCARG(&ap, cmd) = IPC_STAT; + if ((error = sys_msgctl(p, &ap, retval)) != 0) + return error; + error = copyin(&bs, SCARG(&ap, buf), sizeof bs); + if (error) + return error; + bsd_to_svr4_msqid_ds(&bs, &ss); + return copyout(&ss, SCARG(uap, buf), sizeof ss); + + case SVR4_IPC_SET: + SCARG(&ap, cmd) = IPC_SET; + error = copyin(SCARG(uap, buf), &ss, sizeof ss); + if (error) + return error; + svr4_to_bsd_msqid_ds(&ss, &bs); + error = copyout(&bs, SCARG(&ap, buf), sizeof bs); + if (error) + return error; + return sys_msgctl(p, &ap, retval); + + case SVR4_IPC_RMID: + SCARG(&ap, cmd) = IPC_RMID; + error = copyin(SCARG(uap, buf), &ss, sizeof ss); + if (error) + return error; + svr4_to_bsd_msqid_ds(&ss, &bs); + error = copyout(&bs, SCARG(&ap, buf), sizeof bs); + if (error) + return error; + return sys_msgctl(p, &ap, retval); + + default: + return EINVAL; + } +} + +int +svr4_sys_msgsys(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_msgsys_args *uap = v; + + DPRINTF(("svr4_msgsys(%d)\n", SCARG(uap, what))); + + switch (SCARG(uap, what)) { + case SVR4_msgsnd: + return svr4_msgsnd(p, v, retval); + case SVR4_msgrcv: + return svr4_msgrcv(p, v, retval); + case SVR4_msgget: + return svr4_msgget(p, v, retval); + case SVR4_msgctl: + return svr4_msgctl(p, v, retval); + default: + return EINVAL; + } +} +#endif + +#ifdef SYSVSHM + +static void +bsd_to_svr4_shmid_ds(bds, sds) + const struct shmid_ds *bds; + struct svr4_shmid_ds *sds; +{ + bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm); + sds->shm_segsz = bds->shm_segsz; + sds->shm_lkcnt = 0; + sds->shm_lpid = bds->shm_lpid; + sds->shm_cpid = bds->shm_cpid; + sds->shm_amp = bds->shm_internal; + sds->shm_nattch = bds->shm_nattch; + sds->shm_cnattch = 0; + sds->shm_atime = bds->shm_atime; + sds->shm_pad1 = 0; + sds->shm_dtime = bds->shm_dtime; + sds->shm_pad2 = 0; + sds->shm_ctime = bds->shm_ctime; + sds->shm_pad3 = 0; +} + +static void +svr4_to_bsd_shmid_ds(sds, bds) + const struct svr4_shmid_ds *sds; + struct shmid_ds *bds; +{ + svr4_to_bsd_ipc_perm(&sds->shm_perm, &bds->shm_perm); + bds->shm_segsz = sds->shm_segsz; + bds->shm_lpid = sds->shm_lpid; + bds->shm_cpid = sds->shm_cpid; + bds->shm_internal = sds->shm_amp; + bds->shm_nattch = sds->shm_nattch; + bds->shm_atime = sds->shm_atime; + bds->shm_dtime = sds->shm_dtime; + bds->shm_ctime = sds->shm_ctime; +} + +struct svr4_sys_shmat_args { + syscallarg(int) what; + syscallarg(int) shmid; + syscallarg(void *) shmaddr; + syscallarg(int) shmflg; +}; + +static int +svr4_shmat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_shmat_args *uap = v; + struct sys_shmat_args ap; + + SCARG(&ap, shmid) = SCARG(uap, shmid); + SCARG(&ap, shmaddr) = SCARG(uap, shmaddr); + SCARG(&ap, shmflg) = SCARG(uap, shmflg); + + return sys_shmat(p, &ap, retval); +} + +struct svr4_sys_shmdt_args { + syscallarg(int) what; + syscallarg(void *) shmaddr; +}; + +static int +svr4_shmdt(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_shmdt_args *uap = v; + struct sys_shmdt_args ap; + + SCARG(&ap, shmaddr) = SCARG(uap, shmaddr); + + return sys_shmdt(p, &ap, retval); +} + +struct svr4_sys_shmget_args { + syscallarg(int) what; + syscallarg(key_t) key; + syscallarg(int) size; + syscallarg(int) shmflg; +}; + +static int +svr4_shmget(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_shmget_args *uap = v; + struct sys_shmget_args ap; + + SCARG(&ap, key) = SCARG(uap, key); + SCARG(&ap, size) = SCARG(uap, size); + SCARG(&ap, shmflg) = SCARG(uap, shmflg); + + return sys_shmget(p, &ap, retval); +} + +struct svr4_sys_shmctl_args { + syscallarg(int) what; + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct svr4_shmid_ds *) buf; +}; + +int +svr4_shmctl(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_shmctl_args *uap = v; + int error; + caddr_t sg = stackgap_init(); + struct sys_shmctl_args ap; + struct shmid_ds bs; + struct svr4_shmid_ds ss; + + SCARG(&ap, shmid) = SCARG(uap, shmid); + + if (SCARG(uap, buf) != NULL) { + SCARG(&ap, buf) = stackgap_alloc(&sg, sizeof (struct shmid_ds)); + switch (SCARG(uap, cmd)) { + case SVR4_IPC_SET: + case SVR4_IPC_RMID: + case SVR4_SHM_LOCK: + case SVR4_SHM_UNLOCK: + error = copyin(SCARG(uap, buf), (caddr_t) &ss, + sizeof ss); + if (error) + return error; + svr4_to_bsd_shmid_ds(&ss, &bs); + error = copyout(&bs, SCARG(&ap, buf), sizeof bs); + if (error) + return error; + break; + default: + break; + } + } + else + SCARG(&ap, buf) = NULL; + + + switch (SCARG(uap, cmd)) { + case SVR4_IPC_STAT: + SCARG(&ap, cmd) = IPC_STAT; + if ((error = sys_shmctl(p, &ap, retval)) != 0) + return error; + if (SCARG(uap, buf) == NULL) + return 0; + error = copyin(&bs, SCARG(&ap, buf), sizeof bs); + if (error) + return error; + bsd_to_svr4_shmid_ds(&bs, &ss); + return copyout(&ss, SCARG(uap, buf), sizeof ss); + + case SVR4_IPC_SET: + SCARG(&ap, cmd) = IPC_SET; + return sys_shmctl(p, &ap, retval); + + case SVR4_IPC_RMID: + case SVR4_SHM_LOCK: + case SVR4_SHM_UNLOCK: + switch (SCARG(uap, cmd)) { + case SVR4_IPC_RMID: + SCARG(&ap, cmd) = IPC_RMID; + break; + case SVR4_SHM_LOCK: + SCARG(&ap, cmd) = SHM_LOCK; + break; + case SVR4_SHM_UNLOCK: + SCARG(&ap, cmd) = SHM_UNLOCK; + break; + default: + return EINVAL; + } + return sys_shmctl(p, &ap, retval); + + default: + return EINVAL; + } +} + +int +svr4_sys_shmsys(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct svr4_sys_shmsys_args *uap = v; + + DPRINTF(("svr4_shmsys(%d)\n", SCARG(uap, what))); + + switch (SCARG(uap, what)) { + case SVR4_shmat: + return svr4_shmat(p, v, retval); + case SVR4_shmdt: + return svr4_shmdt(p, v, retval); + case SVR4_shmget: + return svr4_shmget(p, v, retval); + case SVR4_shmctl: + return svr4_shmctl(p, v, retval); + default: + return ENOSYS; + } +} +#endif /* SYSVSHM */ diff --git a/sys/compat/svr4/svr4_ipc.h b/sys/compat/svr4/svr4_ipc.h new file mode 100644 index 0000000..6aadb7e --- /dev/null +++ b/sys/compat/svr4/svr4_ipc.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1995 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_IPC_H_ +#define _SVR4_IPC_H_ + +/* + * General IPC + */ +#define SVR4_IPC_RMID 10 +#define SVR4_IPC_SET 11 +#define SVR4_IPC_STAT 12 + +struct svr4_ipc_perm { + svr4_uid_t uid; + svr4_gid_t gid; + svr4_uid_t cuid; + svr4_gid_t cgid; + svr4_mode_t mode; + u_long seq; + svr4_key_t key; + long pad[4]; +}; + +/* + * Message queues + */ +#define SVR4_msgget 0 +#define SVR4_msgctl 1 +#define SVR4_msgrcv 2 +#define SVR4_msgsnd 3 + +struct svr4_msg { + struct svr4_msg *msg_next; + long msg_type; + u_short msg_ts; + short msg_spot; +}; + +struct svr4_msqid_ds { + struct svr4_ipc_perm msg_perm; + struct svr4_msg *msg_first; + struct svr4_msg *msg_last; + u_long msg_cbytes; + u_long msg_qnum; + u_long msg_qbytes; + svr4_pid_t msg_lspid; + svr4_pid_t msg_lrpid; + svr4_time_t msg_stime; + long msg_pad1; + svr4_time_t msg_rtime; + long msg_pad2; + svr4_time_t msg_ctime; + long msg_pad3; + short msg_cv; + short msg_qnum_cv; + long msg_pad4[3]; +}; + +struct svr4_msgbuf { + long mtype; /* message type */ + char mtext[1]; /* message text */ +}; + +struct svr4_msginfo { + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + u_short msgseg; +}; + +/* + * Shared memory + */ +#define SVR4_shmat 0 +#define SVR4_shmctl 1 +#define SVR4_shmdt 2 +#define SVR4_shmget 3 + +/* shmctl() operations */ +#define SVR4_SHM_LOCK 3 +#define SVR4_SHM_UNLOCK 4 + +struct svr4_shmid_ds { + struct svr4_ipc_perm shm_perm; + int shm_segsz; + void *shm_amp; + u_short shm_lkcnt; + svr4_pid_t shm_lpid; + svr4_pid_t shm_cpid; + u_long shm_nattch; + u_long shm_cnattch; + svr4_time_t shm_atime; + long shm_pad1; + svr4_time_t shm_dtime; + long shm_pad2; + svr4_time_t shm_ctime; + long shm_pad3; + long shm_pad4[4]; +}; + +/* + * Semaphores + */ +#define SVR4_semctl 0 +#define SVR4_semget 1 +#define SVR4_semop 2 + +/* semctl() operations */ +#define SVR4_SEM_GETNCNT 3 +#define SVR4_SEM_GETPID 4 +#define SVR4_SEM_GETVAL 5 +#define SVR4_SEM_GETALL 6 +#define SVR4_SEM_GETZCNT 7 +#define SVR4_SEM_SETVAL 8 +#define SVR4_SEM_SETALL 9 + +struct svr4_sem { + u_short semval; + svr4_pid_t sempid; + u_short semncnt; + u_short semzcnt; + u_short semncnt_cv; + u_short semzcnt_cv; +}; + +struct svr4_semid_ds { + struct svr4_ipc_perm sem_perm; + struct svr4_sem *sem_base; + u_short sem_nsems; + svr4_time_t sem_otime; + long sem_pad1; + svr4_time_t sem_ctime; + long sem_pad2; + long sem_pad3[4]; +}; + +struct svr4_sembuf { + u_short sem_num; + short sem_op; + short sem_flg; +}; + +#endif /* _SVR4_IPC_H */ diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c new file mode 100644 index 0000000..f60d62c --- /dev/null +++ b/sys/compat/svr4/svr4_misc.c @@ -0,0 +1,1744 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * SVR4 compatibility module. + * + * SVR4 system calls that are implemented differently in BSD are + * handled here. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/dirent.h> +#include <sys/fcntl.h> +#include <sys/filedesc.h> +#include <sys/jail.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/file.h> /* Must come after sys/malloc.h */ +#include <sys/mman.h> +#include <sys/mount.h> +#include <sys/msg.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/ptrace.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> +#include <sys/sem.h> +#include <sys/stat.h> +#include <sys/sx.h> +#include <sys/sysproto.h> +#include <sys/time.h> +#include <sys/times.h> +#include <sys/uio.h> +#include <sys/user.h> +#include <sys/vnode.h> +#include <sys/wait.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_sysconfig.h> +#include <compat/svr4/svr4_dirent.h> +#include <compat/svr4/svr4_acl.h> +#include <compat/svr4/svr4_ulimit.h> +#include <compat/svr4/svr4_statvfs.h> +#include <compat/svr4/svr4_hrt.h> +#include <compat/svr4/svr4_mman.h> +#include <compat/svr4/svr4_wait.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_map.h> +#if defined(__FreeBSD__) +#include <vm/uma.h> +#endif + +#if defined(NetBSD) +# if defined(UVM) +# include <uvm/uvm_extern.h> +# endif +#endif + +#define BSD_DIRENT(cp) ((struct dirent *)(cp)) + +static int svr4_mknod(struct thread *, register_t *, char *, + svr4_mode_t, svr4_dev_t); + +static __inline clock_t timeval_to_clock_t(struct timeval *); +static int svr4_setinfo (struct proc *, int, svr4_siginfo_t *); + +struct svr4_hrtcntl_args; +static int svr4_hrtcntl (struct thread *, struct svr4_hrtcntl_args *, + register_t *); +static void bsd_statfs_to_svr4_statvfs(const struct statfs *, + struct svr4_statvfs *); +static void bsd_statfs_to_svr4_statvfs64(const struct statfs *, + struct svr4_statvfs64 *); +static struct proc *svr4_pfind(pid_t pid); + +/* BOGUS noop */ +#if defined(BOGUS) +int +svr4_sys_setitimer(td, uap) + register struct thread *td; + struct svr4_sys_setitimer_args *uap; +{ + td->td_retval[0] = 0; + return 0; +} +#endif + +int +svr4_sys_wait(td, uap) + struct thread *td; + struct svr4_sys_wait_args *uap; +{ + struct wait_args w4; + int error, *retval = td->td_retval, st, sig; + size_t sz = sizeof(*SCARG(&w4, status)); + + SCARG(&w4, rusage) = NULL; + SCARG(&w4, options) = 0; + + if (SCARG(uap, status) == NULL) { + caddr_t sg = stackgap_init(); + + SCARG(&w4, status) = stackgap_alloc(&sg, sz); + } + else + SCARG(&w4, status) = SCARG(uap, status); + + SCARG(&w4, pid) = WAIT_ANY; + + if ((error = wait4(td, &w4)) != 0) + return error; + + if ((error = copyin(SCARG(&w4, status), &st, sizeof(st))) != 0) + return error; + + if (WIFSIGNALED(st)) { + sig = WTERMSIG(st); + if (sig >= 0 && sig < NSIG) + st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig); + } else if (WIFSTOPPED(st)) { + sig = WSTOPSIG(st); + if (sig >= 0 && sig < NSIG) + st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8); + } + + /* + * It looks like wait(2) on svr4/solaris/2.4 returns + * the status in retval[1], and the pid on retval[0]. + */ + retval[1] = st; + + if (SCARG(uap, status)) + if ((error = copyout(&st, SCARG(uap, status), sizeof(st))) != 0) + return error; + + return 0; +} + +int +svr4_sys_execv(td, uap) + struct thread *td; + struct svr4_sys_execv_args *uap; +{ + struct execve_args ap; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&ap, fname) = SCARG(uap, path); + SCARG(&ap, argv) = SCARG(uap, argp); + SCARG(&ap, envv) = NULL; + + return execve(td, &ap); +} + +int +svr4_sys_execve(td, uap) + struct thread *td; + struct svr4_sys_execve_args *uap; +{ + struct execve_args ap; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(td, &sg, uap->path); + + SCARG(&ap, fname) = SCARG(uap, path); + SCARG(&ap, argv) = SCARG(uap, argp); + SCARG(&ap, envv) = SCARG(uap, envp); + + return execve(td, &ap); +} + +int +svr4_sys_time(td, v) + struct thread *td; + struct svr4_sys_time_args *v; +{ + struct svr4_sys_time_args *uap = v; + int error = 0; + struct timeval tv; + + microtime(&tv); + if (SCARG(uap, t)) + error = copyout(&tv.tv_sec, SCARG(uap, t), + sizeof(*(SCARG(uap, t)))); + td->td_retval[0] = (int) tv.tv_sec; + + return error; +} + + +/* + * Read SVR4-style directory entries. We suck them into kernel space so + * that they can be massaged before being copied out to user code. + * + * This code is ported from the Linux emulator: Changes to the VFS interface + * between FreeBSD and NetBSD have made it simpler to port it from there than + * to adapt the NetBSD version. + */ +int +svr4_sys_getdents64(td, uap) + struct thread *td; + struct svr4_sys_getdents64_args *uap; +{ + register struct dirent *bdp; + struct vnode *vp; + caddr_t inp, buf; /* BSD-format */ + int len, reclen; /* BSD-format */ + caddr_t outp; /* SVR4-format */ + int resid, svr4reclen=0; /* SVR4-format */ + struct file *fp; + struct uio auio; + struct iovec aiov; + struct vattr va; + off_t off; + struct svr4_dirent64 svr4_dirent; + int buflen, error, eofflag, nbytes, justone; + u_long *cookies = NULL, *cookiep; + int ncookies; + + DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n", + SCARG(uap, fd), SCARG(uap, nbytes))); + if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) { + return (error); + } + + if ((fp->f_flag & FREAD) == 0) { + fdrop(fp, td); + return (EBADF); + } + + vp = (struct vnode *) fp->f_data; + + if (vp->v_type != VDIR) { + fdrop(fp, td); + return (EINVAL); + } + + if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { + fdrop(fp, td); + return error; + } + + nbytes = SCARG(uap, nbytes); + if (nbytes == 1) { + nbytes = sizeof (struct svr4_dirent64); + justone = 1; + } + else + justone = 0; + + off = fp->f_offset; +#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ + buflen = max(DIRBLKSIZ, nbytes); + buflen = min(buflen, MAXBSIZE); + buf = malloc(buflen, M_TEMP, M_WAITOK); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +again: + aiov.iov_base = buf; + aiov.iov_len = buflen; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_td = td; + auio.uio_resid = buflen; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; + } + + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, + &ncookies, &cookies); + if (error) { + goto out; + } + + inp = buf; + outp = (caddr_t) SCARG(uap, dp); + resid = nbytes; + if ((len = buflen - auio.uio_resid) <= 0) { + goto eof; + } + + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + bdp = (struct dirent *) inp; + len -= bdp->d_reclen; + inp += bdp->d_reclen; + cookiep++; + ncookies--; + } + } + + while (len > 0) { + if (cookiep && ncookies == 0) + break; + bdp = (struct dirent *) inp; + reclen = bdp->d_reclen; + if (reclen & 3) { + DPRINTF(("svr4_readdir: reclen=%d\n", reclen)); + error = EFAULT; + goto out; + } + + if (bdp->d_fileno == 0) { + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + len -= reclen; + continue; + } + svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen); + if (reclen > len || resid < svr4reclen) { + outp++; + break; + } + svr4_dirent.d_ino = (long) bdp->d_fileno; + if (justone) { + /* + * old svr4-style readdir usage. + */ + svr4_dirent.d_off = (svr4_off_t) svr4reclen; + svr4_dirent.d_reclen = (u_short) bdp->d_namlen; + } else { + svr4_dirent.d_off = (svr4_off_t)(off + reclen); + svr4_dirent.d_reclen = (u_short) svr4reclen; + } + strcpy(svr4_dirent.d_name, bdp->d_name); + if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen))) + goto out; + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + outp += svr4reclen; + resid -= svr4reclen; + len -= reclen; + if (justone) + break; + } + + if (outp == (caddr_t) SCARG(uap, dp)) + goto again; + fp->f_offset = off; + + if (justone) + nbytes = resid + svr4reclen; + +eof: + td->td_retval[0] = nbytes - resid; +out: + VOP_UNLOCK(vp, 0, td); + fdrop(fp, td); + if (cookies) + free(cookies, M_TEMP); + free(buf, M_TEMP); + return error; +} + + +int +svr4_sys_getdents(td, uap) + struct thread *td; + struct svr4_sys_getdents_args *uap; +{ + struct dirent *bdp; + struct vnode *vp; + caddr_t inp, buf; /* BSD-format */ + int len, reclen; /* BSD-format */ + caddr_t outp; /* SVR4-format */ + int resid, svr4_reclen; /* SVR4-format */ + struct file *fp; + struct uio auio; + struct iovec aiov; + struct svr4_dirent idb; + off_t off; /* true file offset */ + int buflen, error, eofflag; + u_long *cookiebuf = NULL, *cookie; + int ncookies = 0, *retval = td->td_retval; + + if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) + return (error); + + if ((fp->f_flag & FREAD) == 0) { + fdrop(fp, td); + return (EBADF); + } + + vp = (struct vnode *)fp->f_data; + if (vp->v_type != VDIR) { + fdrop(fp, td); + return (EINVAL); + } + + buflen = min(MAXBSIZE, SCARG(uap, nbytes)); + buf = malloc(buflen, M_TEMP, M_WAITOK); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + off = fp->f_offset; +again: + aiov.iov_base = buf; + aiov.iov_len = buflen; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_td = td; + auio.uio_resid = buflen; + auio.uio_offset = off; + /* + * First we read into the malloc'ed buffer, then + * we massage it into user space, one record at a time. + */ + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, + &cookiebuf); + if (error) { + goto out; + } + + inp = buf; + outp = SCARG(uap, buf); + resid = SCARG(uap, nbytes); + if ((len = buflen - auio.uio_resid) == 0) + goto eof; + + for (cookie = cookiebuf; len > 0; len -= reclen) { + bdp = (struct dirent *)inp; + reclen = bdp->d_reclen; + if (reclen & 3) + panic("svr4_sys_getdents64: bad reclen"); + off = *cookie++; /* each entry points to the next */ + if ((off >> 32) != 0) { + uprintf("svr4_sys_getdents64: dir offset too large for emulated program"); + error = EINVAL; + goto out; + } + if (bdp->d_fileno == 0) { + inp += reclen; /* it is a hole; squish it out */ + continue; + } + svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen); + if (reclen > len || resid < svr4_reclen) { + /* entry too big for buffer, so just stop */ + outp++; + break; + } + /* + * Massage in place to make a SVR4-shaped dirent (otherwise + * we have to worry about touching user memory outside of + * the copyout() call). + */ + idb.d_ino = (svr4_ino_t)bdp->d_fileno; + idb.d_off = (svr4_off_t)off; + idb.d_reclen = (u_short)svr4_reclen; + strcpy(idb.d_name, bdp->d_name); + if ((error = copyout((caddr_t)&idb, outp, svr4_reclen))) + goto out; + /* advance past this real entry */ + inp += reclen; + /* advance output past SVR4-shaped entry */ + outp += svr4_reclen; + resid -= svr4_reclen; + } + + /* if we squished out the whole block, try again */ + if (outp == SCARG(uap, buf)) + goto again; + fp->f_offset = off; /* update the vnode offset */ + +eof: + *retval = SCARG(uap, nbytes) - resid; +out: + VOP_UNLOCK(vp, 0, td); + fdrop(fp, td); + if (cookiebuf) + free(cookiebuf, M_TEMP); + free(buf, M_TEMP); + return error; +} + + +int +svr4_sys_mmap(td, uap) + struct thread *td; + struct svr4_sys_mmap_args *uap; +{ + struct mmap_args mm; + int *retval; + + retval = td->td_retval; +#define _MAP_NEW 0x80000000 + /* + * Verify the arguments. + */ + if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return EINVAL; /* XXX still needed? */ + + if (SCARG(uap, len) == 0) + return EINVAL; + + SCARG(&mm, prot) = SCARG(uap, prot); + SCARG(&mm, len) = SCARG(uap, len); + SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW; + SCARG(&mm, fd) = SCARG(uap, fd); + SCARG(&mm, addr) = SCARG(uap, addr); + SCARG(&mm, pos) = SCARG(uap, pos); + + return mmap(td, &mm); +} + +int +svr4_sys_mmap64(td, uap) + struct thread *td; + struct svr4_sys_mmap64_args *uap; +{ + struct mmap_args mm; + void *rp; + +#define _MAP_NEW 0x80000000 + /* + * Verify the arguments. + */ + if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return EINVAL; /* XXX still needed? */ + + if (SCARG(uap, len) == 0) + return EINVAL; + + SCARG(&mm, prot) = SCARG(uap, prot); + SCARG(&mm, len) = SCARG(uap, len); + SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW; + SCARG(&mm, fd) = SCARG(uap, fd); + SCARG(&mm, addr) = SCARG(uap, addr); + SCARG(&mm, pos) = SCARG(uap, pos); + + rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz)); + if ((SCARG(&mm, flags) & MAP_FIXED) == 0 && + SCARG(&mm, addr) != 0 && (void *)SCARG(&mm, addr) < rp) + SCARG(&mm, addr) = rp; + + return mmap(td, &mm); +} + + +int +svr4_sys_fchroot(td, uap) + struct thread *td; + struct svr4_sys_fchroot_args *uap; +{ + struct filedesc *fdp = td->td_proc->p_fd; + struct vnode *vp, *vpold; + struct file *fp; + int error; + + if ((error = suser(td)) != 0) + return error; + if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) + return error; + vp = (struct vnode *) fp->f_data; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + if (vp->v_type != VDIR) + error = ENOTDIR; + else + error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td); + VOP_UNLOCK(vp, 0, td); + if (error) { + fdrop(fp, td); + return error; + } + VREF(vp); + FILEDESC_LOCK(fdp); + vpold = fdp->fd_rdir; + fdp->fd_rdir = vp; + FILEDESC_UNLOCK(fdp); + if (vpold != NULL) + vrele(vpold); + fdrop(fp, td); + return 0; +} + + +static int +svr4_mknod(td, retval, path, mode, dev) + struct thread *td; + register_t *retval; + char *path; + svr4_mode_t mode; + svr4_dev_t dev; +{ + caddr_t sg = stackgap_init(); + + CHECKALTEXIST(td, &sg, path); + + if (S_ISFIFO(mode)) { + struct mkfifo_args ap; + SCARG(&ap, path) = path; + SCARG(&ap, mode) = mode; + return mkfifo(td, &ap); + } else { + struct mknod_args ap; + SCARG(&ap, path) = path; + SCARG(&ap, mode) = mode; + SCARG(&ap, dev) = dev; + return mknod(td, &ap); + } +} + + +int +svr4_sys_mknod(td, uap) + register struct thread *td; + struct svr4_sys_mknod_args *uap; +{ + int *retval = td->td_retval; + return svr4_mknod(td, retval, + SCARG(uap, path), SCARG(uap, mode), + (svr4_dev_t)svr4_to_bsd_odev_t(SCARG(uap, dev))); +} + + +int +svr4_sys_xmknod(td, uap) + struct thread *td; + struct svr4_sys_xmknod_args *uap; +{ + int *retval = td->td_retval; + return svr4_mknod(td, retval, + SCARG(uap, path), SCARG(uap, mode), + (svr4_dev_t)svr4_to_bsd_dev_t(SCARG(uap, dev))); +} + + +int +svr4_sys_vhangup(td, uap) + struct thread *td; + struct svr4_sys_vhangup_args *uap; +{ + return 0; +} + + +int +svr4_sys_sysconfig(td, uap) + struct thread *td; + struct svr4_sys_sysconfig_args *uap; +{ + int *retval; + + retval = &(td->td_retval[0]); + + switch (SCARG(uap, name)) { + case SVR4_CONFIG_UNUSED: + *retval = 0; + break; + case SVR4_CONFIG_NGROUPS: + *retval = NGROUPS_MAX; + break; + case SVR4_CONFIG_CHILD_MAX: + *retval = maxproc; + break; + case SVR4_CONFIG_OPEN_FILES: + *retval = maxfiles; + break; + case SVR4_CONFIG_POSIX_VER: + *retval = 198808; + break; + case SVR4_CONFIG_PAGESIZE: + *retval = PAGE_SIZE; + break; + case SVR4_CONFIG_CLK_TCK: + *retval = 60; /* should this be `hz', ie. 100? */ + break; + case SVR4_CONFIG_XOPEN_VER: + *retval = 2; /* XXX: What should that be? */ + break; + case SVR4_CONFIG_PROF_TCK: + *retval = 60; /* XXX: What should that be? */ + break; + case SVR4_CONFIG_NPROC_CONF: + *retval = 1; /* Only one processor for now */ + break; + case SVR4_CONFIG_NPROC_ONLN: + *retval = 1; /* And it better be online */ + break; + case SVR4_CONFIG_AIO_LISTIO_MAX: + case SVR4_CONFIG_AIO_MAX: + case SVR4_CONFIG_AIO_PRIO_DELTA_MAX: + *retval = 0; /* No aio support */ + break; + case SVR4_CONFIG_DELAYTIMER_MAX: + *retval = 0; /* No delaytimer support */ + break; + case SVR4_CONFIG_MQ_OPEN_MAX: + *retval = msginfo.msgmni; + break; + case SVR4_CONFIG_MQ_PRIO_MAX: + *retval = 0; /* XXX: Don't know */ + break; + case SVR4_CONFIG_RTSIG_MAX: + *retval = 0; + break; + case SVR4_CONFIG_SEM_NSEMS_MAX: + *retval = seminfo.semmni; + break; + case SVR4_CONFIG_SEM_VALUE_MAX: + *retval = seminfo.semvmx; + break; + case SVR4_CONFIG_SIGQUEUE_MAX: + *retval = 0; /* XXX: Don't know */ + break; + case SVR4_CONFIG_SIGRT_MIN: + case SVR4_CONFIG_SIGRT_MAX: + *retval = 0; /* No real time signals */ + break; + case SVR4_CONFIG_TIMER_MAX: + *retval = 3; /* XXX: real, virtual, profiling */ + break; +#if defined(NOTYET) + case SVR4_CONFIG_PHYS_PAGES: +#if defined(UVM) + *retval = uvmexp.free; /* XXX: free instead of total */ +#else + *retval = cnt.v_free_count; /* XXX: free instead of total */ +#endif + break; + case SVR4_CONFIG_AVPHYS_PAGES: +#if defined(UVM) + *retval = uvmexp.active; /* XXX: active instead of avg */ +#else + *retval = cnt.v_active_count; /* XXX: active instead of avg */ +#endif + break; +#endif /* NOTYET */ + + default: + return EINVAL; + } + return 0; +} + +extern int swap_pager_full; + +/* ARGSUSED */ +int +svr4_sys_break(td, uap) + struct thread *td; + struct svr4_sys_break_args *uap; +{ + struct vmspace *vm = td->td_proc->p_vmspace; + vm_offset_t new, old, base, ns; + int rv; + + base = round_page((vm_offset_t) vm->vm_daddr); + ns = (vm_offset_t)SCARG(uap, nsize); + new = round_page(ns); + /* For p_rlimit. */ + mtx_assert(&Giant, MA_OWNED); + if (new > base) { + if ((new - base) > (unsigned) td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur) { + return ENOMEM; + } + if (new >= VM_MAXUSER_ADDRESS) { + return (ENOMEM); + } + } else if (new < base) { + /* + * This is simply an invalid value. If someone wants to + * do fancy address space manipulations, mmap and munmap + * can do most of what the user would want. + */ + return EINVAL; + } + + old = base + ctob(vm->vm_dsize); + + if (new > old) { + vm_size_t diff; + if (swap_pager_full) { + return (ENOMEM); + } + diff = new - old; + rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE, + VM_PROT_ALL, VM_PROT_ALL, 0); + if (rv != KERN_SUCCESS) { + return (ENOMEM); + } + vm->vm_dsize += btoc(diff); + } else if (new < old) { + rv = vm_map_remove(&vm->vm_map, new, old); + if (rv != KERN_SUCCESS) { + return (ENOMEM); + } + vm->vm_dsize -= btoc(old - new); + } + + return (0); +} + +static __inline clock_t +timeval_to_clock_t(tv) + struct timeval *tv; +{ + return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz); +} + + +int +svr4_sys_times(td, uap) + struct thread *td; + struct svr4_sys_times_args *uap; +{ + int error, *retval = td->td_retval; + struct tms tms; + struct timeval t; + struct rusage *ru; + struct rusage r; + struct getrusage_args ga; + + caddr_t sg = stackgap_init(); + ru = stackgap_alloc(&sg, sizeof(struct rusage)); + + SCARG(&ga, who) = RUSAGE_SELF; + SCARG(&ga, rusage) = ru; + + error = getrusage(td, &ga); + if (error) + return error; + + if ((error = copyin(ru, &r, sizeof r)) != 0) + return error; + + tms.tms_utime = timeval_to_clock_t(&r.ru_utime); + tms.tms_stime = timeval_to_clock_t(&r.ru_stime); + + SCARG(&ga, who) = RUSAGE_CHILDREN; + error = getrusage(td, &ga); + if (error) + return error; + + if ((error = copyin(ru, &r, sizeof r)) != 0) + return error; + + tms.tms_cutime = timeval_to_clock_t(&r.ru_utime); + tms.tms_cstime = timeval_to_clock_t(&r.ru_stime); + + microtime(&t); + *retval = timeval_to_clock_t(&t); + + return copyout(&tms, SCARG(uap, tp), sizeof(tms)); +} + + +int +svr4_sys_ulimit(td, uap) + struct thread *td; + struct svr4_sys_ulimit_args *uap; +{ + int *retval = td->td_retval; + + switch (SCARG(uap, cmd)) { + case SVR4_GFILLIM: + /* For p_rlimit below. */ + mtx_assert(&Giant, MA_OWNED); + *retval = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512; + if (*retval == -1) + *retval = 0x7fffffff; + return 0; + + case SVR4_SFILLIM: + { + int error; + struct __setrlimit_args srl; + struct rlimit krl; + caddr_t sg = stackgap_init(); + struct rlimit *url = (struct rlimit *) + stackgap_alloc(&sg, sizeof *url); + + krl.rlim_cur = SCARG(uap, newlimit) * 512; + mtx_assert(&Giant, MA_OWNED); + krl.rlim_max = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_max; + + error = copyout(&krl, url, sizeof(*url)); + if (error) + return error; + + SCARG(&srl, which) = RLIMIT_FSIZE; + SCARG(&srl, rlp) = url; + + error = setrlimit(td, &srl); + if (error) + return error; + + mtx_assert(&Giant, MA_OWNED); + *retval = td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur; + if (*retval == -1) + *retval = 0x7fffffff; + return 0; + } + + case SVR4_GMEMLIM: + { + struct vmspace *vm = td->td_proc->p_vmspace; + register_t r; + + mtx_assert(&Giant, MA_OWNED); + r = td->td_proc->p_rlimit[RLIMIT_DATA].rlim_cur; + + if (r == -1) + r = 0x7fffffff; + r += (long) vm->vm_daddr; + if (r < 0) + r = 0x7fffffff; + *retval = r; + return 0; + } + + case SVR4_GDESLIM: + mtx_assert(&Giant, MA_OWNED); + *retval = td->td_proc->p_rlimit[RLIMIT_NOFILE].rlim_cur; + if (*retval == -1) + *retval = 0x7fffffff; + return 0; + + default: + return EINVAL; + } +} + +static struct proc * +svr4_pfind(pid) + pid_t pid; +{ + struct proc *p; + + /* look in the live processes */ + if ((p = pfind(pid)) == NULL) + /* look in the zombies */ + p = zpfind(pid); + + return p; +} + + +int +svr4_sys_pgrpsys(td, uap) + struct thread *td; + struct svr4_sys_pgrpsys_args *uap; +{ + int *retval = td->td_retval; + struct proc *p = td->td_proc; + + switch (SCARG(uap, cmd)) { + case 1: /* setpgrp() */ + /* + * SVR4 setpgrp() (which takes no arguments) has the + * semantics that the session ID is also created anew, so + * in almost every sense, setpgrp() is identical to + * setsid() for SVR4. (Under BSD, the difference is that + * a setpgid(0,0) will not create a new session.) + */ + setsid(td, NULL); + /*FALLTHROUGH*/ + + case 0: /* getpgrp() */ + PROC_LOCK(p); + *retval = p->p_pgrp->pg_id; + PROC_UNLOCK(p); + return 0; + + case 2: /* getsid(pid) */ + if (SCARG(uap, pid) == 0) + PROC_LOCK(p); + else if ((p = svr4_pfind(SCARG(uap, pid))) == NULL) + return ESRCH; + /* + * This has already been initialized to the pid of + * the session leader. + */ + *retval = (register_t) p->p_session->s_sid; + PROC_UNLOCK(p); + return 0; + + case 3: /* setsid() */ + return setsid(td, NULL); + + case 4: /* getpgid(pid) */ + + if (SCARG(uap, pid) == 0) + PROC_LOCK(p); + else if ((p = svr4_pfind(SCARG(uap, pid))) == NULL) + return ESRCH; + + *retval = (int) p->p_pgrp->pg_id; + PROC_UNLOCK(p); + return 0; + + case 5: /* setpgid(pid, pgid); */ + { + struct setpgid_args sa; + + SCARG(&sa, pid) = SCARG(uap, pid); + SCARG(&sa, pgid) = SCARG(uap, pgid); + return setpgid(td, &sa); + } + + default: + return EINVAL; + } +} + +#define syscallarg(x) union { x datum; register_t pad; } + +struct svr4_hrtcntl_args { + int cmd; + int fun; + int clk; + svr4_hrt_interval_t * iv; + svr4_hrt_time_t * ti; +}; + + +static int +svr4_hrtcntl(td, uap, retval) + struct thread *td; + struct svr4_hrtcntl_args *uap; + register_t *retval; +{ + switch (SCARG(uap, fun)) { + case SVR4_HRT_CNTL_RES: + DPRINTF(("htrcntl(RES)\n")); + *retval = SVR4_HRT_USEC; + return 0; + + case SVR4_HRT_CNTL_TOFD: + DPRINTF(("htrcntl(TOFD)\n")); + { + struct timeval tv; + svr4_hrt_time_t t; + if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) { + DPRINTF(("clk == %d\n", SCARG(uap, clk))); + return EINVAL; + } + if (SCARG(uap, ti) == NULL) { + DPRINTF(("ti NULL\n")); + return EINVAL; + } + microtime(&tv); + t.h_sec = tv.tv_sec; + t.h_rem = tv.tv_usec; + t.h_res = SVR4_HRT_USEC; + return copyout(&t, SCARG(uap, ti), sizeof(t)); + } + + case SVR4_HRT_CNTL_START: + DPRINTF(("htrcntl(START)\n")); + return ENOSYS; + + case SVR4_HRT_CNTL_GET: + DPRINTF(("htrcntl(GET)\n")); + return ENOSYS; + default: + DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun))); + return ENOSYS; + } +} + + +int +svr4_sys_hrtsys(td, uap) + struct thread *td; + struct svr4_sys_hrtsys_args *uap; +{ + int *retval = td->td_retval; + + switch (SCARG(uap, cmd)) { + case SVR4_HRT_CNTL: + return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap, + retval); + + case SVR4_HRT_ALRM: + DPRINTF(("hrtalarm\n")); + return ENOSYS; + + case SVR4_HRT_SLP: + DPRINTF(("hrtsleep\n")); + return ENOSYS; + + case SVR4_HRT_CAN: + DPRINTF(("hrtcancel\n")); + return ENOSYS; + + default: + DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd))); + return EINVAL; + } +} + + +static int +svr4_setinfo(p, st, s) + struct proc *p; + int st; + svr4_siginfo_t *s; +{ + svr4_siginfo_t i; + int sig; + + memset(&i, 0, sizeof(i)); + + i.si_signo = SVR4_SIGCHLD; + i.si_errno = 0; /* XXX? */ + + if (p) { + i.si_pid = p->p_pid; + mtx_lock_spin(&sched_lock); + if (p->p_state == PRS_ZOMBIE) { + i.si_stime = p->p_ru->ru_stime.tv_sec; + i.si_utime = p->p_ru->ru_utime.tv_sec; + } + else { + i.si_stime = p->p_stats->p_ru.ru_stime.tv_sec; + i.si_utime = p->p_stats->p_ru.ru_utime.tv_sec; + } + mtx_unlock_spin(&sched_lock); + } + + if (WIFEXITED(st)) { + i.si_status = WEXITSTATUS(st); + i.si_code = SVR4_CLD_EXITED; + } else if (WIFSTOPPED(st)) { + sig = WSTOPSIG(st); + if (sig >= 0 && sig < NSIG) + i.si_status = SVR4_BSD2SVR4_SIG(sig); + + if (i.si_status == SVR4_SIGCONT) + i.si_code = SVR4_CLD_CONTINUED; + else + i.si_code = SVR4_CLD_STOPPED; + } else { + sig = WTERMSIG(st); + if (sig >= 0 && sig < NSIG) + i.si_status = SVR4_BSD2SVR4_SIG(sig); + + if (WCOREDUMP(st)) + i.si_code = SVR4_CLD_DUMPED; + else + i.si_code = SVR4_CLD_KILLED; + } + + DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n", + i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status)); + + return copyout(&i, s, sizeof(i)); +} + + +int +svr4_sys_waitsys(td, uap) + struct thread *td; + struct svr4_sys_waitsys_args *uap; +{ + int nfound; + int error, *retval = td->td_retval; + struct proc *q, *t; + + + switch (SCARG(uap, grp)) { + case SVR4_P_PID: + break; + + case SVR4_P_PGID: + PROC_LOCK(td->td_proc); + SCARG(uap, id) = -td->td_proc->p_pgid; + PROC_UNLOCK(td->td_proc); + break; + + case SVR4_P_ALL: + SCARG(uap, id) = WAIT_ANY; + break; + + default: + return EINVAL; + } + + DPRINTF(("waitsys(%d, %d, %p, %x)\n", + SCARG(uap, grp), SCARG(uap, id), + SCARG(uap, info), SCARG(uap, options))); + +loop: + nfound = 0; + sx_slock(&proctree_lock); + LIST_FOREACH(q, &td->td_proc->p_children, p_sibling) { + PROC_LOCK(q); + if (SCARG(uap, id) != WAIT_ANY && + q->p_pid != SCARG(uap, id) && + q->p_pgid != -SCARG(uap, id)) { + PROC_UNLOCK(q); + DPRINTF(("pid %d pgid %d != %d\n", q->p_pid, + q->p_pgid, SCARG(uap, id))); + continue; + } + nfound++; + mtx_lock_spin(&sched_lock); + if ((q->p_state == PRS_ZOMBIE) && + ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)))) { + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(q); + sx_sunlock(&proctree_lock); + *retval = 0; + DPRINTF(("found %d\n", q->p_pid)); + error = svr4_setinfo(q, q->p_xstat, SCARG(uap, info)); + if (error != 0) + return error; + + + if ((SCARG(uap, options) & SVR4_WNOWAIT)) { + DPRINTF(("Don't wait\n")); + return 0; + } + + /* + * If we got the child via ptrace(2) or procfs, and + * the parent is different (meaning the process was + * attached, rather than run as a child), then we need + * to give it back to the old parent, and send the + * parent a SIGCHLD. The rest of the cleanup will be + * done when the old parent waits on the child. + */ + sx_xlock(&proctree_lock); + PROC_LOCK(q); + if (q->p_flag & P_TRACED) { + if (q->p_oppid != q->p_pptr->p_pid) { + PROC_UNLOCK(q); + t = pfind(q->p_oppid); + if (t == NULL) { + t = initproc; + PROC_LOCK(initproc); + } + PROC_LOCK(q); + proc_reparent(q, t); + q->p_oppid = 0; + q->p_flag &= ~(P_TRACED | P_WAITED); + PROC_UNLOCK(q); + psignal(t, SIGCHLD); + wakeup(t); + PROC_UNLOCK(t); + sx_xunlock(&proctree_lock); + return 0; + } + } + PROC_UNLOCK(q); + sx_xunlock(&proctree_lock); + q->p_xstat = 0; + ruadd(&td->td_proc->p_stats->p_cru, q->p_ru); + FREE(q->p_ru, M_ZOMBIE); + q->p_ru = 0; + + /* + * Decrement the count of procs running with this uid. + */ + (void)chgproccnt(q->p_ucred->cr_ruidinfo, -1, 0); + + /* + * Release reference to text vnode. + */ + if (q->p_textvp) + vrele(q->p_textvp); + + /* + * Free up credentials. + */ + crfree(q->p_ucred); + q->p_ucred = NULL; + + /* + * Remove unused arguments + */ + pargs_drop(q->p_args); + PROC_UNLOCK(q); + + /* + * Finally finished with old proc entry. + * Unlink it from its process group and free it. + */ + sx_xlock(&proctree_lock); + leavepgrp(q); + + sx_xlock(&allproc_lock); + LIST_REMOVE(q, p_list); /* off zombproc */ + sx_xunlock(&allproc_lock); + + LIST_REMOVE(q, p_sibling); + sx_xunlock(&proctree_lock); + + PROC_LOCK(q); + if (--q->p_procsig->ps_refcnt == 0) { + if (q->p_sigacts != &q->p_uarea->u_sigacts) + FREE(q->p_sigacts, M_SUBPROC); + FREE(q->p_procsig, M_SUBPROC); + q->p_procsig = NULL; + } + PROC_UNLOCK(q); + + /* + * Give machine-dependent layer a chance + * to free anything that cpu_exit couldn't + * release while still running in process context. + */ + cpu_wait(q); +#if defined(__NetBSD__) + pool_put(&proc_pool, q); +#endif +#ifdef __FreeBSD__ + mtx_destroy(&q->p_mtx); + uma_zfree(proc_zone, q); +#endif + nprocs--; + return 0; + } + /* XXXKSE this needs clarification */ + if (P_SHOULDSTOP(q) && ((q->p_flag & P_WAITED) == 0) && + (q->p_flag & P_TRACED || + (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED)))) { + mtx_unlock_spin(&sched_lock); + DPRINTF(("jobcontrol %d\n", q->p_pid)); + if (((SCARG(uap, options) & SVR4_WNOWAIT)) == 0) + q->p_flag |= P_WAITED; + PROC_UNLOCK(q); + *retval = 0; + return svr4_setinfo(q, W_STOPCODE(q->p_xstat), + SCARG(uap, info)); + } + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(q); + } + + if (nfound == 0) + return ECHILD; + + if (SCARG(uap, options) & SVR4_WNOHANG) { + *retval = 0; + if ((error = svr4_setinfo(NULL, 0, SCARG(uap, info))) != 0) + return error; + return 0; + } + + if ((error = tsleep((caddr_t)td->td_proc, PWAIT | PCATCH, "svr4_wait", 0)) != 0) + return error; + goto loop; +} + + +static void +bsd_statfs_to_svr4_statvfs(bfs, sfs) + const struct statfs *bfs; + struct svr4_statvfs *sfs; +{ + sfs->f_bsize = bfs->f_iosize; /* XXX */ + sfs->f_frsize = bfs->f_bsize; + sfs->f_blocks = bfs->f_blocks; + sfs->f_bfree = bfs->f_bfree; + sfs->f_bavail = bfs->f_bavail; + sfs->f_files = bfs->f_files; + sfs->f_ffree = bfs->f_ffree; + sfs->f_favail = bfs->f_ffree; + sfs->f_fsid = bfs->f_fsid.val[0]; + memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype)); + sfs->f_flag = 0; + if (bfs->f_flags & MNT_RDONLY) + sfs->f_flag |= SVR4_ST_RDONLY; + if (bfs->f_flags & MNT_NOSUID) + sfs->f_flag |= SVR4_ST_NOSUID; + sfs->f_namemax = MAXNAMLEN; + memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */ + memset(sfs->f_filler, 0, sizeof(sfs->f_filler)); +} + + +static void +bsd_statfs_to_svr4_statvfs64(bfs, sfs) + const struct statfs *bfs; + struct svr4_statvfs64 *sfs; +{ + sfs->f_bsize = bfs->f_iosize; /* XXX */ + sfs->f_frsize = bfs->f_bsize; + sfs->f_blocks = bfs->f_blocks; + sfs->f_bfree = bfs->f_bfree; + sfs->f_bavail = bfs->f_bavail; + sfs->f_files = bfs->f_files; + sfs->f_ffree = bfs->f_ffree; + sfs->f_favail = bfs->f_ffree; + sfs->f_fsid = bfs->f_fsid.val[0]; + memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype)); + sfs->f_flag = 0; + if (bfs->f_flags & MNT_RDONLY) + sfs->f_flag |= SVR4_ST_RDONLY; + if (bfs->f_flags & MNT_NOSUID) + sfs->f_flag |= SVR4_ST_NOSUID; + sfs->f_namemax = MAXNAMLEN; + memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */ + memset(sfs->f_filler, 0, sizeof(sfs->f_filler)); +} + + +int +svr4_sys_statvfs(td, uap) + struct thread *td; + struct svr4_sys_statvfs_args *uap; +{ + struct statfs_args fs_args; + caddr_t sg = stackgap_init(); + struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); + struct statfs bfs; + struct svr4_statvfs sfs; + int error; + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + SCARG(&fs_args, path) = SCARG(uap, path); + SCARG(&fs_args, buf) = fs; + + if ((error = statfs(td, &fs_args)) != 0) + return error; + + if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) + return error; + + bsd_statfs_to_svr4_statvfs(&bfs, &sfs); + + return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); +} + + +int +svr4_sys_fstatvfs(td, uap) + struct thread *td; + struct svr4_sys_fstatvfs_args *uap; +{ + struct fstatfs_args fs_args; + caddr_t sg = stackgap_init(); + struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); + struct statfs bfs; + struct svr4_statvfs sfs; + int error; + + SCARG(&fs_args, fd) = SCARG(uap, fd); + SCARG(&fs_args, buf) = fs; + + if ((error = fstatfs(td, &fs_args)) != 0) + return error; + + if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) + return error; + + bsd_statfs_to_svr4_statvfs(&bfs, &sfs); + + return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); +} + + +int +svr4_sys_statvfs64(td, uap) + struct thread *td; + struct svr4_sys_statvfs64_args *uap; +{ + struct statfs_args fs_args; + caddr_t sg = stackgap_init(); + struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); + struct statfs bfs; + struct svr4_statvfs64 sfs; + int error; + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + SCARG(&fs_args, path) = SCARG(uap, path); + SCARG(&fs_args, buf) = fs; + + if ((error = statfs(td, &fs_args)) != 0) + return error; + + if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) + return error; + + bsd_statfs_to_svr4_statvfs64(&bfs, &sfs); + + return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); +} + + +int +svr4_sys_fstatvfs64(td, uap) + struct thread *td; + struct svr4_sys_fstatvfs64_args *uap; +{ + struct fstatfs_args fs_args; + caddr_t sg = stackgap_init(); + struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs)); + struct statfs bfs; + struct svr4_statvfs64 sfs; + int error; + + SCARG(&fs_args, fd) = SCARG(uap, fd); + SCARG(&fs_args, buf) = fs; + + if ((error = fstatfs(td, &fs_args)) != 0) + return error; + + if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0) + return error; + + bsd_statfs_to_svr4_statvfs64(&bfs, &sfs); + + return copyout(&sfs, SCARG(uap, fs), sizeof(sfs)); +} + +int +svr4_sys_alarm(td, uap) + struct thread *td; + struct svr4_sys_alarm_args *uap; +{ + int error; + struct itimerval *itp, *oitp; + struct setitimer_args sa; + caddr_t sg = stackgap_init(); + + itp = stackgap_alloc(&sg, sizeof(*itp)); + oitp = stackgap_alloc(&sg, sizeof(*oitp)); + timevalclear(&itp->it_interval); + itp->it_value.tv_sec = SCARG(uap, sec); + itp->it_value.tv_usec = 0; + + SCARG(&sa, which) = ITIMER_REAL; + SCARG(&sa, itv) = itp; + SCARG(&sa, oitv) = oitp; + error = setitimer(td, &sa); + if (error) + return error; + if (oitp->it_value.tv_usec) + oitp->it_value.tv_sec++; + td->td_retval[0] = oitp->it_value.tv_sec; + return 0; + +} + +int +svr4_sys_gettimeofday(td, uap) + struct thread *td; + struct svr4_sys_gettimeofday_args *uap; +{ + if (SCARG(uap, tp)) { + struct timeval atv; + + microtime(&atv); + return copyout(&atv, SCARG(uap, tp), sizeof (atv)); + } + + return 0; +} + +int +svr4_sys_facl(td, uap) + struct thread *td; + struct svr4_sys_facl_args *uap; +{ + int *retval; + + retval = td->td_retval; + *retval = 0; + + switch (SCARG(uap, cmd)) { + case SVR4_SYS_SETACL: + /* We don't support acls on any filesystem */ + return ENOSYS; + + case SVR4_SYS_GETACL: + return copyout(retval, &SCARG(uap, num), + sizeof(SCARG(uap, num))); + + case SVR4_SYS_GETACLCNT: + return 0; + + default: + return EINVAL; + } +} + + +int +svr4_sys_acl(td, uap) + struct thread *td; + struct svr4_sys_acl_args *uap; +{ + /* XXX: for now the same */ + return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap); +} + +int +svr4_sys_auditsys(td, uap) + struct thread *td; + struct svr4_sys_auditsys_args *uap; +{ + /* + * XXX: Big brother is *not* watching. + */ + return 0; +} + +int +svr4_sys_memcntl(td, uap) + struct thread *td; + struct svr4_sys_memcntl_args *uap; +{ + switch (SCARG(uap, cmd)) { + case SVR4_MC_SYNC: + { + struct msync_args msa; + + SCARG(&msa, addr) = SCARG(uap, addr); + SCARG(&msa, len) = SCARG(uap, len); + SCARG(&msa, flags) = (int)SCARG(uap, arg); + + return msync(td, &msa); + } + case SVR4_MC_ADVISE: + { + struct madvise_args maa; + + SCARG(&maa, addr) = SCARG(uap, addr); + SCARG(&maa, len) = SCARG(uap, len); + SCARG(&maa, behav) = (int)SCARG(uap, arg); + + return madvise(td, &maa); + } + case SVR4_MC_LOCK: + case SVR4_MC_UNLOCK: + case SVR4_MC_LOCKAS: + case SVR4_MC_UNLOCKAS: + return EOPNOTSUPP; + default: + return ENOSYS; + } +} + + +int +svr4_sys_nice(td, uap) + struct thread *td; + struct svr4_sys_nice_args *uap; +{ + struct setpriority_args ap; + int error; + + SCARG(&ap, which) = PRIO_PROCESS; + SCARG(&ap, who) = 0; + SCARG(&ap, prio) = SCARG(uap, prio); + + if ((error = setpriority(td, &ap)) != 0) + return error; + + /* the cast is stupid, but the structures are the same */ + if ((error = getpriority(td, (struct getpriority_args *)&ap)) != 0) + return error; + + return 0; +} + +int +svr4_sys_resolvepath(td, uap) + struct thread *td; + struct svr4_sys_resolvepath_args *uap; +{ + struct nameidata nd; + int error, *retval = td->td_retval; + + NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE, + SCARG(uap, path), td); + + if ((error = namei(&nd)) != 0) + return error; + + if ((error = copyout(nd.ni_cnd.cn_pnbuf, SCARG(uap, buf), + SCARG(uap, bufsiz))) != 0) + goto bad; + + *retval = strlen(nd.ni_cnd.cn_pnbuf) < SCARG(uap, bufsiz) ? + strlen(nd.ni_cnd.cn_pnbuf) + 1 : SCARG(uap, bufsiz); +bad: + NDFREE(&nd, NDF_ONLY_PNBUF); + vput(nd.ni_vp); + return error; +} diff --git a/sys/compat/svr4/svr4_mman.h b/sys/compat/svr4/svr4_mman.h new file mode 100644 index 0000000..db7c3da --- /dev/null +++ b/sys/compat/svr4/svr4_mman.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1997 Todd Vierling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_MMAN_H_ +#define _SVR4_MMAN_H_ + +/* + * Commands and flags passed to memcntl(). + * Most of them are the same as <sys/mman.h>, but we need the MC_ + * memcntl command definitions. + */ + +#define SVR4_MC_SYNC 1 +#define SVR4_MC_LOCK 2 +#define SVR4_MC_UNLOCK 3 +#define SVR4_MC_ADVISE 4 +#define SVR4_MC_LOCKAS 5 +#define SVR4_MC_UNLOCKAS 6 + +#endif /* !_SVR4_MMAN_H */ diff --git a/sys/compat/svr4/svr4_proto.h b/sys/compat/svr4/svr4_proto.h new file mode 100644 index 0000000..15f66de --- /dev/null +++ b/sys/compat/svr4/svr4_proto.h @@ -0,0 +1,477 @@ +/* + * System call prototypes. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp + */ + +#ifndef _SVR4_SYSPROTO_H_ +#define _SVR4_SYSPROTO_H_ + +#include <sys/signal.h> + +#include <sys/acl.h> + +struct proc; + +struct thread; + +#define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ + 0 : sizeof(register_t) - sizeof(t)) + +struct svr4_sys_open_args { + char * path; char path_[PAD_(char *)]; + int flags; char flags_[PAD_(int)]; + int mode; char mode_[PAD_(int)]; +}; +struct svr4_sys_wait_args { + int * status; char status_[PAD_(int *)]; +}; +struct svr4_sys_creat_args { + char * path; char path_[PAD_(char *)]; + int mode; char mode_[PAD_(int)]; +}; +struct svr4_sys_execv_args { + char * path; char path_[PAD_(char *)]; + char ** argp; char argp_[PAD_(char **)]; +}; +struct svr4_sys_time_args { + time_t * t; char t_[PAD_(time_t *)]; +}; +struct svr4_sys_mknod_args { + char * path; char path_[PAD_(char *)]; + int mode; char mode_[PAD_(int)]; + int dev; char dev_[PAD_(int)]; +}; +struct svr4_sys_break_args { + caddr_t nsize; char nsize_[PAD_(caddr_t)]; +}; +struct svr4_sys_stat_args { + char * path; char path_[PAD_(char *)]; + struct svr4_stat * ub; char ub_[PAD_(struct svr4_stat *)]; +}; +struct svr4_sys_alarm_args { + unsigned sec; char sec_[PAD_(unsigned)]; +}; +struct svr4_sys_fstat_args { + int fd; char fd_[PAD_(int)]; + struct svr4_stat * sb; char sb_[PAD_(struct svr4_stat *)]; +}; +struct svr4_sys_pause_args { + register_t dummy; +}; +struct svr4_sys_utime_args { + char * path; char path_[PAD_(char *)]; + struct svr4_utimbuf * ubuf; char ubuf_[PAD_(struct svr4_utimbuf *)]; +}; +struct svr4_sys_access_args { + char * path; char path_[PAD_(char *)]; + int flags; char flags_[PAD_(int)]; +}; +struct svr4_sys_nice_args { + int prio; char prio_[PAD_(int)]; +}; +struct svr4_sys_kill_args { + int pid; char pid_[PAD_(int)]; + int signum; char signum_[PAD_(int)]; +}; +struct svr4_sys_pgrpsys_args { + int cmd; char cmd_[PAD_(int)]; + int pid; char pid_[PAD_(int)]; + int pgid; char pgid_[PAD_(int)]; +}; +struct svr4_sys_times_args { + struct tms * tp; char tp_[PAD_(struct tms *)]; +}; +struct svr4_sys_signal_args { + int signum; char signum_[PAD_(int)]; + svr4_sig_t handler; char handler_[PAD_(svr4_sig_t)]; +}; +#if defined(NOTYET) +struct svr4_sys_msgsys_args { + int what; char what_[PAD_(int)]; + int a2; char a2_[PAD_(int)]; + int a3; char a3_[PAD_(int)]; + int a4; char a4_[PAD_(int)]; + int a5; char a5_[PAD_(int)]; +}; +#else +#endif +struct svr4_sys_sysarch_args { + int op; char op_[PAD_(int)]; + void * a1; char a1_[PAD_(void *)]; +}; +struct svr4_sys_ioctl_args { + int fd; char fd_[PAD_(int)]; + u_long com; char com_[PAD_(u_long)]; + caddr_t data; char data_[PAD_(caddr_t)]; +}; +struct svr4_sys_utssys_args { + void * a1; char a1_[PAD_(void *)]; + void * a2; char a2_[PAD_(void *)]; + int sel; char sel_[PAD_(int)]; + void * a3; char a3_[PAD_(void *)]; +}; +struct svr4_sys_execve_args { + char * path; char path_[PAD_(char *)]; + char ** argp; char argp_[PAD_(char **)]; + char ** envp; char envp_[PAD_(char **)]; +}; +struct svr4_sys_fcntl_args { + int fd; char fd_[PAD_(int)]; + int cmd; char cmd_[PAD_(int)]; + char * arg; char arg_[PAD_(char *)]; +}; +struct svr4_sys_ulimit_args { + int cmd; char cmd_[PAD_(int)]; + long newlimit; char newlimit_[PAD_(long)]; +}; +struct svr4_sys_getdents_args { + int fd; char fd_[PAD_(int)]; + char * buf; char buf_[PAD_(char *)]; + int nbytes; char nbytes_[PAD_(int)]; +}; +struct svr4_sys_getmsg_args { + int fd; char fd_[PAD_(int)]; + struct svr4_strbuf * ctl; char ctl_[PAD_(struct svr4_strbuf *)]; + struct svr4_strbuf * dat; char dat_[PAD_(struct svr4_strbuf *)]; + int * flags; char flags_[PAD_(int *)]; +}; +struct svr4_sys_putmsg_args { + int fd; char fd_[PAD_(int)]; + struct svr4_strbuf * ctl; char ctl_[PAD_(struct svr4_strbuf *)]; + struct svr4_strbuf * dat; char dat_[PAD_(struct svr4_strbuf *)]; + int flags; char flags_[PAD_(int)]; +}; +struct svr4_sys_poll_args { + struct pollfd * fds; char fds_[PAD_(struct pollfd *)]; + unsigned int nfds; char nfds_[PAD_(unsigned int)]; + int timeout; char timeout_[PAD_(int)]; +}; +struct svr4_sys_lstat_args { + char * path; char path_[PAD_(char *)]; + struct svr4_stat * ub; char ub_[PAD_(struct svr4_stat *)]; +}; +struct svr4_sys_sigprocmask_args { + int how; char how_[PAD_(int)]; + svr4_sigset_t * set; char set_[PAD_(svr4_sigset_t *)]; + svr4_sigset_t * oset; char oset_[PAD_(svr4_sigset_t *)]; +}; +struct svr4_sys_sigsuspend_args { + svr4_sigset_t * ss; char ss_[PAD_(svr4_sigset_t *)]; +}; +struct svr4_sys_sigaltstack_args { + struct svr4_sigaltstack * nss; char nss_[PAD_(struct svr4_sigaltstack *)]; + struct svr4_sigaltstack * oss; char oss_[PAD_(struct svr4_sigaltstack *)]; +}; +struct svr4_sys_sigaction_args { + int signum; char signum_[PAD_(int)]; + struct svr4_sigaction * nsa; char nsa_[PAD_(struct svr4_sigaction *)]; + struct svr4_sigaction * osa; char osa_[PAD_(struct svr4_sigaction *)]; +}; +struct svr4_sys_sigpending_args { + int what; char what_[PAD_(int)]; + svr4_sigset_t * mask; char mask_[PAD_(svr4_sigset_t *)]; +}; +struct svr4_sys_context_args { + int func; char func_[PAD_(int)]; + struct svr4_ucontext * uc; char uc_[PAD_(struct svr4_ucontext *)]; +}; +struct svr4_sys_statvfs_args { + char * path; char path_[PAD_(char *)]; + struct svr4_statvfs * fs; char fs_[PAD_(struct svr4_statvfs *)]; +}; +struct svr4_sys_fstatvfs_args { + int fd; char fd_[PAD_(int)]; + struct svr4_statvfs * fs; char fs_[PAD_(struct svr4_statvfs *)]; +}; +struct svr4_sys_waitsys_args { + int grp; char grp_[PAD_(int)]; + int id; char id_[PAD_(int)]; + union svr4_siginfo * info; char info_[PAD_(union svr4_siginfo *)]; + int options; char options_[PAD_(int)]; +}; +struct svr4_sys_hrtsys_args { + int cmd; char cmd_[PAD_(int)]; + int fun; char fun_[PAD_(int)]; + int sub; char sub_[PAD_(int)]; + void * rv1; char rv1_[PAD_(void *)]; + void * rv2; char rv2_[PAD_(void *)]; +}; +struct svr4_sys_pathconf_args { + char * path; char path_[PAD_(char *)]; + int name; char name_[PAD_(int)]; +}; +struct svr4_sys_mmap_args { + caddr_t addr; char addr_[PAD_(caddr_t)]; + svr4_size_t len; char len_[PAD_(svr4_size_t)]; + int prot; char prot_[PAD_(int)]; + int flags; char flags_[PAD_(int)]; + int fd; char fd_[PAD_(int)]; + svr4_off_t pos; char pos_[PAD_(svr4_off_t)]; +}; +struct svr4_sys_fpathconf_args { + int fd; char fd_[PAD_(int)]; + int name; char name_[PAD_(int)]; +}; +struct svr4_sys_xstat_args { + int two; char two_[PAD_(int)]; + char * path; char path_[PAD_(char *)]; + struct svr4_xstat * ub; char ub_[PAD_(struct svr4_xstat *)]; +}; +struct svr4_sys_lxstat_args { + int two; char two_[PAD_(int)]; + char * path; char path_[PAD_(char *)]; + struct svr4_xstat * ub; char ub_[PAD_(struct svr4_xstat *)]; +}; +struct svr4_sys_fxstat_args { + int two; char two_[PAD_(int)]; + int fd; char fd_[PAD_(int)]; + struct svr4_xstat * sb; char sb_[PAD_(struct svr4_xstat *)]; +}; +struct svr4_sys_xmknod_args { + int two; char two_[PAD_(int)]; + char * path; char path_[PAD_(char *)]; + svr4_mode_t mode; char mode_[PAD_(svr4_mode_t)]; + svr4_dev_t dev; char dev_[PAD_(svr4_dev_t)]; +}; +struct svr4_sys_setrlimit_args { + int which; char which_[PAD_(int)]; + const struct svr4_rlimit * rlp; char rlp_[PAD_(const struct svr4_rlimit *)]; +}; +struct svr4_sys_getrlimit_args { + int which; char which_[PAD_(int)]; + struct svr4_rlimit * rlp; char rlp_[PAD_(struct svr4_rlimit *)]; +}; +struct svr4_sys_memcntl_args { + void * addr; char addr_[PAD_(void *)]; + svr4_size_t len; char len_[PAD_(svr4_size_t)]; + int cmd; char cmd_[PAD_(int)]; + void * arg; char arg_[PAD_(void *)]; + int attr; char attr_[PAD_(int)]; + int mask; char mask_[PAD_(int)]; +}; +struct svr4_sys_uname_args { + struct svr4_utsname * name; char name_[PAD_(struct svr4_utsname *)]; + int dummy; char dummy_[PAD_(int)]; +}; +struct svr4_sys_sysconfig_args { + int name; char name_[PAD_(int)]; +}; +struct svr4_sys_systeminfo_args { + int what; char what_[PAD_(int)]; + char * buf; char buf_[PAD_(char *)]; + long len; char len_[PAD_(long)]; +}; +struct svr4_sys_fchroot_args { + int fd; char fd_[PAD_(int)]; +}; +struct svr4_sys_utimes_args { + char * path; char path_[PAD_(char *)]; + struct timeval * tptr; char tptr_[PAD_(struct timeval *)]; +}; +struct svr4_sys_vhangup_args { + register_t dummy; +}; +struct svr4_sys_gettimeofday_args { + struct timeval * tp; char tp_[PAD_(struct timeval *)]; +}; +struct svr4_sys_llseek_args { + int fd; char fd_[PAD_(int)]; + long offset1; char offset1_[PAD_(long)]; + long offset2; char offset2_[PAD_(long)]; + int whence; char whence_[PAD_(int)]; +}; +struct svr4_sys_acl_args { + char * path; char path_[PAD_(char *)]; + int cmd; char cmd_[PAD_(int)]; + int num; char num_[PAD_(int)]; + struct svr4_aclent * buf; char buf_[PAD_(struct svr4_aclent *)]; +}; +struct svr4_sys_auditsys_args { + int code; char code_[PAD_(int)]; + int a1; char a1_[PAD_(int)]; + int a2; char a2_[PAD_(int)]; + int a3; char a3_[PAD_(int)]; + int a4; char a4_[PAD_(int)]; + int a5; char a5_[PAD_(int)]; +}; +struct svr4_sys_facl_args { + int fd; char fd_[PAD_(int)]; + int cmd; char cmd_[PAD_(int)]; + int num; char num_[PAD_(int)]; + struct svr4_aclent * buf; char buf_[PAD_(struct svr4_aclent *)]; +}; +struct svr4_sys_resolvepath_args { + const char * path; char path_[PAD_(const char *)]; + char * buf; char buf_[PAD_(char *)]; + size_t bufsiz; char bufsiz_[PAD_(size_t)]; +}; +struct svr4_sys_getdents64_args { + int fd; char fd_[PAD_(int)]; + struct svr4_dirent64 * dp; char dp_[PAD_(struct svr4_dirent64 *)]; + int nbytes; char nbytes_[PAD_(int)]; +}; +struct svr4_sys_mmap64_args { + void * addr; char addr_[PAD_(void *)]; + svr4_size_t len; char len_[PAD_(svr4_size_t)]; + int prot; char prot_[PAD_(int)]; + int flags; char flags_[PAD_(int)]; + int fd; char fd_[PAD_(int)]; + svr4_off64_t pos; char pos_[PAD_(svr4_off64_t)]; +}; +struct svr4_sys_stat64_args { + char * path; char path_[PAD_(char *)]; + struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)]; +}; +struct svr4_sys_lstat64_args { + char * path; char path_[PAD_(char *)]; + struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)]; +}; +struct svr4_sys_fstat64_args { + int fd; char fd_[PAD_(int)]; + struct svr4_stat64 * sb; char sb_[PAD_(struct svr4_stat64 *)]; +}; +struct svr4_sys_statvfs64_args { + char * path; char path_[PAD_(char *)]; + struct svr4_statvfs64 * fs; char fs_[PAD_(struct svr4_statvfs64 *)]; +}; +struct svr4_sys_fstatvfs64_args { + int fd; char fd_[PAD_(int)]; + struct svr4_statvfs64 * fs; char fs_[PAD_(struct svr4_statvfs64 *)]; +}; +struct svr4_sys_setrlimit64_args { + int which; char which_[PAD_(int)]; + const struct svr4_rlimit64 * rlp; char rlp_[PAD_(const struct svr4_rlimit64 *)]; +}; +struct svr4_sys_getrlimit64_args { + int which; char which_[PAD_(int)]; + struct svr4_rlimit64 * rlp; char rlp_[PAD_(struct svr4_rlimit64 *)]; +}; +struct svr4_sys_creat64_args { + char * path; char path_[PAD_(char *)]; + int mode; char mode_[PAD_(int)]; +}; +struct svr4_sys_open64_args { + char * path; char path_[PAD_(char *)]; + int flags; char flags_[PAD_(int)]; + int mode; char mode_[PAD_(int)]; +}; +struct svr4_sys_socket_args { + int domain; char domain_[PAD_(int)]; + int type; char type_[PAD_(int)]; + int protocol; char protocol_[PAD_(int)]; +}; +struct svr4_sys_recv_args { + int s; char s_[PAD_(int)]; + caddr_t buf; char buf_[PAD_(caddr_t)]; + int len; char len_[PAD_(int)]; + int flags; char flags_[PAD_(int)]; +}; +struct svr4_sys_send_args { + int s; char s_[PAD_(int)]; + caddr_t buf; char buf_[PAD_(caddr_t)]; + int len; char len_[PAD_(int)]; + int flags; char flags_[PAD_(int)]; +}; +struct svr4_sys_sendto_args { + int s; char s_[PAD_(int)]; + void * buf; char buf_[PAD_(void *)]; + size_t len; char len_[PAD_(size_t)]; + int flags; char flags_[PAD_(int)]; + struct sockaddr * to; char to_[PAD_(struct sockaddr *)]; + int tolen; char tolen_[PAD_(int)]; +}; +int svr4_sys_open(struct thread *, struct svr4_sys_open_args *); +int svr4_sys_wait(struct thread *, struct svr4_sys_wait_args *); +int svr4_sys_creat(struct thread *, struct svr4_sys_creat_args *); +int svr4_sys_execv(struct thread *, struct svr4_sys_execv_args *); +int svr4_sys_time(struct thread *, struct svr4_sys_time_args *); +int svr4_sys_mknod(struct thread *, struct svr4_sys_mknod_args *); +int svr4_sys_break(struct thread *, struct svr4_sys_break_args *); +int svr4_sys_stat(struct thread *, struct svr4_sys_stat_args *); +int svr4_sys_alarm(struct thread *, struct svr4_sys_alarm_args *); +int svr4_sys_fstat(struct thread *, struct svr4_sys_fstat_args *); +int svr4_sys_pause(struct thread *, struct svr4_sys_pause_args *); +int svr4_sys_utime(struct thread *, struct svr4_sys_utime_args *); +int svr4_sys_access(struct thread *, struct svr4_sys_access_args *); +int svr4_sys_nice(struct thread *, struct svr4_sys_nice_args *); +int svr4_sys_kill(struct thread *, struct svr4_sys_kill_args *); +int svr4_sys_pgrpsys(struct thread *, struct svr4_sys_pgrpsys_args *); +int svr4_sys_times(struct thread *, struct svr4_sys_times_args *); +int svr4_sys_signal(struct thread *, struct svr4_sys_signal_args *); +#if defined(NOTYET) +int svr4_sys_msgsys(struct thread *, struct svr4_sys_msgsys_args *); +#else +#endif +int svr4_sys_sysarch(struct thread *, struct svr4_sys_sysarch_args *); +int svr4_sys_ioctl(struct thread *, struct svr4_sys_ioctl_args *); +int svr4_sys_utssys(struct thread *, struct svr4_sys_utssys_args *); +int svr4_sys_execve(struct thread *, struct svr4_sys_execve_args *); +int svr4_sys_fcntl(struct thread *, struct svr4_sys_fcntl_args *); +int svr4_sys_ulimit(struct thread *, struct svr4_sys_ulimit_args *); +int svr4_sys_getdents(struct thread *, struct svr4_sys_getdents_args *); +int svr4_sys_getmsg(struct thread *, struct svr4_sys_getmsg_args *); +int svr4_sys_putmsg(struct thread *, struct svr4_sys_putmsg_args *); +int svr4_sys_poll(struct thread *, struct svr4_sys_poll_args *); +int svr4_sys_lstat(struct thread *, struct svr4_sys_lstat_args *); +int svr4_sys_sigprocmask(struct thread *, struct svr4_sys_sigprocmask_args *); +int svr4_sys_sigsuspend(struct thread *, struct svr4_sys_sigsuspend_args *); +int svr4_sys_sigaltstack(struct thread *, struct svr4_sys_sigaltstack_args *); +int svr4_sys_sigaction(struct thread *, struct svr4_sys_sigaction_args *); +int svr4_sys_sigpending(struct thread *, struct svr4_sys_sigpending_args *); +int svr4_sys_context(struct thread *, struct svr4_sys_context_args *); +int svr4_sys_statvfs(struct thread *, struct svr4_sys_statvfs_args *); +int svr4_sys_fstatvfs(struct thread *, struct svr4_sys_fstatvfs_args *); +int svr4_sys_waitsys(struct thread *, struct svr4_sys_waitsys_args *); +int svr4_sys_hrtsys(struct thread *, struct svr4_sys_hrtsys_args *); +int svr4_sys_pathconf(struct thread *, struct svr4_sys_pathconf_args *); +int svr4_sys_mmap(struct thread *, struct svr4_sys_mmap_args *); +int svr4_sys_fpathconf(struct thread *, struct svr4_sys_fpathconf_args *); +int svr4_sys_xstat(struct thread *, struct svr4_sys_xstat_args *); +int svr4_sys_lxstat(struct thread *, struct svr4_sys_lxstat_args *); +int svr4_sys_fxstat(struct thread *, struct svr4_sys_fxstat_args *); +int svr4_sys_xmknod(struct thread *, struct svr4_sys_xmknod_args *); +int svr4_sys_setrlimit(struct thread *, struct svr4_sys_setrlimit_args *); +int svr4_sys_getrlimit(struct thread *, struct svr4_sys_getrlimit_args *); +int svr4_sys_memcntl(struct thread *, struct svr4_sys_memcntl_args *); +int svr4_sys_uname(struct thread *, struct svr4_sys_uname_args *); +int svr4_sys_sysconfig(struct thread *, struct svr4_sys_sysconfig_args *); +int svr4_sys_systeminfo(struct thread *, struct svr4_sys_systeminfo_args *); +int svr4_sys_fchroot(struct thread *, struct svr4_sys_fchroot_args *); +int svr4_sys_utimes(struct thread *, struct svr4_sys_utimes_args *); +int svr4_sys_vhangup(struct thread *, struct svr4_sys_vhangup_args *); +int svr4_sys_gettimeofday(struct thread *, struct svr4_sys_gettimeofday_args *); +int svr4_sys_llseek(struct thread *, struct svr4_sys_llseek_args *); +int svr4_sys_acl(struct thread *, struct svr4_sys_acl_args *); +int svr4_sys_auditsys(struct thread *, struct svr4_sys_auditsys_args *); +int svr4_sys_facl(struct thread *, struct svr4_sys_facl_args *); +int svr4_sys_resolvepath(struct thread *, struct svr4_sys_resolvepath_args *); +int svr4_sys_getdents64(struct thread *, struct svr4_sys_getdents64_args *); +int svr4_sys_mmap64(struct thread *, struct svr4_sys_mmap64_args *); +int svr4_sys_stat64(struct thread *, struct svr4_sys_stat64_args *); +int svr4_sys_lstat64(struct thread *, struct svr4_sys_lstat64_args *); +int svr4_sys_fstat64(struct thread *, struct svr4_sys_fstat64_args *); +int svr4_sys_statvfs64(struct thread *, struct svr4_sys_statvfs64_args *); +int svr4_sys_fstatvfs64(struct thread *, struct svr4_sys_fstatvfs64_args *); +int svr4_sys_setrlimit64(struct thread *, struct svr4_sys_setrlimit64_args *); +int svr4_sys_getrlimit64(struct thread *, struct svr4_sys_getrlimit64_args *); +int svr4_sys_creat64(struct thread *, struct svr4_sys_creat64_args *); +int svr4_sys_open64(struct thread *, struct svr4_sys_open64_args *); +int svr4_sys_socket(struct thread *, struct svr4_sys_socket_args *); +int svr4_sys_recv(struct thread *, struct svr4_sys_recv_args *); +int svr4_sys_send(struct thread *, struct svr4_sys_send_args *); +int svr4_sys_sendto(struct thread *, struct svr4_sys_sendto_args *); + +#ifdef COMPAT_43 + +#if defined(NOTYET) +#else +#endif + +#endif /* COMPAT_43 */ + +#undef PAD_ + +#endif /* !_SVR4_SYSPROTO_H_ */ diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c new file mode 100644 index 0000000..289e6fa --- /dev/null +++ b/sys/compat/svr4/svr4_resource.c @@ -0,0 +1,324 @@ +/* Derived from: + * $NetBSD: svr4_resource.c,v 1.3 1998/12/13 18:00:52 christos Exp $ + */ + +/*- + * Original copyright: + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Portions of this software have been derived from software contributed + * to the FreeBSD Project by Mark Newton. + * + * Copyright (c) 1999 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/resource.h> +#include <sys/resourcevar.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_resource.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> + +static __inline int svr4_to_native_rl(int); + +static __inline int +svr4_to_native_rl(rl) + int rl; +{ + switch (rl) { + case SVR4_RLIMIT_CPU: + return RLIMIT_CPU; + case SVR4_RLIMIT_FSIZE: + return RLIMIT_FSIZE; + case SVR4_RLIMIT_DATA: + return RLIMIT_DATA; + case SVR4_RLIMIT_STACK: + return RLIMIT_STACK; + case SVR4_RLIMIT_CORE: + return RLIMIT_CORE; + case SVR4_RLIMIT_NOFILE: + return RLIMIT_NOFILE; + case SVR4_RLIMIT_VMEM: + return RLIMIT_RSS; + default: + return -1; + } +} + +/* + * Check if the resource limit fits within the BSD range and it is not + * one of the magic SVR4 limit values + */ +#define OKLIMIT(l) (((int32_t)(l)) >= 0 && ((int32_t)(l)) < 0x7fffffff && \ + ((svr4_rlim_t)(l)) != SVR4_RLIM_INFINITY && \ + ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_CUR && \ + ((svr4_rlim_t)(l)) != SVR4_RLIM_SAVED_MAX) + +#define OKLIMIT64(l) (((rlim_t)(l)) >= 0 && ((rlim_t)(l)) < RLIM_INFINITY && \ + ((svr4_rlim64_t)(l)) != SVR4_RLIM64_INFINITY && \ + ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_CUR && \ + ((svr4_rlim64_t)(l)) != SVR4_RLIM64_SAVED_MAX) + +int +svr4_sys_getrlimit(td, uap) + register struct thread *td; + struct svr4_sys_getrlimit_args *uap; +{ + int rl = svr4_to_native_rl(SCARG(uap, which)); + struct rlimit blim; + struct svr4_rlimit slim; + + if (rl == -1) + return EINVAL; + + /* For p_rlimit. */ + mtx_assert(&Giant, MA_OWNED); + blim = td->td_proc->p_rlimit[rl]; + + /* + * Our infinity, is their maxfiles. + */ + if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY) + blim.rlim_max = maxfiles; + + /* + * If the limit can be be represented, it is returned. + * Otherwise, if rlim_cur == rlim_max, return RLIM_SAVED_MAX + * else return RLIM_SAVED_CUR + */ + if (blim.rlim_max == RLIM_INFINITY) + slim.rlim_max = SVR4_RLIM_INFINITY; + else if (OKLIMIT(blim.rlim_max)) + slim.rlim_max = (svr4_rlim_t) blim.rlim_max; + else + slim.rlim_max = SVR4_RLIM_SAVED_MAX; + + if (blim.rlim_cur == RLIM_INFINITY) + slim.rlim_cur = SVR4_RLIM_INFINITY; + else if (OKLIMIT(blim.rlim_cur)) + slim.rlim_cur = (svr4_rlim_t) blim.rlim_cur; + else if (blim.rlim_max == blim.rlim_cur) + slim.rlim_cur = SVR4_RLIM_SAVED_MAX; + else + slim.rlim_cur = SVR4_RLIM_SAVED_CUR; + + return copyout(&slim, SCARG(uap, rlp), sizeof(*SCARG(uap, rlp))); +} + + +int +svr4_sys_setrlimit(td, uap) + register struct thread *td; + struct svr4_sys_setrlimit_args *uap; +{ + int rl = svr4_to_native_rl(SCARG(uap, which)); + struct rlimit blim, *limp; + struct svr4_rlimit slim; + int error; + + if (rl == -1) + return EINVAL; + + /* For p_rlimit. */ + mtx_assert(&Giant, MA_OWNED); + limp = &td->td_proc->p_rlimit[rl]; + + if ((error = copyin(SCARG(uap, rlp), &slim, sizeof(slim))) != 0) + return error; + + /* + * if the limit is SVR4_RLIM_INFINITY, then we set it to our + * unlimited. + * We should also: If it is SVR4_RLIM_SAVED_MAX, we should set the + * new limit to the corresponding saved hard limit, and if + * it is equal to SVR4_RLIM_SAVED_CUR, we should set it to the + * corresponding saved soft limit. + * + */ + if (slim.rlim_max == SVR4_RLIM_INFINITY) + blim.rlim_max = RLIM_INFINITY; + else if (OKLIMIT(slim.rlim_max)) + blim.rlim_max = (rlim_t) slim.rlim_max; + else if (slim.rlim_max == SVR4_RLIM_SAVED_MAX) + blim.rlim_max = limp->rlim_max; + else if (slim.rlim_max == SVR4_RLIM_SAVED_CUR) + blim.rlim_max = limp->rlim_cur; + + if (slim.rlim_cur == SVR4_RLIM_INFINITY) + blim.rlim_cur = RLIM_INFINITY; + else if (OKLIMIT(slim.rlim_cur)) + blim.rlim_cur = (rlim_t) slim.rlim_cur; + else if (slim.rlim_cur == SVR4_RLIM_SAVED_MAX) + blim.rlim_cur = limp->rlim_max; + else if (slim.rlim_cur == SVR4_RLIM_SAVED_CUR) + blim.rlim_cur = limp->rlim_cur; + + return dosetrlimit(td, rl, &blim); +} + + +int +svr4_sys_getrlimit64(td, uap) + register struct thread *td; + struct svr4_sys_getrlimit64_args *uap; +{ + int rl = svr4_to_native_rl(SCARG(uap, which)); + struct rlimit blim; + struct svr4_rlimit64 slim; + + if (rl == -1) + return EINVAL; + + /* For p_rlimit. */ + mtx_assert(&Giant, MA_OWNED); + blim = td->td_proc->p_rlimit[rl]; + + /* + * Our infinity, is their maxfiles. + */ + if (rl == RLIMIT_NOFILE && blim.rlim_max == RLIM_INFINITY) + blim.rlim_max = maxfiles; + + /* + * If the limit can be be represented, it is returned. + * Otherwise, if rlim_cur == rlim_max, return SVR4_RLIM_SAVED_MAX + * else return SVR4_RLIM_SAVED_CUR + */ + if (blim.rlim_max == RLIM_INFINITY) + slim.rlim_max = SVR4_RLIM64_INFINITY; + else if (OKLIMIT64(blim.rlim_max)) + slim.rlim_max = (svr4_rlim64_t) blim.rlim_max; + else + slim.rlim_max = SVR4_RLIM64_SAVED_MAX; + + if (blim.rlim_cur == RLIM_INFINITY) + slim.rlim_cur = SVR4_RLIM64_INFINITY; + else if (OKLIMIT64(blim.rlim_cur)) + slim.rlim_cur = (svr4_rlim64_t) blim.rlim_cur; + else if (blim.rlim_max == blim.rlim_cur) + slim.rlim_cur = SVR4_RLIM64_SAVED_MAX; + else + slim.rlim_cur = SVR4_RLIM64_SAVED_CUR; + + return copyout(&slim, SCARG(uap, rlp), sizeof(*SCARG(uap, rlp))); +} + + +int +svr4_sys_setrlimit64(td, uap) + register struct thread *td; + struct svr4_sys_setrlimit64_args *uap; +{ + int rl = svr4_to_native_rl(SCARG(uap, which)); + struct rlimit blim, *limp; + struct svr4_rlimit64 slim; + int error; + + if (rl == -1) + return EINVAL; + + /* For p_rlimit. */ + mtx_assert(&Giant, MA_OWNED); + limp = &td->td_proc->p_rlimit[rl]; + + if ((error = copyin(SCARG(uap, rlp), &slim, sizeof(slim))) != 0) + return error; + + /* + * if the limit is SVR4_RLIM64_INFINITY, then we set it to our + * unlimited. + * We should also: If it is SVR4_RLIM64_SAVED_MAX, we should set the + * new limit to the corresponding saved hard limit, and if + * it is equal to SVR4_RLIM64_SAVED_CUR, we should set it to the + * corresponding saved soft limit. + * + */ + if (slim.rlim_max == SVR4_RLIM64_INFINITY) + blim.rlim_max = RLIM_INFINITY; + else if (OKLIMIT64(slim.rlim_max)) + blim.rlim_max = (rlim_t) slim.rlim_max; + else if (slim.rlim_max == SVR4_RLIM64_SAVED_MAX) + blim.rlim_max = limp->rlim_max; + else if (slim.rlim_max == SVR4_RLIM64_SAVED_CUR) + blim.rlim_max = limp->rlim_cur; + + if (slim.rlim_cur == SVR4_RLIM64_INFINITY) + blim.rlim_cur = RLIM_INFINITY; + else if (OKLIMIT64(slim.rlim_cur)) + blim.rlim_cur = (rlim_t) slim.rlim_cur; + else if (slim.rlim_cur == SVR4_RLIM64_SAVED_MAX) + blim.rlim_cur = limp->rlim_max; + else if (slim.rlim_cur == SVR4_RLIM64_SAVED_CUR) + blim.rlim_cur = limp->rlim_cur; + + return dosetrlimit(td, rl, &blim); +} diff --git a/sys/compat/svr4/svr4_resource.h b/sys/compat/svr4/svr4_resource.h new file mode 100644 index 0000000..3512df3 --- /dev/null +++ b/sys/compat/svr4/svr4_resource.h @@ -0,0 +1,109 @@ +/* Derived from: + * $NetBSD: svr4_resource.h,v 1.1 1998/11/28 21:53:02 christos Exp $ */ + +/*- + * Original copyright: + * + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Portions of this code derived from software contributed to the + * FreeBSD Project by Mark Newton. + * + * Copyright (c) 1999 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SVR4_RESOURCE_H_ +#define _SVR4_RESOURCE_H_ + +#define SVR4_RLIMIT_CPU 0 +#define SVR4_RLIMIT_FSIZE 1 +#define SVR4_RLIMIT_DATA 2 +#define SVR4_RLIMIT_STACK 3 +#define SVR4_RLIMIT_CORE 4 +#define SVR4_RLIMIT_NOFILE 5 +#define SVR4_RLIMIT_VMEM 6 +#define SVR4_RLIMIT_AS SVR4_RLIMIT_VMEM +#define SVR4_RLIM_NLIMITS 7 + +typedef u_int32_t svr4_rlim_t; + +#define SVR4_RLIM_SAVED_CUR 0x7ffffffd +#define SVR4_RLIM_SAVED_MAX 0x7ffffffe +#define SVR4_RLIM_INFINITY 0x7fffffff + +struct svr4_rlimit { + svr4_rlim_t rlim_cur; + svr4_rlim_t rlim_max; +}; + +typedef u_int64_t svr4_rlim64_t; + +#define SVR4_RLIM64_SAVED_CUR ((svr4_rlim64_t) -1) +#define SVR4_RLIM64_SAVED_MAX ((svr4_rlim64_t) -2) +#define SVR4_RLIM64_INFINITY ((svr4_rlim64_t) -3) + +struct svr4_rlimit64 { + svr4_rlim64_t rlim_cur; + svr4_rlim64_t rlim_max; +}; + +#endif /* !_SVR4_RESOURCE_H_ */ diff --git a/sys/compat/svr4/svr4_siginfo.h b/sys/compat/svr4/svr4_siginfo.h new file mode 100644 index 0000000..be89837 --- /dev/null +++ b/sys/compat/svr4/svr4_siginfo.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SIGINFO_H_ +#define _SVR4_SIGINFO_H_ + +#define SVR4_ILL_ILLOPC 1 +#define SVR4_ILL_ILLOPN 2 +#define SVR4_ILL_ILLADR 3 +#define SVR4_ILL_ILLTRP 4 +#define SVR4_ILL_PRVOPC 5 +#define SVR4_ILL_PRVREG 6 +#define SVR4_ILL_COPROC 7 +#define SVR4_ILL_BADSTK 8 + +#define SVR4_FPE_INTDIV 1 +#define SVR4_FPE_INTOVF 2 +#define SVR4_FPE_FLTDIV 3 +#define SVR4_FPE_FLTOVF 4 +#define SVR4_FPE_FLTUND 5 +#define SVR4_FPE_FLTRES 6 +#define SVR4_FPE_FLTINV 7 +#define SVR4_FPE_FLTSUB 8 + +#define SVR4_SEGV_MAPERR 1 +#define SVR4_SEGV_ACCERR 2 + +#define SVR4_BUS_ADRALN 1 +#define SVR4_BUS_ADRERR 2 +#define SVR4_BUS_OBJERR 3 + +#define SVR4_TRAP_BRKPT 1 +#define SVR4_TRAP_TRACE 2 + +#define SVR4_POLL_IN 1 +#define SVR4_POLL_OUT 2 +#define SVR4_POLL_MSG 3 +#define SVR4_POLL_ERR 4 +#define SVR4_POLL_PRI 5 + +#define SVR4_CLD_EXITED 1 +#define SVR4_CLD_KILLED 2 +#define SVR4_CLD_DUMPED 3 +#define SVR4_CLD_TRAPPED 4 +#define SVR4_CLD_STOPPED 5 +#define SVR4_CLD_CONTINUED 6 + +#define SVR4_EMT_TAGOVF 1 + +typedef union svr4_siginfo { + char si_pad[128]; /* Total size; for future expansion */ + struct { + int _signo; + int _code; + int _errno; + union { + struct { + svr4_pid_t _pid; + svr4_clock_t _utime; + int _status; + svr4_clock_t _stime; + } _child; + + struct { + caddr_t _addr; + int _trap; + } _fault; + } _reason; + } _info; +} svr4_siginfo_t; + +#define si_signo _info._signo +#define si_code _info._code +#define si_errno _info._errno + +#define si_pid _info._reason._child._pid +#define si_stime _info._reason._child._stime +#define si_status _info._reason._child._status +#define si_utime _info._reason._child._utime + +#define si_addr _info._reason._fault._addr +#define si_trap _info._reason._fault._trap + +#endif /* !_SVR4_SIGINFO_H_ */ diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c new file mode 100644 index 0000000..fea5317 --- /dev/null +++ b/sys/compat/svr4/svr4_signal.c @@ -0,0 +1,676 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/filedesc.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/signal.h> +#include <sys/signalvar.h> +#include <sys/sysproto.h> + +#include <machine/cpu.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_ucontext.h> + +#define svr4_sigmask(n) (1 << (((n) - 1) & 31)) +#define svr4_sigword(n) (((n) - 1) >> 5) +#define svr4_sigemptyset(s) memset((s), 0, sizeof(*(s))) +#define svr4_sigismember(s, n) ((s)->bits[svr4_sigword(n)] & svr4_sigmask(n)) +#define svr4_sigaddset(s, n) ((s)->bits[svr4_sigword(n)] |= svr4_sigmask(n)) + +void svr4_to_bsd_sigaction(const struct svr4_sigaction *, struct sigaction *); +void bsd_to_svr4_sigaction(const struct sigaction *, struct svr4_sigaction *); +void svr4_sigfillset(svr4_sigset_t *); + +int bsd_to_svr4_sig[SVR4_SIGTBLSZ] = { + SVR4_SIGHUP, + SVR4_SIGINT, + SVR4_SIGQUIT, + SVR4_SIGILL, + SVR4_SIGTRAP, + SVR4_SIGABRT, + SVR4_SIGEMT, + SVR4_SIGFPE, + SVR4_SIGKILL, + SVR4_SIGBUS, + SVR4_SIGSEGV, + SVR4_SIGSYS, + SVR4_SIGPIPE, + SVR4_SIGALRM, + SVR4_SIGTERM, + SVR4_SIGURG, + SVR4_SIGSTOP, + SVR4_SIGTSTP, + SVR4_SIGCONT, + SVR4_SIGCHLD, + SVR4_SIGTTIN, + SVR4_SIGTTOU, + SVR4_SIGIO, + SVR4_SIGXCPU, + SVR4_SIGXFSZ, + SVR4_SIGVTALRM, + SVR4_SIGPROF, + SVR4_SIGWINCH, + 0, /* SIGINFO */ + SVR4_SIGUSR1, + SVR4_SIGUSR2, +}; + +int svr4_to_bsd_sig[SVR4_SIGTBLSZ] = { + SIGHUP, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + SIGABRT, + SIGEMT, + SIGFPE, + SIGKILL, + SIGBUS, + SIGSEGV, + SIGSYS, + SIGPIPE, + SIGALRM, + SIGTERM, + SIGUSR1, + SIGUSR2, + SIGCHLD, + 0, /* XXX NetBSD uses SIGPWR here, but we don't seem to have one */ + SIGWINCH, + SIGURG, + SIGIO, + SIGSTOP, + SIGTSTP, + SIGCONT, + SIGTTIN, + SIGTTOU, + SIGVTALRM, + SIGPROF, + SIGXCPU, + SIGXFSZ, +}; + +void +svr4_sigfillset(s) + svr4_sigset_t *s; +{ + int i; + + svr4_sigemptyset(s); + for (i = 0; i < SVR4_NSIG; i++) + if (svr4_to_bsd_sig[i] != 0) + svr4_sigaddset(s, i); +} + +void +svr4_to_bsd_sigset(sss, bss) + const svr4_sigset_t *sss; + sigset_t *bss; +{ + int i, newsig; + + SIGEMPTYSET(*bss); + for (i = 0; i < SVR4_NSIG; i++) + if (svr4_sigismember(sss, i + 1)) { + newsig = svr4_to_bsd_sig[i]; + if (newsig) + SIGADDSET(*bss, newsig); + } +} + +void +bsd_to_svr4_sigset(bss, sss) + const sigset_t *bss; + svr4_sigset_t *sss; +{ + int i, newsig; + + svr4_sigemptyset(sss); + sss->bits[0] = bss->__bits[0] & ~((1U << SVR4_SIGTBLSZ) - 1); + sss->bits[1] = bss->__bits[1]; + sss->bits[2] = bss->__bits[2]; + sss->bits[3] = bss->__bits[3]; + for (i = 1; i <= SVR4_SIGTBLSZ; i++) { + if (SIGISMEMBER(*bss, i)) { + newsig = bsd_to_svr4_sig[_SIG_IDX(i)]; + if (newsig) + svr4_sigaddset(sss, newsig); + } + } +} + +/* + * XXX: Only a subset of the flags is currently implemented. + */ +void +svr4_to_bsd_sigaction(ssa, bsa) + const struct svr4_sigaction *ssa; + struct sigaction *bsa; +{ + + bsa->sa_handler = (sig_t) ssa->ssa_handler; + svr4_to_bsd_sigset(&ssa->ssa_mask, &bsa->sa_mask); + bsa->sa_flags = 0; + if ((ssa->ssa_flags & SVR4_SA_ONSTACK) != 0) + bsa->sa_flags |= SA_ONSTACK; + if ((ssa->ssa_flags & SVR4_SA_RESETHAND) != 0) + bsa->sa_flags |= SA_RESETHAND; + if ((ssa->ssa_flags & SVR4_SA_RESTART) != 0) + bsa->sa_flags |= SA_RESTART; + if ((ssa->ssa_flags & SVR4_SA_SIGINFO) != 0) + DPRINTF(("svr4_to_bsd_sigaction: SA_SIGINFO ignored\n")); + if ((ssa->ssa_flags & SVR4_SA_NOCLDSTOP) != 0) + bsa->sa_flags |= SA_NOCLDSTOP; + if ((ssa->ssa_flags & SVR4_SA_NODEFER) != 0) + bsa->sa_flags |= SA_NODEFER; + if ((ssa->ssa_flags & SVR4_SA_NOCLDWAIT) != 0) + bsa->sa_flags |= SA_NOCLDWAIT; + if ((ssa->ssa_flags & ~SVR4_SA_ALLBITS) != 0) + DPRINTF(("svr4_to_bsd_sigaction: extra bits ignored\n")); +} + +void +bsd_to_svr4_sigaction(bsa, ssa) + const struct sigaction *bsa; + struct svr4_sigaction *ssa; +{ + + ssa->ssa_handler = (svr4_sig_t) bsa->sa_handler; + bsd_to_svr4_sigset(&bsa->sa_mask, &ssa->ssa_mask); + ssa->ssa_flags = 0; + if ((bsa->sa_flags & SA_ONSTACK) != 0) + ssa->ssa_flags |= SVR4_SA_ONSTACK; + if ((bsa->sa_flags & SA_RESETHAND) != 0) + ssa->ssa_flags |= SVR4_SA_RESETHAND; + if ((bsa->sa_flags & SA_RESTART) != 0) + ssa->ssa_flags |= SVR4_SA_RESTART; + if ((bsa->sa_flags & SA_NODEFER) != 0) + ssa->ssa_flags |= SVR4_SA_NODEFER; + if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) + ssa->ssa_flags |= SVR4_SA_NOCLDSTOP; +} + +void +svr4_to_bsd_sigaltstack(sss, bss) + const struct svr4_sigaltstack *sss; + struct sigaltstack *bss; +{ + + bss->ss_sp = sss->ss_sp; + bss->ss_size = sss->ss_size; + bss->ss_flags = 0; + if ((sss->ss_flags & SVR4_SS_DISABLE) != 0) + bss->ss_flags |= SS_DISABLE; + if ((sss->ss_flags & SVR4_SS_ONSTACK) != 0) + bss->ss_flags |= SS_ONSTACK; + if ((sss->ss_flags & ~SVR4_SS_ALLBITS) != 0) + /*XXX*/ uprintf("svr4_to_bsd_sigaltstack: extra bits ignored\n"); +} + +void +bsd_to_svr4_sigaltstack(bss, sss) + const struct sigaltstack *bss; + struct svr4_sigaltstack *sss; +{ + + sss->ss_sp = bss->ss_sp; + sss->ss_size = bss->ss_size; + sss->ss_flags = 0; + if ((bss->ss_flags & SS_DISABLE) != 0) + sss->ss_flags |= SVR4_SS_DISABLE; + if ((bss->ss_flags & SS_ONSTACK) != 0) + sss->ss_flags |= SVR4_SS_ONSTACK; +} + +int +svr4_sys_sigaction(td, uap) + register struct thread *td; + struct svr4_sys_sigaction_args *uap; +{ + struct svr4_sigaction *nisa, *oisa, tmpisa; + struct sigaction *nbsa, *obsa, tmpbsa; + struct sigaction_args sa; + caddr_t sg; + int error; + + DPRINTF(("@@@ svr4_sys_sigaction(%d, %d, %d)\n", td->td_proc->p_pid, + SCARG(uap, signum), + SVR4_SVR42BSD_SIG(SCARG(uap, signum)))); + + sg = stackgap_init(); + nisa = SCARG(uap, nsa); + oisa = SCARG(uap, osa); + + if (oisa != NULL) + obsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + else + obsa = NULL; + + if (nisa != NULL) { + nbsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0) + return error; + svr4_to_bsd_sigaction(&tmpisa, &tmpbsa); + if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0) + return error; + } else + nbsa = NULL; + +#if defined(DEBUG_SVR4) + { + int i; + for (i = 0; i < 4; i++) + DPRINTF(("\tssa_mask[%d] = %lx\n", i, + nisa->ssa_mask.bits[i])); + DPRINTF(("\tssa_handler = %p\n", nisa->ssa_handler)); + } +#endif + + SCARG(&sa, sig) = SVR4_SVR42BSD_SIG(SCARG(uap, signum)); + SCARG(&sa, act) = nbsa; + SCARG(&sa, oact) = obsa; + + if ((error = sigaction(td, &sa)) != 0) + return error; + + if (oisa != NULL) { + if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0) + return error; + bsd_to_svr4_sigaction(&tmpbsa, &tmpisa); + if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0) + return error; + } + + return 0; +} + +int +svr4_sys_sigaltstack(td, uap) + register struct thread *td; + struct svr4_sys_sigaltstack_args *uap; +{ + struct svr4_sigaltstack *nsss, *osss, tmpsss; + struct sigaltstack *nbss, *obss, tmpbss; + struct sigaltstack_args sa; + caddr_t sg; + int error, *retval; + + retval = td->td_retval; + sg = stackgap_init(); + nsss = SCARG(uap, nss); + osss = SCARG(uap, oss); + + if (osss != NULL) + obss = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + else + obss = NULL; + + if (nsss != NULL) { + nbss = stackgap_alloc(&sg, sizeof(struct sigaltstack)); + if ((error = copyin(nsss, &tmpsss, sizeof(tmpsss))) != 0) + return error; + svr4_to_bsd_sigaltstack(&tmpsss, &tmpbss); + if ((error = copyout(&tmpbss, nbss, sizeof(tmpbss))) != 0) + return error; + } else + nbss = NULL; + + SCARG(&sa, ss) = nbss; + SCARG(&sa, oss) = obss; + + if ((error = sigaltstack(td, &sa)) != 0) + return error; + + if (obss != NULL) { + if ((error = copyin(obss, &tmpbss, sizeof(tmpbss))) != 0) + return error; + bsd_to_svr4_sigaltstack(&tmpbss, &tmpsss); + if ((error = copyout(&tmpsss, osss, sizeof(tmpsss))) != 0) + return error; + } + + return 0; +} + +/* + * Stolen from the ibcs2 one + */ +int +svr4_sys_signal(td, uap) + register struct thread *td; + struct svr4_sys_signal_args *uap; +{ + int signum; + int error, *retval = td->td_retval; + caddr_t sg = stackgap_init(); + + DPRINTF(("@@@ svr4_sys_signal(%d)\n", td->td_proc->p_pid)); + + signum = SVR4_SVR42BSD_SIG(SVR4_SIGNO(SCARG(uap, signum))); + if (signum <= 0 || signum > SVR4_NSIG) + return (EINVAL); + + switch (SVR4_SIGCALL(SCARG(uap, signum))) { + case SVR4_SIGDEFER_MASK: + if (SCARG(uap, handler) == SVR4_SIG_HOLD) + goto sighold; + /* FALLTHROUGH */ + + case SVR4_SIGNAL_MASK: + { + struct sigaction_args sa_args; + struct sigaction *nbsa, *obsa, sa; + + nbsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + obsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(&sa_args, sig) = signum; + SCARG(&sa_args, act) = nbsa; + SCARG(&sa_args, oact) = obsa; + + sa.sa_handler = (sig_t) SCARG(uap, handler); + SIGEMPTYSET(sa.sa_mask); + sa.sa_flags = 0; + + if (signum != SIGALRM) + sa.sa_flags = SA_RESTART; + + if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0) + return error; + if ((error = sigaction(td, &sa_args)) != 0) { + DPRINTF(("signal: sigaction failed: %d\n", + error)); + *retval = (int)SVR4_SIG_ERR; + return error; + } + if ((error = copyin(obsa, &sa, sizeof(sa))) != 0) + return error; + *retval = (int)sa.sa_handler; + return 0; + } + + case SVR4_SIGHOLD_MASK: +sighold: + { + struct sigprocmask_args sa; + sigset_t *set; + + set = stackgap_alloc(&sg, sizeof(sigset_t)); + SIGEMPTYSET(*set); + SIGADDSET(*set, signum); + SCARG(&sa, how) = SIG_BLOCK; + SCARG(&sa, set) = set; + SCARG(&sa, oset) = NULL; + return sigprocmask(td, &sa); + } + + case SVR4_SIGRELSE_MASK: + { + struct sigprocmask_args sa; + sigset_t *set; + + set = stackgap_alloc(&sg, sizeof(sigset_t)); + SIGEMPTYSET(*set); + SIGADDSET(*set, signum); + SCARG(&sa, how) = SIG_UNBLOCK; + SCARG(&sa, set) = set; + SCARG(&sa, oset) = NULL; + return sigprocmask(td, &sa); + } + + case SVR4_SIGIGNORE_MASK: + { + struct sigaction_args sa_args; + struct sigaction *bsa, sa; + + bsa = stackgap_alloc(&sg, sizeof(struct sigaction)); + SCARG(&sa_args, sig) = signum; + SCARG(&sa_args, act) = bsa; + SCARG(&sa_args, oact) = NULL; + + sa.sa_handler = SIG_IGN; + SIGEMPTYSET(sa.sa_mask); + sa.sa_flags = 0; + if ((error = copyout(&sa, bsa, sizeof(sa))) != 0) + return error; + if ((error = sigaction(td, &sa_args)) != 0) { + DPRINTF(("sigignore: sigaction failed\n")); + return error; + } + return 0; + } + + case SVR4_SIGPAUSE_MASK: + { + struct sigsuspend_args sa; + sigset_t *set; + + set = stackgap_alloc(&sg, sizeof(sigset_t)); + PROC_LOCK(td->td_proc); + *set = td->td_proc->p_sigmask; + PROC_UNLOCK(td->td_proc); + SIGDELSET(*set, signum); + SCARG(&sa, sigmask) = set; + return sigsuspend(td, &sa); + } + + default: + return (ENOSYS); + } +} + + +int +svr4_sys_sigprocmask(td, uap) + struct thread *td; + struct svr4_sys_sigprocmask_args *uap; +{ + svr4_sigset_t sss; + sigset_t bss; + int error = 0, *retval; + + retval = td->td_retval; + if (SCARG(uap, oset) != NULL) { + /* Fix the return value first if needed */ + PROC_LOCK(td->td_proc); + bsd_to_svr4_sigset(&td->td_proc->p_sigmask, &sss); + PROC_UNLOCK(td->td_proc); + if ((error = copyout(&sss, SCARG(uap, oset), sizeof(sss))) != 0) + return error; + } + + if (SCARG(uap, set) == NULL) + /* Just examine */ + return 0; + + if ((error = copyin(SCARG(uap, set), &sss, sizeof(sss))) != 0) + return error; + + svr4_to_bsd_sigset(&sss, &bss); + + PROC_LOCK(td->td_proc); + switch (SCARG(uap, how)) { + case SVR4_SIG_BLOCK: + SIGSETOR(td->td_proc->p_sigmask, bss); + SIG_CANTMASK(td->td_proc->p_sigmask); + break; + + case SVR4_SIG_UNBLOCK: + SIGSETNAND(td->td_proc->p_sigmask, bss); + signotify(td->td_proc); + break; + + case SVR4_SIG_SETMASK: + td->td_proc->p_sigmask = bss; + SIG_CANTMASK(td->td_proc->p_sigmask); + signotify(td->td_proc); + break; + + default: + error = EINVAL; + break; + } + PROC_UNLOCK(td->td_proc); + + return error; +} + +int +svr4_sys_sigpending(td, uap) + struct thread *td; + struct svr4_sys_sigpending_args *uap; +{ + sigset_t bss; + int *retval; + svr4_sigset_t sss; + + DPRINTF(("@@@ svr4_sys_sigpending(%d)\n", td->td_proc->p_pid)); + retval = td->td_retval; + switch (SCARG(uap, what)) { + case 1: /* sigpending */ + if (SCARG(uap, mask) == NULL) + return 0; + PROC_LOCK(td->td_proc); + bss = td->td_proc->p_siglist; + SIGSETAND(bss, td->td_proc->p_sigmask); + PROC_UNLOCK(td->td_proc); + bsd_to_svr4_sigset(&bss, &sss); + break; + + case 2: /* sigfillset */ + svr4_sigfillset(&sss); +#if defined(DEBUG_SVR4) + { + int i; + for (i = 0; i < 4; i++) + DPRINTF(("new sigset[%d] = %lx\n", i, (long)sss.bits[i])); + } +#endif + break; + + default: + return EINVAL; + } + + return copyout(&sss, SCARG(uap, mask), sizeof(sss)); +} + +int +svr4_sys_sigsuspend(td, uap) + register struct thread *td; + struct svr4_sys_sigsuspend_args *uap; +{ + svr4_sigset_t sss; + sigset_t *bss; + struct sigsuspend_args sa; + int error; + caddr_t sg = stackgap_init(); + + if ((error = copyin(SCARG(uap, ss), &sss, sizeof(sss))) != 0) + return error; + + bss = stackgap_alloc(&sg, sizeof(sigset_t)); + svr4_to_bsd_sigset(&sss, bss); + + SCARG(&sa, sigmask) = bss; + return sigsuspend(td, &sa); +} + + +int +svr4_sys_kill(td, uap) + register struct thread *td; + struct svr4_sys_kill_args *uap; +{ + struct kill_args ka; + + SCARG(&ka, pid) = SCARG(uap, pid); + SCARG(&ka, signum) = SVR4_SVR42BSD_SIG(SCARG(uap, signum)); + return kill(td, &ka); +} + + +int +svr4_sys_context(td, uap) + register struct thread *td; + struct svr4_sys_context_args *uap; +{ + struct svr4_ucontext uc; + int error; + + switch (uap->func) { + case 0: + PROC_LOCK(td->td_proc); + DPRINTF(("getcontext(%p)\n", uap->uc)); + svr4_getcontext(td, &uc, &td->td_proc->p_sigmask, + sigonstack(cpu_getstack(td))); + PROC_UNLOCK(td->td_proc); + return copyout(&uc, uap->uc, sizeof(uc)); + + case 1: + DPRINTF(("setcontext(%p)\n", uap->uc)); + if ((error = copyin(uap->uc, &uc, sizeof(uc))) != 0) + return error; + DPRINTF(("uc_flags = %lx\n", uc.uc_flags)); +#if defined(DEBUG_SVR4) + { + int i; + for (i = 0; i < 4; i++) + DPRINTF(("uc_sigmask[%d] = %lx\n", i, + uc.uc_sigmask.bits[i])); + } +#endif + return svr4_setcontext(td, &uc); + + default: + DPRINTF(("context(%d, %p)\n", uap->func, + uap->uc)); + return ENOSYS; + } + return 0; +} + +int +svr4_sys_pause(td, uap) + register struct thread *td; + struct svr4_sys_pause_args *uap; +{ + struct sigsuspend_args bsa; + + SCARG(&bsa, sigmask) = &td->td_proc->p_sigmask; + return sigsuspend(td, &bsa); +} diff --git a/sys/compat/svr4/svr4_signal.h b/sys/compat/svr4/svr4_signal.h new file mode 100644 index 0000000..5a01a8f --- /dev/null +++ b/sys/compat/svr4/svr4_signal.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SIGNAL_H_ +#define _SVR4_SIGNAL_H_ + +#include <i386/svr4/svr4_machdep.h> +#include <compat/svr4/svr4_siginfo.h> + +#define SVR4_SIGHUP 1 +#define SVR4_SIGINT 2 +#define SVR4_SIGQUIT 3 +#define SVR4_SIGILL 4 +#define SVR4_SIGTRAP 5 +#define SVR4_SIGIOT 6 +#define SVR4_SIGABRT 6 +#define SVR4_SIGEMT 7 +#define SVR4_SIGFPE 8 +#define SVR4_SIGKILL 9 +#define SVR4_SIGBUS 10 +#define SVR4_SIGSEGV 11 +#define SVR4_SIGSYS 12 +#define SVR4_SIGPIPE 13 +#define SVR4_SIGALRM 14 +#define SVR4_SIGTERM 15 +#define SVR4_SIGUSR1 16 +#define SVR4_SIGUSR2 17 +#define SVR4_SIGCLD 18 +#define SVR4_SIGCHLD 18 +#define SVR4_SIGPWR 19 +#define SVR4_SIGWINCH 20 +#define SVR4_SIGURG 21 +#define SVR4_SIGPOLL 22 +#define SVR4_SIGIO 22 +#define SVR4_SIGSTOP 23 +#define SVR4_SIGTSTP 24 +#define SVR4_SIGCONT 25 +#define SVR4_SIGTTIN 26 +#define SVR4_SIGTTOU 27 +#define SVR4_SIGVTALRM 28 +#define SVR4_SIGPROF 29 +#define SVR4_SIGXCPU 30 +#define SVR4_SIGXFSZ 31 +#define SVR4_NSIG 32 +#define SVR4_SIGTBLSZ 31 + +#define SVR4_SIGNO_MASK 0x00FF +#define SVR4_SIGNAL_MASK 0x0000 +#define SVR4_SIGDEFER_MASK 0x0100 +#define SVR4_SIGHOLD_MASK 0x0200 +#define SVR4_SIGRELSE_MASK 0x0400 +#define SVR4_SIGIGNORE_MASK 0x0800 +#define SVR4_SIGPAUSE_MASK 0x1000 + +typedef void (*svr4_sig_t)(int, svr4_siginfo_t *, void *); +#define SVR4_SIG_DFL (svr4_sig_t) 0 +#define SVR4_SIG_ERR (svr4_sig_t) -1 +#define SVR4_SIG_IGN (svr4_sig_t) 1 +#define SVR4_SIG_HOLD (svr4_sig_t) 2 + +#define SVR4_SIGNO(a) ((a) & SVR4_SIGNO_MASK) +#define SVR4_SIGCALL(a) ((a) & ~SVR4_SIGNO_MASK) + +#define SVR4_SIG_BLOCK 1 +#define SVR4_SIG_UNBLOCK 2 +#define SVR4_SIG_SETMASK 3 + +extern int bsd_to_svr4_sig[]; +extern int svr4_to_bsd_sig[]; + +#define SVR4_BSD2SVR4_SIG(sig) \ + (((sig) <= SVR4_SIGTBLSZ) ? bsd_to_svr4_sig[_SIG_IDX(sig)] : sig) +#define SVR4_SVR42BSD_SIG(sig) \ + (((sig) <= SVR4_SIGTBLSZ) ? svr4_to_bsd_sig[_SIG_IDX(sig)] : sig) + +typedef struct { + u_long bits[4]; +} svr4_sigset_t; + +struct svr4_sigaction { + int ssa_flags; + svr4_sig_t ssa_handler; + svr4_sigset_t ssa_mask; + int ssa_reserved[2]; +}; + +struct svr4_sigaltstack { + char *ss_sp; + int ss_size; + int ss_flags; +}; + +/* sa_flags */ +#define SVR4_SA_ONSTACK 0x00000001 +#define SVR4_SA_RESETHAND 0x00000002 +#define SVR4_SA_RESTART 0x00000004 +#define SVR4_SA_SIGINFO 0x00000008 +#define SVR4_SA_NODEFER 0x00000010 +#define SVR4_SA_NOCLDWAIT 0x00010000 /* No zombies */ +#define SVR4_SA_NOCLDSTOP 0x00020000 /* No jcl */ +#define SVR4_SA_ALLBITS 0x0003001f + +/* ss_flags */ +#define SVR4_SS_ONSTACK 0x00000001 +#define SVR4_SS_DISABLE 0x00000002 +#define SVR4_SS_ALLBITS 0x00000003 + +#define SVR4_MINSIGSTKSZ 8192 + +void bsd_to_svr4_sigaltstack(const struct sigaltstack *, struct svr4_sigaltstack *); +void bsd_to_svr4_sigset(const sigset_t *, svr4_sigset_t *); +void svr4_to_bsd_sigaltstack(const struct svr4_sigaltstack *, struct sigaltstack *); +void svr4_to_bsd_sigset(const svr4_sigset_t *, sigset_t *); +void svr4_sendsig(sig_t, int, sigset_t *, u_long); + +#endif /* !_SVR4_SIGNAL_H_ */ diff --git a/sys/compat/svr4/svr4_socket.c b/sys/compat/svr4/svr4_socket.c new file mode 100644 index 0000000..b4f2b55 --- /dev/null +++ b/sys/compat/svr4/svr4_socket.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1996 Christos Zoulas. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * In SVR4 unix domain sockets are referenced sometimes + * (in putmsg(2) for example) as a [device, inode] pair instead of a pathname. + * Since there is no iname() routine in the kernel, and we need access to + * a mapping from inode to pathname, we keep our own table. This is a simple + * linked list that contains the pathname, the [device, inode] pair, the + * file corresponding to that socket and the process. When the + * socket gets closed we remove the item from the list. The list gets loaded + * every time a stat(2) call finds a socket. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/queue.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/sysproto.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <sys/proc.h> +#include <sys/malloc.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_socket.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_sockmod.h> +#include <compat/svr4/svr4_proto.h> + +struct svr4_sockcache_entry { + struct proc *p; /* Process for the socket */ + void *cookie; /* Internal cookie used for matching */ + struct sockaddr_un sock;/* Pathname for the socket */ + udev_t dev; /* Device where the socket lives on */ + ino_t ino; /* Inode where the socket lives on */ + TAILQ_ENTRY(svr4_sockcache_entry) entries; +}; + +extern TAILQ_HEAD(svr4_sockcache_head, svr4_sockcache_entry) svr4_head; +extern int svr4_str_initialized; + +struct sockaddr_un * +svr4_find_socket(td, fp, dev, ino) + struct thread *td; + struct file *fp; + udev_t dev; + ino_t ino; +{ + struct svr4_sockcache_entry *e; + void *cookie = ((struct socket *) fp->f_data)->so_emuldata; + + if (svr4_str_initialized != 2) { + if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) { + DPRINTF(("svr4_find_socket: uninitialized [%p,%d,%d]\n", + td, dev, ino)); + TAILQ_INIT(&svr4_head); + atomic_store_rel_int(&svr4_str_initialized, 2); + } + return NULL; + } + + + DPRINTF(("svr4_find_socket: [%p,%d,%d]: ", td, dev, ino)); + TAILQ_FOREACH(e, &svr4_head, entries) + if (e->p == td->td_proc && e->dev == dev && e->ino == ino) { +#ifdef DIAGNOSTIC + if (e->cookie != NULL && e->cookie != cookie) + panic("svr4 socket cookie mismatch"); +#endif + e->cookie = cookie; + DPRINTF(("%s\n", e->sock.sun_path)); + return &e->sock; + } + + DPRINTF(("not found\n")); + return NULL; +} + + +/* + * svr4_delete_socket() is in sys/dev/streams.c (because it's called by + * the streams "soo_close()" routine). + */ +int +svr4_add_socket(td, path, st) + struct thread *td; + const char *path; + struct stat *st; +{ + struct svr4_sockcache_entry *e; + int len, error; + + /* + * Wait for the TAILQ to be initialized. Only the very first CPU + * will succeed on the atomic_cmpset(). The other CPU's will spin + * until the first one finishes the initialization. Once the + * initialization is complete, the condition will always fail + * avoiding expensive atomic operations in the common case. + */ + while (svr4_str_initialized != 2) + if (atomic_cmpset_acq_int(&svr4_str_initialized, 0, 1)) { + TAILQ_INIT(&svr4_head); + atomic_store_rel_int(&svr4_str_initialized, 2); + } + + e = malloc(sizeof(*e), M_TEMP, M_WAITOK); + e->cookie = NULL; + e->dev = st->st_dev; + e->ino = st->st_ino; + e->p = td->td_proc; + + if ((error = copyinstr(path, e->sock.sun_path, + sizeof(e->sock.sun_path), &len)) != 0) { + DPRINTF(("svr4_add_socket: copyinstr failed %d\n", error)); + free(e, M_TEMP); + return error; + } + + e->sock.sun_family = AF_LOCAL; + e->sock.sun_len = len; + + TAILQ_INSERT_HEAD(&svr4_head, e, entries); + DPRINTF(("svr4_add_socket: %s [%p,%d,%d]\n", e->sock.sun_path, + td->td_proc, e->dev, e->ino)); + return 0; +} + + +int +svr4_sys_socket(td, uap) + struct thread *td; + struct svr4_sys_socket_args *uap; +{ + switch (SCARG(uap, type)) { + case SVR4_SOCK_DGRAM: + SCARG(uap, type) = SOCK_DGRAM; + break; + + case SVR4_SOCK_STREAM: + SCARG(uap, type) = SOCK_STREAM; + break; + + case SVR4_SOCK_RAW: + SCARG(uap, type) = SOCK_RAW; + break; + + case SVR4_SOCK_RDM: + SCARG(uap, type) = SOCK_RDM; + break; + + case SVR4_SOCK_SEQPACKET: + SCARG(uap, type) = SOCK_SEQPACKET; + break; + default: + return EINVAL; + } + return socket(td, (struct socket_args *)uap); +} diff --git a/sys/compat/svr4/svr4_socket.h b/sys/compat/svr4/svr4_socket.h new file mode 100644 index 0000000..434f1f2 --- /dev/null +++ b/sys/compat/svr4/svr4_socket.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1996 Christos Zoulas. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SOCKET_H_ +#define _SVR4_SOCKET_H_ + +#include <netinet/in.h> + +struct sockaddr_un; +struct proc; +struct thread; +struct file; + +struct svr4_sockaddr_in { + u_char sin_family; + u_short sin_port; + struct in_addr sin_addr; + u_char sin_zero[8]; +}; + +struct sockaddr_un *svr4_find_socket(struct thread *, struct file *, + udev_t, ino_t); +void svr4_delete_socket(struct proc *, struct file *); +int svr4_add_socket(struct thread *, const char *, struct stat *); + +#endif /* _SVR4_SOCKET_H_ */ diff --git a/sys/compat/svr4/svr4_sockio.c b/sys/compat/svr4/svr4_sockio.c new file mode 100644 index 0000000..9f41e10 --- /dev/null +++ b/sys/compat/svr4/svr4_sockio.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1995 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <net/if.h> + + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_ioctl.h> +#include <compat/svr4/svr4_sockio.h> + +static int bsd_to_svr4_flags(int); + +#define bsd_to_svr4_flag(a) \ + if (bf & __CONCAT(I,a)) sf |= __CONCAT(SVR4_I,a) + +static int +bsd_to_svr4_flags(bf) + int bf; +{ + int sf = 0; + bsd_to_svr4_flag(FF_UP); + bsd_to_svr4_flag(FF_BROADCAST); + bsd_to_svr4_flag(FF_DEBUG); + bsd_to_svr4_flag(FF_LOOPBACK); + bsd_to_svr4_flag(FF_POINTOPOINT); +#if defined(IFF_NOTRAILERS) + bsd_to_svr4_flag(FF_NOTRAILERS); +#endif + bsd_to_svr4_flag(FF_RUNNING); + bsd_to_svr4_flag(FF_NOARP); + bsd_to_svr4_flag(FF_PROMISC); + bsd_to_svr4_flag(FF_ALLMULTI); + bsd_to_svr4_flag(FF_MULTICAST); + return sf; +} + +int +svr4_sock_ioctl(fp, td, retval, fd, cmd, data) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t data; +{ + int error; + + *retval = 0; + + switch (cmd) { + case SVR4_SIOCGIFNUM: + { + struct ifnet *ifp; + struct ifaddr *ifa; + int ifnum = 0; + + /* + * This does not return the number of physical + * interfaces (if_index), but the number of interfaces + * + addresses like ifconf() does, because this number + * is used by code that will call SVR4_SIOCGIFCONF to + * find the space needed for SVR4_SIOCGIFCONF. So we + * count the number of ifreq entries that the next + * SVR4_SIOCGIFCONF will return. Maybe a more correct + * fix is to make SVR4_SIOCGIFCONF return only one + * entry per physical interface? + */ + + TAILQ_FOREACH(ifp, &ifnet, if_link) + if (TAILQ_FIRST(&ifp->if_addrhead) == NULL) + ifnum++; + else + TAILQ_FOREACH(ifa, &ifp->if_addrhead, + ifa_link) + ifnum++; + + + DPRINTF(("SIOCGIFNUM %d\n", ifnum)); + return copyout(&ifnum, data, sizeof(ifnum)); + } + + case SVR4_SIOCGIFFLAGS: + { + struct ifreq br; + struct svr4_ifreq sr; + + if ((error = copyin(data, &sr, sizeof(sr))) != 0) + return error; + + (void) strncpy(br.ifr_name, sr.svr4_ifr_name, + sizeof(br.ifr_name)); + if ((error = fo_ioctl(fp, SIOCGIFFLAGS, + (caddr_t) &br, td)) != 0) { + DPRINTF(("SIOCGIFFLAGS (%s) %s: error %d\n", + br.ifr_name, sr.svr4_ifr_name, error)); + return error; + } + + sr.svr4_ifr_flags = bsd_to_svr4_flags(br.ifr_flags); + DPRINTF(("SIOCGIFFLAGS %s = %x\n", + sr.svr4_ifr_name, sr.svr4_ifr_flags)); + return copyout(&sr, data, sizeof(sr)); + } + + case SVR4_SIOCGIFCONF: + { + struct svr4_ifconf sc; + + if ((error = copyin(data, &sc, sizeof(sc))) != 0) + return error; + + DPRINTF(("ifreq %d svr4_ifreq %d ifc_len %d\n", + sizeof(struct ifreq), sizeof(struct svr4_ifreq), + sc.svr4_ifc_len)); + + if ((error = fo_ioctl(fp, OSIOCGIFCONF, + (caddr_t) &sc, td)) != 0) + return error; + + DPRINTF(("SIOCGIFCONF\n")); + return 0; + } + + + default: + DPRINTF(("Unknown svr4 sockio %lx\n", cmd)); + return 0; /* ENOSYS really */ + } +} diff --git a/sys/compat/svr4/svr4_sockio.h b/sys/compat/svr4/svr4_sockio.h new file mode 100644 index 0000000..dd4e220 --- /dev/null +++ b/sys/compat/svr4/svr4_sockio.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1995 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SOCKIO_H_ +#define _SVR4_SOCKIO_H_ + +#define SVR4_IFF_UP 0x0001 +#define SVR4_IFF_BROADCAST 0x0002 +#define SVR4_IFF_DEBUG 0x0004 +#define SVR4_IFF_LOOPBACK 0x0008 +#define SVR4_IFF_POINTOPOINT 0x0010 +#define SVR4_IFF_NOTRAILERS 0x0020 +#define SVR4_IFF_RUNNING 0x0040 +#define SVR4_IFF_NOARP 0x0080 +#define SVR4_IFF_PROMISC 0x0100 +#define SVR4_IFF_ALLMULTI 0x0200 +#define SVR4_IFF_INTELLIGENT 0x0400 +#define SVR4_IFF_MULTICAST 0x0800 +#define SVR4_IFF_MULTI_BCAST 0x1000 +#define SVR4_IFF_UNNUMBERED 0x2000 +#define SVR4_IFF_PRIVATE 0x8000 + +struct svr4_ifreq { +#define SVR4_IFNAMSIZ 16 + char svr4_ifr_name[SVR4_IFNAMSIZ]; + union { + struct osockaddr ifru_addr; + struct osockaddr ifru_dstaddr; + struct osockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + char ifru_data; + char ifru_enaddr[6]; + int if_muxid[2]; + + } ifr_ifru; + +#define svr4_ifr_addr ifr_ifru.ifru_addr +#define svr4_ifr_dstaddr ifr_ifru.ifru_dstaddr +#define svr4_ifr_broadaddr ifr_ifru.ifru_broadaddr +#define svr4_ifr_flags ifr_ifru.ifru_flags +#define svr4_ifr_metric ifr_ifru.ifru_metric +#define svr4_ifr_data ifr_ifru.ifru_data +#define svr4_ifr_enaddr ifr_ifru.ifru_enaddr +#define svr4_ifr_muxid ifr_ifru.ifru_muxid + +}; + +struct svr4_ifconf { + int svr4_ifc_len; + union { + caddr_t ifcu_buf; + struct svr4_ifreq *ifcu_req; + } ifc_ifcu; + +#define svr4_ifc_buf ifc_ifcu.ifcu_buf +#define svr4_ifc_req ifc_ifcu.ifcu_req +}; + +#define SVR4_SIOC ('i' << 8) + +#define SVR4_SIOCGIFFLAGS SVR4_IOWR('i', 17, struct svr4_ifreq) +#define SVR4_SIOCGIFCONF SVR4_IOWR('i', 20, struct svr4_ifconf) +#define SVR4_SIOCGIFNUM SVR4_IOR('i', 87, int) + +#endif /* !_SVR4_SOCKIO_H_ */ diff --git a/sys/compat/svr4/svr4_sockmod.h b/sys/compat/svr4/svr4_sockmod.h new file mode 100644 index 0000000..927ba0d --- /dev/null +++ b/sys/compat/svr4/svr4_sockmod.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SOCKMOD_H_ +#define _SVR4_SOCKMOD_H_ + +#define SVR4_SIMOD ('I' << 8) + +#define SVR4_SI_OGETUDATA (SVR4_SIMOD|101) +#define SVR4_SI_SHUTDOWN (SVR4_SIMOD|102) +#define SVR4_SI_LISTEN (SVR4_SIMOD|103) +#define SVR4_SI_SETMYNAME (SVR4_SIMOD|104) +#define SVR4_SI_SETPEERNAME (SVR4_SIMOD|105) +#define SVR4_SI_GETINTRANSIT (SVR4_SIMOD|106) +#define SVR4_SI_TCL_LINK (SVR4_SIMOD|107) +#define SVR4_SI_TCL_UNLINK (SVR4_SIMOD|108) +#define SVR4_SI_SOCKPARAMS (SVR4_SIMOD|109) +#define SVR4_SI_GETUDATA (SVR4_SIMOD|110) + + +#define SVR4_SOCK_DGRAM 1 +#define SVR4_SOCK_STREAM 2 +#define SVR4_SOCK_STREAM_ORD 3 +#define SVR4_SOCK_RAW 4 +#define SVR4_SOCK_RDM 5 +#define SVR4_SOCK_SEQPACKET 6 + +struct svr4_si_sockparms { + int family; + int type; + int protocol; +}; + +struct svr4_si_oudata { + int tidusize; + int addrsize; + int optsize; + int etsdusize; + int servtype; + int so_state; + int so_options; + int tsdusize; +}; + +struct svr4_si_udata { + int tidusize; + int addrsize; + int optsize; + int etsdusize; + int servtype; + int so_state; + int so_options; + int tsdusize; + struct svr4_si_sockparms sockparms; +}; +#endif /* !_SVR4_SOCKMOD_H_ */ diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c new file mode 100644 index 0000000..b1d63ec --- /dev/null +++ b/sys/compat/svr4/svr4_stat.c @@ -0,0 +1,775 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/stat.h> +#include <sys/filedesc.h> +#include <sys/jail.h> +#include <sys/kernel.h> +#include <sys/unistd.h> +#include <sys/time.h> +#include <sys/sysctl.h> +#include <sys/sysproto.h> + +#include <vm/vm.h> + +#include <netinet/in.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_stat.h> +#include <compat/svr4/svr4_ustat.h> +#include <compat/svr4/svr4_utsname.h> +#include <compat/svr4/svr4_systeminfo.h> +#include <compat/svr4/svr4_socket.h> +#include <compat/svr4/svr4_time.h> +#if defined(NOTYET) +#include "svr4_fuser.h" +#endif + +#ifdef sparc +/* + * Solaris-2.4 on the sparc has the old stat call using the new + * stat data structure... + */ +# define SVR4_NO_OSTAT +#endif + +struct svr4_ustat_args { + svr4_dev_t dev; + struct svr4_ustat * name; +}; + +static void bsd_to_svr4_xstat(struct stat *, struct svr4_xstat *); +static void bsd_to_svr4_stat64(struct stat *, struct svr4_stat64 *); +int svr4_ustat(struct thread *, struct svr4_ustat_args *); +static int svr4_to_bsd_pathconf(int); + +/* + * SVR4 uses named pipes as named sockets, so we tell programs + * that sockets are named pipes with mode 0 + */ +#define BSD_TO_SVR4_MODE(mode) (S_ISSOCK(mode) ? S_IFIFO : (mode)) + + +#ifndef SVR4_NO_OSTAT +static void bsd_to_svr4_stat(struct stat *, struct svr4_stat *); + +static void +bsd_to_svr4_stat(st, st4) + struct stat *st; + struct svr4_stat *st4; +{ + memset(st4, 0, sizeof(*st4)); + st4->st_dev = bsd_to_svr4_odev_t(st->st_dev); + st4->st_ino = st->st_ino; + st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode); + st4->st_nlink = st->st_nlink; + st4->st_uid = st->st_uid; + st4->st_gid = st->st_gid; + st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev); + st4->st_size = st->st_size; + st4->st_atim = st->st_atimespec.tv_sec; + st4->st_mtim = st->st_mtimespec.tv_sec; + st4->st_ctim = st->st_ctimespec.tv_sec; +} +#endif + + +static void +bsd_to_svr4_xstat(st, st4) + struct stat *st; + struct svr4_xstat *st4; +{ + memset(st4, 0, sizeof(*st4)); + st4->st_dev = bsd_to_svr4_dev_t(st->st_dev); + st4->st_ino = st->st_ino; + st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode); + st4->st_nlink = st->st_nlink; + st4->st_uid = st->st_uid; + st4->st_gid = st->st_gid; + st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev); + st4->st_size = st->st_size; + st4->st_atim = st->st_atimespec; + st4->st_mtim = st->st_mtimespec; + st4->st_ctim = st->st_ctimespec; + st4->st_blksize = st->st_blksize; + st4->st_blocks = st->st_blocks; + strcpy(st4->st_fstype, "unknown"); +} + + +static void +bsd_to_svr4_stat64(st, st4) + struct stat *st; + struct svr4_stat64 *st4; +{ + memset(st4, 0, sizeof(*st4)); + st4->st_dev = bsd_to_svr4_dev_t(st->st_dev); + st4->st_ino = st->st_ino; + st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode); + st4->st_nlink = st->st_nlink; + st4->st_uid = st->st_uid; + st4->st_gid = st->st_gid; + st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev); + st4->st_size = st->st_size; + st4->st_atim = st->st_atimespec; + st4->st_mtim = st->st_mtimespec; + st4->st_ctim = st->st_ctimespec; + st4->st_blksize = st->st_blksize; + st4->st_blocks = st->st_blocks; + strcpy(st4->st_fstype, "unknown"); +} + +int +svr4_sys_stat(td, uap) + struct thread *td; + struct svr4_sys_stat_args *uap; +{ + struct stat st; + struct svr4_stat svr4_st; + struct stat_args cup; + int error; + caddr_t sg = stackgap_init(); + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + + if ((error = stat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_lstat(td, uap) + register struct thread *td; + struct svr4_sys_lstat_args *uap; +{ + struct stat st; + struct svr4_stat svr4_st; + struct lstat_args cup; + int error; + caddr_t sg = stackgap_init(); + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = lstat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_fstat(td, uap) + register struct thread *td; + struct svr4_sys_fstat_args *uap; +{ + struct stat st; + struct svr4_stat svr4_st; + struct fstat_args cup; + int error; + caddr_t sg = stackgap_init(); + + SCARG(&cup, fd) = SCARG(uap, fd); + SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = fstat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat(&st, &svr4_st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_xstat(td, uap) + register struct thread *td; + struct svr4_sys_xstat_args *uap; +{ + struct stat st; + struct svr4_xstat svr4_st; + struct stat_args cup; + int error; + + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = stat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_xstat(&st, &svr4_st); + +#if defined(SOCKET_NOTYET) + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); +#endif + + if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0) + return error; + + return 0; +} + +int +svr4_sys_lxstat(td, uap) + register struct thread *td; + struct svr4_sys_lxstat_args *uap; +{ + struct stat st; + struct svr4_xstat svr4_st; + struct lstat_args cup; + int error; + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = lstat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_xstat(&st, &svr4_st); + +#if defined(SOCKET_NOTYET) + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); +#endif + if ((error = copyout(&svr4_st, SCARG(uap, ub), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_fxstat(td, uap) + register struct thread *td; + struct svr4_sys_fxstat_args *uap; +{ + struct stat st; + struct svr4_xstat svr4_st; + struct fstat_args cup; + int error; + + caddr_t sg = stackgap_init(); + + SCARG(&cup, fd) = SCARG(uap, fd); + SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = fstat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_xstat(&st, &svr4_st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + +int +svr4_sys_stat64(td, uap) + register struct thread *td; + struct svr4_sys_stat64_args *uap; +{ + struct stat st; + struct svr4_stat64 svr4_st; + struct stat_args cup; + int error; + caddr_t sg = stackgap_init(); + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = stat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat64(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_lstat64(td, uap) + register struct thread *td; + struct svr4_sys_lstat64_args *uap; +{ + struct stat st; + struct svr4_stat64 svr4_st; + struct stat_args cup; + int error; + caddr_t sg = stackgap_init(); + + CHECKALTEXIST(td, &sg, (char *) SCARG(uap, path)); + + SCARG(&cup, path) = SCARG(uap, path); + SCARG(&cup, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = lstat(td, (struct lstat_args *)&cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, ub), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat64(&st, &svr4_st); + + if (S_ISSOCK(st.st_mode)) + (void) svr4_add_socket(td, SCARG(uap, path), &st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_sys_fstat64(td, uap) + register struct thread *td; + struct svr4_sys_fstat64_args *uap; +{ + struct stat st; + struct svr4_stat64 svr4_st; + struct fstat_args cup; + int error; + caddr_t sg = stackgap_init(); + + SCARG(&cup, fd) = SCARG(uap, fd); + SCARG(&cup, sb) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = fstat(td, &cup)) != 0) + return error; + + if ((error = copyin(SCARG(&cup, sb), &st, sizeof st)) != 0) + return error; + + bsd_to_svr4_stat64(&st, &svr4_st); + + if ((error = copyout(&svr4_st, SCARG(uap, sb), sizeof svr4_st)) != 0) + return error; + + return 0; +} + + +int +svr4_ustat(td, uap) + register struct thread *td; + struct svr4_ustat_args *uap; +{ + struct svr4_ustat us; + int error; + + memset(&us, 0, sizeof us); + + /* + * XXX: should set f_tfree and f_tinode at least + * How do we translate dev -> fstat? (and then to svr4_ustat) + */ + if ((error = copyout(&us, SCARG(uap, name), sizeof us)) != 0) + return (error); + + return 0; +} + +/*extern char ostype[], hostname[], osrelease[], version[], machine[];*/ + +int +svr4_sys_uname(td, uap) + register struct thread *td; + struct svr4_sys_uname_args *uap; +{ + struct svr4_utsname sut; + + memset(&sut, 0, sizeof(sut)); + + strncpy(sut.sysname, ostype, sizeof(sut.sysname)); + sut.sysname[sizeof(sut.sysname) - 1] = '\0'; + + getcredhostname(td->td_ucred, sut.nodename, sizeof(sut.nodename)); + + strncpy(sut.release, osrelease, sizeof(sut.release)); + sut.release[sizeof(sut.release) - 1] = '\0'; + + strncpy(sut.version, version, sizeof(sut.version)); + sut.version[sizeof(sut.version) - 1] = '\0'; + + strncpy(sut.machine, machine, sizeof(sut.machine)); + sut.machine[sizeof(sut.machine) - 1] = '\0'; + + return copyout((caddr_t) &sut, (caddr_t) SCARG(uap, name), + sizeof(struct svr4_utsname)); +} + +int +svr4_sys_systeminfo(td, uap) + struct thread *td; + struct svr4_sys_systeminfo_args *uap; +{ + char *str = NULL; + int error = 0; + register_t *retval = td->td_retval; + size_t len = 0; + char buf[1]; /* XXX NetBSD uses 256, but that seems + like awfully excessive kstack usage + for an empty string... */ + u_int rlen = SCARG(uap, len); + + switch (SCARG(uap, what)) { + case SVR4_SI_SYSNAME: + str = ostype; + break; + + case SVR4_SI_HOSTNAME: + str = hostname; + break; + + case SVR4_SI_RELEASE: + str = osrelease; + break; + + case SVR4_SI_VERSION: + str = version; + break; + + case SVR4_SI_MACHINE: + str = machine; + break; + + case SVR4_SI_ARCHITECTURE: + str = machine; + break; + + case SVR4_SI_HW_SERIAL: + str = "0"; + break; + + case SVR4_SI_HW_PROVIDER: + str = ostype; + break; + + case SVR4_SI_SRPC_DOMAIN: + str = domainname; + break; + + case SVR4_SI_PLATFORM: +#ifdef __i386__ + str = "i86pc"; +#else + str = "unknown"; +#endif + break; + + case SVR4_SI_KERB_REALM: + str = "unsupported"; + break; +#if defined(WHY_DOES_AN_EMULATOR_WANT_TO_SET_HOSTNAMES) + case SVR4_SI_SET_HOSTNAME: + if ((error = suser(td)) != 0) + return error; + name = KERN_HOSTNAME; + return kern_sysctl(&name, 1, 0, 0, SCARG(uap, buf), rlen, td); + + case SVR4_SI_SET_SRPC_DOMAIN: + if ((error = suser(td)) != 0) + return error; + name = KERN_NISDOMAINNAME; + return kern_sysctl(&name, 1, 0, 0, SCARG(uap, buf), rlen, td); +#else + case SVR4_SI_SET_HOSTNAME: + case SVR4_SI_SET_SRPC_DOMAIN: + /* FALLTHROUGH */ +#endif + case SVR4_SI_SET_KERB_REALM: + return 0; + + default: + DPRINTF(("Bad systeminfo command %d\n", SCARG(uap, what))); + return ENOSYS; + } + + if (str) { + len = strlen(str) + 1; + if (len > rlen) + len = rlen; + + if (SCARG(uap, buf)) { + error = copyout(str, SCARG(uap, buf), len); + if (error) + return error; + /* make sure we are NULL terminated */ + buf[0] = '\0'; + error = copyout(buf, &(SCARG(uap, buf)[len - 1]), 1); + } + else + error = 0; + } + /* XXX NetBSD has hostname setting stuff here. Why would an emulator + want to do that? */ + + *retval = len; + return error; +} + +int +svr4_sys_utssys(td, uap) + register struct thread *td; + struct svr4_sys_utssys_args *uap; +{ + switch (SCARG(uap, sel)) { + case 0: /* uname(2) */ + { + struct svr4_sys_uname_args ua; + SCARG(&ua, name) = SCARG(uap, a1); + return svr4_sys_uname(td, &ua); + } + + case 2: /* ustat(2) */ + { + struct svr4_ustat_args ua; + SCARG(&ua, dev) = (svr4_dev_t) SCARG(uap, a2); + SCARG(&ua, name) = SCARG(uap, a1); + return svr4_ustat(td, &ua); + } + + case 3: /* fusers(2) */ + return ENOSYS; + + default: + return ENOSYS; + } + return ENOSYS; +} + + +int +svr4_sys_utime(td, uap) + register struct thread *td; + struct svr4_sys_utime_args *uap; +{ + struct svr4_utimbuf ub; + struct timeval tbuf[2]; + struct utimes_args ap; + int error; + caddr_t sg = stackgap_init(); + void *ttp; + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + SCARG(&ap, path) = SCARG(uap, path); + if (SCARG(uap, ubuf) != NULL) { + if ((error = copyin(SCARG(uap, ubuf), &ub, sizeof(ub))) != 0) + return error; + tbuf[0].tv_sec = ub.actime; + tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = ub.modtime; + tbuf[1].tv_usec = 0; + ttp = stackgap_alloc(&sg, sizeof(tbuf)); + error = copyout(tbuf, ttp, sizeof(tbuf)); + if (error) + return error; + SCARG(&ap, tptr) = ttp; + } + else + SCARG(&ap, tptr) = NULL; + return utimes(td, &ap); +} + + +int +svr4_sys_utimes(td, uap) + register struct thread *td; + struct svr4_sys_utimes_args *uap; +{ + caddr_t sg = stackgap_init(); + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + return utimes(td, (struct utimes_args *)uap); +} + +static int +svr4_to_bsd_pathconf(name) + int name; +{ + switch (name) { + case SVR4_PC_LINK_MAX: + return _PC_LINK_MAX; + + case SVR4_PC_MAX_CANON: + return _PC_MAX_CANON; + + case SVR4_PC_MAX_INPUT: + return _PC_MAX_INPUT; + + case SVR4_PC_NAME_MAX: + return _PC_NAME_MAX; + + case SVR4_PC_PATH_MAX: + return _PC_PATH_MAX; + + case SVR4_PC_PIPE_BUF: + return _PC_PIPE_BUF; + + case SVR4_PC_NO_TRUNC: + return _PC_NO_TRUNC; + + case SVR4_PC_VDISABLE: + return _PC_VDISABLE; + + case SVR4_PC_CHOWN_RESTRICTED: + return _PC_CHOWN_RESTRICTED; + case SVR4_PC_SYNC_IO: +#if defined(_PC_SYNC_IO) + return _PC_SYNC_IO; +#else + return 0; +#endif + case SVR4_PC_ASYNC_IO: + case SVR4_PC_PRIO_IO: + /* Not supported */ + return 0; + + default: + /* Invalid */ + return -1; + } +} + + +int +svr4_sys_pathconf(td, uap) + register struct thread *td; + struct svr4_sys_pathconf_args *uap; +{ + caddr_t sg = stackgap_init(); + register_t *retval = td->td_retval; + + CHECKALTEXIST(td, &sg, SCARG(uap, path)); + + SCARG(uap, name) = svr4_to_bsd_pathconf(SCARG(uap, name)); + + switch (SCARG(uap, name)) { + case -1: + *retval = -1; + return EINVAL; + case 0: + *retval = 0; + return 0; + default: + return pathconf(td, (struct pathconf_args *)uap); + } +} + + +int +svr4_sys_fpathconf(td, uap) + register struct thread *td; + struct svr4_sys_fpathconf_args *uap; +{ + register_t *retval = td->td_retval; + + SCARG(uap, name) = svr4_to_bsd_pathconf(SCARG(uap, name)); + + switch (SCARG(uap, name)) { + case -1: + *retval = -1; + return EINVAL; + case 0: + *retval = 0; + return 0; + default: + return fpathconf(td, (struct fpathconf_args *)uap); + } +} diff --git a/sys/compat/svr4/svr4_stat.h b/sys/compat/svr4/svr4_stat.h new file mode 100644 index 0000000..e92aea6 --- /dev/null +++ b/sys/compat/svr4/svr4_stat.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_STAT_H_ +#define _SVR4_STAT_H_ + +#include <compat/svr4/svr4_types.h> +#include <sys/stat.h> + +struct svr4_stat { + svr4_o_dev_t st_dev; + svr4_o_ino_t st_ino; + svr4_o_mode_t st_mode; + svr4_o_nlink_t st_nlink; + svr4_o_uid_t st_uid; + svr4_o_gid_t st_gid; + svr4_o_dev_t st_rdev; + svr4_off_t st_size; + svr4_time_t st_atim; + svr4_time_t st_mtim; + svr4_time_t st_ctim; +}; + +struct svr4_xstat { + svr4_dev_t st_dev; + long st_pad1[3]; + svr4_ino_t st_ino; + svr4_mode_t st_mode; + svr4_nlink_t st_nlink; + svr4_uid_t st_uid; + svr4_gid_t st_gid; + svr4_dev_t st_rdev; + long st_pad2[2]; + svr4_off_t st_size; + long st_pad3; + svr4_timestruc_t st_atim; + svr4_timestruc_t st_mtim; + svr4_timestruc_t st_ctim; + long st_blksize; + svr4_blkcnt_t st_blocks; + char st_fstype[16]; + long st_pad4[8]; +}; + +struct svr4_stat64 { + svr4_dev_t st_dev; + long st_pad1[3]; + svr4_ino64_t st_ino; + svr4_mode_t st_mode; + svr4_nlink_t st_nlink; + svr4_uid_t st_uid; + svr4_gid_t st_gid; + svr4_dev_t st_rdev; + long st_pad2[2]; + svr4_off64_t st_size; + svr4_timestruc_t st_atim; + svr4_timestruc_t st_mtim; + svr4_timestruc_t st_ctim; + long st_blksize; + svr4_blkcnt64_t st_blocks; + char st_fstype[16]; + long st_pad4[8]; +}; + +#define SVR4_PC_LINK_MAX 1 +#define SVR4_PC_MAX_CANON 2 +#define SVR4_PC_MAX_INPUT 3 +#define SVR4_PC_NAME_MAX 4 +#define SVR4_PC_PATH_MAX 5 +#define SVR4_PC_PIPE_BUF 6 +#define SVR4_PC_NO_TRUNC 7 +#define SVR4_PC_VDISABLE 8 +#define SVR4_PC_CHOWN_RESTRICTED 9 +#define SVR4_PC_ASYNC_IO 10 +#define SVR4_PC_PRIO_IO 11 +#define SVR4_PC_SYNC_IO 12 + +#endif /* !_SVR4_STAT_H_ */ diff --git a/sys/compat/svr4/svr4_statvfs.h b/sys/compat/svr4/svr4_statvfs.h new file mode 100644 index 0000000..b3bf473 --- /dev/null +++ b/sys/compat/svr4/svr4_statvfs.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_STATVFS_H_ +#define _SVR4_STATVFS_H_ + +typedef struct svr4_statvfs { + u_long f_bsize; + u_long f_frsize; + svr4_fsblkcnt_t f_blocks; + svr4_fsblkcnt_t f_bfree; + svr4_fsblkcnt_t f_bavail; + svr4_fsblkcnt_t f_files; + svr4_fsblkcnt_t f_ffree; + svr4_fsblkcnt_t f_favail; + u_long f_fsid; + char f_basetype[16]; + u_long f_flag; + u_long f_namemax; + char f_fstr[32]; + u_long f_filler[16]; +} svr4_statvfs_t; + +typedef struct svr4_statvfs64 { + u_long f_bsize; + u_long f_frsize; + svr4_fsblkcnt64_t f_blocks; + svr4_fsblkcnt64_t f_bfree; + svr4_fsblkcnt64_t f_bavail; + svr4_fsblkcnt64_t f_files; + svr4_fsblkcnt64_t f_ffree; + svr4_fsblkcnt64_t f_favail; + u_long f_fsid; + char f_basetype[16]; + u_long f_flag; + u_long f_namemax; + char f_fstr[32]; + u_long f_filler[16]; +} svr4_statvfs64_t; + +#define SVR4_ST_RDONLY 0x01 +#define SVR4_ST_NOSUID 0x02 +#define SVR4_ST_NOTRUNC 0x04 + +#endif /* !_SVR4_STATVFS_H_ */ diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c new file mode 100644 index 0000000..2f0d5e3 --- /dev/null +++ b/sys/compat/svr4/svr4_stream.c @@ -0,0 +1,2295 @@ +/* + * Copyright (c) 1998 Mark Newton. All rights reserved. + * Copyright (c) 1994, 1996 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Pretend that we have streams... + * Yes, this is gross. + * + * ToDo: The state machine for getmsg needs re-thinking + */ + +#define COMPAT_43 1 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/fcntl.h> +#include <sys/filedesc.h> +#include <sys/filio.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/file.h> /* Must come after sys/malloc.h */ +#include <sys/mbuf.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/protosw.h> +#include <sys/signal.h> +#include <sys/signalvar.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/stat.h> +#include <sys/sysproto.h> +#include <sys/uio.h> +#include <sys/ktrace.h> /* Must come after sys/uio.h */ +#include <sys/un.h> + +#include <netinet/in.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_stropts.h> +#include <compat/svr4/svr4_timod.h> +#include <compat/svr4/svr4_sockmod.h> +#include <compat/svr4/svr4_ioctl.h> +#include <compat/svr4/svr4_socket.h> + +/* Utils */ +static int clean_pipe(struct thread *, const char *); +static void getparm(struct file *, struct svr4_si_sockparms *); +static int svr4_do_putmsg(struct thread *, struct svr4_sys_putmsg_args *, + struct file *); +static int svr4_do_getmsg(struct thread *, struct svr4_sys_getmsg_args *, + struct file *); + +/* Address Conversions */ +static void sockaddr_to_netaddr_in(struct svr4_strmcmd *, + const struct sockaddr_in *); +static void sockaddr_to_netaddr_un(struct svr4_strmcmd *, + const struct sockaddr_un *); +static void netaddr_to_sockaddr_in(struct sockaddr_in *, + const struct svr4_strmcmd *); +static void netaddr_to_sockaddr_un(struct sockaddr_un *, + const struct svr4_strmcmd *); + +/* stream ioctls */ +static int i_nread(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int i_fdinsert(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int i_str(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int i_setsig(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int i_getsig(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int _i_bind_rsvd(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); +static int _i_rele_rsvd(struct file *, struct thread *, register_t *, int, + u_long, caddr_t); + +/* i_str sockmod calls */ +static int sockmod(struct file *, int, struct svr4_strioctl *, + struct thread *); +static int si_listen(struct file *, int, struct svr4_strioctl *, + struct thread *); +static int si_ogetudata(struct file *, int, struct svr4_strioctl *, + struct thread *); +static int si_sockparams(struct file *, int, struct svr4_strioctl *, + struct thread *); +static int si_shutdown (struct file *, int, struct svr4_strioctl *, + struct thread *); +static int si_getudata(struct file *, int, struct svr4_strioctl *, + struct thread *); + +/* i_str timod calls */ +static int timod(struct file *, int, struct svr4_strioctl *, struct thread *); +static int ti_getinfo(struct file *, int, struct svr4_strioctl *, + struct thread *); +static int ti_bind(struct file *, int, struct svr4_strioctl *, struct thread *); + +/* infrastructure */ +static int svr4_sendit(struct thread *td, int s, struct msghdr *mp, int flags); + +static int svr4_recvit(struct thread *td, int s, struct msghdr *mp, + caddr_t namelenp); + +/* <sigh> Ok, so we shouldn't use sendit() in uipc_syscalls.c because + * it isn't part of a "public" interface; We're supposed to use + * pru_sosend instead. Same goes for recvit()/pru_soreceive() for + * that matter. Solution: Suck sendit()/recvit() into here where we + * can do what we like. + * + * I hate code duplication. + * + * I will take out all the #ifdef COMPAT_OLDSOCK gumph, though. + */ +static int +svr4_sendit(td, s, mp, flags) + register struct thread *td; + int s; + register struct msghdr *mp; + int flags; +{ + struct uio auio; + register struct iovec *iov; + register int i; + struct mbuf *control; + struct sockaddr *to; + int len, error; + struct socket *so; +#ifdef KTRACE + struct iovec *ktriov = NULL; + struct uio ktruio; +#endif + + if ((error = fgetsock(td, s, &so, NULL)) != 0) + return (error); + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = td; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + if ((auio.uio_resid += iov->iov_len) < 0) { + error = EINVAL; + goto done1; + } + } + if (mp->msg_name) { + error = getsockaddr(&to, mp->msg_name, mp->msg_namelen); + if (error) + goto done1; + } else { + to = 0; + } + if (mp->msg_control) { + if (mp->msg_controllen < sizeof(struct cmsghdr)) { + error = EINVAL; + goto bad; + } + error = sockargs(&control, mp->msg_control, + mp->msg_controllen, MT_CONTROL); + if (error) + goto bad; + } else { + control = 0; + } +#ifdef KTRACE + if (KTRPOINT(td, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + ktruio = auio; + } +#endif + len = auio.uio_resid; + error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, + flags, td); + if (error) { + if (auio.uio_resid != len && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + if (error == EPIPE) { + PROC_LOCK(td->td_proc); + psignal(td->td_proc, SIGPIPE); + PROC_UNLOCK(td->td_proc); + } + } + if (error == 0) + td->td_retval[0] = len - auio.uio_resid; +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) { + ktruio.uio_iov = ktriov; + ktruio.uio_resid = td->td_retval[0]; + ktrgenio(s, UIO_WRITE, &ktruio, error); + } + FREE(ktriov, M_TEMP); + } +#endif +bad: + if (to) + FREE(to, M_SONAME); +done1: + fputsock(so); + return (error); +} + +static int +svr4_recvit(td, s, mp, namelenp) + register struct thread *td; + int s; + register struct msghdr *mp; + caddr_t namelenp; +{ + struct uio auio; + register struct iovec *iov; + register int i; + int len, error; + struct mbuf *m, *control = 0; + caddr_t ctlbuf; + struct socket *so; + struct sockaddr *fromsa = 0; +#ifdef KTRACE + struct iovec *ktriov = NULL; + struct uio ktruio; +#endif + + if ((error = fgetsock(td, s, &so, NULL)) != 0) + return (error); + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++, iov++) { + if ((auio.uio_resid += iov->iov_len) < 0) { + error = EINVAL; + goto done1; + } + } +#ifdef KTRACE + if (KTRPOINT(td, KTR_GENIO)) { + int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + + MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); + bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); + ktruio = auio; + } +#endif + len = auio.uio_resid; + error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, + (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0, + &mp->msg_flags); + if (error) { + if (auio.uio_resid != len && (error == ERESTART || + error == EINTR || error == EWOULDBLOCK)) + error = 0; + } +#ifdef KTRACE + if (ktriov != NULL) { + if (error == 0) { + ktruio.uio_iov = ktriov; + ktruio.uio_resid = len - auio.uio_resid; + ktrgenio(s, UIO_READ, &ktruio, error); + } + FREE(ktriov, M_TEMP); + } +#endif + if (error) + goto out; + td->td_retval[0] = len - auio.uio_resid; + if (mp->msg_name) { + len = mp->msg_namelen; + if (len <= 0 || fromsa == 0) + len = 0; + else { +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif + /* save sa_len before it is destroyed by MSG_COMPAT */ + len = MIN(len, fromsa->sa_len); + error = copyout(fromsa, + (caddr_t)mp->msg_name, (unsigned)len); + if (error) + goto out; + } + mp->msg_namelen = len; + if (namelenp && + (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) { + goto out; + } + } + if (mp->msg_control) { + len = mp->msg_controllen; + m = control; + mp->msg_controllen = 0; + ctlbuf = (caddr_t) mp->msg_control; + + while (m && len > 0) { + unsigned int tocopy; + + if (len >= m->m_len) + tocopy = m->m_len; + else { + mp->msg_flags |= MSG_CTRUNC; + tocopy = len; + } + + if ((error = copyout((caddr_t)mtod(m, caddr_t), + ctlbuf, tocopy)) != 0) + goto out; + + ctlbuf += tocopy; + len -= tocopy; + m = m->m_next; + } + mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control; + } +out: + if (fromsa) + FREE(fromsa, M_SONAME); + if (control) + m_freem(control); +done1: + fputsock(so); + return (error); +} + +#ifdef DEBUG_SVR4 +static void bufprint(u_char *, size_t); +static int show_ioc(const char *, struct svr4_strioctl *); +static int show_strbuf(struct svr4_strbuf *); +static void show_msg(const char *, int, struct svr4_strbuf *, + struct svr4_strbuf *, int); + +static void +bufprint(buf, len) + u_char *buf; + size_t len; +{ + size_t i; + + uprintf("\n\t"); + for (i = 0; i < len; i++) { + uprintf("%x ", buf[i]); + if (i && (i % 16) == 0) + uprintf("\n\t"); + } +} + +static int +show_ioc(str, ioc) + const char *str; + struct svr4_strioctl *ioc; +{ + u_char *ptr = (u_char *) malloc(ioc->len, M_TEMP, M_WAITOK); + int error; + + uprintf("%s cmd = %ld, timeout = %d, len = %d, buf = %p { ", + str, ioc->cmd, ioc->timeout, ioc->len, ioc->buf); + + if ((error = copyin(ioc->buf, ptr, ioc->len)) != 0) { + free((char *) ptr, M_TEMP); + return error; + } + + bufprint(ptr, ioc->len); + + uprintf("}\n"); + + free((char *) ptr, M_TEMP); + return 0; +} + + +static int +show_strbuf(str) + struct svr4_strbuf *str; +{ + int error; + u_char *ptr = NULL; + int maxlen = str->maxlen; + int len = str->len; + + if (maxlen < 0) + maxlen = 0; + + if (len >= maxlen) + len = maxlen; + + if (len > 0) { + ptr = (u_char *) malloc(len, M_TEMP, M_WAITOK); + + if ((error = copyin(str->buf, ptr, len)) != 0) { + free((char *) ptr, M_TEMP); + return error; + } + } + + uprintf(", { %d, %d, %p=[ ", str->maxlen, str->len, str->buf); + + if (ptr) + bufprint(ptr, len); + + uprintf("]}"); + + if (ptr) + free((char *) ptr, M_TEMP); + + return 0; +} + + +static void +show_msg(str, fd, ctl, dat, flags) + const char *str; + int fd; + struct svr4_strbuf *ctl; + struct svr4_strbuf *dat; + int flags; +{ + struct svr4_strbuf buf; + int error; + + uprintf("%s(%d", str, fd); + if (ctl != NULL) { + if ((error = copyin(ctl, &buf, sizeof(buf))) != 0) + return; + show_strbuf(&buf); + } + else + uprintf(", NULL"); + + if (dat != NULL) { + if ((error = copyin(dat, &buf, sizeof(buf))) != 0) + return; + show_strbuf(&buf); + } + else + uprintf(", NULL"); + + uprintf(", %x);\n", flags); +} + +#endif /* DEBUG_SVR4 */ + +/* + * We are faced with an interesting situation. On svr4 unix sockets + * are really pipes. But we really have sockets, and we might as + * well use them. At the point where svr4 calls TI_BIND, it has + * already created a named pipe for the socket using mknod(2). + * We need to create a socket with the same name when we bind, + * so we need to remove the pipe before, otherwise we'll get address + * already in use. So we *carefully* remove the pipe, to avoid + * using this as a random file removal tool. We use system calls + * to avoid code duplication. + */ +static int +clean_pipe(td, path) + struct thread *td; + const char *path; +{ + struct lstat_args la; + struct unlink_args ua; + struct stat st; + int error; + caddr_t sg = stackgap_init(); + size_t l = strlen(path) + 1; + void *tpath; + + tpath = stackgap_alloc(&sg, l); + SCARG(&la, ub) = stackgap_alloc(&sg, sizeof(struct stat)); + + if ((error = copyout(path, tpath, l)) != 0) + return error; + + SCARG(&la, path) = tpath; + + if ((error = lstat(td, &la)) != 0) + return 0; + + if ((error = copyin(SCARG(&la, ub), &st, sizeof(st))) != 0) + return 0; + + /* + * Make sure we are dealing with a mode 0 named pipe. + */ + if ((st.st_mode & S_IFMT) != S_IFIFO) + return 0; + + if ((st.st_mode & ALLPERMS) != 0) + return 0; + + SCARG(&ua, path) = SCARG(&la, path); + + if ((error = unlink(td, &ua)) != 0) { + DPRINTF(("clean_pipe: unlink failed %d\n", error)); + return error; + } + + return 0; +} + + +static void +sockaddr_to_netaddr_in(sc, sain) + struct svr4_strmcmd *sc; + const struct sockaddr_in *sain; +{ + struct svr4_netaddr_in *na; + na = SVR4_ADDROF(sc); + + na->family = sain->sin_family; + na->port = sain->sin_port; + na->addr = sain->sin_addr.s_addr; + DPRINTF(("sockaddr_in -> netaddr %d %d %lx\n", na->family, na->port, + na->addr)); +} + + +static void +sockaddr_to_netaddr_un(sc, saun) + struct svr4_strmcmd *sc; + const struct sockaddr_un *saun; +{ + struct svr4_netaddr_un *na; + char *dst, *edst = ((char *) sc) + sc->offs + sizeof(na->family) + 1 - + sizeof(*sc); + const char *src; + + na = SVR4_ADDROF(sc); + na->family = saun->sun_family; + for (src = saun->sun_path, dst = na->path; (*dst++ = *src++) != '\0'; ) + if (dst == edst) + break; + DPRINTF(("sockaddr_un -> netaddr %d %s\n", na->family, na->path)); +} + + +static void +netaddr_to_sockaddr_in(sain, sc) + struct sockaddr_in *sain; + const struct svr4_strmcmd *sc; +{ + const struct svr4_netaddr_in *na; + + + na = SVR4_C_ADDROF(sc); + memset(sain, 0, sizeof(*sain)); + sain->sin_len = sizeof(*sain); + sain->sin_family = na->family; + sain->sin_port = na->port; + sain->sin_addr.s_addr = na->addr; + DPRINTF(("netaddr -> sockaddr_in %d %d %x\n", sain->sin_family, + sain->sin_port, sain->sin_addr.s_addr)); +} + + +static void +netaddr_to_sockaddr_un(saun, sc) + struct sockaddr_un *saun; + const struct svr4_strmcmd *sc; +{ + const struct svr4_netaddr_un *na; + char *dst, *edst = &saun->sun_path[sizeof(saun->sun_path) - 1]; + const char *src; + + na = SVR4_C_ADDROF(sc); + memset(saun, 0, sizeof(*saun)); + saun->sun_family = na->family; + for (src = na->path, dst = saun->sun_path; (*dst++ = *src++) != '\0'; ) + if (dst == edst) + break; + saun->sun_len = dst - saun->sun_path; + DPRINTF(("netaddr -> sockaddr_un %d %s\n", saun->sun_family, + saun->sun_path)); +} + + +static void +getparm(fp, pa) + struct file *fp; + struct svr4_si_sockparms *pa; +{ + struct svr4_strm *st; + struct socket *so; + + st = svr4_stream_get(fp); + if (st == NULL) + return; + + so = (struct socket *) fp->f_data; + + pa->family = st->s_family; + + switch (so->so_type) { + case SOCK_DGRAM: + pa->type = SVR4_T_CLTS; + pa->protocol = IPPROTO_UDP; + DPRINTF(("getparm(dgram)\n")); + return; + + case SOCK_STREAM: + pa->type = SVR4_T_COTS; /* What about T_COTS_ORD? XXX */ + pa->protocol = IPPROTO_IP; + DPRINTF(("getparm(stream)\n")); + return; + + case SOCK_RAW: + pa->type = SVR4_T_CLTS; + pa->protocol = IPPROTO_RAW; + DPRINTF(("getparm(raw)\n")); + return; + + default: + pa->type = 0; + pa->protocol = 0; + DPRINTF(("getparm(type %d?)\n", so->so_type)); + return; + } +} + + +static int +si_ogetudata(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct svr4_si_oudata ud; + struct svr4_si_sockparms pa; + + if (ioc->len != sizeof(ud) && ioc->len != sizeof(ud) - sizeof(int)) { + DPRINTF(("SI_OGETUDATA: Wrong size %d != %d\n", + sizeof(ud), ioc->len)); + return EINVAL; + } + + if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) + return error; + + getparm(fp, &pa); + + switch (pa.family) { + case AF_INET: + ud.tidusize = 16384; + ud.addrsize = sizeof(struct svr4_sockaddr_in); + if (pa.type == SVR4_SOCK_STREAM) + ud.etsdusize = 1; + else + ud.etsdusize = 0; + break; + + case AF_LOCAL: + ud.tidusize = 65536; + ud.addrsize = 128; + ud.etsdusize = 128; + break; + + default: + DPRINTF(("SI_OGETUDATA: Unsupported address family %d\n", + pa.family)); + return ENOSYS; + } + + /* I have no idea what these should be! */ + ud.optsize = 128; + ud.tsdusize = 128; + + ud.servtype = pa.type; + + /* XXX: Fixme */ + ud.so_state = 0; + ud.so_options = 0; + return copyout(&ud, ioc->buf, ioc->len); +} + + +static int +si_sockparams(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + struct svr4_si_sockparms pa; + + getparm(fp, &pa); + return copyout(&pa, ioc->buf, sizeof(pa)); +} + + +static int +si_listen(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct svr4_strm *st = svr4_stream_get(fp); + struct svr4_strmcmd lst; + struct listen_args la; + + if (st == NULL) + return EINVAL; + + if ((error = copyin(ioc->buf, &lst, ioc->len)) != 0) + return error; + + if (lst.cmd != SVR4_TI_OLD_BIND_REQUEST) { + DPRINTF(("si_listen: bad request %ld\n", lst.cmd)); + return EINVAL; + } + + /* + * We are making assumptions again... + */ + SCARG(&la, s) = fd; + DPRINTF(("SI_LISTEN: fileno %d backlog = %d\n", fd, 5)); + SCARG(&la, backlog) = 5; + + if ((error = listen(td, &la)) != 0) { + DPRINTF(("SI_LISTEN: listen failed %d\n", error)); + return error; + } + + st->s_cmd = SVR4_TI__ACCEPT_WAIT; + lst.cmd = SVR4_TI_BIND_REPLY; + + switch (st->s_family) { + case AF_INET: + /* XXX: Fill the length here */ + break; + + case AF_LOCAL: + lst.len = 140; + lst.pad[28] = 0x00000000; /* magic again */ + lst.pad[29] = 0x00000800; /* magic again */ + lst.pad[30] = 0x80001400; /* magic again */ + break; + + default: + DPRINTF(("SI_LISTEN: Unsupported address family %d\n", + st->s_family)); + return ENOSYS; + } + + + if ((error = copyout(&lst, ioc->buf, ioc->len)) != 0) + return error; + + return 0; +} + + +static int +si_getudata(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct svr4_si_udata ud; + + if (sizeof(ud) != ioc->len) { + DPRINTF(("SI_GETUDATA: Wrong size %d != %d\n", + sizeof(ud), ioc->len)); + return EINVAL; + } + + if ((error = copyin(ioc->buf, &ud, sizeof(ud))) != 0) + return error; + + getparm(fp, &ud.sockparms); + + switch (ud.sockparms.family) { + case AF_INET: + DPRINTF(("getudata_inet\n")); + ud.tidusize = 16384; + ud.tsdusize = 16384; + ud.addrsize = sizeof(struct svr4_sockaddr_in); + if (ud.sockparms.type == SVR4_SOCK_STREAM) + ud.etsdusize = 1; + else + ud.etsdusize = 0; + ud.optsize = 0; + break; + + case AF_LOCAL: + DPRINTF(("getudata_local\n")); + ud.tidusize = 65536; + ud.tsdusize = 128; + ud.addrsize = 128; + ud.etsdusize = 128; + ud.optsize = 128; + break; + + default: + DPRINTF(("SI_GETUDATA: Unsupported address family %d\n", + ud.sockparms.family)); + return ENOSYS; + } + + + ud.servtype = ud.sockparms.type; + DPRINTF(("ud.servtype = %d\n", ud.servtype)); + /* XXX: Fixme */ + ud.so_state = 0; + ud.so_options = 0; + return copyout(&ud, ioc->buf, sizeof(ud)); +} + + +static int +si_shutdown(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct shutdown_args ap; + + if (ioc->len != sizeof(SCARG(&ap, how))) { + DPRINTF(("SI_SHUTDOWN: Wrong size %d != %d\n", + sizeof(SCARG(&ap, how)), ioc->len)); + return EINVAL; + } + + if ((error = copyin(ioc->buf, &SCARG(&ap, how), ioc->len)) != 0) + return error; + + SCARG(&ap, s) = fd; + + return shutdown(td, &ap); +} + + +static int +sockmod(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + switch (ioc->cmd) { + case SVR4_SI_OGETUDATA: + DPRINTF(("SI_OGETUDATA\n")); + return si_ogetudata(fp, fd, ioc, td); + + case SVR4_SI_SHUTDOWN: + DPRINTF(("SI_SHUTDOWN\n")); + return si_shutdown(fp, fd, ioc, td); + + case SVR4_SI_LISTEN: + DPRINTF(("SI_LISTEN\n")); + return si_listen(fp, fd, ioc, td); + + case SVR4_SI_SETMYNAME: + DPRINTF(("SI_SETMYNAME\n")); + return 0; + + case SVR4_SI_SETPEERNAME: + DPRINTF(("SI_SETPEERNAME\n")); + return 0; + + case SVR4_SI_GETINTRANSIT: + DPRINTF(("SI_GETINTRANSIT\n")); + return 0; + + case SVR4_SI_TCL_LINK: + DPRINTF(("SI_TCL_LINK\n")); + return 0; + + case SVR4_SI_TCL_UNLINK: + DPRINTF(("SI_TCL_UNLINK\n")); + return 0; + + case SVR4_SI_SOCKPARAMS: + DPRINTF(("SI_SOCKPARAMS\n")); + return si_sockparams(fp, fd, ioc, td); + + case SVR4_SI_GETUDATA: + DPRINTF(("SI_GETUDATA\n")); + return si_getudata(fp, fd, ioc, td); + + default: + DPRINTF(("Unknown sockmod ioctl %lx\n", ioc->cmd)); + return 0; + + } +} + + +static int +ti_getinfo(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct svr4_infocmd info; + + memset(&info, 0, sizeof(info)); + + if ((error = copyin(ioc->buf, &info, ioc->len)) != 0) + return error; + + if (info.cmd != SVR4_TI_INFO_REQUEST) + return EINVAL; + + info.cmd = SVR4_TI_INFO_REPLY; + info.tsdu = 0; + info.etsdu = 1; + info.cdata = -2; + info.ddata = -2; + info.addr = 16; + info.opt = -1; + info.tidu = 16384; + info.serv = 2; + info.current = 0; + info.provider = 2; + + ioc->len = sizeof(info); + if ((error = copyout(&info, ioc->buf, ioc->len)) != 0) + return error; + + return 0; +} + + +static int +ti_bind(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + int error; + struct svr4_strm *st = svr4_stream_get(fp); + struct sockaddr_in sain; + struct sockaddr_un saun; + caddr_t sg; + void *skp, *sup = NULL; + int sasize; + struct svr4_strmcmd bnd; + struct bind_args ba; + + if (st == NULL) { + DPRINTF(("ti_bind: bad file descriptor\n")); + return EINVAL; + } + + if ((error = copyin(ioc->buf, &bnd, ioc->len)) != 0) + return error; + + if (bnd.cmd != SVR4_TI_OLD_BIND_REQUEST) { + DPRINTF(("ti_bind: bad request %ld\n", bnd.cmd)); + return EINVAL; + } + + switch (st->s_family) { + case AF_INET: + skp = &sain; + sasize = sizeof(sain); + + if (bnd.offs == 0) + goto reply; + + netaddr_to_sockaddr_in(&sain, &bnd); + + DPRINTF(("TI_BIND: fam %d, port %d, addr %x\n", + sain.sin_family, sain.sin_port, + sain.sin_addr.s_addr)); + break; + + case AF_LOCAL: + skp = &saun; + sasize = sizeof(saun); + if (bnd.offs == 0) + goto reply; + + netaddr_to_sockaddr_un(&saun, &bnd); + + if (saun.sun_path[0] == '\0') + goto reply; + + DPRINTF(("TI_BIND: fam %d, path %s\n", + saun.sun_family, saun.sun_path)); + + if ((error = clean_pipe(td, saun.sun_path)) != 0) + return error; + + bnd.pad[28] = 0x00001000; /* magic again */ + break; + + default: + DPRINTF(("TI_BIND: Unsupported address family %d\n", + st->s_family)); + return ENOSYS; + } + + sg = stackgap_init(); + sup = stackgap_alloc(&sg, sasize); + + if ((error = copyout(skp, sup, sasize)) != 0) + return error; + + SCARG(&ba, s) = fd; + DPRINTF(("TI_BIND: fileno %d\n", fd)); + SCARG(&ba, name) = (void *) sup; + SCARG(&ba, namelen) = sasize; + + if ((error = bind(td, &ba)) != 0) { + DPRINTF(("TI_BIND: bind failed %d\n", error)); + return error; + } + +reply: + if (sup == NULL) { + memset(&bnd, 0, sizeof(bnd)); + bnd.len = sasize + 4; + bnd.offs = 0x10; /* XXX */ + } + + bnd.cmd = SVR4_TI_BIND_REPLY; + + if ((error = copyout(&bnd, ioc->buf, ioc->len)) != 0) + return error; + + return 0; +} + + +static int +timod(fp, fd, ioc, td) + struct file *fp; + int fd; + struct svr4_strioctl *ioc; + struct thread *td; +{ + switch (ioc->cmd) { + case SVR4_TI_GETINFO: + DPRINTF(("TI_GETINFO\n")); + return ti_getinfo(fp, fd, ioc, td); + + case SVR4_TI_OPTMGMT: + DPRINTF(("TI_OPTMGMT\n")); + return 0; + + case SVR4_TI_BIND: + DPRINTF(("TI_BIND\n")); + return ti_bind(fp, fd, ioc, td); + + case SVR4_TI_UNBIND: + DPRINTF(("TI_UNBIND\n")); + return 0; + + default: + DPRINTF(("Unknown timod ioctl %lx\n", ioc->cmd)); + return 0; + } +} + + +int +svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat; + struct svr4_strm *st = svr4_stream_get(fp); + int error; + void *skp, *sup; + struct sockaddr_in sain; + struct sockaddr_un saun; + struct svr4_strmcmd sc; + int sasize; + caddr_t sg; + int *lenp; + + DPRINTF(("svr4_stream_ti_ioctl\n")); + + if (st == NULL) + return EINVAL; + + sc.offs = 0x10; + + if ((error = copyin(sub, &skb, sizeof(skb))) != 0) { + DPRINTF(("ti_ioctl: error copying in strbuf\n")); + return error; + } + + switch (st->s_family) { + case AF_INET: + skp = &sain; + sasize = sizeof(sain); + break; + + case AF_LOCAL: + skp = &saun; + sasize = sizeof(saun); + break; + + default: + DPRINTF(("ti_ioctl: Unsupported address family %d\n", + st->s_family)); + return ENOSYS; + } + + sg = stackgap_init(); + sup = stackgap_alloc(&sg, sasize); + lenp = stackgap_alloc(&sg, sizeof(*lenp)); + + if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) { + DPRINTF(("ti_ioctl: error copying out lenp\n")); + return error; + } + + switch (cmd) { + case SVR4_TI_GETMYNAME: + DPRINTF(("TI_GETMYNAME\n")); + { + struct getsockname_args ap; + SCARG(&ap, fdes) = fd; + SCARG(&ap, asa) = sup; + SCARG(&ap, alen) = lenp; + if ((error = getsockname(td, &ap)) != 0) { + DPRINTF(("ti_ioctl: getsockname error\n")); + return error; + } + } + break; + + case SVR4_TI_GETPEERNAME: + DPRINTF(("TI_GETPEERNAME\n")); + { + struct getpeername_args ap; + SCARG(&ap, fdes) = fd; + SCARG(&ap, asa) = sup; + SCARG(&ap, alen) = lenp; + if ((error = getpeername(td, &ap)) != 0) { + DPRINTF(("ti_ioctl: getpeername error\n")); + return error; + } + } + break; + + case SVR4_TI_SETMYNAME: + DPRINTF(("TI_SETMYNAME\n")); + return 0; + + case SVR4_TI_SETPEERNAME: + DPRINTF(("TI_SETPEERNAME\n")); + return 0; + default: + DPRINTF(("ti_ioctl: Unknown ioctl %lx\n", cmd)); + return ENOSYS; + } + + if ((error = copyin(sup, skp, sasize)) != 0) { + DPRINTF(("ti_ioctl: error copying in socket data\n")); + return error; + } + + if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) { + DPRINTF(("ti_ioctl: error copying in socket size\n")); + return error; + } + + switch (st->s_family) { + case AF_INET: + sockaddr_to_netaddr_in(&sc, &sain); + skb.len = sasize; + break; + + case AF_LOCAL: + sockaddr_to_netaddr_un(&sc, &saun); + skb.len = sasize + 4; + break; + + default: + return ENOSYS; + } + + + if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) { + DPRINTF(("ti_ioctl: error copying out socket data\n")); + return error; + } + + + if ((error = copyout(&skb, sub, sizeof(skb))) != 0) { + DPRINTF(("ti_ioctl: error copying out strbuf\n")); + return error; + } + + return error; +} + + + + +static int +i_nread(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + int error; + int nread = 0; + + /* + * We are supposed to return the message length in nread, and the + * number of messages in retval. We don't have the notion of number + * of stream messages, so we just find out if we have any bytes waiting + * for us, and if we do, then we assume that we have at least one + * message waiting for us. + */ + if ((error = fo_ioctl(fp, FIONREAD, (caddr_t) &nread, td)) != 0) + return error; + + if (nread != 0) + *retval = 1; + else + *retval = 0; + + return copyout(&nread, dat, sizeof(nread)); +} + +static int +i_fdinsert(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + /* + * Major hack again here. We assume that we are using this to + * implement accept(2). If that is the case, we have already + * called accept, and we have stored the file descriptor in + * afd. We find the file descriptor that the code wants to use + * in fd insert, and then we dup2() our accepted file descriptor + * to it. + */ + int error; + struct svr4_strm *st = svr4_stream_get(fp); + struct svr4_strfdinsert fdi; + struct dup2_args d2p; + struct close_args clp; + + if (st == NULL) { + DPRINTF(("fdinsert: bad file type\n")); + return EINVAL; + } + + if (st->s_afd == -1) { + DPRINTF(("fdinsert: accept fd not found\n")); + return ENOENT; + } + + if ((error = copyin(dat, &fdi, sizeof(fdi))) != 0) { + DPRINTF(("fdinsert: copyin failed %d\n", error)); + return error; + } + + SCARG(&d2p, from) = st->s_afd; + SCARG(&d2p, to) = fdi.fd; + + if ((error = dup2(td, &d2p)) != 0) { + DPRINTF(("fdinsert: dup2(%d, %d) failed %d\n", + st->s_afd, fdi.fd, error)); + return error; + } + + SCARG(&clp, fd) = st->s_afd; + + if ((error = close(td, &clp)) != 0) { + DPRINTF(("fdinsert: close(%d) failed %d\n", + st->s_afd, error)); + return error; + } + + st->s_afd = -1; + + *retval = 0; + return 0; +} + + +static int +_i_bind_rsvd(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + struct mkfifo_args ap; + + /* + * This is a supposed to be a kernel and library only ioctl. + * It gets called before ti_bind, when we have a unix + * socket, to physically create the socket transport and + * ``reserve'' it. I don't know how this get reserved inside + * the kernel, but we are going to create it nevertheless. + */ + SCARG(&ap, path) = dat; + SCARG(&ap, mode) = S_IFIFO; + + return mkfifo(td, &ap); +} + +static int +_i_rele_rsvd(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + struct unlink_args ap; + + /* + * This is a supposed to be a kernel and library only ioctl. + * I guess it is supposed to release the socket. + */ + SCARG(&ap, path) = dat; + + return unlink(td, &ap); +} + +static int +i_str(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + int error; + struct svr4_strioctl ioc; + + if ((error = copyin(dat, &ioc, sizeof(ioc))) != 0) + return error; + +#ifdef DEBUG_SVR4 + if ((error = show_ioc(">", &ioc)) != 0) + return error; +#endif /* DEBUG_SVR4 */ + + switch (ioc.cmd & 0xff00) { + case SVR4_SIMOD: + if ((error = sockmod(fp, fd, &ioc, td)) != 0) + return error; + break; + + case SVR4_TIMOD: + if ((error = timod(fp, fd, &ioc, td)) != 0) + return error; + break; + + default: + DPRINTF(("Unimplemented module %c %ld\n", + (char) (cmd >> 8), cmd & 0xff)); + return 0; + } + +#ifdef DEBUG_SVR4 + if ((error = show_ioc("<", &ioc)) != 0) + return error; +#endif /* DEBUG_SVR4 */ + return copyout(&ioc, dat, sizeof(ioc)); +} + +static int +i_setsig(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + /* + * This is the best we can do for now; we cannot generate + * signals only for specific events so the signal mask gets + * ignored; we save it just to pass it to a possible I_GETSIG... + * + * We alse have to fix the O_ASYNC fcntl bit, so the + * process will get SIGPOLLs. + */ + struct fcntl_args fa; + int error; + register_t oflags, flags; + struct svr4_strm *st = svr4_stream_get(fp); + + if (st == NULL) { + DPRINTF(("i_setsig: bad file descriptor\n")); + return EINVAL; + } + /* get old status flags */ + SCARG(&fa, fd) = fd; + SCARG(&fa, cmd) = F_GETFL; + if ((error = fcntl(td, &fa)) != 0) + return error; + + oflags = td->td_retval[0]; + + /* update the flags */ + if (dat != NULL) { + int mask; + + flags = oflags | O_ASYNC; + if ((error = copyin(dat, &mask, sizeof(mask))) != 0) { + DPRINTF(("i_setsig: bad eventmask pointer\n")); + return error; + } + if (mask & SVR4_S_ALLMASK) { + DPRINTF(("i_setsig: bad eventmask data %x\n", mask)); + return EINVAL; + } + st->s_eventmask = mask; + } + else { + flags = oflags & ~O_ASYNC; + st->s_eventmask = 0; + } + + /* set the new flags, if changed */ + if (flags != oflags) { + SCARG(&fa, cmd) = F_SETFL; + SCARG(&fa, arg) = (long) flags; + if ((error = fcntl(td, &fa)) != 0) + return error; + flags = td->td_retval[0]; + } + + /* set up SIGIO receiver if needed */ + if (dat != NULL) { + SCARG(&fa, cmd) = F_SETOWN; + SCARG(&fa, arg) = (long) td->td_proc->p_pid; + return fcntl(td, &fa); + } + return 0; +} + +static int +i_getsig(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + int error; + + if (dat != NULL) { + struct svr4_strm *st = svr4_stream_get(fp); + + if (st == NULL) { + DPRINTF(("i_getsig: bad file descriptor\n")); + return EINVAL; + } + if ((error = copyout(&st->s_eventmask, dat, + sizeof(st->s_eventmask))) != 0) { + DPRINTF(("i_getsig: bad eventmask pointer\n")); + return error; + } + } + return 0; +} + +int +svr4_stream_ioctl(fp, td, retval, fd, cmd, dat) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t dat; +{ + *retval = 0; + + /* + * All the following stuff assumes "sockmod" is pushed... + */ + switch (cmd) { + case SVR4_I_NREAD: + DPRINTF(("I_NREAD\n")); + return i_nread(fp, td, retval, fd, cmd, dat); + + case SVR4_I_PUSH: + DPRINTF(("I_PUSH %p\n", dat)); +#if defined(DEBUG_SVR4) + show_strbuf((struct svr4_strbuf *)dat); +#endif + return 0; + + case SVR4_I_POP: + DPRINTF(("I_POP\n")); + return 0; + + case SVR4_I_LOOK: + DPRINTF(("I_LOOK\n")); + return 0; + + case SVR4_I_FLUSH: + DPRINTF(("I_FLUSH\n")); + return 0; + + case SVR4_I_SRDOPT: + DPRINTF(("I_SRDOPT\n")); + return 0; + + case SVR4_I_GRDOPT: + DPRINTF(("I_GRDOPT\n")); + return 0; + + case SVR4_I_STR: + DPRINTF(("I_STR\n")); + return i_str(fp, td, retval, fd, cmd, dat); + + case SVR4_I_SETSIG: + DPRINTF(("I_SETSIG\n")); + return i_setsig(fp, td, retval, fd, cmd, dat); + + case SVR4_I_GETSIG: + DPRINTF(("I_GETSIG\n")); + return i_getsig(fp, td, retval, fd, cmd, dat); + + case SVR4_I_FIND: + DPRINTF(("I_FIND\n")); + /* + * Here we are not pushing modules really, we just + * pretend all are present + */ + *retval = 0; + return 0; + + case SVR4_I_LINK: + DPRINTF(("I_LINK\n")); + return 0; + + case SVR4_I_UNLINK: + DPRINTF(("I_UNLINK\n")); + return 0; + + case SVR4_I_ERECVFD: + DPRINTF(("I_ERECVFD\n")); + return 0; + + case SVR4_I_PEEK: + DPRINTF(("I_PEEK\n")); + return 0; + + case SVR4_I_FDINSERT: + DPRINTF(("I_FDINSERT\n")); + return i_fdinsert(fp, td, retval, fd, cmd, dat); + + case SVR4_I_SENDFD: + DPRINTF(("I_SENDFD\n")); + return 0; + + case SVR4_I_RECVFD: + DPRINTF(("I_RECVFD\n")); + return 0; + + case SVR4_I_SWROPT: + DPRINTF(("I_SWROPT\n")); + return 0; + + case SVR4_I_GWROPT: + DPRINTF(("I_GWROPT\n")); + return 0; + + case SVR4_I_LIST: + DPRINTF(("I_LIST\n")); + return 0; + + case SVR4_I_PLINK: + DPRINTF(("I_PLINK\n")); + return 0; + + case SVR4_I_PUNLINK: + DPRINTF(("I_PUNLINK\n")); + return 0; + + case SVR4_I_SETEV: + DPRINTF(("I_SETEV\n")); + return 0; + + case SVR4_I_GETEV: + DPRINTF(("I_GETEV\n")); + return 0; + + case SVR4_I_STREV: + DPRINTF(("I_STREV\n")); + return 0; + + case SVR4_I_UNSTREV: + DPRINTF(("I_UNSTREV\n")); + return 0; + + case SVR4_I_FLUSHBAND: + DPRINTF(("I_FLUSHBAND\n")); + return 0; + + case SVR4_I_CKBAND: + DPRINTF(("I_CKBAND\n")); + return 0; + + case SVR4_I_GETBAND: + DPRINTF(("I_GETBANK\n")); + return 0; + + case SVR4_I_ATMARK: + DPRINTF(("I_ATMARK\n")); + return 0; + + case SVR4_I_SETCLTIME: + DPRINTF(("I_SETCLTIME\n")); + return 0; + + case SVR4_I_GETCLTIME: + DPRINTF(("I_GETCLTIME\n")); + return 0; + + case SVR4_I_CANPUT: + DPRINTF(("I_CANPUT\n")); + return 0; + + case SVR4__I_BIND_RSVD: + DPRINTF(("_I_BIND_RSVD\n")); + return _i_bind_rsvd(fp, td, retval, fd, cmd, dat); + + case SVR4__I_RELE_RSVD: + DPRINTF(("_I_RELE_RSVD\n")); + return _i_rele_rsvd(fp, td, retval, fd, cmd, dat); + + default: + DPRINTF(("unimpl cmd = %lx\n", cmd)); + break; + } + + return 0; +} + + + +int +svr4_sys_putmsg(td, uap) + register struct thread *td; + struct svr4_sys_putmsg_args *uap; +{ + struct file *fp; + int error; + + if ((error = fget(td, uap->fd, &fp)) != 0) { +#ifdef DEBUG_SVR4 + uprintf("putmsg: bad fp\n"); +#endif + return EBADF; + } + error = svr4_do_putmsg(td, uap, fp); + fdrop(fp, td); + return (error); +} + +static int +svr4_do_putmsg(td, uap, fp) + struct thread *td; + struct svr4_sys_putmsg_args *uap; + struct file *fp; +{ + struct svr4_strbuf dat, ctl; + struct svr4_strmcmd sc; + struct sockaddr_in sain; + struct sockaddr_un saun; + void *skp, *sup; + int sasize, *retval; + struct svr4_strm *st; + int error; + caddr_t sg; + + retval = td->td_retval; + +#ifdef DEBUG_SVR4 + show_msg(">putmsg", SCARG(uap, fd), SCARG(uap, ctl), + SCARG(uap, dat), SCARG(uap, flags)); +#endif /* DEBUG_SVR4 */ + + FILE_LOCK_ASSERT(fp, MA_NOTOWNED); + + if (SCARG(uap, ctl) != NULL) { + if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) { +#ifdef DEBUG_SVR4 + uprintf("putmsg: copyin(): %d\n", error); +#endif + return error; + } + } + else + ctl.len = -1; + + if (SCARG(uap, dat) != NULL) { + if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) { +#ifdef DEBUG_SVR4 + uprintf("putmsg: copyin(): %d (2)\n", error); +#endif + return error; + } + } + else + dat.len = -1; + + /* + * Only for sockets for now. + */ + if ((st = svr4_stream_get(fp)) == NULL) { + DPRINTF(("putmsg: bad file type\n")); + return EINVAL; + } + + if (ctl.len > sizeof(sc)) { + DPRINTF(("putmsg: Bad control size %d != %d\n", ctl.len, + sizeof(struct svr4_strmcmd))); + return EINVAL; + } + + if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) + return error; + + switch (st->s_family) { + case AF_INET: + if (sc.len != sizeof(sain)) { + if (sc.cmd == SVR4_TI_DATA_REQUEST) { + struct write_args wa; + + /* Solaris seems to use sc.cmd = 3 to + * send "expedited" data. telnet uses + * this for options processing, sending EOF, + * etc. I'm sure other things use it too. + * I don't have any documentation + * on it, so I'm making a guess that this + * is how it works. newton@atdot.dotat.org XXX + */ + DPRINTF(("sending expedited data ??\n")); + SCARG(&wa, fd) = SCARG(uap, fd); + SCARG(&wa, buf) = dat.buf; + SCARG(&wa, nbyte) = dat.len; + return write(td, &wa); + } + DPRINTF(("putmsg: Invalid inet length %ld\n", sc.len)); + return EINVAL; + } + netaddr_to_sockaddr_in(&sain, &sc); + skp = &sain; + sasize = sizeof(sain); + error = sain.sin_family != st->s_family; + break; + + case AF_LOCAL: + if (ctl.len == 8) { + /* We are doing an accept; succeed */ + DPRINTF(("putmsg: Do nothing\n")); + *retval = 0; + return 0; + } + else { + /* Maybe we've been given a device/inode pair */ + udev_t *dev = SVR4_ADDROF(&sc); + ino_t *ino = (ino_t *) &dev[1]; + skp = svr4_find_socket(td, fp, *dev, *ino); + if (skp == NULL) { + skp = &saun; + /* I guess we have it by name */ + netaddr_to_sockaddr_un(skp, &sc); + } + sasize = sizeof(saun); + } + break; + + default: + DPRINTF(("putmsg: Unsupported address family %d\n", + st->s_family)); + return ENOSYS; + } + + sg = stackgap_init(); + sup = stackgap_alloc(&sg, sasize); + + if ((error = copyout(skp, sup, sasize)) != 0) + return error; + + switch (st->s_cmd = sc.cmd) { + case SVR4_TI_CONNECT_REQUEST: /* connect */ + { + struct connect_args co; + + SCARG(&co, s) = SCARG(uap, fd); + SCARG(&co, name) = (void *) sup; + SCARG(&co, namelen) = (int) sasize; + + return connect(td, &co); + } + + case SVR4_TI_SENDTO_REQUEST: /* sendto */ + { + struct msghdr msg; + struct iovec aiov; + + msg.msg_name = (caddr_t) sup; + msg.msg_namelen = sasize; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; + msg.msg_control = 0; + msg.msg_flags = 0; + aiov.iov_base = dat.buf; + aiov.iov_len = dat.len; +#if 0 + error = so->so_proto->pr_usrreqs->pru_sosend(so, 0, + uio, 0, 0, 0, uio->uio_td); +#endif + error = svr4_sendit(td, SCARG(uap, fd), &msg, + SCARG(uap, flags)); + DPRINTF(("sendto_request error: %d\n", error)); + *retval = 0; + return error; + } + + default: + DPRINTF(("putmsg: Unimplemented command %lx\n", sc.cmd)); + return ENOSYS; + } +} + +int +svr4_sys_getmsg(td, uap) + struct thread *td; + struct svr4_sys_getmsg_args *uap; +{ + struct file *fp; + int error; + + if ((error = fget(td, uap->fd, &fp)) != 0) { +#ifdef DEBUG_SVR4 + uprintf("getmsg: bad fp\n"); +#endif + return EBADF; + } + error = svr4_do_getmsg(td, uap, fp); + fdrop(fp, td); + return (error); +} + +int +svr4_do_getmsg(td, uap, fp) + register struct thread *td; + struct svr4_sys_getmsg_args *uap; + struct file *fp; +{ + struct getpeername_args ga; + struct accept_args aa; + struct svr4_strbuf dat, ctl; + struct svr4_strmcmd sc; + int error, *retval; + struct msghdr msg; + struct iovec aiov; + struct sockaddr_in sain; + struct sockaddr_un saun; + void *skp, *sup; + int sasize; + struct svr4_strm *st; + int *flen; + int fl; + caddr_t sg; + + retval = td->td_retval; + + FILE_LOCK_ASSERT(fp, MA_NOTOWNED); + + memset(&sc, 0, sizeof(sc)); + +#ifdef DEBUG_SVR4 + show_msg(">getmsg", SCARG(uap, fd), SCARG(uap, ctl), + SCARG(uap, dat), 0); +#endif /* DEBUG_SVR4 */ + + if (SCARG(uap, ctl) != NULL) { + if ((error = copyin(SCARG(uap, ctl), &ctl, sizeof(ctl))) != 0) + return error; + } + else { + ctl.len = -1; + ctl.maxlen = 0; + } + + if (SCARG(uap, dat) != NULL) { + if ((error = copyin(SCARG(uap, dat), &dat, sizeof(dat))) != 0) + return error; + } + else { + dat.len = -1; + dat.maxlen = 0; + } + + /* + * Only for sockets for now. + */ + if ((st = svr4_stream_get(fp)) == NULL) { + DPRINTF(("getmsg: bad file type\n")); + return EINVAL; + } + + if (ctl.maxlen == -1 || dat.maxlen == -1) { + DPRINTF(("getmsg: Cannot handle -1 maxlen (yet)\n")); + return ENOSYS; + } + + switch (st->s_family) { + case AF_INET: + skp = &sain; + sasize = sizeof(sain); + break; + + case AF_LOCAL: + skp = &saun; + sasize = sizeof(saun); + break; + + default: + DPRINTF(("getmsg: Unsupported address family %d\n", + st->s_family)); + return ENOSYS; + } + + sg = stackgap_init(); + sup = stackgap_alloc(&sg, sasize); + flen = (int *) stackgap_alloc(&sg, sizeof(*flen)); + + fl = sasize; + if ((error = copyout(&fl, flen, sizeof(fl))) != 0) + return error; + + switch (st->s_cmd) { + case SVR4_TI_CONNECT_REQUEST: + DPRINTF(("getmsg: TI_CONNECT_REQUEST\n")); + /* + * We do the connect in one step, so the putmsg should + * have gotten the error. + */ + sc.cmd = SVR4_TI_OK_REPLY; + sc.len = 0; + + ctl.len = 8; + dat.len = -1; + fl = 1; + st->s_cmd = sc.cmd; + break; + + case SVR4_TI_OK_REPLY: + DPRINTF(("getmsg: TI_OK_REPLY\n")); + /* + * We are immediately after a connect reply, so we send + * a connect verification. + */ + + SCARG(&ga, fdes) = SCARG(uap, fd); + SCARG(&ga, asa) = (void *) sup; + SCARG(&ga, alen) = flen; + + if ((error = getpeername(td, &ga)) != 0) { + DPRINTF(("getmsg: getpeername failed %d\n", error)); + return error; + } + + if ((error = copyin(sup, skp, sasize)) != 0) + return error; + + sc.cmd = SVR4_TI_CONNECT_REPLY; + sc.pad[0] = 0x4; + sc.offs = 0x18; + sc.pad[1] = 0x14; + sc.pad[2] = 0x04000402; + + switch (st->s_family) { + case AF_INET: + sc.len = sasize; + sockaddr_to_netaddr_in(&sc, &sain); + break; + + case AF_LOCAL: + sc.len = sasize + 4; + sockaddr_to_netaddr_un(&sc, &saun); + break; + + default: + return ENOSYS; + } + + ctl.len = 40; + dat.len = -1; + fl = 0; + st->s_cmd = sc.cmd; + break; + + case SVR4_TI__ACCEPT_OK: + DPRINTF(("getmsg: TI__ACCEPT_OK\n")); + /* + * We do the connect in one step, so the putmsg should + * have gotten the error. + */ + sc.cmd = SVR4_TI_OK_REPLY; + sc.len = 1; + + ctl.len = 8; + dat.len = -1; + fl = 1; + st->s_cmd = SVR4_TI__ACCEPT_WAIT; + break; + + case SVR4_TI__ACCEPT_WAIT: + DPRINTF(("getmsg: TI__ACCEPT_WAIT\n")); + /* + * We are after a listen, so we try to accept... + */ + SCARG(&aa, s) = SCARG(uap, fd); + SCARG(&aa, name) = (void *) sup; + SCARG(&aa, anamelen) = flen; + + if ((error = accept(td, &aa)) != 0) { + DPRINTF(("getmsg: accept failed %d\n", error)); + return error; + } + + st->s_afd = *retval; + + DPRINTF(("getmsg: Accept fd = %d\n", st->s_afd)); + + if ((error = copyin(sup, skp, sasize)) != 0) + return error; + + sc.cmd = SVR4_TI_ACCEPT_REPLY; + sc.offs = 0x18; + sc.pad[0] = 0x0; + + switch (st->s_family) { + case AF_INET: + sc.pad[1] = 0x28; + sockaddr_to_netaddr_in(&sc, &sain); + ctl.len = 40; + sc.len = sasize; + break; + + case AF_LOCAL: + sc.pad[1] = 0x00010000; + sc.pad[2] = 0xf6bcdaa0; /* I don't know what that is */ + sc.pad[3] = 0x00010000; + ctl.len = 134; + sc.len = sasize + 4; + break; + + default: + return ENOSYS; + } + + dat.len = -1; + fl = 0; + st->s_cmd = SVR4_TI__ACCEPT_OK; + break; + + case SVR4_TI_SENDTO_REQUEST: + DPRINTF(("getmsg: TI_SENDTO_REQUEST\n")); + if (ctl.maxlen > 36 && ctl.len < 36) + ctl.len = 36; + + if ((error = copyin(ctl.buf, &sc, ctl.len)) != 0) + return error; + + switch (st->s_family) { + case AF_INET: + sockaddr_to_netaddr_in(&sc, &sain); + break; + + case AF_LOCAL: + sockaddr_to_netaddr_un(&sc, &saun); + break; + + default: + return ENOSYS; + } + + msg.msg_name = (caddr_t) sup; + msg.msg_namelen = sasize; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; + msg.msg_control = 0; + aiov.iov_base = dat.buf; + aiov.iov_len = dat.maxlen; + msg.msg_flags = 0; + + error = svr4_recvit(td, SCARG(uap, fd), &msg, (caddr_t) flen); + + if (error) { + DPRINTF(("getmsg: recvit failed %d\n", error)); + return error; + } + + if ((error = copyin(msg.msg_name, skp, sasize)) != 0) + return error; + + sc.cmd = SVR4_TI_RECVFROM_IND; + + switch (st->s_family) { + case AF_INET: + sc.len = sasize; + sockaddr_to_netaddr_in(&sc, &sain); + break; + + case AF_LOCAL: + sc.len = sasize + 4; + sockaddr_to_netaddr_un(&sc, &saun); + break; + + default: + return ENOSYS; + } + + dat.len = *retval; + fl = 0; + st->s_cmd = sc.cmd; + break; + + default: + st->s_cmd = sc.cmd; + if (st->s_cmd == SVR4_TI_CONNECT_REQUEST) { + struct read_args ra; + + /* More weirdness: Again, I can't find documentation + * to back this up, but when a process does a generic + * "getmsg()" call it seems that the command field is + * zero and the length of the data area is zero. I + * think processes expect getmsg() to fill in dat.len + * after reading at most dat.maxlen octets from the + * stream. Since we're using sockets I can let + * read() look after it and frob return values + * appropriately (or inappropriately :-) + * -- newton@atdot.dotat.org XXX + */ + SCARG(&ra, fd) = SCARG(uap, fd); + SCARG(&ra, buf) = dat.buf; + SCARG(&ra, nbyte) = dat.maxlen; + if ((error = read(td, &ra)) != 0) { + return error; + } + dat.len = *retval; + *retval = 0; + st->s_cmd = SVR4_TI_SENDTO_REQUEST; + break; + } + DPRINTF(("getmsg: Unknown state %x\n", st->s_cmd)); + return EINVAL; + } + + if (SCARG(uap, ctl)) { + if (ctl.len != -1) + if ((error = copyout(&sc, ctl.buf, ctl.len)) != 0) + return error; + + if ((error = copyout(&ctl, SCARG(uap, ctl), sizeof(ctl))) != 0) + return error; + } + + if (SCARG(uap, dat)) { + if ((error = copyout(&dat, SCARG(uap, dat), sizeof(dat))) != 0) + return error; + } + + if (SCARG(uap, flags)) { /* XXX: Need translation */ + if ((error = copyout(&fl, SCARG(uap, flags), sizeof(fl))) != 0) + return error; + } + + *retval = 0; + +#ifdef DEBUG_SVR4 + show_msg("<getmsg", SCARG(uap, fd), SCARG(uap, ctl), + SCARG(uap, dat), fl); +#endif /* DEBUG_SVR4 */ + return error; +} + +int svr4_sys_send(td, uap) + struct thread *td; + struct svr4_sys_send_args *uap; +{ + struct osend_args osa; + SCARG(&osa, s) = SCARG(uap, s); + SCARG(&osa, buf) = SCARG(uap, buf); + SCARG(&osa, len) = SCARG(uap, len); + SCARG(&osa, flags) = SCARG(uap, flags); + return osend(td, &osa); +} + +int svr4_sys_recv(td, uap) + struct thread *td; + struct svr4_sys_recv_args *uap; +{ + struct orecv_args ora; + SCARG(&ora, s) = SCARG(uap, s); + SCARG(&ora, buf) = SCARG(uap, buf); + SCARG(&ora, len) = SCARG(uap, len); + SCARG(&ora, flags) = SCARG(uap, flags); + return orecv(td, &ora); +} + +/* + * XXX This isn't necessary, but it's handy for inserting debug code into + * sendto(). Let's leave it here for now... + */ +int +svr4_sys_sendto(td, uap) + struct thread *td; + struct svr4_sys_sendto_args *uap; +{ + struct sendto_args sa; + + SCARG(&sa, s) = SCARG(uap, s); + SCARG(&sa, buf) = SCARG(uap, buf); + SCARG(&sa, len) = SCARG(uap, len); + SCARG(&sa, flags) = SCARG(uap, flags); + SCARG(&sa, to) = (caddr_t)SCARG(uap, to); + SCARG(&sa, tolen) = SCARG(uap, tolen); + + DPRINTF(("calling sendto()\n")); + return sendto(td, &sa); +} + diff --git a/sys/compat/svr4/svr4_stropts.h b/sys/compat/svr4/svr4_stropts.h new file mode 100644 index 0000000..e5a39e9 --- /dev/null +++ b/sys/compat/svr4/svr4_stropts.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_STROPTS_H_ +#define _SVR4_STROPTS_H_ + + +struct svr4_strbuf { + int maxlen; + int len; + char *buf; +}; + +#define SVR4_STR ('S' << 8) +#define SVR4_I_NREAD (SVR4_STR| 1) +#define SVR4_I_PUSH (SVR4_STR| 2) +#define SVR4_I_POP (SVR4_STR| 3) +#define SVR4_I_LOOK (SVR4_STR| 4) +#define SVR4_I_FLUSH (SVR4_STR| 5) +#define SVR4_I_SRDOPT (SVR4_STR| 6) +#define SVR4_I_GRDOPT (SVR4_STR| 7) +#define SVR4_I_STR (SVR4_STR| 8) +#define SVR4_I_SETSIG (SVR4_STR| 9) +#define SVR4_I_GETSIG (SVR4_STR|10) +#define SVR4_I_FIND (SVR4_STR|11) +#define SVR4_I_LINK (SVR4_STR|12) +#define SVR4_I_UNLINK (SVR4_STR|13) +#define SVR4_I_ERECVFD (SVR4_STR|14) +#define SVR4_I_PEEK (SVR4_STR|15) +#define SVR4_I_FDINSERT (SVR4_STR|16) +#define SVR4_I_SENDFD (SVR4_STR|17) +#define SVR4_I_RECVFD (SVR4_STR|18) +#define SVR4_I_SWROPT (SVR4_STR|19) +#define SVR4_I_GWROPT (SVR4_STR|20) +#define SVR4_I_LIST (SVR4_STR|21) +#define SVR4_I_PLINK (SVR4_STR|22) +#define SVR4_I_PUNLINK (SVR4_STR|23) +#define SVR4_I_SETEV (SVR4_STR|24) +#define SVR4_I_GETEV (SVR4_STR|25) +#define SVR4_I_STREV (SVR4_STR|26) +#define SVR4_I_UNSTREV (SVR4_STR|27) +#define SVR4_I_FLUSHBAND (SVR4_STR|28) +#define SVR4_I_CKBAND (SVR4_STR|29) +#define SVR4_I_GETBAND (SVR4_STR|30) +#define SVR4_I_ATMARK (SVR4_STR|31) +#define SVR4_I_SETCLTIME (SVR4_STR|32) +#define SVR4_I_GETCLTIME (SVR4_STR|33) +#define SVR4_I_CANPUT (SVR4_STR|34) + +/* + * The following two ioctls are OS specific and + * undocumented. + */ +#define SVR4__I_BIND_RSVD (SVR4_STR|242) +#define SVR4__I_RELE_RSVD (SVR4_STR|243) + +/* + * Service type definitions + */ +#define SVR4_T_COTS 1 /* Connection-orieted */ +#define SVR4_T_COTS_ORD 2 /* Local connection-oriented */ +#define SVR4_T_CLTS 3 /* Connectionless */ + +/* Struct passed for SVR4_I_STR */ +struct svr4_strioctl { + u_long cmd; + int timeout; + int len; + char *buf; +}; + +/* + * Bits for I_{G,S}ETSIG + */ +#define SVR4_S_INPUT 0x0001 /* any message on read queue no HIPRI */ +#define SVR4_S_HIPRI 0x0002 /* high prio message on read queue */ +#define SVR4_S_OUTPUT 0x0004 /* write queue has free space */ +#define SVR4_S_MSG 0x0008 /* signal message in read queue head */ +#define SVR4_S_ERROR 0x0010 /* error message in read queue head */ +#define SVR4_S_HANGUP 0x0020 /* hangup message in read queue head */ +#define SVR4_S_RDNORM 0x0040 /* normal message on read queue */ +#define SVR4_S_WRNORM S_OUTPUT /* write queue has free space */ +#define SVR4_S_RDBAND 0x0080 /* out of band message on read queue */ +#define SVR4_S_WRBAND 0x0100 /* write queue has free space for oob */ +#define SVR4_S_BANDURG 0x0200 /* generate SIGURG instead of SIGPOLL */ +#define SVR4_S_ALLMASK 0x03ff /* all events mask */ + +/* + * Our internal state for the stream + * For now we keep almost nothing... In the future we can keep more + * streams state. + */ +struct svr4_strm { + int s_family; /* socket family */ + int s_cmd; /* last getmsg reply or putmsg request */ + int s_afd; /* last accepted fd; [for fd_insert] */ + int s_eventmask; /* state info from I_SETSIG et al */ +}; + +/* + * The following structures are determined empirically. + */ +struct svr4_strmcmd { + long cmd; /* command ? */ + long len; /* Address len */ + long offs; /* Address offset */ + long pad[61]; +}; + +struct svr4_infocmd { + long cmd; + long tsdu; + long etsdu; + long cdata; + long ddata; + long addr; + long opt; + long tidu; + long serv; + long current; + long provider; +}; + +struct svr4_strfdinsert { + struct svr4_strbuf ctl; + struct svr4_strbuf data; + long flags; + int fd; + int offset; +}; + +struct svr4_netaddr_in { + u_short family; + u_short port; + u_long addr; +}; + +struct svr4_netaddr_un { + u_short family; + char path[1]; +}; + +#define SVR4_ADDROF(sc) (void *) (((char *) (sc)) + (sc)->offs) +#define SVR4_C_ADDROF(sc) (const void *) (((const char *) (sc)) + (sc)->offs) + +struct svr4_strm *svr4_stream_get(struct file *fp); + +#endif /* !_SVR4_STROPTS */ diff --git a/sys/compat/svr4/svr4_syscall.h b/sys/compat/svr4/svr4_syscall.h new file mode 100644 index 0000000..b1898b5 --- /dev/null +++ b/sys/compat/svr4/svr4_syscall.h @@ -0,0 +1,145 @@ +/* + * System call numbers. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp + */ + +#define SVR4_SYS_exit 1 +#define SVR4_SYS_fork 2 +#define SVR4_SYS_read 3 +#define SVR4_SYS_write 4 +#define SVR4_SYS_svr4_sys_open 5 +#define SVR4_SYS_close 6 +#define SVR4_SYS_svr4_sys_wait 7 +#define SVR4_SYS_svr4_sys_creat 8 +#define SVR4_SYS_link 9 +#define SVR4_SYS_unlink 10 +#define SVR4_SYS_svr4_sys_execv 11 +#define SVR4_SYS_chdir 12 +#define SVR4_SYS_svr4_sys_time 13 +#define SVR4_SYS_svr4_sys_mknod 14 +#define SVR4_SYS_chmod 15 +#define SVR4_SYS_chown 16 +#define SVR4_SYS_svr4_sys_break 17 +#define SVR4_SYS_svr4_sys_stat 18 +#define SVR4_SYS_lseek 19 +#define SVR4_SYS_getpid 20 +#define SVR4_SYS_setuid 23 +#define SVR4_SYS_getuid 24 +#define SVR4_SYS_svr4_sys_alarm 27 +#define SVR4_SYS_svr4_sys_fstat 28 +#define SVR4_SYS_svr4_sys_pause 29 +#define SVR4_SYS_svr4_sys_utime 30 +#define SVR4_SYS_svr4_sys_access 33 +#define SVR4_SYS_svr4_sys_nice 34 +#define SVR4_SYS_sync 36 +#define SVR4_SYS_svr4_sys_kill 37 +#define SVR4_SYS_svr4_sys_pgrpsys 39 +#define SVR4_SYS_dup 41 +#define SVR4_SYS_pipe 42 +#define SVR4_SYS_svr4_sys_times 43 +#define SVR4_SYS_setgid 46 +#define SVR4_SYS_getgid 47 +#define SVR4_SYS_svr4_sys_signal 48 +#define SVR4_SYS_svr4_sys_msgsys 49 +#define SVR4_SYS_svr4_sys_sysarch 50 +#define SVR4_SYS_svr4_sys_ioctl 54 +#define SVR4_SYS_svr4_sys_utssys 57 +#define SVR4_SYS_fsync 58 +#define SVR4_SYS_svr4_sys_execve 59 +#define SVR4_SYS_umask 60 +#define SVR4_SYS_chroot 61 +#define SVR4_SYS_svr4_sys_fcntl 62 +#define SVR4_SYS_svr4_sys_ulimit 63 +#define SVR4_SYS_rmdir 79 +#define SVR4_SYS_mkdir 80 +#define SVR4_SYS_svr4_sys_getdents 81 +#define SVR4_SYS_svr4_sys_getmsg 85 +#define SVR4_SYS_svr4_sys_putmsg 86 +#define SVR4_SYS_svr4_sys_poll 87 +#define SVR4_SYS_svr4_sys_lstat 88 +#define SVR4_SYS_symlink 89 +#define SVR4_SYS_readlink 90 +#define SVR4_SYS_getgroups 91 +#define SVR4_SYS_setgroups 92 +#define SVR4_SYS_fchmod 93 +#define SVR4_SYS_fchown 94 +#define SVR4_SYS_svr4_sys_sigprocmask 95 +#define SVR4_SYS_svr4_sys_sigsuspend 96 +#define SVR4_SYS_svr4_sys_sigaltstack 97 +#define SVR4_SYS_svr4_sys_sigaction 98 +#define SVR4_SYS_svr4_sys_sigpending 99 +#define SVR4_SYS_svr4_sys_context 100 +#define SVR4_SYS_svr4_sys_statvfs 103 +#define SVR4_SYS_svr4_sys_fstatvfs 104 +#define SVR4_SYS_svr4_sys_waitsys 107 +#define SVR4_SYS_svr4_sys_hrtsys 109 +#define SVR4_SYS_svr4_sys_pathconf 113 +#define SVR4_SYS_svr4_sys_mmap 115 +#define SVR4_SYS_mprotect 116 +#define SVR4_SYS_munmap 117 +#define SVR4_SYS_svr4_sys_fpathconf 118 +#define SVR4_SYS_vfork 119 +#define SVR4_SYS_fchdir 120 +#define SVR4_SYS_readv 121 +#define SVR4_SYS_writev 122 +#define SVR4_SYS_svr4_sys_xstat 123 +#define SVR4_SYS_svr4_sys_lxstat 124 +#define SVR4_SYS_svr4_sys_fxstat 125 +#define SVR4_SYS_svr4_sys_xmknod 126 +#define SVR4_SYS_svr4_sys_setrlimit 128 +#define SVR4_SYS_svr4_sys_getrlimit 129 +#define SVR4_SYS_lchown 130 +#define SVR4_SYS_svr4_sys_memcntl 131 +#define SVR4_SYS_rename 134 +#define SVR4_SYS_svr4_sys_uname 135 +#define SVR4_SYS_setegid 136 +#define SVR4_SYS_svr4_sys_sysconfig 137 +#define SVR4_SYS_adjtime 138 +#define SVR4_SYS_svr4_sys_systeminfo 139 +#define SVR4_SYS_seteuid 141 +#define SVR4_SYS_svr4_sys_fchroot 153 +#define SVR4_SYS_svr4_sys_utimes 154 +#define SVR4_SYS_svr4_sys_vhangup 155 +#define SVR4_SYS_svr4_sys_gettimeofday 156 +#define SVR4_SYS_getitimer 157 +#define SVR4_SYS_setitimer 158 +#define SVR4_SYS_svr4_sys_llseek 175 +#define SVR4_SYS_svr4_sys_acl 185 +#define SVR4_SYS_svr4_sys_auditsys 186 +#define SVR4_SYS_nanosleep 199 +#define SVR4_SYS_svr4_sys_facl 200 +#define SVR4_SYS_setreuid 202 +#define SVR4_SYS_setregid 203 +#define SVR4_SYS_svr4_sys_resolvepath 209 +#define SVR4_SYS_svr4_sys_getdents64 213 +#define SVR4_SYS_svr4_sys_mmap64 214 +#define SVR4_SYS_svr4_sys_stat64 215 +#define SVR4_SYS_svr4_sys_lstat64 216 +#define SVR4_SYS_svr4_sys_fstat64 217 +#define SVR4_SYS_svr4_sys_statvfs64 218 +#define SVR4_SYS_svr4_sys_fstatvfs64 219 +#define SVR4_SYS_svr4_sys_setrlimit64 220 +#define SVR4_SYS_svr4_sys_getrlimit64 221 +#define SVR4_SYS_svr4_sys_creat64 224 +#define SVR4_SYS_svr4_sys_open64 225 +#define SVR4_SYS_svr4_sys_socket 230 +#define SVR4_SYS_socketpair 231 +#define SVR4_SYS_bind 232 +#define SVR4_SYS_listen 233 +#define SVR4_SYS_accept 234 +#define SVR4_SYS_connect 235 +#define SVR4_SYS_shutdown 236 +#define SVR4_SYS_svr4_sys_recv 237 +#define SVR4_SYS_recvfrom 238 +#define SVR4_SYS_recvmsg 239 +#define SVR4_SYS_svr4_sys_send 240 +#define SVR4_SYS_sendmsg 241 +#define SVR4_SYS_svr4_sys_sendto 242 +#define SVR4_SYS_getpeername 243 +#define SVR4_SYS_getsockname 244 +#define SVR4_SYS_getsockopt 245 +#define SVR4_SYS_setsockopt 246 +#define SVR4_SYS_MAXSYSCALL 250 diff --git a/sys/compat/svr4/svr4_syscallnames.c b/sys/compat/svr4/svr4_syscallnames.c new file mode 100644 index 0000000..1f9add4 --- /dev/null +++ b/sys/compat/svr4/svr4_syscallnames.c @@ -0,0 +1,264 @@ +/* + * System call names. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp + */ + +char *svr4_syscallnames[] = { + "#0", /* 0 = unused */ + "exit", /* 1 = exit */ + "fork", /* 2 = fork */ + "read", /* 3 = read */ + "write", /* 4 = write */ + "svr4_sys_open", /* 5 = svr4_sys_open */ + "close", /* 6 = close */ + "svr4_sys_wait", /* 7 = svr4_sys_wait */ + "svr4_sys_creat", /* 8 = svr4_sys_creat */ + "link", /* 9 = link */ + "unlink", /* 10 = unlink */ + "svr4_sys_execv", /* 11 = svr4_sys_execv */ + "chdir", /* 12 = chdir */ + "svr4_sys_time", /* 13 = svr4_sys_time */ + "svr4_sys_mknod", /* 14 = svr4_sys_mknod */ + "chmod", /* 15 = chmod */ + "chown", /* 16 = chown */ + "svr4_sys_break", /* 17 = svr4_sys_break */ + "svr4_sys_stat", /* 18 = svr4_sys_stat */ + "lseek", /* 19 = lseek */ + "getpid", /* 20 = getpid */ + "#21", /* 21 = old_mount */ + "#22", /* 22 = sysv_umount */ + "setuid", /* 23 = setuid */ + "getuid", /* 24 = getuid */ + "#25", /* 25 = stime */ + "#26", /* 26 = ptrace */ + "svr4_sys_alarm", /* 27 = svr4_sys_alarm */ + "svr4_sys_fstat", /* 28 = svr4_sys_fstat */ + "svr4_sys_pause", /* 29 = svr4_sys_pause */ + "svr4_sys_utime", /* 30 = svr4_sys_utime */ + "#31", /* 31 = stty */ + "#32", /* 32 = gtty */ + "svr4_sys_access", /* 33 = svr4_sys_access */ + "svr4_sys_nice", /* 34 = svr4_sys_nice */ + "#35", /* 35 = statfs */ + "sync", /* 36 = sync */ + "svr4_sys_kill", /* 37 = svr4_sys_kill */ + "#38", /* 38 = fstatfs */ + "svr4_sys_pgrpsys", /* 39 = svr4_sys_pgrpsys */ + "#40", /* 40 = xenix */ + "dup", /* 41 = dup */ + "pipe", /* 42 = pipe */ + "svr4_sys_times", /* 43 = svr4_sys_times */ + "#44", /* 44 = profil */ + "#45", /* 45 = plock */ + "setgid", /* 46 = setgid */ + "getgid", /* 47 = getgid */ + "svr4_sys_signal", /* 48 = svr4_sys_signal */ +#if defined(NOTYET) + "svr4_sys_msgsys", /* 49 = svr4_sys_msgsys */ +#else + "#49", /* 49 = msgsys */ +#endif + "svr4_sys_sysarch", /* 50 = svr4_sys_sysarch */ + "#51", /* 51 = acct */ + "#52", /* 52 = shmsys */ + "#53", /* 53 = semsys */ + "svr4_sys_ioctl", /* 54 = svr4_sys_ioctl */ + "#55", /* 55 = uadmin */ + "#56", /* 56 = exch */ + "svr4_sys_utssys", /* 57 = svr4_sys_utssys */ + "fsync", /* 58 = fsync */ + "svr4_sys_execve", /* 59 = svr4_sys_execve */ + "umask", /* 60 = umask */ + "chroot", /* 61 = chroot */ + "svr4_sys_fcntl", /* 62 = svr4_sys_fcntl */ + "svr4_sys_ulimit", /* 63 = svr4_sys_ulimit */ + "#64", /* 64 = reserved */ + "#65", /* 65 = reserved */ + "#66", /* 66 = reserved */ + "#67", /* 67 = reserved */ + "#68", /* 68 = reserved */ + "#69", /* 69 = reserved */ + "#70", /* 70 = advfs */ + "#71", /* 71 = unadvfs */ + "#72", /* 72 = rmount */ + "#73", /* 73 = rumount */ + "#74", /* 74 = rfstart */ + "#75", /* 75 = sigret */ + "#76", /* 76 = rdebug */ + "#77", /* 77 = rfstop */ + "#78", /* 78 = rfsys */ + "rmdir", /* 79 = rmdir */ + "mkdir", /* 80 = mkdir */ + "svr4_sys_getdents", /* 81 = svr4_sys_getdents */ + "#82", /* 82 = libattach */ + "#83", /* 83 = libdetach */ + "#84", /* 84 = sysfs */ + "svr4_sys_getmsg", /* 85 = svr4_sys_getmsg */ + "svr4_sys_putmsg", /* 86 = svr4_sys_putmsg */ + "svr4_sys_poll", /* 87 = svr4_sys_poll */ + "svr4_sys_lstat", /* 88 = svr4_sys_lstat */ + "symlink", /* 89 = symlink */ + "readlink", /* 90 = readlink */ + "getgroups", /* 91 = getgroups */ + "setgroups", /* 92 = setgroups */ + "fchmod", /* 93 = fchmod */ + "fchown", /* 94 = fchown */ + "svr4_sys_sigprocmask", /* 95 = svr4_sys_sigprocmask */ + "svr4_sys_sigsuspend", /* 96 = svr4_sys_sigsuspend */ + "svr4_sys_sigaltstack", /* 97 = svr4_sys_sigaltstack */ + "svr4_sys_sigaction", /* 98 = svr4_sys_sigaction */ + "svr4_sys_sigpending", /* 99 = svr4_sys_sigpending */ + "svr4_sys_context", /* 100 = svr4_sys_context */ + "#101", /* 101 = evsys */ + "#102", /* 102 = evtrapret */ + "svr4_sys_statvfs", /* 103 = svr4_sys_statvfs */ + "svr4_sys_fstatvfs", /* 104 = svr4_sys_fstatvfs */ + "#105", /* 105 = whoknows */ + "#106", /* 106 = nfssvc */ + "svr4_sys_waitsys", /* 107 = svr4_sys_waitsys */ + "#108", /* 108 = sigsendsys */ + "svr4_sys_hrtsys", /* 109 = svr4_sys_hrtsys */ + "#110", /* 110 = acancel */ + "#111", /* 111 = async */ + "#112", /* 112 = priocntlsys */ + "svr4_sys_pathconf", /* 113 = svr4_sys_pathconf */ + "#114", /* 114 = mincore */ + "svr4_sys_mmap", /* 115 = svr4_sys_mmap */ + "mprotect", /* 116 = mprotect */ + "munmap", /* 117 = munmap */ + "svr4_sys_fpathconf", /* 118 = svr4_sys_fpathconf */ + "vfork", /* 119 = vfork */ + "fchdir", /* 120 = fchdir */ + "readv", /* 121 = readv */ + "writev", /* 122 = writev */ + "svr4_sys_xstat", /* 123 = svr4_sys_xstat */ + "svr4_sys_lxstat", /* 124 = svr4_sys_lxstat */ + "svr4_sys_fxstat", /* 125 = svr4_sys_fxstat */ + "svr4_sys_xmknod", /* 126 = svr4_sys_xmknod */ + "#127", /* 127 = clocal */ + "svr4_sys_setrlimit", /* 128 = svr4_sys_setrlimit */ + "svr4_sys_getrlimit", /* 129 = svr4_sys_getrlimit */ + "lchown", /* 130 = lchown */ + "svr4_sys_memcntl", /* 131 = svr4_sys_memcntl */ + "#132", /* 132 = getpmsg */ + "#133", /* 133 = putpmsg */ + "rename", /* 134 = rename */ + "svr4_sys_uname", /* 135 = svr4_sys_uname */ + "setegid", /* 136 = setegid */ + "svr4_sys_sysconfig", /* 137 = svr4_sys_sysconfig */ + "adjtime", /* 138 = adjtime */ + "svr4_sys_systeminfo", /* 139 = svr4_sys_systeminfo */ + "#140", /* 140 = notused */ + "seteuid", /* 141 = seteuid */ + "#142", /* 142 = vtrace */ + "#143", /* 143 = { */ + "#144", /* 144 = sigtimedwait */ + "#145", /* 145 = lwp_info */ + "#146", /* 146 = yield */ + "#147", /* 147 = lwp_sema_wait */ + "#148", /* 148 = lwp_sema_post */ + "#149", /* 149 = lwp_sema_trywait */ + "#150", /* 150 = notused */ + "#151", /* 151 = notused */ + "#152", /* 152 = modctl */ + "svr4_sys_fchroot", /* 153 = svr4_sys_fchroot */ + "svr4_sys_utimes", /* 154 = svr4_sys_utimes */ + "svr4_sys_vhangup", /* 155 = svr4_sys_vhangup */ + "svr4_sys_gettimeofday", /* 156 = svr4_sys_gettimeofday */ + "getitimer", /* 157 = getitimer */ + "setitimer", /* 158 = setitimer */ + "#159", /* 159 = lwp_create */ + "#160", /* 160 = lwp_exit */ + "#161", /* 161 = lwp_suspend */ + "#162", /* 162 = lwp_continue */ + "#163", /* 163 = lwp_kill */ + "#164", /* 164 = lwp_self */ + "#165", /* 165 = lwp_getprivate */ + "#166", /* 166 = lwp_setprivate */ + "#167", /* 167 = lwp_wait */ + "#168", /* 168 = lwp_mutex_unlock */ + "#169", /* 169 = lwp_mutex_lock */ + "#170", /* 170 = lwp_cond_wait */ + "#171", /* 171 = lwp_cond_signal */ + "#172", /* 172 = lwp_cond_broadcast */ + "#173", /* 173 = { */ + "#174", /* 174 = { */ + "svr4_sys_llseek", /* 175 = svr4_sys_llseek */ + "#176", /* 176 = inst_sync */ + "#177", /* 177 = whoknows */ + "#178", /* 178 = kaio */ + "#179", /* 179 = whoknows */ + "#180", /* 180 = whoknows */ + "#181", /* 181 = whoknows */ + "#182", /* 182 = whoknows */ + "#183", /* 183 = whoknows */ + "#184", /* 184 = tsolsys */ + "svr4_sys_acl", /* 185 = svr4_sys_acl */ + "svr4_sys_auditsys", /* 186 = svr4_sys_auditsys */ + "#187", /* 187 = processor_bind */ + "#188", /* 188 = processor_info */ + "#189", /* 189 = p_online */ + "#190", /* 190 = sigqueue */ + "#191", /* 191 = clock_gettime */ + "#192", /* 192 = clock_settime */ + "#193", /* 193 = clock_getres */ + "#194", /* 194 = timer_create */ + "#195", /* 195 = timer_delete */ + "#196", /* 196 = timer_settime */ + "#197", /* 197 = timer_gettime */ + "#198", /* 198 = timer_overrun */ + "nanosleep", /* 199 = nanosleep */ + "svr4_sys_facl", /* 200 = svr4_sys_facl */ + "#201", /* 201 = door */ + "setreuid", /* 202 = setreuid */ + "setregid", /* 203 = setregid */ + "#204", /* 204 = install_utrap */ + "#205", /* 205 = signotify */ + "#206", /* 206 = schedctl */ + "#207", /* 207 = pset */ + "#208", /* 208 = whoknows */ + "svr4_sys_resolvepath", /* 209 = svr4_sys_resolvepath */ + "#210", /* 210 = signotifywait */ + "#211", /* 211 = lwp_sigredirect */ + "#212", /* 212 = lwp_alarm */ + "svr4_sys_getdents64", /* 213 = svr4_sys_getdents64 */ + "svr4_sys_mmap64", /* 214 = svr4_sys_mmap64 */ + "svr4_sys_stat64", /* 215 = svr4_sys_stat64 */ + "svr4_sys_lstat64", /* 216 = svr4_sys_lstat64 */ + "svr4_sys_fstat64", /* 217 = svr4_sys_fstat64 */ + "svr4_sys_statvfs64", /* 218 = svr4_sys_statvfs64 */ + "svr4_sys_fstatvfs64", /* 219 = svr4_sys_fstatvfs64 */ + "svr4_sys_setrlimit64", /* 220 = svr4_sys_setrlimit64 */ + "svr4_sys_getrlimit64", /* 221 = svr4_sys_getrlimit64 */ + "#222", /* 222 = pread64 */ + "#223", /* 223 = pwrite64 */ + "svr4_sys_creat64", /* 224 = svr4_sys_creat64 */ + "svr4_sys_open64", /* 225 = svr4_sys_open64 */ + "#226", /* 226 = rpcsys */ + "#227", /* 227 = whoknows */ + "#228", /* 228 = whoknows */ + "#229", /* 229 = whoknows */ + "svr4_sys_socket", /* 230 = svr4_sys_socket */ + "socketpair", /* 231 = socketpair */ + "bind", /* 232 = bind */ + "listen", /* 233 = listen */ + "accept", /* 234 = accept */ + "connect", /* 235 = connect */ + "shutdown", /* 236 = shutdown */ + "svr4_sys_recv", /* 237 = svr4_sys_recv */ + "recvfrom", /* 238 = recvfrom */ + "recvmsg", /* 239 = recvmsg */ + "svr4_sys_send", /* 240 = svr4_sys_send */ + "sendmsg", /* 241 = sendmsg */ + "svr4_sys_sendto", /* 242 = svr4_sys_sendto */ + "getpeername", /* 243 = getpeername */ + "getsockname", /* 244 = getsockname */ + "getsockopt", /* 245 = getsockopt */ + "setsockopt", /* 246 = setsockopt */ + "#247", /* 247 = sockconfig */ + "#248", /* 248 = { */ + "#249", /* 249 = { */ +}; diff --git a/sys/compat/svr4/svr4_sysconfig.h b/sys/compat/svr4/svr4_sysconfig.h new file mode 100644 index 0000000..874c565 --- /dev/null +++ b/sys/compat/svr4/svr4_sysconfig.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1995 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SYSCONFIG_H_ +#define _SVR4_SYSCONFIG_H_ + +#define SVR4_CONFIG_UNUSED 0x01 +#define SVR4_CONFIG_NGROUPS 0x02 +#define SVR4_CONFIG_CHILD_MAX 0x03 +#define SVR4_CONFIG_OPEN_FILES 0x04 +#define SVR4_CONFIG_POSIX_VER 0x05 +#define SVR4_CONFIG_PAGESIZE 0x06 +#define SVR4_CONFIG_CLK_TCK 0x07 +#define SVR4_CONFIG_XOPEN_VER 0x08 +#define SVR4_CONFIG_UNUSED_9 0x09 +#define SVR4_CONFIG_PROF_TCK 0x0a +#define SVR4_CONFIG_NPROC_CONF 0x0b +#define SVR4_CONFIG_NPROC_ONLN 0x0c +#define SVR4_CONFIG_AIO_LISTIO_MAX 0x0e +#define SVR4_CONFIG_AIO_MAX 0x0f +#define SVR4_CONFIG_AIO_PRIO_DELTA_MAX 0x10 +#define SVR4_CONFIG_DELAYTIMER_MAX 0x11 +#define SVR4_CONFIG_MQ_OPEN_MAX 0x12 +#define SVR4_CONFIG_MQ_PRIO_MAX 0x13 +#define SVR4_CONFIG_RTSIG_MAX 0x14 +#define SVR4_CONFIG_SEM_NSEMS_MAX 0x15 +#define SVR4_CONFIG_SEM_VALUE_MAX 0x16 +#define SVR4_CONFIG_SIGQUEUE_MAX 0x17 +#define SVR4_CONFIG_SIGRT_MIN 0x18 +#define SVR4_CONFIG_SIGRT_MAX 0x19 +#define SVR4_CONFIG_TIMER_MAX 0x20 +#define SVR4_CONFIG_PHYS_PAGES 0x21 +#define SVR4_CONFIG_AVPHYS_PAGES 0x22 + +#endif /* !_SVR4_SYSCONFIG_H_ */ diff --git a/sys/compat/svr4/svr4_sysent.c b/sys/compat/svr4/svr4_sysent.c new file mode 100644 index 0000000..2bb003e --- /dev/null +++ b/sys/compat/svr4/svr4_sysent.c @@ -0,0 +1,276 @@ +/* + * System call switch table. + * + * DO NOT EDIT-- this file is automatically generated. + * $FreeBSD$ + * created from FreeBSD: src/sys/compat/svr4/syscalls.master,v 1.11 2000/08/31 22:54:05 obrien Exp + */ + +#include <sys/types.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <netinet/in.h> +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> + +#define AS(name) (sizeof(struct name) / sizeof(register_t)) + +/* The casts are bogus but will do for now. */ +struct sysent svr4_sysent[] = { + { 0, (sy_call_t *)nosys }, /* 0 = unused */ + { AS(sys_exit_args), (sy_call_t *)sys_exit }, /* 1 = exit */ + { 0, (sy_call_t *)fork }, /* 2 = fork */ + { AS(read_args), (sy_call_t *)read }, /* 3 = read */ + { AS(write_args), (sy_call_t *)write }, /* 4 = write */ + { AS(svr4_sys_open_args), (sy_call_t *)svr4_sys_open }, /* 5 = svr4_sys_open */ + { AS(close_args), (sy_call_t *)close }, /* 6 = close */ + { AS(svr4_sys_wait_args), (sy_call_t *)svr4_sys_wait }, /* 7 = svr4_sys_wait */ + { AS(svr4_sys_creat_args), (sy_call_t *)svr4_sys_creat }, /* 8 = svr4_sys_creat */ + { AS(link_args), (sy_call_t *)link }, /* 9 = link */ + { AS(unlink_args), (sy_call_t *)unlink }, /* 10 = unlink */ + { AS(svr4_sys_execv_args), (sy_call_t *)svr4_sys_execv }, /* 11 = svr4_sys_execv */ + { AS(chdir_args), (sy_call_t *)chdir }, /* 12 = chdir */ + { AS(svr4_sys_time_args), (sy_call_t *)svr4_sys_time }, /* 13 = svr4_sys_time */ + { AS(svr4_sys_mknod_args), (sy_call_t *)svr4_sys_mknod }, /* 14 = svr4_sys_mknod */ + { AS(chmod_args), (sy_call_t *)chmod }, /* 15 = chmod */ + { AS(chown_args), (sy_call_t *)chown }, /* 16 = chown */ + { AS(svr4_sys_break_args), (sy_call_t *)svr4_sys_break }, /* 17 = svr4_sys_break */ + { AS(svr4_sys_stat_args), (sy_call_t *)svr4_sys_stat }, /* 18 = svr4_sys_stat */ + { AS(lseek_args), (sy_call_t *)lseek }, /* 19 = lseek */ + { 0, (sy_call_t *)getpid }, /* 20 = getpid */ + { 0, (sy_call_t *)nosys }, /* 21 = old_mount */ + { 0, (sy_call_t *)nosys }, /* 22 = sysv_umount */ + { AS(setuid_args), (sy_call_t *)setuid }, /* 23 = setuid */ + { 0, (sy_call_t *)getuid }, /* 24 = getuid */ + { 0, (sy_call_t *)nosys }, /* 25 = stime */ + { 0, (sy_call_t *)nosys }, /* 26 = ptrace */ + { AS(svr4_sys_alarm_args), (sy_call_t *)svr4_sys_alarm }, /* 27 = svr4_sys_alarm */ + { AS(svr4_sys_fstat_args), (sy_call_t *)svr4_sys_fstat }, /* 28 = svr4_sys_fstat */ + { 0, (sy_call_t *)svr4_sys_pause }, /* 29 = svr4_sys_pause */ + { AS(svr4_sys_utime_args), (sy_call_t *)svr4_sys_utime }, /* 30 = svr4_sys_utime */ + { 0, (sy_call_t *)nosys }, /* 31 = stty */ + { 0, (sy_call_t *)nosys }, /* 32 = gtty */ + { AS(svr4_sys_access_args), (sy_call_t *)svr4_sys_access }, /* 33 = svr4_sys_access */ + { AS(svr4_sys_nice_args), (sy_call_t *)svr4_sys_nice }, /* 34 = svr4_sys_nice */ + { 0, (sy_call_t *)nosys }, /* 35 = statfs */ + { 0, (sy_call_t *)sync }, /* 36 = sync */ + { AS(svr4_sys_kill_args), (sy_call_t *)svr4_sys_kill }, /* 37 = svr4_sys_kill */ + { 0, (sy_call_t *)nosys }, /* 38 = fstatfs */ + { AS(svr4_sys_pgrpsys_args), (sy_call_t *)svr4_sys_pgrpsys }, /* 39 = svr4_sys_pgrpsys */ + { 0, (sy_call_t *)nosys }, /* 40 = xenix */ + { AS(dup_args), (sy_call_t *)dup }, /* 41 = dup */ + { 0, (sy_call_t *)pipe }, /* 42 = pipe */ + { AS(svr4_sys_times_args), (sy_call_t *)svr4_sys_times }, /* 43 = svr4_sys_times */ + { 0, (sy_call_t *)nosys }, /* 44 = profil */ + { 0, (sy_call_t *)nosys }, /* 45 = plock */ + { AS(setgid_args), (sy_call_t *)setgid }, /* 46 = setgid */ + { 0, (sy_call_t *)getgid }, /* 47 = getgid */ + { AS(svr4_sys_signal_args), (sy_call_t *)svr4_sys_signal }, /* 48 = svr4_sys_signal */ +#if defined(NOTYET) + { AS(svr4_sys_msgsys_args), (sy_call_t *)svr4_sys_msgsys }, /* 49 = svr4_sys_msgsys */ +#else + { 0, (sy_call_t *)nosys }, /* 49 = msgsys */ +#endif + { AS(svr4_sys_sysarch_args), (sy_call_t *)svr4_sys_sysarch }, /* 50 = svr4_sys_sysarch */ + { 0, (sy_call_t *)nosys }, /* 51 = acct */ + { 0, (sy_call_t *)nosys }, /* 52 = shmsys */ + { 0, (sy_call_t *)nosys }, /* 53 = semsys */ + { AS(svr4_sys_ioctl_args), (sy_call_t *)svr4_sys_ioctl }, /* 54 = svr4_sys_ioctl */ + { 0, (sy_call_t *)nosys }, /* 55 = uadmin */ + { 0, (sy_call_t *)nosys }, /* 56 = exch */ + { AS(svr4_sys_utssys_args), (sy_call_t *)svr4_sys_utssys }, /* 57 = svr4_sys_utssys */ + { AS(fsync_args), (sy_call_t *)fsync }, /* 58 = fsync */ + { AS(svr4_sys_execve_args), (sy_call_t *)svr4_sys_execve }, /* 59 = svr4_sys_execve */ + { AS(umask_args), (sy_call_t *)umask }, /* 60 = umask */ + { AS(chroot_args), (sy_call_t *)chroot }, /* 61 = chroot */ + { AS(svr4_sys_fcntl_args), (sy_call_t *)svr4_sys_fcntl }, /* 62 = svr4_sys_fcntl */ + { AS(svr4_sys_ulimit_args), (sy_call_t *)svr4_sys_ulimit }, /* 63 = svr4_sys_ulimit */ + { 0, (sy_call_t *)nosys }, /* 64 = reserved */ + { 0, (sy_call_t *)nosys }, /* 65 = reserved */ + { 0, (sy_call_t *)nosys }, /* 66 = reserved */ + { 0, (sy_call_t *)nosys }, /* 67 = reserved */ + { 0, (sy_call_t *)nosys }, /* 68 = reserved */ + { 0, (sy_call_t *)nosys }, /* 69 = reserved */ + { 0, (sy_call_t *)nosys }, /* 70 = advfs */ + { 0, (sy_call_t *)nosys }, /* 71 = unadvfs */ + { 0, (sy_call_t *)nosys }, /* 72 = rmount */ + { 0, (sy_call_t *)nosys }, /* 73 = rumount */ + { 0, (sy_call_t *)nosys }, /* 74 = rfstart */ + { 0, (sy_call_t *)nosys }, /* 75 = sigret */ + { 0, (sy_call_t *)nosys }, /* 76 = rdebug */ + { 0, (sy_call_t *)nosys }, /* 77 = rfstop */ + { 0, (sy_call_t *)nosys }, /* 78 = rfsys */ + { AS(rmdir_args), (sy_call_t *)rmdir }, /* 79 = rmdir */ + { AS(mkdir_args), (sy_call_t *)mkdir }, /* 80 = mkdir */ + { AS(svr4_sys_getdents_args), (sy_call_t *)svr4_sys_getdents }, /* 81 = svr4_sys_getdents */ + { 0, (sy_call_t *)nosys }, /* 82 = libattach */ + { 0, (sy_call_t *)nosys }, /* 83 = libdetach */ + { 0, (sy_call_t *)nosys }, /* 84 = sysfs */ + { AS(svr4_sys_getmsg_args), (sy_call_t *)svr4_sys_getmsg }, /* 85 = svr4_sys_getmsg */ + { AS(svr4_sys_putmsg_args), (sy_call_t *)svr4_sys_putmsg }, /* 86 = svr4_sys_putmsg */ + { AS(svr4_sys_poll_args), (sy_call_t *)svr4_sys_poll }, /* 87 = svr4_sys_poll */ + { AS(svr4_sys_lstat_args), (sy_call_t *)svr4_sys_lstat }, /* 88 = svr4_sys_lstat */ + { AS(symlink_args), (sy_call_t *)symlink }, /* 89 = symlink */ + { AS(readlink_args), (sy_call_t *)readlink }, /* 90 = readlink */ + { AS(getgroups_args), (sy_call_t *)getgroups }, /* 91 = getgroups */ + { AS(setgroups_args), (sy_call_t *)setgroups }, /* 92 = setgroups */ + { AS(fchmod_args), (sy_call_t *)fchmod }, /* 93 = fchmod */ + { AS(fchown_args), (sy_call_t *)fchown }, /* 94 = fchown */ + { AS(svr4_sys_sigprocmask_args), (sy_call_t *)svr4_sys_sigprocmask }, /* 95 = svr4_sys_sigprocmask */ + { AS(svr4_sys_sigsuspend_args), (sy_call_t *)svr4_sys_sigsuspend }, /* 96 = svr4_sys_sigsuspend */ + { AS(svr4_sys_sigaltstack_args), (sy_call_t *)svr4_sys_sigaltstack }, /* 97 = svr4_sys_sigaltstack */ + { AS(svr4_sys_sigaction_args), (sy_call_t *)svr4_sys_sigaction }, /* 98 = svr4_sys_sigaction */ + { AS(svr4_sys_sigpending_args), (sy_call_t *)svr4_sys_sigpending }, /* 99 = svr4_sys_sigpending */ + { AS(svr4_sys_context_args), (sy_call_t *)svr4_sys_context }, /* 100 = svr4_sys_context */ + { 0, (sy_call_t *)nosys }, /* 101 = evsys */ + { 0, (sy_call_t *)nosys }, /* 102 = evtrapret */ + { AS(svr4_sys_statvfs_args), (sy_call_t *)svr4_sys_statvfs }, /* 103 = svr4_sys_statvfs */ + { AS(svr4_sys_fstatvfs_args), (sy_call_t *)svr4_sys_fstatvfs }, /* 104 = svr4_sys_fstatvfs */ + { 0, (sy_call_t *)nosys }, /* 105 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 106 = nfssvc */ + { AS(svr4_sys_waitsys_args), (sy_call_t *)svr4_sys_waitsys }, /* 107 = svr4_sys_waitsys */ + { 0, (sy_call_t *)nosys }, /* 108 = sigsendsys */ + { AS(svr4_sys_hrtsys_args), (sy_call_t *)svr4_sys_hrtsys }, /* 109 = svr4_sys_hrtsys */ + { 0, (sy_call_t *)nosys }, /* 110 = acancel */ + { 0, (sy_call_t *)nosys }, /* 111 = async */ + { 0, (sy_call_t *)nosys }, /* 112 = priocntlsys */ + { AS(svr4_sys_pathconf_args), (sy_call_t *)svr4_sys_pathconf }, /* 113 = svr4_sys_pathconf */ + { 0, (sy_call_t *)nosys }, /* 114 = mincore */ + { AS(svr4_sys_mmap_args), (sy_call_t *)svr4_sys_mmap }, /* 115 = svr4_sys_mmap */ + { AS(mprotect_args), (sy_call_t *)mprotect }, /* 116 = mprotect */ + { AS(munmap_args), (sy_call_t *)munmap }, /* 117 = munmap */ + { AS(svr4_sys_fpathconf_args), (sy_call_t *)svr4_sys_fpathconf }, /* 118 = svr4_sys_fpathconf */ + { 0, (sy_call_t *)vfork }, /* 119 = vfork */ + { AS(fchdir_args), (sy_call_t *)fchdir }, /* 120 = fchdir */ + { AS(readv_args), (sy_call_t *)readv }, /* 121 = readv */ + { AS(writev_args), (sy_call_t *)writev }, /* 122 = writev */ + { AS(svr4_sys_xstat_args), (sy_call_t *)svr4_sys_xstat }, /* 123 = svr4_sys_xstat */ + { AS(svr4_sys_lxstat_args), (sy_call_t *)svr4_sys_lxstat }, /* 124 = svr4_sys_lxstat */ + { AS(svr4_sys_fxstat_args), (sy_call_t *)svr4_sys_fxstat }, /* 125 = svr4_sys_fxstat */ + { AS(svr4_sys_xmknod_args), (sy_call_t *)svr4_sys_xmknod }, /* 126 = svr4_sys_xmknod */ + { 0, (sy_call_t *)nosys }, /* 127 = clocal */ + { AS(svr4_sys_setrlimit_args), (sy_call_t *)svr4_sys_setrlimit }, /* 128 = svr4_sys_setrlimit */ + { AS(svr4_sys_getrlimit_args), (sy_call_t *)svr4_sys_getrlimit }, /* 129 = svr4_sys_getrlimit */ + { AS(lchown_args), (sy_call_t *)lchown }, /* 130 = lchown */ + { AS(svr4_sys_memcntl_args), (sy_call_t *)svr4_sys_memcntl }, /* 131 = svr4_sys_memcntl */ + { 0, (sy_call_t *)nosys }, /* 132 = getpmsg */ + { 0, (sy_call_t *)nosys }, /* 133 = putpmsg */ + { AS(rename_args), (sy_call_t *)rename }, /* 134 = rename */ + { AS(svr4_sys_uname_args), (sy_call_t *)svr4_sys_uname }, /* 135 = svr4_sys_uname */ + { AS(setegid_args), (sy_call_t *)setegid }, /* 136 = setegid */ + { AS(svr4_sys_sysconfig_args), (sy_call_t *)svr4_sys_sysconfig }, /* 137 = svr4_sys_sysconfig */ + { AS(adjtime_args), (sy_call_t *)adjtime }, /* 138 = adjtime */ + { AS(svr4_sys_systeminfo_args), (sy_call_t *)svr4_sys_systeminfo }, /* 139 = svr4_sys_systeminfo */ + { 0, (sy_call_t *)nosys }, /* 140 = notused */ + { AS(seteuid_args), (sy_call_t *)seteuid }, /* 141 = seteuid */ + { 0, (sy_call_t *)nosys }, /* 142 = vtrace */ + { 0, (sy_call_t *)nosys }, /* 143 = { */ + { 0, (sy_call_t *)nosys }, /* 144 = sigtimedwait */ + { 0, (sy_call_t *)nosys }, /* 145 = lwp_info */ + { 0, (sy_call_t *)nosys }, /* 146 = yield */ + { 0, (sy_call_t *)nosys }, /* 147 = lwp_sema_wait */ + { 0, (sy_call_t *)nosys }, /* 148 = lwp_sema_post */ + { 0, (sy_call_t *)nosys }, /* 149 = lwp_sema_trywait */ + { 0, (sy_call_t *)nosys }, /* 150 = notused */ + { 0, (sy_call_t *)nosys }, /* 151 = notused */ + { 0, (sy_call_t *)nosys }, /* 152 = modctl */ + { AS(svr4_sys_fchroot_args), (sy_call_t *)svr4_sys_fchroot }, /* 153 = svr4_sys_fchroot */ + { AS(svr4_sys_utimes_args), (sy_call_t *)svr4_sys_utimes }, /* 154 = svr4_sys_utimes */ + { 0, (sy_call_t *)svr4_sys_vhangup }, /* 155 = svr4_sys_vhangup */ + { AS(svr4_sys_gettimeofday_args), (sy_call_t *)svr4_sys_gettimeofday }, /* 156 = svr4_sys_gettimeofday */ + { AS(getitimer_args), (sy_call_t *)getitimer }, /* 157 = getitimer */ + { AS(setitimer_args), (sy_call_t *)setitimer }, /* 158 = setitimer */ + { 0, (sy_call_t *)nosys }, /* 159 = lwp_create */ + { 0, (sy_call_t *)nosys }, /* 160 = lwp_exit */ + { 0, (sy_call_t *)nosys }, /* 161 = lwp_suspend */ + { 0, (sy_call_t *)nosys }, /* 162 = lwp_continue */ + { 0, (sy_call_t *)nosys }, /* 163 = lwp_kill */ + { 0, (sy_call_t *)nosys }, /* 164 = lwp_self */ + { 0, (sy_call_t *)nosys }, /* 165 = lwp_getprivate */ + { 0, (sy_call_t *)nosys }, /* 166 = lwp_setprivate */ + { 0, (sy_call_t *)nosys }, /* 167 = lwp_wait */ + { 0, (sy_call_t *)nosys }, /* 168 = lwp_mutex_unlock */ + { 0, (sy_call_t *)nosys }, /* 169 = lwp_mutex_lock */ + { 0, (sy_call_t *)nosys }, /* 170 = lwp_cond_wait */ + { 0, (sy_call_t *)nosys }, /* 171 = lwp_cond_signal */ + { 0, (sy_call_t *)nosys }, /* 172 = lwp_cond_broadcast */ + { 0, (sy_call_t *)nosys }, /* 173 = { */ + { 0, (sy_call_t *)nosys }, /* 174 = { */ + { AS(svr4_sys_llseek_args), (sy_call_t *)svr4_sys_llseek }, /* 175 = svr4_sys_llseek */ + { 0, (sy_call_t *)nosys }, /* 176 = inst_sync */ + { 0, (sy_call_t *)nosys }, /* 177 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 178 = kaio */ + { 0, (sy_call_t *)nosys }, /* 179 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 180 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 181 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 182 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 183 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 184 = tsolsys */ + { AS(svr4_sys_acl_args), (sy_call_t *)svr4_sys_acl }, /* 185 = svr4_sys_acl */ + { AS(svr4_sys_auditsys_args), (sy_call_t *)svr4_sys_auditsys }, /* 186 = svr4_sys_auditsys */ + { 0, (sy_call_t *)nosys }, /* 187 = processor_bind */ + { 0, (sy_call_t *)nosys }, /* 188 = processor_info */ + { 0, (sy_call_t *)nosys }, /* 189 = p_online */ + { 0, (sy_call_t *)nosys }, /* 190 = sigqueue */ + { 0, (sy_call_t *)nosys }, /* 191 = clock_gettime */ + { 0, (sy_call_t *)nosys }, /* 192 = clock_settime */ + { 0, (sy_call_t *)nosys }, /* 193 = clock_getres */ + { 0, (sy_call_t *)nosys }, /* 194 = timer_create */ + { 0, (sy_call_t *)nosys }, /* 195 = timer_delete */ + { 0, (sy_call_t *)nosys }, /* 196 = timer_settime */ + { 0, (sy_call_t *)nosys }, /* 197 = timer_gettime */ + { 0, (sy_call_t *)nosys }, /* 198 = timer_overrun */ + { AS(nanosleep_args), (sy_call_t *)nanosleep }, /* 199 = nanosleep */ + { AS(svr4_sys_facl_args), (sy_call_t *)svr4_sys_facl }, /* 200 = svr4_sys_facl */ + { 0, (sy_call_t *)nosys }, /* 201 = door */ + { AS(setreuid_args), (sy_call_t *)setreuid }, /* 202 = setreuid */ + { AS(setregid_args), (sy_call_t *)setregid }, /* 203 = setregid */ + { 0, (sy_call_t *)nosys }, /* 204 = install_utrap */ + { 0, (sy_call_t *)nosys }, /* 205 = signotify */ + { 0, (sy_call_t *)nosys }, /* 206 = schedctl */ + { 0, (sy_call_t *)nosys }, /* 207 = pset */ + { 0, (sy_call_t *)nosys }, /* 208 = whoknows */ + { AS(svr4_sys_resolvepath_args), (sy_call_t *)svr4_sys_resolvepath }, /* 209 = svr4_sys_resolvepath */ + { 0, (sy_call_t *)nosys }, /* 210 = signotifywait */ + { 0, (sy_call_t *)nosys }, /* 211 = lwp_sigredirect */ + { 0, (sy_call_t *)nosys }, /* 212 = lwp_alarm */ + { AS(svr4_sys_getdents64_args), (sy_call_t *)svr4_sys_getdents64 }, /* 213 = svr4_sys_getdents64 */ + { AS(svr4_sys_mmap64_args), (sy_call_t *)svr4_sys_mmap64 }, /* 214 = svr4_sys_mmap64 */ + { AS(svr4_sys_stat64_args), (sy_call_t *)svr4_sys_stat64 }, /* 215 = svr4_sys_stat64 */ + { AS(svr4_sys_lstat64_args), (sy_call_t *)svr4_sys_lstat64 }, /* 216 = svr4_sys_lstat64 */ + { AS(svr4_sys_fstat64_args), (sy_call_t *)svr4_sys_fstat64 }, /* 217 = svr4_sys_fstat64 */ + { AS(svr4_sys_statvfs64_args), (sy_call_t *)svr4_sys_statvfs64 }, /* 218 = svr4_sys_statvfs64 */ + { AS(svr4_sys_fstatvfs64_args), (sy_call_t *)svr4_sys_fstatvfs64 }, /* 219 = svr4_sys_fstatvfs64 */ + { AS(svr4_sys_setrlimit64_args), (sy_call_t *)svr4_sys_setrlimit64 }, /* 220 = svr4_sys_setrlimit64 */ + { AS(svr4_sys_getrlimit64_args), (sy_call_t *)svr4_sys_getrlimit64 }, /* 221 = svr4_sys_getrlimit64 */ + { 0, (sy_call_t *)nosys }, /* 222 = pread64 */ + { 0, (sy_call_t *)nosys }, /* 223 = pwrite64 */ + { AS(svr4_sys_creat64_args), (sy_call_t *)svr4_sys_creat64 }, /* 224 = svr4_sys_creat64 */ + { AS(svr4_sys_open64_args), (sy_call_t *)svr4_sys_open64 }, /* 225 = svr4_sys_open64 */ + { 0, (sy_call_t *)nosys }, /* 226 = rpcsys */ + { 0, (sy_call_t *)nosys }, /* 227 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 228 = whoknows */ + { 0, (sy_call_t *)nosys }, /* 229 = whoknows */ + { AS(svr4_sys_socket_args), (sy_call_t *)svr4_sys_socket }, /* 230 = svr4_sys_socket */ + { AS(socketpair_args), (sy_call_t *)socketpair }, /* 231 = socketpair */ + { AS(bind_args), (sy_call_t *)bind }, /* 232 = bind */ + { AS(listen_args), (sy_call_t *)listen }, /* 233 = listen */ + { AS(accept_args), (sy_call_t *)accept }, /* 234 = accept */ + { AS(connect_args), (sy_call_t *)connect }, /* 235 = connect */ + { AS(shutdown_args), (sy_call_t *)shutdown }, /* 236 = shutdown */ + { AS(svr4_sys_recv_args), (sy_call_t *)svr4_sys_recv }, /* 237 = svr4_sys_recv */ + { AS(recvfrom_args), (sy_call_t *)recvfrom }, /* 238 = recvfrom */ + { AS(recvmsg_args), (sy_call_t *)recvmsg }, /* 239 = recvmsg */ + { AS(svr4_sys_send_args), (sy_call_t *)svr4_sys_send }, /* 240 = svr4_sys_send */ + { AS(sendmsg_args), (sy_call_t *)sendmsg }, /* 241 = sendmsg */ + { AS(svr4_sys_sendto_args), (sy_call_t *)svr4_sys_sendto }, /* 242 = svr4_sys_sendto */ + { AS(getpeername_args), (sy_call_t *)getpeername }, /* 243 = getpeername */ + { AS(getsockname_args), (sy_call_t *)getsockname }, /* 244 = getsockname */ + { AS(getsockopt_args), (sy_call_t *)getsockopt }, /* 245 = getsockopt */ + { AS(setsockopt_args), (sy_call_t *)setsockopt }, /* 246 = setsockopt */ + { 0, (sy_call_t *)nosys }, /* 247 = sockconfig */ + { 0, (sy_call_t *)nosys }, /* 248 = { */ + { 0, (sy_call_t *)nosys }, /* 249 = { */ +}; diff --git a/sys/compat/svr4/svr4_systeminfo.h b/sys/compat/svr4/svr4_systeminfo.h new file mode 100644 index 0000000..40bc2b8 --- /dev/null +++ b/sys/compat/svr4/svr4_systeminfo.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_SYSTEMINFO_H_ +#define _SVR4_SYSTEMINFO_H_ + +#define SVR4_SI_SYSNAME 1 +#define SVR4_SI_HOSTNAME 2 +#define SVR4_SI_RELEASE 3 +#define SVR4_SI_VERSION 4 +#define SVR4_SI_MACHINE 5 +#define SVR4_SI_ARCHITECTURE 6 +#define SVR4_SI_HW_SERIAL 7 +#define SVR4_SI_HW_PROVIDER 8 +#define SVR4_SI_SRPC_DOMAIN 9 +#define SVR4_SI_SET_HOSTNAME 258 +#define SVR4_SI_SET_SRPC_DOMAIN 265 +#define SVR4_SI_SET_KERB_REALM 266 +#define SVR4_SI_KERB_REALM 267 +#define SVR4_SI_PLATFORM 513 +#define SVR4_SI_ISALIST 514 + +#endif /* !_SVR4_SYSTEMINFO_H_ */ diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c new file mode 100644 index 0000000..c7d67ff --- /dev/null +++ b/sys/compat/svr4/svr4_sysvec.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 1998 Mark Newton + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* XXX we use functions that might not exist. */ +#include "opt_compat.h" + +#ifndef COMPAT_43 +#error "Unable to compile SVR4-emulator due to missing COMPAT_43 option!" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/sysent.h> +#include <sys/imgact.h> +#include <sys/imgact_elf.h> +#include <sys/socket.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/namei.h> +#include <sys/vnode.h> +#include <sys/module.h> +#include <vm/vm.h> +#include <sys/exec.h> +#include <sys/kernel.h> +#include <machine/cpu.h> +#include <netinet/in.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_syscall.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_sockio.h> +#include <compat/svr4/svr4_socket.h> +#include <compat/svr4/svr4_errno.h> +#include <compat/svr4/svr4_proto.h> +#include <compat/svr4/svr4_siginfo.h> +#include <compat/svr4/svr4_util.h> + +int bsd_to_svr4_errno[ELAST+1] = { + 0, + SVR4_EPERM, + SVR4_ENOENT, + SVR4_ESRCH, + SVR4_EINTR, + SVR4_EIO, + SVR4_ENXIO, + SVR4_E2BIG, + SVR4_ENOEXEC, + SVR4_EBADF, + SVR4_ECHILD, + SVR4_EDEADLK, + SVR4_ENOMEM, + SVR4_EACCES, + SVR4_EFAULT, + SVR4_ENOTBLK, + SVR4_EBUSY, + SVR4_EEXIST, + SVR4_EXDEV, + SVR4_ENODEV, + SVR4_ENOTDIR, + SVR4_EISDIR, + SVR4_EINVAL, + SVR4_ENFILE, + SVR4_EMFILE, + SVR4_ENOTTY, + SVR4_ETXTBSY, + SVR4_EFBIG, + SVR4_ENOSPC, + SVR4_ESPIPE, + SVR4_EROFS, + SVR4_EMLINK, + SVR4_EPIPE, + SVR4_EDOM, + SVR4_ERANGE, + SVR4_EAGAIN, + SVR4_EINPROGRESS, + SVR4_EALREADY, + SVR4_ENOTSOCK, + SVR4_EDESTADDRREQ, + SVR4_EMSGSIZE, + SVR4_EPROTOTYPE, + SVR4_ENOPROTOOPT, + SVR4_EPROTONOSUPPORT, + SVR4_ESOCKTNOSUPPORT, + SVR4_EOPNOTSUPP, + SVR4_EPFNOSUPPORT, + SVR4_EAFNOSUPPORT, + SVR4_EADDRINUSE, + SVR4_EADDRNOTAVAIL, + SVR4_ENETDOWN, + SVR4_ENETUNREACH, + SVR4_ENETRESET, + SVR4_ECONNABORTED, + SVR4_ECONNRESET, + SVR4_ENOBUFS, + SVR4_EISCONN, + SVR4_ENOTCONN, + SVR4_ESHUTDOWN, + SVR4_ETOOMANYREFS, + SVR4_ETIMEDOUT, + SVR4_ECONNREFUSED, + SVR4_ELOOP, + SVR4_ENAMETOOLONG, + SVR4_EHOSTDOWN, + SVR4_EHOSTUNREACH, + SVR4_ENOTEMPTY, + SVR4_EPROCLIM, + SVR4_EUSERS, + SVR4_EDQUOT, + SVR4_ESTALE, + SVR4_EREMOTE, + SVR4_EBADRPC, + SVR4_ERPCMISMATCH, + SVR4_EPROGUNAVAIL, + SVR4_EPROGMISMATCH, + SVR4_EPROCUNAVAIL, + SVR4_ENOLCK, + SVR4_ENOSYS, + SVR4_EFTYPE, + SVR4_EAUTH, + SVR4_ENEEDAUTH, + SVR4_EIDRM, + SVR4_ENOMSG, +}; + + +static int svr4_fixup(register_t **stack_base, struct image_params *imgp); + +extern struct sysent svr4_sysent[]; +#undef szsigcode +#undef sigcode + +extern int svr4_szsigcode; +extern char svr4_sigcode[]; + +struct sysentvec svr4_sysvec = { + SVR4_SYS_MAXSYSCALL, + svr4_sysent, + 0xff, + SVR4_SIGTBLSZ, + bsd_to_svr4_sig, + ELAST, /* ELAST */ + bsd_to_svr4_errno, + 0, + svr4_fixup, + svr4_sendsig, + svr4_sigcode, + &svr4_szsigcode, + NULL, + "SVR4", + elf32_coredump, + NULL, + SVR4_MINSIGSTKSZ +}; + +Elf32_Brandinfo svr4_brand = { + ELFOSABI_SYSV, + EM_386, /* XXX only implemented for x86 so far. */ + "SVR4", + svr4_emul_path, + "/lib/libc.so.1", + &svr4_sysvec +}; + +const char svr4_emul_path[] = "/compat/svr4"; + +static int +svr4_fixup(register_t **stack_base, struct image_params *imgp) +{ + Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs; + register_t *pos; + + pos = *stack_base + (imgp->argc + imgp->envc + 2); + + if (args->trace) { + AUXARGS_ENTRY(pos, AT_DEBUG, 1); + } + if (args->execfd != -1) { + AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd); + } + AUXARGS_ENTRY(pos, AT_PHDR, args->phdr); + AUXARGS_ENTRY(pos, AT_PHENT, args->phent); + AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum); + AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz); + AUXARGS_ENTRY(pos, AT_FLAGS, args->flags); + AUXARGS_ENTRY(pos, AT_ENTRY, args->entry); + AUXARGS_ENTRY(pos, AT_BASE, args->base); + PROC_LOCK(imgp->proc); + AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid); + AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid); + AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid); + AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid); + PROC_UNLOCK(imgp->proc); + AUXARGS_ENTRY(pos, AT_NULL, 0); + + free(imgp->auxargs, M_TEMP); + imgp->auxargs = NULL; + + (*stack_base)--; + **stack_base = (int)imgp->argc; + return 0; +} + +/* + * Search an alternate path before passing pathname arguments on + * to system calls. Useful for keeping a separate 'emulation tree'. + * + * If cflag is set, we check if an attempt can be made to create + * the named file, i.e. we check if the directory it should + * be in exists. + * + * Code shamelessly stolen by Mark Newton from IBCS2 emulation code. + */ +int +svr4_emul_find(td, sgp, prefix, path, pbuf, cflag) + struct thread *td; + caddr_t *sgp; /* Pointer to stackgap memory */ + const char *prefix; + char *path; + char **pbuf; + int cflag; +{ + struct nameidata nd; + struct nameidata ndroot; + struct vattr vat; + struct vattr vatroot; + int error; + char *ptr, *buf, *cp; + size_t sz, len; + + buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); + *pbuf = path; + + for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) + continue; + + sz = MAXPATHLEN - (ptr - buf); + + /* + * If sgp is not given then the path is already in kernel space + */ + if (sgp == NULL) + error = copystr(path, ptr, sz, &len); + else + error = copyinstr(path, ptr, sz, &len); + + if (error) { + free(buf, M_TEMP); + return error; + } + + if (*ptr != '/') { + free(buf, M_TEMP); + return EINVAL; + } + + /* + * We know that there is a / somewhere in this pathname. + * Search backwards for it, to find the file's parent dir + * to see if it exists in the alternate tree. If it does, + * and we want to create a file (cflag is set). We don't + * need to worry about the root comparison in this case. + */ + + if (cflag) { + for (cp = &ptr[len] - 1; *cp != '/'; cp--); + *cp = '\0'; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + NDFREE(&nd, NDF_ONLY_PNBUF); + + *cp = '/'; + } + else { + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); + + if ((error = namei(&nd)) != 0) { + free(buf, M_TEMP); + return error; + } + NDFREE(&nd, NDF_ONLY_PNBUF); + + /* + * We now compare the vnode of the svr4_root to the one + * vnode asked. If they resolve to be the same, then we + * ignore the match so that the real root gets used. + * This avoids the problem of traversing "../.." to find the + * root directory and never finding it, because "/" resolves + * to the emulation root directory. This is expensive :-( + */ + NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, svr4_emul_path, + td); + + if ((error = namei(&ndroot)) != 0) { + /* Cannot happen! */ + free(buf, M_TEMP); + vrele(nd.ni_vp); + return error; + } + NDFREE(&ndroot, NDF_ONLY_PNBUF); + + if ((error = VOP_GETATTR(nd.ni_vp, &vat, td->td_ucred, td)) != 0) { + goto done; + } + + if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, td->td_ucred, td)) + != 0) { + goto done; + } + + if (vat.va_fsid == vatroot.va_fsid && + vat.va_fileid == vatroot.va_fileid) { + error = ENOENT; + goto done; + } + + } + if (sgp == NULL) + *pbuf = buf; + else { + sz = &ptr[len] - buf; + *pbuf = stackgap_alloc(sgp, sz + 1); + error = copyout(buf, *pbuf, sz); + free(buf, M_TEMP); + } + + +done: + vrele(nd.ni_vp); + if (!cflag) + vrele(ndroot.ni_vp); + return error; +} + +static int +svr4_elf_modevent(module_t mod, int type, void *data) +{ + int error; + + error = 0; + + switch(type) { + case MOD_LOAD: + if (elf32_insert_brand_entry(&svr4_brand) < 0) + error = EINVAL; + if (error) + printf("cannot insert svr4 elf brand handler\n"); + else if (bootverbose) + printf("svr4 ELF exec handler installed\n"); + break; + case MOD_UNLOAD: + /* Only allow the emulator to be removed if it isn't in use. */ + if (elf32_brand_inuse(&svr4_brand) != 0) { + error = EBUSY; + } else if (elf32_remove_brand_entry(&svr4_brand) < 0) { + error = EINVAL; + } + + if (error) + printf("Could not deinstall ELF interpreter entry (error %d)\n", + error); + else if (bootverbose) + printf("svr4 ELF exec handler removed\n"); + break; + default: + break; + } + return error; +} + +static moduledata_t svr4_elf_mod = { + "svr4elf", + svr4_elf_modevent, + 0 +}; +DECLARE_MODULE(svr4elf, svr4_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY); +MODULE_DEPEND(svr4elf, streams, 1, 1, 1); diff --git a/sys/compat/svr4/svr4_termios.c b/sys/compat/svr4/svr4_termios.c new file mode 100644 index 0000000..5fdd5a6 --- /dev/null +++ b/sys/compat/svr4/svr4_termios.c @@ -0,0 +1,607 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/termios.h> + +#include <sys/sysproto.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_ioctl.h> +#include <compat/svr4/svr4_termios.h> + +#ifndef __CONCAT3 +# if __STDC__ +# define __CONCAT3(a,b,c) a ## b ## c +# else +# define __CONCAT3(a,b,c) a/**/b/**/c +# endif +#endif + +static u_long bsd_to_svr4_speed(u_long, u_long); +static u_long svr4_to_bsd_speed(u_long, u_long); +static void svr4_to_bsd_termios(const struct svr4_termios *, + struct termios *, int); +static void bsd_to_svr4_termios(const struct termios *, + struct svr4_termios *); +static void svr4_termio_to_termios(const struct svr4_termio *, + struct svr4_termios *); +static void svr4_termios_to_termio(const struct svr4_termios *, + struct svr4_termio *); +#ifdef DEBUG_SVR4 +static void print_svr4_termios(const struct svr4_termios *); +static void print_bsd_termios(const struct termios *); +#endif /* DEBUG_SVR4 */ + +#define undefined_char(a,b) /**/ +#define undefined_flag1(f,a,b) /**/ +#define undefined_flag2(f,a,b,c1,t1,c2,t2) /**/ +#define undefined_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) /**/ + +#define svr4_to_bsd_char(a,b) \ + if (new || __CONCAT3(SVR4_,a,b) < SVR4_NCC) { \ + if (st->c_cc[__CONCAT3(SVR4_,a,b)] == SVR4_POSIX_VDISABLE) \ + bt->c_cc[__CONCAT(a,b)] = _POSIX_VDISABLE; \ + else \ + bt->c_cc[__CONCAT(a,b)] = st->c_cc[__CONCAT3(SVR4_,a,b)]; \ + } + +#define svr4_to_bsd_flag1(f,a,b) \ + if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ + if (st->f & __CONCAT3(SVR4_,a,b)) \ + bt->f |= __CONCAT(a,b); \ + else \ + bt->f &= ~__CONCAT(a,b); \ + } + +#define svr4_to_bsd_flag2(f,a,b,c1,t1,c2,t2) \ + if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ + bt->f &= ~__CONCAT(a,b); \ + switch (st->f & __CONCAT3(SVR4_,a,b)) { \ + case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ + case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ + } \ + } + +#define svr4_to_bsd_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ + if (new || __CONCAT3(SVR4_,a,b) < 0200000) { \ + bt->f &= ~__CONCAT(a,b); \ + switch (st->f & __CONCAT3(SVR4_,a,b)) { \ + case __CONCAT3(SVR4_,c1,t1): bt->f |= __CONCAT(c1,t1); break; \ + case __CONCAT3(SVR4_,c2,t2): bt->f |= __CONCAT(c2,t2); break; \ + case __CONCAT3(SVR4_,c3,t3): bt->f |= __CONCAT(c3,t3); break; \ + case __CONCAT3(SVR4_,c4,t4): bt->f |= __CONCAT(c4,t4); break; \ + } \ + } + + +#define bsd_to_svr4_char(a,b) \ + if (bt->c_cc[__CONCAT(a,b)] == _POSIX_VDISABLE) \ + st->c_cc[__CONCAT3(SVR4_,a,b)] = SVR4_POSIX_VDISABLE; \ + else \ + st->c_cc[__CONCAT3(SVR4_,a,b)] = bt->c_cc[__CONCAT(a,b)] + +#define bsd_to_svr4_flag1(f,a,b) \ + if (bt->f & __CONCAT(a,b)) \ + st->f |= __CONCAT3(SVR4_,a,b); \ + else \ + st->f &= ~__CONCAT3(SVR4_,a,b) + +#define bsd_to_svr4_flag2(f,a,b,c1,t1,c2,t2) \ + st->f &= ~__CONCAT(a,b); \ + switch (bt->f & __CONCAT(a,b)) { \ + case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ + case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ + } + +#define bsd_to_svr4_flag4(f,a,b,c1,t1,c2,t2,c3,t3,c4,t4) \ + st->f &= ~__CONCAT(a,b); \ + switch (bt->f & __CONCAT(a,b)) { \ + case __CONCAT(c1,t1): st->f |= __CONCAT3(SVR4_,c1,t1); break; \ + case __CONCAT(c2,t2): st->f |= __CONCAT3(SVR4_,c2,t2); break; \ + case __CONCAT(c3,t3): st->f |= __CONCAT3(SVR4_,c3,t3); break; \ + case __CONCAT(c4,t4): st->f |= __CONCAT3(SVR4_,c4,t4); break; \ + } + +#ifdef DEBUG_SVR4 +static void +print_svr4_termios(st) + const struct svr4_termios *st; +{ + int i; + DPRINTF(("SVR4\niflag=%lo oflag=%lo cflag=%lo lflag=%lo\n", + st->c_iflag, st->c_oflag, st->c_cflag, st->c_lflag)); + DPRINTF(("cc: ")); + for (i = 0; i < SVR4_NCCS; i++) + DPRINTF(("%o ", st->c_cc[i])); + DPRINTF(("\n")); +} + + +static void +print_bsd_termios(bt) + const struct termios *bt; +{ + int i; + uprintf("BSD\niflag=%o oflag=%o cflag=%o lflag=%o\n", + bt->c_iflag, bt->c_oflag, bt->c_cflag, bt->c_lflag); + uprintf("cc: "); + for (i = 0; i < NCCS; i++) + uprintf("%o ", bt->c_cc[i]); + uprintf("\n"); +} +#endif /* DEBUG_SVR4 */ + +static u_long +bsd_to_svr4_speed(sp, mask) + u_long sp; + u_long mask; +{ + switch (sp) { +#undef getval +#define getval(a,b) case __CONCAT(a,b): sp = __CONCAT3(SVR4_,a,b) + getval(B,0); + getval(B,50); + getval(B,75); + getval(B,110); + getval(B,134); + getval(B,150); + getval(B,200); + getval(B,300); + getval(B,600); + getval(B,1200); + getval(B,1800); + getval(B,2400); + getval(B,4800); + getval(B,9600); + getval(B,19200); + getval(B,38400); + getval(B,57600); + getval(B,115200); + default: sp = SVR4_B9600; /* XXX */ + } + + while ((mask & 1) == 0) { + mask >>= 1; + sp <<= 1; + } + + return sp; +} + + +static u_long +svr4_to_bsd_speed(sp, mask) + u_long sp; + u_long mask; +{ + while ((mask & 1) == 0) { + mask >>= 1; + sp >>= 1; + } + + switch (sp & mask) { +#undef getval +#define getval(a,b) case __CONCAT3(SVR4_,a,b): return __CONCAT(a,b) + getval(B,0); + getval(B,50); + getval(B,75); + getval(B,110); + getval(B,134); + getval(B,150); + getval(B,200); + getval(B,300); + getval(B,600); + getval(B,1200); + getval(B,1800); + getval(B,2400); + getval(B,4800); + getval(B,9600); + getval(B,19200); + getval(B,38400); + getval(B,57600); + getval(B,115200); + default: return B9600; /* XXX */ + } +} + + +static void +svr4_to_bsd_termios(st, bt, new) + const struct svr4_termios *st; + struct termios *bt; + int new; +{ + /* control characters */ + /* + * We process VMIN and VTIME first, + * because they are shared with VEOF and VEOL + */ + svr4_to_bsd_char(V,MIN); + svr4_to_bsd_char(V,TIME); + + svr4_to_bsd_char(V,INTR); + svr4_to_bsd_char(V,QUIT); + svr4_to_bsd_char(V,ERASE); + svr4_to_bsd_char(V,KILL); + svr4_to_bsd_char(V,EOF); + svr4_to_bsd_char(V,EOL); + svr4_to_bsd_char(V,EOL2); + undefined_char(V,SWTCH); + svr4_to_bsd_char(V,START); + svr4_to_bsd_char(V,STOP); + svr4_to_bsd_char(V,SUSP); + svr4_to_bsd_char(V,DSUSP); + svr4_to_bsd_char(V,REPRINT); + svr4_to_bsd_char(V,DISCARD); + svr4_to_bsd_char(V,WERASE); + svr4_to_bsd_char(V,LNEXT); + + /* Input modes */ + svr4_to_bsd_flag1(c_iflag,I,GNBRK); + svr4_to_bsd_flag1(c_iflag,B,RKINT); + svr4_to_bsd_flag1(c_iflag,I,GNPAR); + svr4_to_bsd_flag1(c_iflag,P,ARMRK); + svr4_to_bsd_flag1(c_iflag,I,NPCK); + svr4_to_bsd_flag1(c_iflag,I,STRIP); + svr4_to_bsd_flag1(c_iflag,I,NLCR); + svr4_to_bsd_flag1(c_iflag,I,GNCR); + svr4_to_bsd_flag1(c_iflag,I,CRNL); + undefined_flag1(c_iflag,I,UCLC); + svr4_to_bsd_flag1(c_iflag,I,XON); + svr4_to_bsd_flag1(c_iflag,I,XANY); + svr4_to_bsd_flag1(c_iflag,I,XOFF); + svr4_to_bsd_flag1(c_iflag,I,MAXBEL); + undefined_flag1(c_iflag,D,OSMODE); + + /* Output modes */ + svr4_to_bsd_flag1(c_oflag,O,POST); + undefined_flag1(c_oflag,O,LCUC); + svr4_to_bsd_flag1(c_oflag,O,NLCR); + undefined_flag1(c_oflag,O,CRNL); + undefined_flag1(c_oflag,O,NOCR); + undefined_flag1(c_oflag,O,NLRET); + undefined_flag1(c_oflag,O,FILL); + undefined_flag1(c_oflag,O,FDEL); + undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); + undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); + undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); + undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); + undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); + undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); + undefined_flag1(c_oflag,P,AGEOUT); + undefined_flag1(c_oflag,W,RAP); + + /* Control modes */ + bt->c_ospeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CBAUD); + svr4_to_bsd_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) + svr4_to_bsd_flag1(c_cflag,C,STOPB); + svr4_to_bsd_flag1(c_cflag,C,READ); + svr4_to_bsd_flag1(c_cflag,P,ARENB); + svr4_to_bsd_flag1(c_cflag,P,ARODD); + svr4_to_bsd_flag1(c_cflag,H,UPCL); + svr4_to_bsd_flag1(c_cflag,C,LOCAL); + undefined_flag1(c_cflag,R,CV1EN); + undefined_flag1(c_cflag,X,MT1EN); + undefined_flag1(c_cflag,L,OBLK); + undefined_flag1(c_cflag,X,CLUDE); + bt->c_ispeed = svr4_to_bsd_speed(st->c_cflag, SVR4_CIBAUD); + undefined_flag1(c_cflag,P,AREXT); + + /* line discipline modes */ + svr4_to_bsd_flag1(c_lflag,I,SIG); + svr4_to_bsd_flag1(c_lflag,I,CANON); + undefined_flag1(c_lflag,X,CASE); + svr4_to_bsd_flag1(c_lflag,E,CHO); + svr4_to_bsd_flag1(c_lflag,E,CHOE); + svr4_to_bsd_flag1(c_lflag,E,CHOK); + svr4_to_bsd_flag1(c_lflag,E,CHONL); + svr4_to_bsd_flag1(c_lflag,N,OFLSH); + svr4_to_bsd_flag1(c_lflag,T,OSTOP); + svr4_to_bsd_flag1(c_lflag,E,CHOCTL); + svr4_to_bsd_flag1(c_lflag,E,CHOPRT); + svr4_to_bsd_flag1(c_lflag,E,CHOKE); + undefined_flag1(c_lflag,D,EFECHO); + svr4_to_bsd_flag1(c_lflag,F,LUSHO); + svr4_to_bsd_flag1(c_lflag,P,ENDIN); + svr4_to_bsd_flag1(c_lflag,I,EXTEN); +} + + +static void +bsd_to_svr4_termios(bt, st) + const struct termios *bt; + struct svr4_termios *st; +{ + /* control characters */ + /* + * We process VMIN and VTIME first, + * because they are shared with VEOF and VEOL + */ + bsd_to_svr4_char(V,MIN); + bsd_to_svr4_char(V,TIME); + bsd_to_svr4_char(V,INTR); + bsd_to_svr4_char(V,QUIT); + bsd_to_svr4_char(V,ERASE); + bsd_to_svr4_char(V,KILL); + bsd_to_svr4_char(V,EOF); + bsd_to_svr4_char(V,EOL); + bsd_to_svr4_char(V,EOL2); + undefined_char(V,SWTCH); + bsd_to_svr4_char(V,START); + bsd_to_svr4_char(V,STOP); + bsd_to_svr4_char(V,SUSP); + bsd_to_svr4_char(V,DSUSP); + bsd_to_svr4_char(V,REPRINT); + bsd_to_svr4_char(V,DISCARD); + bsd_to_svr4_char(V,WERASE); + bsd_to_svr4_char(V,LNEXT); + + /* Input modes */ + bsd_to_svr4_flag1(c_iflag,I,GNBRK); + bsd_to_svr4_flag1(c_iflag,B,RKINT); + bsd_to_svr4_flag1(c_iflag,I,GNPAR); + bsd_to_svr4_flag1(c_iflag,P,ARMRK); + bsd_to_svr4_flag1(c_iflag,I,NPCK); + bsd_to_svr4_flag1(c_iflag,I,STRIP); + bsd_to_svr4_flag1(c_iflag,I,NLCR); + bsd_to_svr4_flag1(c_iflag,I,GNCR); + bsd_to_svr4_flag1(c_iflag,I,CRNL); + undefined_flag1(c_iflag,I,UCLC); + bsd_to_svr4_flag1(c_iflag,I,XON); + bsd_to_svr4_flag1(c_iflag,I,XANY); + bsd_to_svr4_flag1(c_iflag,I,XOFF); + bsd_to_svr4_flag1(c_iflag,I,MAXBEL); + undefined_flag1(c_iflag,D,OSMODE); + + /* Output modes */ + bsd_to_svr4_flag1(c_oflag,O,POST); + undefined_flag1(c_oflag,O,LCUC); + bsd_to_svr4_flag1(c_oflag,O,NLCR); + undefined_flag1(c_oflag,O,CRNL); + undefined_flag1(c_oflag,O,NOCR); + undefined_flag1(c_oflag,O,NLRET); + undefined_flag1(c_oflag,O,FILL); + undefined_flag1(c_oflag,O,FDEL); + undefined_flag2(c_oflag,N,LDLY,N,L0,N,L1); + undefined_flag4(c_oflag,C,RDLY,C,R0,C,R1,C,R2,C,R3); + undefined_flag4(c_oflag,T,ABDLY,T,AB0,T,AB1,T,AB2,T,AB3); + undefined_flag2(c_oflag,B,SDLY,B,S0,B,S1); + undefined_flag2(c_oflag,V,TDLY,V,T0,V,T1); + undefined_flag2(c_oflag,F,FDLY,F,F0,F,F1); + undefined_flag1(c_oflag,P,AGEOUT); + undefined_flag1(c_oflag,W,RAP); + + /* Control modes */ + st->c_cflag &= ~SVR4_CBAUD; + st->c_cflag |= bsd_to_svr4_speed(bt->c_ospeed, SVR4_CBAUD); + bsd_to_svr4_flag4(c_cflag,C,SIZE,C,S5,C,S6,C,S7,C,S8) + bsd_to_svr4_flag1(c_cflag,C,STOPB); + bsd_to_svr4_flag1(c_cflag,C,READ); + bsd_to_svr4_flag1(c_cflag,P,ARENB); + bsd_to_svr4_flag1(c_cflag,P,ARODD); + bsd_to_svr4_flag1(c_cflag,H,UPCL); + bsd_to_svr4_flag1(c_cflag,C,LOCAL); + undefined_flag1(c_cflag,R,CV1EN); + undefined_flag1(c_cflag,X,MT1EN); + undefined_flag1(c_cflag,L,OBLK); + undefined_flag1(c_cflag,X,CLUDE); + st->c_cflag &= ~SVR4_CIBAUD; + st->c_cflag |= bsd_to_svr4_speed(bt->c_ispeed, SVR4_CIBAUD); + + undefined_flag1(c_oflag,P,AREXT); + + /* line discipline modes */ + bsd_to_svr4_flag1(c_lflag,I,SIG); + bsd_to_svr4_flag1(c_lflag,I,CANON); + undefined_flag1(c_lflag,X,CASE); + bsd_to_svr4_flag1(c_lflag,E,CHO); + bsd_to_svr4_flag1(c_lflag,E,CHOE); + bsd_to_svr4_flag1(c_lflag,E,CHOK); + bsd_to_svr4_flag1(c_lflag,E,CHONL); + bsd_to_svr4_flag1(c_lflag,N,OFLSH); + bsd_to_svr4_flag1(c_lflag,T,OSTOP); + bsd_to_svr4_flag1(c_lflag,E,CHOCTL); + bsd_to_svr4_flag1(c_lflag,E,CHOPRT); + bsd_to_svr4_flag1(c_lflag,E,CHOKE); + undefined_flag1(c_lflag,D,EFECHO); + bsd_to_svr4_flag1(c_lflag,F,LUSHO); + bsd_to_svr4_flag1(c_lflag,P,ENDIN); + bsd_to_svr4_flag1(c_lflag,I,EXTEN); +} + + +static void +svr4_termio_to_termios(t, ts) + const struct svr4_termio *t; + struct svr4_termios *ts; +{ + int i; + + ts->c_iflag = (svr4_tcflag_t) t->c_iflag; + ts->c_oflag = (svr4_tcflag_t) t->c_oflag; + ts->c_cflag = (svr4_tcflag_t) t->c_cflag; + ts->c_lflag = (svr4_tcflag_t) t->c_lflag; + + for (i = 0; i < SVR4_NCC; i++) + ts->c_cc[i] = (svr4_cc_t) t->c_cc[i]; +} + + +static void +svr4_termios_to_termio(ts, t) + const struct svr4_termios *ts; + struct svr4_termio *t; +{ + int i; + + t->c_iflag = (u_short) ts->c_iflag; + t->c_oflag = (u_short) ts->c_oflag; + t->c_cflag = (u_short) ts->c_cflag; + t->c_lflag = (u_short) ts->c_lflag; + t->c_line = 0; /* XXX */ + + for (i = 0; i < SVR4_NCC; i++) + t->c_cc[i] = (u_char) ts->c_cc[i]; +} + +int +svr4_term_ioctl(fp, td, retval, fd, cmd, data) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t data; +{ + struct termios bt; + struct svr4_termios st; + struct svr4_termio t; + int error, new; + + *retval = 0; + + DPRINTF(("TERM ioctl %lx\n", cmd)); + + switch (cmd) { + case SVR4_TCGETA: + case SVR4_TCGETS: + DPRINTF(("ioctl(TCGET%c);\n", cmd == SVR4_TCGETA ? 'A' : 'S')); + if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0) + return error; + + memset(&st, 0, sizeof(st)); + bsd_to_svr4_termios(&bt, &st); + +#ifdef DEBUG_SVR4 + print_bsd_termios(&bt); + print_svr4_termios(&st); +#endif /* DEBUG_SVR4 */ + + if (cmd == SVR4_TCGETA) { + svr4_termios_to_termio(&st, &t); + return copyout(&t, data, sizeof(t)); + } + else { + return copyout(&st, data, sizeof(st)); + } + + case SVR4_TCSETA: + case SVR4_TCSETS: + case SVR4_TCSETAW: + case SVR4_TCSETSW: + case SVR4_TCSETAF: + case SVR4_TCSETSF: + DPRINTF(("TCSET{A,S,AW,SW,AF,SF}\n")); + /* get full BSD termios so we don't lose information */ + if ((error = fo_ioctl(fp, TIOCGETA, (caddr_t) &bt, td)) != 0) + return error; + + switch (cmd) { + case SVR4_TCSETS: + case SVR4_TCSETSW: + case SVR4_TCSETSF: + if ((error = copyin(data, &st, sizeof(st))) != 0) + return error; + new = 1; + break; + + case SVR4_TCSETA: + case SVR4_TCSETAW: + case SVR4_TCSETAF: + if ((error = copyin(data, &t, sizeof(t))) != 0) + return error; + + svr4_termio_to_termios(&t, &st); + new = 0; + break; + + default: + return EINVAL; + } + + svr4_to_bsd_termios(&st, &bt, new); + + switch (cmd) { + case SVR4_TCSETA: + case SVR4_TCSETS: + DPRINTF(("ioctl(TCSET[A|S]);\n")); + cmd = TIOCSETA; + break; + case SVR4_TCSETAW: + case SVR4_TCSETSW: + DPRINTF(("ioctl(TCSET[A|S]W);\n")); + cmd = TIOCSETAW; + break; + case SVR4_TCSETAF: + case SVR4_TCSETSF: + DPRINTF(("ioctl(TCSET[A|S]F);\n")); + cmd = TIOCSETAF; + break; + } + +#ifdef DEBUG_SVR4 + print_bsd_termios(&bt); + print_svr4_termios(&st); +#endif /* DEBUG_SVR4 */ + + return fo_ioctl(fp, cmd, (caddr_t) &bt, td); + + case SVR4_TIOCGWINSZ: + DPRINTF(("TIOCGWINSZ\n")); + { + struct svr4_winsize ws; + + error = fo_ioctl(fp, TIOCGWINSZ, (caddr_t) &ws, td); + if (error) + return error; + return copyout(&ws, data, sizeof(ws)); + } + + case SVR4_TIOCSWINSZ: + DPRINTF(("TIOCSWINSZ\n")); + { + struct svr4_winsize ws; + + if ((error = copyin(data, &ws, sizeof(ws))) != 0) + return error; + return fo_ioctl(fp, TIOCSWINSZ, (caddr_t) &ws, td); + } + + default: + DPRINTF(("teleport to STREAMS ioctls...\n")); + return svr4_stream_ti_ioctl(fp, td, retval, fd, cmd, data); + } +} diff --git a/sys/compat/svr4/svr4_termios.h b/sys/compat/svr4/svr4_termios.h new file mode 100644 index 0000000..8afa4f3 --- /dev/null +++ b/sys/compat/svr4/svr4_termios.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_TERMIOS_H_ +#define _SVR4_TERMIOS_H_ + +#define SVR4_POSIX_VDISABLE 0 +#define SVR4_NCC 8 +#define SVR4_NCCS 19 + +typedef u_long svr4_tcflag_t; +typedef u_char svr4_cc_t; +typedef u_long svr4_speed_t; + +struct svr4_termios { + svr4_tcflag_t c_iflag; + svr4_tcflag_t c_oflag; + svr4_tcflag_t c_cflag; + svr4_tcflag_t c_lflag; + svr4_cc_t c_cc[SVR4_NCCS]; +}; + +struct svr4_termio { + u_short c_iflag; + u_short c_oflag; + u_short c_cflag; + u_short c_lflag; + char c_line; + u_char c_cc[SVR4_NCC]; +}; + +/* control characters */ +#define SVR4_VINTR 0 +#define SVR4_VQUIT 1 +#define SVR4_VERASE 2 +#define SVR4_VKILL 3 +#define SVR4_VEOF 4 +#define SVR4_VEOL 5 +#define SVR4_VEOL2 6 +#define SVR4_VMIN 4 +#define SVR4_VTIME 5 +#define SVR4_VSWTCH 7 +#define SVR4_VSTART 8 +#define SVR4_VSTOP 9 +#define SVR4_VSUSP 10 +#define SVR4_VDSUSP 11 +#define SVR4_VREPRINT 12 +#define SVR4_VDISCARD 13 +#define SVR4_VWERASE 14 +#define SVR4_VLNEXT 15 + +/* Input modes */ +#define SVR4_IGNBRK 00000001 +#define SVR4_BRKINT 00000002 +#define SVR4_IGNPAR 00000004 +#define SVR4_PARMRK 00000010 +#define SVR4_INPCK 00000020 +#define SVR4_ISTRIP 00000040 +#define SVR4_INLCR 00000100 +#define SVR4_IGNCR 00000200 +#define SVR4_ICRNL 00000400 +#define SVR4_IUCLC 00001000 +#define SVR4_IXON 00002000 +#define SVR4_IXANY 00004000 +#define SVR4_IXOFF 00010000 +#define SVR4_IMAXBEL 00020000 +#define SVR4_DOSMODE 00100000 + +/* Output modes */ +#define SVR4_OPOST 00000001 +#define SVR4_OLCUC 00000002 +#define SVR4_ONLCR 00000004 +#define SVR4_OCRNL 00000010 +#define SVR4_ONOCR 00000020 +#define SVR4_ONLRET 00000040 +#define SVR4_OFILL 00000100 +#define SVR4_OFDEL 00000200 +#define SVR4_NLDLY 00000400 +#define SVR4_NL0 00000000 +#define SVR4_NL1 00000400 +#define SVR4_CRDLY 00003000 +#define SVR4_CR0 00000000 +#define SVR4_CR1 00001000 +#define SVR4_CR2 00002000 +#define SVR4_CR3 00003000 +#define SVR4_TABDLY 00014000 +#define SVR4_TAB0 00000000 +#define SVR4_TAB1 00004000 +#define SVR4_TAB2 00010000 +#define SVR4_TAB3 00014000 +#define SVR4_XTABS 00014000 +#define SVR4_BSDLY 00020000 +#define SVR4_BS0 00000000 +#define SVR4_BS1 00020000 +#define SVR4_VTDLY 00040000 +#define SVR4_VT0 00000000 +#define SVR4_VT1 00040000 +#define SVR4_FFDLY 00100000 +#define SVR4_FF0 00000000 +#define SVR4_FF1 00100000 +#define SVR4_PAGEOUT 00200000 +#define SVR4_WRAP 00400000 + +/* Control modes */ +#define SVR4_CBAUD 00000017 +#define SVR4_CSIZE 00000060 +#define SVR4_CS5 00000000 +#define SVR4_CS6 00000200 +#define SVR4_CS7 00000040 +#define SVR4_CS8 00000006 +#define SVR4_CSTOPB 00000100 +#define SVR4_CREAD 00000200 +#define SVR4_PARENB 00000400 +#define SVR4_PARODD 00001000 +#define SVR4_HUPCL 00002000 +#define SVR4_CLOCAL 00004000 +#define SVR4_RCV1EN 00010000 +#define SVR4_XMT1EN 00020000 +#define SVR4_LOBLK 00040000 +#define SVR4_XCLUDE 00100000 +#define SVR4_CIBAUD 03600000 +#define SVR4_PAREXT 04000000 + +/* line discipline modes */ +#define SVR4_ISIG 00000001 +#define SVR4_ICANON 00000002 +#define SVR4_XCASE 00000004 +#define SVR4_ECHO 00000010 +#define SVR4_ECHOE 00000020 +#define SVR4_ECHOK 00000040 +#define SVR4_ECHONL 00000100 +#define SVR4_NOFLSH 00000200 +#define SVR4_TOSTOP 00000400 +#define SVR4_ECHOCTL 00001000 +#define SVR4_ECHOPRT 00002000 +#define SVR4_ECHOKE 00004000 +#define SVR4_DEFECHO 00010000 +#define SVR4_FLUSHO 00020000 +#define SVR4_PENDIN 00040000 +#define SVR4_IEXTEN 00100000 + +#define SVR4_TIOC ('T' << 8) + +#define SVR4_TCGETA (SVR4_TIOC| 1) +#define SVR4_TCSETA (SVR4_TIOC| 2) +#define SVR4_TCSETAW (SVR4_TIOC| 3) +#define SVR4_TCSETAF (SVR4_TIOC| 4) +#define SVR4_TCSBRK (SVR4_TIOC| 5) +#define SVR4_TCXONC (SVR4_TIOC| 6) +#define SVR4_TCFLSH (SVR4_TIOC| 7) +#define SVR4_TIOCKBON (SVR4_TIOC| 8) +#define SVR4_TIOCKBOF (SVR4_TIOC| 9) +#define SVR4_KBENABLED (SVR4_TIOC|10) +#define SVR4_TCGETS (SVR4_TIOC|13) +#define SVR4_TCSETS (SVR4_TIOC|14) +#define SVR4_TCSETSW (SVR4_TIOC|15) +#define SVR4_TCSETSF (SVR4_TIOC|16) +#define SVR4_TCDSET (SVR4_TIOC|32) +#define SVR4_RTS_TOG (SVR4_TIOC|33) +#define SVR4_TCGETSC (SVR4_TIOC|34) +#define SVR4_TCSETSC (SVR4_TIOC|35) +#define SVR4_TCMOUSE (SVR4_TIOC|36) +#define SVR4_TIOCGWINSZ (SVR4_TIOC|104) +#define SVR4_TIOCSWINSZ (SVR4_TIOC|103) + +struct svr4_winsize { + u_short ws_row; + u_short ws_col; + u_short ws_xpixel; + u_short ws_ypixel; +}; + +#define SVR4_B0 0 +#define SVR4_B50 1 +#define SVR4_B75 2 +#define SVR4_B110 3 +#define SVR4_B134 4 +#define SVR4_B150 5 +#define SVR4_B200 6 +#define SVR4_B300 7 +#define SVR4_B600 8 +#define SVR4_B1200 9 +#define SVR4_B1800 10 +#define SVR4_B2400 11 +#define SVR4_B4800 12 +#define SVR4_B9600 13 +#define SVR4_B19200 14 +#define SVR4_B38400 15 +#define SVR4_B57600 16 +#define SVR4_B76800 17 +#define SVR4_B115200 18 +#define SVR4_B153600 19 +#define SVR4_B230400 20 +#define SVR4_B307200 21 +#define SVR4_B460800 22 + +#endif /* !_SVR4_TERMIOS_H_ */ diff --git a/sys/compat/svr4/svr4_time.h b/sys/compat/svr4/svr4_time.h new file mode 100644 index 0000000..3d61771 --- /dev/null +++ b/sys/compat/svr4/svr4_time.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_TIME_H_ +#define _SVR4_TIME_H_ + +#include <sys/time.h> + +struct svr4_utimbuf { + time_t actime; + time_t modtime; +}; + +#endif /* !_SVR4_TIME_H_ */ diff --git a/sys/compat/svr4/svr4_timod.h b/sys/compat/svr4/svr4_timod.h new file mode 100644 index 0000000..f0c508f --- /dev/null +++ b/sys/compat/svr4/svr4_timod.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_TIMOD_H_ +#define _SVR4_TIMOD_H_ + +#define SVR4_TIMOD ('T' << 8) +#define SVR4_TI_GETINFO (SVR4_TIMOD|140) +#define SVR4_TI_OPTMGMT (SVR4_TIMOD|141) +#define SVR4_TI_BIND (SVR4_TIMOD|142) +#define SVR4_TI_UNBIND (SVR4_TIMOD|143) +#define SVR4_TI_GETMYNAME (SVR4_TIMOD|144) +#define SVR4_TI_GETPEERNAME (SVR4_TIMOD|145) +#define SVR4_TI_SETMYNAME (SVR4_TIMOD|146) +#define SVR4_TI_SETPEERNAME (SVR4_TIMOD|147) +#define SVR4_TI_SYNC (SVR4_TIMOD|148) +#define SVR4_TI_GETADDRS (SVR4_TIMOD|149) + +#define SVR4_TI_CONNECT_REQUEST 0x00 +#define SVR4_TI_CONNECT_RESPONSE 0x01 +#define SVR4_TI_DISCONNECT_REQUEST 0x02 +#define SVR4_TI_DATA_REQUEST 0x03 +#define SVR4_TI_EXPDATA_REQUEST 0x04 +#define SVR4_TI_INFO_REQUEST 0x05 +#define SVR4_TI_OLD_BIND_REQUEST 0x06 +#define SVR4_TI_UNBIND_REQUEST 0x07 +#define SVR4_TI_SENDTO_REQUEST 0x08 +#define SVR4_TI_OLD_OPTMGMT_REQUEST 0x09 +#define SVR4_TI_ORDREL_REQUEST 0x0a + +#define SVR4_TI_ACCEPT_REPLY 0x0b +#define SVR4_TI_CONNECT_REPLY 0x0c +#define SVR4_TI_DISCONNECT_IND 0x0d +#define SVR4_TI_DATA_IND 0x0e +#define SVR4_TI_EXPDATA_IND 0x0f +#define SVR4_TI_INFO_REPLY 0x10 +#define SVR4_TI_BIND_REPLY 0x11 +#define SVR4_TI_ERROR_REPLY 0x12 +#define SVR4_TI_OK_REPLY 0x13 +#define SVR4_TI_RECVFROM_IND 0x14 +#define SVR4_TI_RECVFROM_ERROR_IND 0x15 +#define SVR4_TI_OPTMGMT_REPLY 0x16 +#define SVR4_TI_ORDREL_IND 0x17 + +#define SVR4_TI_ADDRESS_REQUEST 0x18 +#define SVR4_TI_ADDRESS_REPLY 0x19 + +#define SVR4_TI_BIND_REQUEST 0x20 +#define SVR4_TI_OPTMGMT_REQUEST 0x21 + +#define SVR4_TI__ACCEPT_WAIT 0x10000001 +#define SVR4_TI__ACCEPT_OK 0x10000002 + +struct svr4_netbuf { + u_int maxlen; + u_int len; + char *buf; +}; + +#endif /* !_SVR4_TIMOD_H_ */ diff --git a/sys/compat/svr4/svr4_ttold.c b/sys/compat/svr4/svr4_ttold.c new file mode 100644 index 0000000..47a8135 --- /dev/null +++ b/sys/compat/svr4/svr4_ttold.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/file.h> +#include <sys/filedesc.h> +#include <sys/ioctl_compat.h> +#include <sys/termios.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_util.h> +#include <compat/svr4/svr4_ttold.h> +#include <compat/svr4/svr4_ioctl.h> + + +static void svr4_tchars_to_bsd_tchars(const struct svr4_tchars *st, + struct tchars *bt); +static void bsd_tchars_to_svr4_tchars(const struct tchars *bt, + struct svr4_tchars *st); +static void svr4_sgttyb_to_bsd_sgttyb(const struct svr4_sgttyb *ss, + struct sgttyb *bs); +static void bsd_sgttyb_to_svr4_sgttyb(const struct sgttyb *bs, + struct svr4_sgttyb *ss); +static void svr4_ltchars_to_bsd_ltchars(const struct svr4_ltchars *sl, + struct ltchars *bl); +static void bsd_ltchars_to_svr4_ltchars(const struct ltchars *bl, + struct svr4_ltchars *sl); + +#ifdef DEBUG_SVR4 +static void print_svr4_sgttyb(const char *, struct svr4_sgttyb *); +static void print_svr4_tchars(const char *, struct svr4_tchars *); +static void print_svr4_ltchars(const char *, struct svr4_ltchars *); + +static void +print_svr4_sgttyb(str, ss) + const char *str; + struct svr4_sgttyb *ss; +{ + + uprintf("%s\nispeed=%o ospeed=%o ", str, ss->sg_ispeed, ss->sg_ospeed); + uprintf("erase=%o kill=%o flags=%o\n", ss->sg_erase, ss->sg_kill, + ss->sg_flags); +} + +static void +print_svr4_tchars(str, st) + const char *str; + struct svr4_tchars *st; +{ + uprintf("%s\nintrc=%o quitc=%o ", str, st->t_intrc, st->t_quitc); + uprintf("startc=%o stopc=%o eofc=%o brkc=%o\n", st->t_startc, + st->t_stopc, st->t_eofc, st->t_brkc); +} + +static void +print_svr4_ltchars(str, sl) + const char *str; + struct svr4_ltchars *sl; +{ + uprintf("%s\nsuspc=%o dsuspc=%o ", str, sl->t_suspc, sl->t_dsuspc); + uprintf("rprntc=%o flushc=%o werasc=%o lnextc=%o\n", sl->t_rprntc, + sl->t_flushc, sl->t_werasc, sl->t_lnextc); +} +#endif /* DEBUG_SVR4 */ + +static void +svr4_tchars_to_bsd_tchars(st, bt) + const struct svr4_tchars *st; + struct tchars *bt; +{ + bt->t_intrc = st->t_intrc; + bt->t_quitc = st->t_quitc; + bt->t_startc = st->t_startc; + bt->t_stopc = st->t_stopc; + bt->t_eofc = st->t_eofc; + bt->t_brkc = st->t_brkc; +} + + +static void +bsd_tchars_to_svr4_tchars(bt, st) + const struct tchars *bt; + struct svr4_tchars *st; +{ + st->t_intrc = bt->t_intrc; + st->t_quitc = bt->t_quitc; + st->t_startc = bt->t_startc; + st->t_stopc = bt->t_stopc; + st->t_eofc = bt->t_eofc; + st->t_brkc = bt->t_brkc; +} + + +static void +svr4_sgttyb_to_bsd_sgttyb(ss, bs) + const struct svr4_sgttyb *ss; + struct sgttyb *bs; +{ + bs->sg_ispeed = ss->sg_ispeed; + bs->sg_ospeed = ss->sg_ospeed; + bs->sg_erase = ss->sg_erase; + bs->sg_kill = ss->sg_kill; + bs->sg_flags = ss->sg_flags; +}; + + +static void +bsd_sgttyb_to_svr4_sgttyb(bs, ss) + const struct sgttyb *bs; + struct svr4_sgttyb *ss; +{ + ss->sg_ispeed = bs->sg_ispeed; + ss->sg_ospeed = bs->sg_ospeed; + ss->sg_erase = bs->sg_erase; + ss->sg_kill = bs->sg_kill; + ss->sg_flags = bs->sg_flags; +} + + +static void +svr4_ltchars_to_bsd_ltchars(sl, bl) + const struct svr4_ltchars *sl; + struct ltchars *bl; +{ + bl->t_suspc = sl->t_suspc; + bl->t_dsuspc = sl->t_dsuspc; + bl->t_rprntc = sl->t_rprntc; + bl->t_flushc = sl->t_flushc; + bl->t_werasc = sl->t_werasc; + bl->t_lnextc = sl->t_lnextc; +} + + +static void +bsd_ltchars_to_svr4_ltchars(bl, sl) + const struct ltchars *bl; + struct svr4_ltchars *sl; +{ + sl->t_suspc = bl->t_suspc; + sl->t_dsuspc = bl->t_dsuspc; + sl->t_rprntc = bl->t_rprntc; + sl->t_flushc = bl->t_flushc; + sl->t_werasc = bl->t_werasc; + sl->t_lnextc = bl->t_lnextc; +} + + +int +svr4_ttold_ioctl(fp, td, retval, fd, cmd, data) + struct file *fp; + struct thread *td; + register_t *retval; + int fd; + u_long cmd; + caddr_t data; +{ + int error; + + *retval = 0; + + switch (cmd) { + case SVR4_TIOCGPGRP: + { + pid_t pid; + + if ((error = fo_ioctl(fp, TIOCGPGRP, (caddr_t) &pid, td)) != 0) + return error; + + DPRINTF(("TIOCGPGRP %d\n", pid)); + + if ((error = copyout(&pid, data, sizeof(pid))) != 0) + return error; + + } + + case SVR4_TIOCSPGRP: + { + pid_t pid; + + if ((error = copyin(data, &pid, sizeof(pid))) != 0) + return error; + + DPRINTF(("TIOCSPGRP %d\n", pid)); + + return fo_ioctl(fp, TIOCSPGRP, (caddr_t) &pid, td); + } + + case SVR4_TIOCGSID: + { +#if defined(TIOCGSID) + pid_t pid; + if ((error = fo_ioctl(fp, TIOCGSID, (caddr_t) &pid, td)) != 0) + return error; + + DPRINTF(("TIOCGSID %d\n", pid)); + + return copyout(&pid, data, sizeof(pid)); +#else + uprintf("ioctl(TIOCGSID) for pid %d unsupported\n", td->td_proc->p_pid); + return EINVAL; +#endif + } + + case SVR4_TIOCGETP: + { + struct sgttyb bs; + struct svr4_sgttyb ss; + + error = fo_ioctl(fp, TIOCGETP, (caddr_t) &bs, td); + if (error) + return error; + + bsd_sgttyb_to_svr4_sgttyb(&bs, &ss); +#ifdef DEBUG_SVR4 + print_svr4_sgttyb("SVR4_TIOCGETP", &ss); +#endif /* DEBUG_SVR4 */ + return copyout(&ss, data, sizeof(ss)); + } + + case SVR4_TIOCSETP: + case SVR4_TIOCSETN: + { + struct sgttyb bs; + struct svr4_sgttyb ss; + + if ((error = copyin(data, &ss, sizeof(ss))) != 0) + return error; + + svr4_sgttyb_to_bsd_sgttyb(&ss, &bs); +#ifdef DEBUG_SVR4 + print_svr4_sgttyb("SVR4_TIOCSET{P,N}", &ss); +#endif /* DEBUG_SVR4 */ + cmd = (cmd == SVR4_TIOCSETP) ? TIOCSETP : TIOCSETN; + return fo_ioctl(fp, cmd, (caddr_t) &bs, td); + } + + case SVR4_TIOCGETC: + { + struct tchars bt; + struct svr4_tchars st; + + error = fo_ioctl(fp, TIOCGETC, (caddr_t) &bt, td); + if (error) + return error; + + bsd_tchars_to_svr4_tchars(&bt, &st); +#ifdef DEBUG_SVR4 + print_svr4_tchars("SVR4_TIOCGETC", &st); +#endif /* DEBUG_SVR4 */ + return copyout(&st, data, sizeof(st)); + } + + case SVR4_TIOCSETC: + { + struct tchars bt; + struct svr4_tchars st; + + if ((error = copyin(data, &st, sizeof(st))) != 0) + return error; + + svr4_tchars_to_bsd_tchars(&st, &bt); +#ifdef DEBUG_SVR4 + print_svr4_tchars("SVR4_TIOCSETC", &st); +#endif /* DEBUG_SVR4 */ + return fo_ioctl(fp, TIOCSETC, (caddr_t) &bt, td); + } + + case SVR4_TIOCGLTC: + { + struct ltchars bl; + struct svr4_ltchars sl; + + error = fo_ioctl(fp, TIOCGLTC, (caddr_t) &bl, td); + if (error) + return error; + + bsd_ltchars_to_svr4_ltchars(&bl, &sl); +#ifdef DEBUG_SVR4 + print_svr4_ltchars("SVR4_TIOCGLTC", &sl); +#endif /* DEBUG_SVR4 */ + return copyout(&sl, data, sizeof(sl)); + } + + case SVR4_TIOCSLTC: + { + struct ltchars bl; + struct svr4_ltchars sl; + + if ((error = copyin(data, &sl, sizeof(sl))) != 0) + return error; + + svr4_ltchars_to_bsd_ltchars(&sl, &bl); +#ifdef DEBUG_SVR4 + print_svr4_ltchars("SVR4_TIOCSLTC", &sl); +#endif /* DEBUG_SVR4 */ + return fo_ioctl(fp, TIOCSLTC, (caddr_t) &bl, td); + } + + case SVR4_TIOCLGET: + { + int flags; + if ((error = fo_ioctl(fp, TIOCLGET, (caddr_t) &flags, td)) != 0) + return error; + DPRINTF(("SVR4_TIOCLGET %o\n", flags)); + return copyout(&flags, data, sizeof(flags)); + } + + case SVR4_TIOCLSET: + case SVR4_TIOCLBIS: + case SVR4_TIOCLBIC: + { + int flags; + + if ((error = copyin(data, &flags, sizeof(flags))) != 0) + return error; + + switch (cmd) { + case SVR4_TIOCLSET: + cmd = TIOCLSET; + break; + case SVR4_TIOCLBIS: + cmd = TIOCLBIS; + break; + case SVR4_TIOCLBIC: + cmd = TIOCLBIC; + break; + } + + DPRINTF(("SVR4_TIOCL{SET,BIS,BIC} %o\n", flags)); + return fo_ioctl(fp, cmd, (caddr_t) &flags, td); + } + + default: + DPRINTF(("Unknown svr4 ttold %lx\n", cmd)); + return 0; /* ENOSYS really */ + } +} diff --git a/sys/compat/svr4/svr4_ttold.h b/sys/compat/svr4/svr4_ttold.h new file mode 100644 index 0000000..c578170 --- /dev/null +++ b/sys/compat/svr4/svr4_ttold.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_TTOLD_H_ +#define _SVR4_TTOLD_H_ + +struct svr4_tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct svr4_sgttyb { + u_char sg_ispeed; + u_char sg_ospeed; + u_char sg_erase; + u_char sg_kill; + int sg_flags; +}; + +struct svr4_ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + +#ifndef SVR4_tIOC +#define SVR4_tIOC ('t' << 8) +#endif + +#define SVR4_TIOCGETD (SVR4_tIOC | 0) +#define SVR4_TIOCSETD (SVR4_tIOC | 1) +#define SVR4_TIOCHPCL (SVR4_tIOC | 2) +#define SVR4_TIOCGETP (SVR4_tIOC | 8) +#define SVR4_TIOCSETP (SVR4_tIOC | 9) +#define SVR4_TIOCSETN (SVR4_tIOC | 10) +#define SVR4_TIOCEXCL (SVR4_tIOC | 13) +#define SVR4_TIOCNXCL (SVR4_tIOC | 14) +#define SVR4_TIOCFLUSH (SVR4_tIOC | 16) +#define SVR4_TIOCSETC (SVR4_tIOC | 17) +#define SVR4_TIOCGETC (SVR4_tIOC | 18) +#define SVR4_TIOCGPGRP (SVR4_tIOC | 20) +#define SVR4_TIOCSPGRP (SVR4_tIOC | 21) +#define SVR4_TIOCGSID (SVR4_tIOC | 22) +#define SVR4_TIOCSTI (SVR4_tIOC | 23) +#define SVR4_TIOCSSID (SVR4_tIOC | 24) +#define SVR4_TIOCMSET (SVR4_tIOC | 26) +#define SVR4_TIOCMBIS (SVR4_tIOC | 27) +#define SVR4_TIOCMBIC (SVR4_tIOC | 28) +#define SVR4_TIOCMGET (SVR4_tIOC | 29) +#define SVR4_TIOCREMOTE (SVR4_tIOC | 30) +#define SVR4_TIOCSIGNAL (SVR4_tIOC | 31) + +#define SVR4_TIOCSTART (SVR4_tIOC | 110) +#define SVR4_TIOCSTOP (SVR4_tIOC | 111) +#define SVR4_TIOCNOTTY (SVR4_tIOC | 113) +#define SVR4_TIOCOUTQ (SVR4_tIOC | 115) +#define SVR4_TIOCGLTC (SVR4_tIOC | 116) +#define SVR4_TIOCSLTC (SVR4_tIOC | 117) +#define SVR4_TIOCCDTR (SVR4_tIOC | 120) +#define SVR4_TIOCSDTR (SVR4_tIOC | 121) +#define SVR4_TIOCCBRK (SVR4_tIOC | 122) +#define SVR4_TIOCSBRK (SVR4_tIOC | 123) +#define SVR4_TIOCLGET (SVR4_tIOC | 124) +#define SVR4_TIOCLSET (SVR4_tIOC | 125) +#define SVR4_TIOCLBIC (SVR4_tIOC | 126) +#define SVR4_TIOCLBIS (SVR4_tIOC | 127) + +#define SVR4_TIOCM_LE 0001 +#define SVR4_TIOCM_DTR 0002 +#define SVR4_TIOCM_RTS 0004 +#define SVR4_TIOCM_ST 0010 +#define SVR4_TIOCM_SR 0020 +#define SVR4_TIOCM_CTS 0040 +#define SVR4_TIOCM_CAR 0100 +#define SVR4_TIOCM_CD SVR4_TIOCM_CAR +#define SVR4_TIOCM_RNG 0200 +#define SVR4_TIOCM_RI SVR4_TIOCM_RNG +#define SVR4_TIOCM_DSR 0400 + +#define SVR4_OTTYDISC 0 +#define SVR4_NETLDISC 1 +#define SVR4_NTTYDISC 2 +#define SVR4_TABLDISC 3 +#define SVR4_NTABLDISC 4 +#define SVR4_MOUSELDISC 5 +#define SVR4_KBDLDISC 6 + +#endif /* !_SVR4_TTOLD_H_ */ diff --git a/sys/compat/svr4/svr4_types.h b/sys/compat/svr4/svr4_types.h new file mode 100644 index 0000000..410746b --- /dev/null +++ b/sys/compat/svr4/svr4_types.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_TYPES_H_ +#define _SVR4_TYPES_H_ + +typedef u_quad_t svr4_ino64_t; +typedef quad_t svr4_off64_t; +typedef quad_t svr4_blkcnt64_t; +typedef u_quad_t svr4_fsblkcnt64_t; + +typedef long svr4_off_t; +typedef u_long svr4_dev_t; +typedef u_long svr4_ino_t; +typedef u_long svr4_mode_t; +typedef u_long svr4_nlink_t; +typedef long svr4_uid_t; +typedef long svr4_gid_t; +typedef long svr4_daddr_t; +typedef long svr4_pid_t; +typedef long svr4_time_t; +typedef long svr4_blkcnt_t; +typedef u_long svr4_fsblkcnt_t; +typedef char *svr4_caddr_t; +typedef u_int svr4_size_t; + +typedef short svr4_o_dev_t; +typedef short svr4_o_pid_t; +typedef u_short svr4_o_ino_t; +typedef u_short svr4_o_mode_t; +typedef short svr4_o_nlink_t; +typedef u_short svr4_o_uid_t; +typedef u_short svr4_o_gid_t; +typedef long svr4_clock_t; +typedef int svr4_key_t; + +typedef struct timespec svr4_timestruc_t; + +#define svr4_omajor(x) ((int32_t)((((x) & 0x7f00) >> 8))) +#define svr4_ominor(x) ((int32_t)((((x) & 0x00ff) >> 0))) +#define svr4_omakedev(x,y) ((svr4_o_dev_t)((((x) << 8) & 0x7f00) | \ + (((y) << 0) & 0x00ff))) + +#define svr4_to_bsd_odev_t(d) makedev(svr4_omajor(d), svr4_ominor(d)) +#define bsd_to_svr4_odev_t(d) svr4_omakedev(umajor(d), uminor(d)) + +#define svr4_major(x) ((int32_t)((((x) & 0xfffc0000) >> 18))) +#define svr4_minor(x) ((int32_t)((((x) & 0x0003ffff) >> 0))) +#define svr4_makedev(x,y) ((svr4_dev_t)((((x) << 18) & 0xfffc0000) | \ + (((y) << 0) & 0x0003ffff))) +#define svr4_to_bsd_dev_t(d) makedev(svr4_major(d), svr4_minor(d)) +#define bsd_to_svr4_dev_t(d) svr4_makedev(umajor(d), uminor(d)) + +#endif /* !_SVR4_TYPES_H_ */ diff --git a/sys/compat/svr4/svr4_ucontext.h b/sys/compat/svr4/svr4_ucontext.h new file mode 100644 index 0000000..04bebe6 --- /dev/null +++ b/sys/compat/svr4/svr4_ucontext.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_UCONTEXT_H_ +#define _SVR4_UCONTEXT_H_ + +/* + * Machine context + */ + +#define SVR4_UC_SIGMASK 0x01 +#define SVR4_UC_STACK 0x02 + +#define SVR4_UC_CPU 0x04 +#define SVR4_UC_FPU 0x08 +#define SVR4_UC_WEITEK 0x10 + +#define SVR4_UC_MCONTEXT (SVR4_UC_CPU|SVR4_UC_FPU|SVR4_UC_WEITEK) + +#define SVR4_UC_ALL (SVR4_UC_SIGMASK|SVR4_UC_STACK|SVR4_UC_MCONTEXT) + +typedef struct svr4_ucontext { + u_long uc_flags; + /* struct svr4_ucontext *uc_link;*/ + void *uc_link; + svr4_sigset_t uc_sigmask; + struct svr4_sigaltstack uc_stack; + svr4_mcontext_t uc_mcontext; + long uc_pad[5]; +} svr4_ucontext_t; + +#define SVR4_UC_GETREGSET 0 +#define SVR4_UC_SETREGSET 1 + +/* + * Signal frame + */ +struct svr4_sigframe { + int sf_signum; + union svr4_siginfo *sf_sip; + struct svr4_ucontext *sf_ucp; + sig_t sf_handler; + struct svr4_ucontext sf_uc; + union svr4_siginfo sf_si; +}; + +#endif /* !_SVR4_UCONTEXT_H_ */ diff --git a/sys/compat/svr4/svr4_ulimit.h b/sys/compat/svr4/svr4_ulimit.h new file mode 100644 index 0000000..0735d42 --- /dev/null +++ b/sys/compat/svr4/svr4_ulimit.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_ULIMIT_H_ +#define _SVR4_ULIMIT_H_ + +#define SVR4_GFILLIM 1 +#define SVR4_SFILLIM 2 +#define SVR4_GMEMLIM 3 +#define SVR4_GDESLIM 4 +#define SVR4_GTXTOFF 64 + + +#endif /* !_SVR4_ULIMIT_H_ */ diff --git a/sys/compat/svr4/svr4_ustat.h b/sys/compat/svr4/svr4_ustat.h new file mode 100644 index 0000000..e9ebffb --- /dev/null +++ b/sys/compat/svr4/svr4_ustat.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_USTAT_H_ +#define _SVR4_USTAT_H_ + +#include <compat/svr4/svr4_types.h> + +struct svr4_ustat { + svr4_daddr_t f_tfree; + svr4_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +#endif /* !_SVR4_USTAT_H_ */ diff --git a/sys/compat/svr4/svr4_util.h b/sys/compat/svr4/svr4_util.h new file mode 100644 index 0000000..9e5be7f --- /dev/null +++ b/sys/compat/svr4/svr4_util.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_UTIL_H_ +#define _SVR4_UTIL_H_ + +/*#include <compat/common/compat_util.h>*/ +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <machine/vmparam.h> +#include <sys/exec.h> +#include <sys/sysent.h> +#include <sys/cdefs.h> + +#ifdef DEBUG_SVR4 +#define DPRINTF(a) uprintf a; +#else +#define DPRINTF(a) +#endif + + +static __inline caddr_t stackgap_init(void); +static __inline void *stackgap_alloc(caddr_t *, size_t); + +static __inline caddr_t +stackgap_init() +{ +#define szsigcode (*(curthread->td_proc->p_sysent->sv_szsigcode)) + return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE); +} + +static __inline void * +stackgap_alloc(sgp, sz) + caddr_t *sgp; + size_t sz; +{ + void *p = (void *) *sgp; + *sgp += ALIGN(sz); + return p; +} + +extern const char svr4_emul_path[]; +int svr4_emul_find(struct thread *, caddr_t *, const char *, char *, + char **, int); + +#define CHECKALT(p, sgp, path, i) \ + do { \ + int _error; \ + \ + _error = svr4_emul_find(p, sgp, svr4_emul_path, path, \ + &path, i); \ + if (_error == EFAULT) \ + return (_error); \ + } while (0) + +#define CHECKALTEXIST(p, sgp, path) CHECKALT(p, sgp, path, 0) +#define CHECKALTCREAT(p, sgp, path) CHECKALT(p, sgp, path, 1) + +#endif /* !_SVR4_UTIL_H_ */ diff --git a/sys/compat/svr4/svr4_utsname.h b/sys/compat/svr4/svr4_utsname.h new file mode 100644 index 0000000..0ff6dea --- /dev/null +++ b/sys/compat/svr4/svr4_utsname.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_UTSNAME_H_ +#define _SVR4_UTSNAME_H_ + +#include <compat/svr4/svr4_types.h> + +struct svr4_utsname { + char sysname[257]; + char nodename[257]; + char release[257]; + char version[257]; + char machine[257]; +}; + +#endif /* !_SVR4_UTSNAME_H_ */ diff --git a/sys/compat/svr4/svr4_wait.h b/sys/compat/svr4/svr4_wait.h new file mode 100644 index 0000000..9a92c01 --- /dev/null +++ b/sys/compat/svr4/svr4_wait.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1998 Mark Newton + * Copyright (c) 1994 Christos Zoulas + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SVR4_WAIT_H_ +#define _SVR4_WAIT_H_ + + +#define SVR4_P_PID 0 +#define SVR4_P_PPID 1 +#define SVR4_P_PGID 2 +#define SVR4_P_SID 3 +#define SVR4_P_CID 4 +#define SVR4_P_UID 5 +#define SVR4_P_GID 6 +#define SVR4_P_ALL 7 + +#define SVR4_WEXITED 0x01 +#define SVR4_WTRAPPED 0x02 +#define SVR4_WSTOPPED 0x04 +#define SVR4_WCONTINUED 0x08 +#define SVR4_WUNDEF1 0x10 +#define SVR4_WUNDEF2 0x20 +#define SVR4_WNOHANG 0x40 +#define SVR4_WNOWAIT 0x80 + +#define SVR4_WOPTMASK (SVR4_WEXITED|SVR4_WTRAPPED|SVR4_WSTOPPED|\ + SVR4_WCONTINUED|SVR4_WNOHANG|SVR4_WNOWAIT) + +#endif /* !_SVR4_WAIT_H_ */ diff --git a/sys/compat/svr4/syscalls.conf b/sys/compat/svr4/syscalls.conf new file mode 100644 index 0000000..46f7bd3 --- /dev/null +++ b/sys/compat/svr4/syscalls.conf @@ -0,0 +1,12 @@ +# $FreeBSD$ +sysnames="svr4_syscallnames.c" +sysproto="svr4_proto.h" +sysproto_h=_SVR4_SYSPROTO_H_ +syshdr="svr4_syscall.h" +syssw="svr4_sysent.c" +sysmk="/dev/null" +syshide="/dev/null" +syscallprefix="SVR4_SYS_" +switchname="svr4_sysent" +namesname="svr4_syscallnames" +sysvec="\n" diff --git a/sys/compat/svr4/syscalls.master b/sys/compat/svr4/syscalls.master new file mode 100644 index 0000000..f085587 --- /dev/null +++ b/sys/compat/svr4/syscalls.master @@ -0,0 +1,366 @@ + $FreeBSD$ +; from: @(#)syscalls.master 8.1 (Berkeley) 7/19/93 +; +; System call name/number master file (or rather, slave, from SVR4). +; Processed to create svr4_sysent.c, svr4_syscalls.c and svr4_syscall.h. + +; Columns: number type nargs namespc name alt{name,tag,rtyp}/comments +; number system call number, must be in order +; type one of STD, OBSOL, UNIMPL, COMPAT +; namespc one of POSIX, BSD, STD, NOHIDE (I dont care :-) -Peter +; name psuedo-prototype of syscall routine +; If one of the following alts is different, then all appear: +; altname name of system call if different +; alttag name of args struct tag if different from [o]`name'"_args" +; altrtyp return type if not int (bogus - syscalls always return int) +; for UNIMPL/OBSOL, name continues with comments + +; types: +; STD always included +; COMPAT included on COMPAT #ifdef +; LIBCOMPAT included on COMPAT #ifdef, and placed in syscall.h +; OBSOL obsolete, not included in system, only specifies name +; UNIMPL not implemented, placeholder only + +; #ifdef's, etc. may be included, and are copied to the output files. + +#include <sys/types.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <netinet/in.h> + +#include <compat/svr4/svr4.h> +#include <compat/svr4/svr4_types.h> +#include <compat/svr4/svr4_signal.h> +#include <compat/svr4/svr4_proto.h> + +0 UNIMPL SVR4 unused +1 NOPROTO POSIX { void sys_exit(int rval); } exit sys_exit_args void +2 MNOPROTO POSIX { int fork(void); } +3 NOPROTO POSIX { int read(int fd, char *buf, u_int nbyte); } +4 NOPROTO SVR4 { int write(int fd, char *buf, u_int nbyte); } +5 STD SVR4 { int svr4_sys_open(char *path, int flags, int mode); } +6 NOPROTO SVR4 { int close(int fd); } +7 STD SVR4 { int svr4_sys_wait(int *status); } +8 STD SVR4 { int svr4_sys_creat(char *path, int mode); } +9 NOPROTO SVR4 { int link(char *path, char *link); } +10 NOPROTO SVR4 { int unlink(char *path); } +11 STD SVR4 { int svr4_sys_execv(char *path, char **argp); } +12 NOPROTO SVR4 { int chdir(char *path); } +13 STD SVR4 { int svr4_sys_time(time_t *t); } +14 STD SVR4 { int svr4_sys_mknod(char* path, int mode, int dev); } +15 NOPROTO SVR4 { int chmod(char *path, int mode); } +16 NOPROTO SVR4 { int chown(char *path, uid_t uid, gid_t gid); } +17 STD SVR4 { int svr4_sys_break(caddr_t nsize); } +18 STD SVR4 { int svr4_sys_stat(char* path, \ + struct svr4_stat* ub); } +19 NOPROTO SVR4 { int lseek(int filedes, off_t *offset, int whence); } +20 NOPROTO SVR4 { pid_t getpid(void); } +21 UNIMPL SVR4 old_mount +22 UNIMPL SVR4 sysv_umount +23 NOPROTO SVR4 { int setuid(uid_t uid); } +24 NOPROTO SVR4 { uid_t getuid(void); } +25 UNIMPL SVR4 stime +26 UNIMPL SVR4 ptrace +27 STD SVR4 { int svr4_sys_alarm(unsigned sec); } +28 STD SVR4 { int svr4_sys_fstat(int fd, struct svr4_stat *sb); } +29 STD SVR4 { int svr4_sys_pause(void); } +30 STD SVR4 { int svr4_sys_utime(char *path, \ + struct svr4_utimbuf *ubuf); } +31 UNIMPL SVR4 stty +32 UNIMPL SVR4 gtty +33 STD SVR4 { int svr4_sys_access(char *path, int flags); } +34 STD SVR4 { int svr4_sys_nice(int prio); } +35 UNIMPL SVR4 statfs +36 NOPROTO SVR4 { int sync(void); } +37 STD SVR4 { int svr4_sys_kill(int pid, int signum); } +38 UNIMPL SVR4 fstatfs +39 STD SVR4 { int svr4_sys_pgrpsys(int cmd, int pid, int pgid); } +40 UNIMPL SVR4 xenix +41 NOPROTO SVR4 { int dup(u_int fd); } +42 NOPROTO SVR4 { int pipe(void); } +43 STD SVR4 { int svr4_sys_times(struct tms *tp); } +44 UNIMPL SVR4 profil +45 UNIMPL SVR4 plock +46 NOPROTO SVR4 { int setgid(gid_t gid); } +47 NOPROTO SVR4 { gid_t getgid(void); } +48 STD SVR4 { int svr4_sys_signal(int signum, \ + svr4_sig_t handler); } +#if defined(NOTYET) +49 STD SVR4 { int svr4_sys_msgsys(int what, int a2, int a3, \ + int a4, int a5); } +#else +49 UNIMPL SVR4 msgsys +#endif +50 STD SVR4 { int svr4_sys_sysarch(int op, void *a1); } +51 UNIMPL SVR4 acct +52 UNIMPL SVR4 shmsys +53 UNIMPL SVR4 semsys +54 STD SVR4 { int svr4_sys_ioctl(int fd, u_long com, \ + caddr_t data); } +55 UNIMPL SVR4 uadmin +56 UNIMPL SVR4 exch +57 STD SVR4 { int svr4_sys_utssys(void *a1, void *a2, int sel, \ + void *a3); } +58 NOPROTO SVR4 { int fsync(int fd); } +59 STD SVR4 { int svr4_sys_execve(char *path, char **argp, \ + char **envp); } +60 NOPROTO SVR4 { int umask(int newmask); } +61 NOPROTO SVR4 { int chroot(char *path); } +62 STD SVR4 { int svr4_sys_fcntl(int fd, int cmd, char *arg); } +63 STD SVR4 { int svr4_sys_ulimit(int cmd, long newlimit); } +64 UNIMPL SVR4 reserved +65 UNIMPL SVR4 reserved +66 UNIMPL SVR4 reserved +67 UNIMPL SVR4 reserved +68 UNIMPL SVR4 reserved +69 UNIMPL SVR4 reserved +70 UNIMPL SVR4 advfs +71 UNIMPL SVR4 unadvfs +72 UNIMPL SVR4 rmount +73 UNIMPL SVR4 rumount +74 UNIMPL SVR4 rfstart +75 UNIMPL SVR4 sigret +76 UNIMPL SVR4 rdebug +77 UNIMPL SVR4 rfstop +78 UNIMPL SVR4 rfsys +79 NOPROTO SVR4 { int rmdir(char *path); } +80 NOPROTO SVR4 { int mkdir(char *path, int mode); } +81 STD SVR4 { int svr4_sys_getdents(int fd, char *buf, \ + int nbytes); } +82 UNIMPL SVR4 libattach +83 UNIMPL SVR4 libdetach +84 UNIMPL SVR4 sysfs +85 STD SVR4 { int svr4_sys_getmsg(int fd, struct svr4_strbuf *ctl, \ + struct svr4_strbuf *dat, int *flags); } +86 STD SVR4 { int svr4_sys_putmsg(int fd, struct svr4_strbuf *ctl, \ + struct svr4_strbuf *dat, int flags); } +87 STD SVR4 { int svr4_sys_poll(struct pollfd *fds, unsigned int nfds, \ + int timeout); } +88 STD SVR4 { int svr4_sys_lstat(char *path, \ + struct svr4_stat *ub); } +89 NOPROTO SVR4 { int symlink(char *path, char *link); } +90 NOPROTO SVR4 { int readlink(char *path, char *buf, int count); } +91 NOPROTO SVR4 { int getgroups(u_int gidsetsize, gid_t *gidset); } +92 NOPROTO SVR4 { int setgroups(u_int gidsetsize, gid_t *gidset); } +93 NOPROTO SVR4 { int fchmod(int fd, int mode); } +94 NOPROTO SVR4 { int fchown(int fd, int uid, int gid); } +95 STD SVR4 { int svr4_sys_sigprocmask(int how, \ + svr4_sigset_t *set, svr4_sigset_t *oset); } +96 STD SVR4 { int svr4_sys_sigsuspend(svr4_sigset_t *ss); } +97 STD SVR4 { int svr4_sys_sigaltstack( \ + struct svr4_sigaltstack *nss, \ + struct svr4_sigaltstack *oss); } +98 STD SVR4 { int svr4_sys_sigaction(int signum, \ + struct svr4_sigaction *nsa, \ + struct svr4_sigaction *osa); } +99 STD SVR4 { int svr4_sys_sigpending(int what, \ + svr4_sigset_t *mask); } +100 STD SVR4 { int svr4_sys_context(int func, \ + struct svr4_ucontext *uc); } +101 UNIMPL SVR4 evsys +102 UNIMPL SVR4 evtrapret +103 STD SVR4 { int svr4_sys_statvfs(char *path, \ + struct svr4_statvfs *fs); } +104 STD SVR4 { int svr4_sys_fstatvfs(int fd, \ + struct svr4_statvfs *fs); } +105 UNIMPL SVR4 whoknows +106 UNIMPL SVR4 nfssvc +107 STD SVR4 { int svr4_sys_waitsys(int grp, int id, \ + union svr4_siginfo *info, int options); } +108 UNIMPL SVR4 sigsendsys +109 STD SVR4 { int svr4_sys_hrtsys(int cmd, int fun, int sub, \ + void *rv1, void *rv2); } +110 UNIMPL SVR4 acancel +111 UNIMPL SVR4 async +112 UNIMPL SVR4 priocntlsys +113 STD SVR4 { int svr4_sys_pathconf(char *path, int name); } +114 UNIMPL SVR4 mincore +115 STD SVR4 { caddr_t svr4_sys_mmap( caddr_t addr, svr4_size_t len, \ + int prot, int flags, int fd, svr4_off_t pos); } +116 NOPROTO SVR4 { int mprotect(void *addr, int len, int prot); } +117 NOPROTO SVR4 { int munmap(void *addr, int len); } +118 STD SVR4 { int svr4_sys_fpathconf(int fd, int name); } +119 MNOPROTO SVR4 { int vfork(void); } +120 NOPROTO SVR4 { int fchdir(int fd); } +121 NOPROTO SVR4 { int readv(int fd, struct iovec *iovp, \ + u_int iovcnt); } +122 NOPROTO SVR4 { int writev(int fd, struct iovec *iovp, \ + u_int iovcnt); } +123 STD SVR4 { int svr4_sys_xstat(int two, char *path, \ + struct svr4_xstat *ub); } +124 STD SVR4 { int svr4_sys_lxstat(int two, char *path, \ + struct svr4_xstat *ub); } +125 STD SVR4 { int svr4_sys_fxstat(int two, int fd, \ + struct svr4_xstat *sb); } +126 STD SVR4 { int svr4_sys_xmknod(int two, char *path, \ + svr4_mode_t mode, svr4_dev_t dev); } +127 UNIMPL SVR4 clocal +128 STD SVR4 { int svr4_sys_setrlimit(int which, \ + const struct svr4_rlimit *rlp); } +129 STD SVR4 { int svr4_sys_getrlimit(int which, \ + struct svr4_rlimit *rlp); } +130 NOPROTO SVR4 { int lchown(char *path, uid_t uid, gid_t gid); } +131 STD SVR4 { int svr4_sys_memcntl(void * addr, \ + svr4_size_t len, int cmd, void * arg, \ + int attr, int mask); } +132 UNIMPL SVR4 getpmsg +133 UNIMPL SVR4 putpmsg +134 NOPROTO SVR4 { int rename(char *from, char *to); } +135 STD SVR4 { int svr4_sys_uname(struct svr4_utsname* name, \ + int dummy); } +136 NOPROTO SVR4 { int setegid(gid_t egid); } +137 STD SVR4 { int svr4_sys_sysconfig(int name); } +138 MNOPROTO SVR4 { int adjtime(struct timeval *delta, \ + struct timeval *olddelta); } +139 STD SVR4 { long svr4_sys_systeminfo(int what, char *buf, \ + long len); } +140 UNIMPL SVR4 notused +141 NOPROTO SVR4 { int seteuid(uid_t euid); } +142 UNIMPL SVR4 vtrace +; fork1 +143 MUNIMPL SVR4 { int fork(void); } +144 UNIMPL SVR4 sigtimedwait +145 UNIMPL SVR4 lwp_info +146 UNIMPL SVR4 yield +147 UNIMPL SVR4 lwp_sema_wait +148 UNIMPL SVR4 lwp_sema_post +149 UNIMPL SVR4 lwp_sema_trywait +150 UNIMPL SVR4 notused +151 UNIMPL SVR4 notused +152 UNIMPL SVR4 modctl +153 STD SVR4 { int svr4_sys_fchroot(int fd); } +154 STD SVR4 { int svr4_sys_utimes(char *path, \ + struct timeval *tptr); } +155 STD SVR4 { int svr4_sys_vhangup(void); } +156 STD SVR4 { int svr4_sys_gettimeofday(struct timeval *tp); } +157 MNOPROTO SVR4 { int getitimer(u_int which, struct itimerval *itv); } +158 MNOPROTO SVR4 { int setitimer(u_int which, struct itimerval *itv, \ + struct itimerval *oitv); } +159 UNIMPL SVR4 lwp_create +160 UNIMPL SVR4 lwp_exit +161 UNIMPL SVR4 lwp_suspend +162 UNIMPL SVR4 lwp_continue +163 UNIMPL SVR4 lwp_kill +164 UNIMPL SVR4 lwp_self +165 UNIMPL SVR4 lwp_getprivate +166 UNIMPL SVR4 lwp_setprivate +167 UNIMPL SVR4 lwp_wait +168 UNIMPL SVR4 lwp_mutex_unlock +169 UNIMPL SVR4 lwp_mutex_lock +170 UNIMPL SVR4 lwp_cond_wait +171 UNIMPL SVR4 lwp_cond_signal +172 UNIMPL SVR4 lwp_cond_broadcast +173 UNIMPL SVR4 { ssize_t svr4_sys_pread(int fd, void *buf, \ + size_t nbyte, svr4_off_t off); } +174 UNIMPL SVR4 { ssize_t svr4_sys_pwrite(int fd, const void *buf, \ + size_t nbyte, svr4_off_t off); } +175 STD SVR4 { svr4_off64_t svr4_sys_llseek(int fd, long offset1, \ + long offset2, int whence); } +176 UNIMPL SVR4 inst_sync +177 UNIMPL SVR4 whoknows +178 UNIMPL SVR4 kaio +179 UNIMPL SVR4 whoknows +180 UNIMPL SVR4 whoknows +181 UNIMPL SVR4 whoknows +182 UNIMPL SVR4 whoknows +183 UNIMPL SVR4 whoknows +184 UNIMPL SVR4 tsolsys +185 STD SVR4 { int svr4_sys_acl(char *path, int cmd, int num, \ + struct svr4_aclent *buf); } +186 STD SVR4 { int svr4_sys_auditsys(int code, int a1, int a2, \ + int a3, int a4, int a5); } +187 UNIMPL SVR4 processor_bind +188 UNIMPL SVR4 processor_info +189 UNIMPL SVR4 p_online +190 UNIMPL SVR4 sigqueue +191 UNIMPL SVR4 clock_gettime +192 UNIMPL SVR4 clock_settime +193 UNIMPL SVR4 clock_getres +194 UNIMPL SVR4 timer_create +195 UNIMPL SVR4 timer_delete +196 UNIMPL SVR4 timer_settime +197 UNIMPL SVR4 timer_gettime +198 UNIMPL SVR4 timer_overrun +199 MNOPROTO SVR4 { int nanosleep(const struct timespec *rqtp, \ + struct timespec *rmtp); } +200 STD SVR4 { int svr4_sys_facl(int fd, int cmd, int num, \ + struct svr4_aclent *buf); } +201 UNIMPL SVR4 door +202 NOPROTO SVR4 { int setreuid(int ruid, int euid); } +203 NOPROTO SVR4 { int setregid(int rgid, int egid); } +204 UNIMPL SVR4 install_utrap +205 UNIMPL SVR4 signotify +206 UNIMPL SVR4 schedctl +207 UNIMPL SVR4 pset +208 UNIMPL SVR4 whoknows +209 STD SVR4 { int svr4_sys_resolvepath(const char *path, \ + char *buf, size_t bufsiz); } +210 UNIMPL SVR4 signotifywait +211 UNIMPL SVR4 lwp_sigredirect +212 UNIMPL SVR4 lwp_alarm +213 STD SVR4 { int svr4_sys_getdents64(int fd, \ + struct svr4_dirent64 *dp, \ + int nbytes); } +;213 UNIMPL SVR4 getdents64 +214 STD SVR4 { caddr_t svr4_sys_mmap64(void *addr, \ + svr4_size_t len, int prot, int flags, int fd, \ + svr4_off64_t pos); } +215 STD SVR4 { int svr4_sys_stat64(char *path, \ + struct svr4_stat64 *sb); } +216 STD SVR4 { int svr4_sys_lstat64(char *path, \ + struct svr4_stat64 *sb); } +217 STD SVR4 { int svr4_sys_fstat64(int fd, \ + struct svr4_stat64 *sb); } +218 STD SVR4 { int svr4_sys_statvfs64(char *path, \ + struct svr4_statvfs64 *fs); } +219 STD SVR4 { int svr4_sys_fstatvfs64(int fd, \ + struct svr4_statvfs64 *fs); } +220 STD SVR4 { int svr4_sys_setrlimit64(int which, \ + const struct svr4_rlimit64 *rlp); } +221 STD SVR4 { int svr4_sys_getrlimit64(int which, \ + struct svr4_rlimit64 *rlp); } +222 UNIMPL SVR4 pread64 +223 UNIMPL SVR4 pwrite64 +224 STD SVR4 { int svr4_sys_creat64(char *path, int mode); } +225 STD SVR4 { int svr4_sys_open64(char *path, int flags, \ + int mode); } +226 UNIMPL SVR4 rpcsys +227 UNIMPL SVR4 whoknows +228 UNIMPL SVR4 whoknows +229 UNIMPL SVR4 whoknows +230 STD SVR4 { int svr4_sys_socket(int domain, int type, \ + int protocol); } +231 NOPROTO SVR4 { int socketpair(int domain, int type, \ + int protocol, int *rsv); } +232 NOPROTO SVR4 { int bind(int s, const struct sockaddr *name, \ + int namelen); } +233 NOPROTO SVR4 { int listen(int s, int backlog); } +234 NOPROTO SVR4 { int accept(int s, struct sockaddr *name, \ + int *anamelen); } +235 NOPROTO SVR4 { int connect(int s, const struct sockaddr *name, \ + int namelen); } +236 NOPROTO SVR4 { int shutdown(int s, int how); } +237 STD SVR4 { int svr4_sys_recv(int s, caddr_t buf, int len, int flags); } +238 NOPROTO SVR4 { ssize_t recvfrom(int s, void *buf, size_t len, \ + int flags, struct sockaddr *from, \ + int *fromlenaddr); } +239 NOPROTO SVR4 { ssize_t recvmsg(int s, struct msghdr *msg, \ + int flags); } +240 STD SVR4 { int svr4_sys_send(int s, caddr_t buf, int len, int flags); } +241 NOPROTO SVR4 { ssize_t sendmsg(int s, const struct msghdr *msg, \ + int flags); } +242 STD SVR4 { ssize_t svr4_sys_sendto(int s, void *buf, \ + size_t len, int flags, \ + struct sockaddr *to, int tolen); } +243 NOPROTO SVR4 { int getpeername(int fdes, struct sockaddr *asa, \ + int *alen); } +244 NOPROTO SVR4 { int getsockname(int fdes, struct sockaddr *asa, \ + int *alen); } +245 NOPROTO SVR4 { int getsockopt(int s, int level, int name, \ + void *val, int *avalsize); } +246 NOPROTO SVR4 { int setsockopt(int s, int level, int name, \ + const void *val, int valsize); } +247 UNIMPL SVR4 sockconfig +248 UNIMPL SVR4 { int ntp_gettime(struct ntptimeval *ntvp); } +249 MUNIMPL SVR4 { int ntp_adjtime(struct timex *tp); } |