linux_misc.c revision 12689
19313Ssos/*-
29313Ssos * Copyright (c) 1994-1995 S�ren Schmidt
39313Ssos * All rights reserved.
49313Ssos *
59313Ssos * Redistribution and use in source and binary forms, with or without
69313Ssos * modification, are permitted provided that the following conditions
79313Ssos * are met:
89313Ssos * 1. Redistributions of source code must retain the above copyright
99313Ssos *    notice, this list of conditions and the following disclaimer
109313Ssos *    in this position and unchanged.
119313Ssos * 2. Redistributions in binary form must reproduce the above copyright
129313Ssos *    notice, this list of conditions and the following disclaimer in the
139313Ssos *    documentation and/or other materials provided with the distribution.
149313Ssos * 3. The name of the author may not be used to endorse or promote products
159313Ssos *    derived from this software withough specific prior written permission
169313Ssos *
179313Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
189313Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
199313Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
209313Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
219313Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
229313Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239313Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249313Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259313Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
269313Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279313Ssos *
2812689Speter *  $Id: linux_misc.c,v 1.5 1995/12/06 19:14:16 bde Exp $
299313Ssos */
309313Ssos
319313Ssos#include <sys/param.h>
329313Ssos#include <sys/systm.h>
3312458Sbde#include <sys/sysproto.h>
3412458Sbde#include <sys/kernel.h>
359313Ssos#include <sys/exec.h>
369313Ssos#include <sys/mman.h>
379313Ssos#include <sys/proc.h>
389313Ssos#include <sys/dirent.h>
399313Ssos#include <sys/file.h>
409313Ssos#include <sys/filedesc.h>
419313Ssos#include <sys/ioctl.h>
429313Ssos#include <sys/imgact_aout.h>
439313Ssos#include <sys/mount.h>
449313Ssos#include <sys/namei.h>
459313Ssos#include <sys/resource.h>
469313Ssos#include <sys/resourcevar.h>
479313Ssos#include <sys/stat.h>
4812458Sbde#include <sys/sysctl.h>
499313Ssos#include <sys/times.h>
509313Ssos#include <sys/utsname.h>
519313Ssos#include <sys/vnode.h>
529313Ssos#include <sys/wait.h>
539313Ssos
5412652Sbde#include <vm/vm.h>
5512689Speter#include <vm/vm_param.h>
5612689Speter#include <vm/pmap.h>
5712689Speter#include <vm/lock.h>
5812458Sbde#include <vm/vm_kern.h>
5912689Speter#include <vm/vm_prot.h>
6012689Speter#include <vm/vm_map.h>
6112458Sbde
629313Ssos#include <machine/cpu.h>
639313Ssos#include <machine/psl.h>
649313Ssos
6512458Sbde#include <i386/linux/linux.h>
6612458Sbde#include <i386/linux/sysproto.h>
679313Ssos
689313Ssosstruct linux_alarm_args {
699313Ssos    unsigned int secs;
709313Ssos};
719313Ssos
729313Ssosint
739313Ssoslinux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
749313Ssos{
759313Ssos    struct itimerval it, old_it;
769313Ssos    int s;
779313Ssos
789313Ssos#ifdef DEBUG
799313Ssos    printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs);
809313Ssos#endif
819313Ssos    it.it_value.tv_sec = (long)args->secs;
829313Ssos    it.it_value.tv_usec = 0;
839313Ssos    it.it_interval.tv_sec = 0;
849313Ssos    it.it_interval.tv_usec = 0;
859313Ssos    s = splclock();
869313Ssos    old_it = p->p_realtimer;
879313Ssos    if (timerisset(&old_it.it_value))
889313Ssos	if (timercmp(&old_it.it_value, &time, <))
899313Ssos	    timerclear(&old_it.it_value);
909313Ssos	else
919313Ssos	    timevalsub(&old_it.it_value, &time);
929313Ssos    splx(s);
939313Ssos    if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
949313Ssos	return EINVAL;
959313Ssos    s = splclock();
969313Ssos    untimeout(realitexpire, (caddr_t)p);
979313Ssos    if (timerisset(&it.it_value)) {
989313Ssos	timevaladd(&it.it_value, &time);
999313Ssos	timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
1009313Ssos    }
1019313Ssos    p->p_realtimer = it;
1029313Ssos    splx(s);
1039313Ssos    if (old_it.it_value.tv_usec)
1049313Ssos	old_it.it_value.tv_sec++;
1059313Ssos    *retval = old_it.it_value.tv_sec;
1069313Ssos    return 0;
1079313Ssos}
1089313Ssos
1099313Ssosstruct linux_brk_args {
1109313Ssos    linux_caddr_t dsend;
1119313Ssos};
1129313Ssos
1139313Ssosint
1149313Ssoslinux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
1159313Ssos{
1169313Ssos#if 0
1179313Ssos    struct vmspace *vm = p->p_vmspace;
1189313Ssos    vm_offset_t new, old;
1199313Ssos    int error;
1209313Ssos
1219313Ssos    if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
1229313Ssos	return EINVAL;
1239313Ssos    if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
1249313Ssos	> p->p_rlimit[RLIMIT_DATA].rlim_cur)
1259313Ssos	return ENOMEM;
1269313Ssos
1279313Ssos    old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
1289313Ssos    new = round_page((vm_offset_t)args->dsend);
1299313Ssos    *retval = old;
1309313Ssos    if ((new-old) > 0) {
1319313Ssos	if (swap_pager_full)
1329313Ssos	    return ENOMEM;
1339313Ssos	error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE);
1349313Ssos	if (error)
1359313Ssos	    return error;
1369313Ssos	vm->vm_dsize += btoc((new-old));
1379313Ssos	*retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
1389313Ssos    }
1399313Ssos    return 0;
1409313Ssos#else
1419313Ssos    struct vmspace *vm = p->p_vmspace;
1429313Ssos    vm_offset_t new, old;
1439313Ssos    struct obreak_args {
1449313Ssos	vm_offset_t newsize;
1459313Ssos    } tmp;
1469313Ssos
1479313Ssos#ifdef DEBUG
1489313Ssos    printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend);
1499313Ssos#endif
1509313Ssos    old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize);
1519313Ssos    new = (vm_offset_t)args->dsend;
1529313Ssos    tmp.newsize = new;
1539313Ssos    if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp, retval))
1549313Ssos	retval[0] = (int)new;
1559313Ssos    else
1569313Ssos	retval[0] = (int)old;
1579313Ssos
1589313Ssos    return 0;
1599313Ssos#endif
1609313Ssos}
1619313Ssos
1629313Ssosstruct linux_uselib_args {
1639313Ssos    char *library;
1649313Ssos};
1659313Ssos
1669313Ssosint
1679313Ssoslinux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
1689313Ssos{
1699313Ssos    struct nameidata ni;
17012130Sdg    struct vnode *vp;
1719313Ssos    struct exec *a_out = 0;
1729313Ssos    struct vattr attr;
1739313Ssos    unsigned long vmaddr, virtual_offset, file_offset;
1749313Ssos    unsigned long buffer, bss_size;
1759313Ssos    char *ptr;
1769313Ssos    char path[MAXPATHLEN];
1779313Ssos    const char *prefix = "/compat/linux";
1789313Ssos    size_t sz, len;
1799313Ssos    int error;
1809313Ssos
1819313Ssos#ifdef DEBUG
1829313Ssos    printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
1839313Ssos#endif
1849313Ssos
1859313Ssos    for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ;
1869313Ssos    sz = MAXPATHLEN - (ptr - path);
1879313Ssos    if (error = copyinstr(args->library, ptr, sz, &len))
1889313Ssos	return error;
1899313Ssos    if (*ptr != '/')
1909313Ssos	return EINVAL;
1919313Ssos
1929313Ssos#ifdef DEBUG
1939313Ssos    printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path);
1949313Ssos#endif
1959313Ssos
19611163Sjulian    NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
1979313Ssos    if (error = namei(&ni))
1989313Ssos	return error;
1999313Ssos
20012130Sdg    vp = ni.ni_vp;
20112130Sdg    if (vp == NULL)
2029313Ssos	    return ENOEXEC;
2039313Ssos
20412130Sdg    if (vp->v_writecount) {
20512130Sdg	    VOP_UNLOCK(vp);
2069313Ssos	    return ETXTBSY;
20711163Sjulian    }
2089313Ssos
20912130Sdg    if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) {
21012130Sdg	    VOP_UNLOCK(vp);
21111163Sjulian	    return error;
21211163Sjulian    }
2139313Ssos
21412130Sdg    if ((vp->v_mount->mnt_flag & MNT_NOEXEC)
2159313Ssos	|| ((attr.va_mode & 0111) == 0)
21611163Sjulian	|| (attr.va_type != VREG)) {
21712130Sdg	    VOP_UNLOCK(vp);
2189313Ssos	    return ENOEXEC;
21911163Sjulian    }
2209313Ssos
22111163Sjulian    if (attr.va_size == 0) {
22212130Sdg	    VOP_UNLOCK(vp);
2239313Ssos	    return ENOEXEC;
22411163Sjulian    }
2259313Ssos
22612130Sdg    if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) {
22712130Sdg	VOP_UNLOCK(vp);
2289313Ssos	return error;
22911163Sjulian    }
2309313Ssos
23112130Sdg    if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) {
23212130Sdg	VOP_UNLOCK(vp);
2339313Ssos	return error;
23411163Sjulian    }
2359313Ssos
23612130Sdg    VOP_UNLOCK(vp);	/* lock no longer needed */
23711163Sjulian
2389313Ssos    error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, 1024,
23912130Sdg	    	    VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0);
2409313Ssos    if (error)
2419313Ssos	return (error);
2429313Ssos
2439313Ssos    /*
2449313Ssos     * Is it a Linux binary ?
2459313Ssos     */
2469313Ssos    if (((a_out->a_magic >> 16) & 0xff) != 0x64)
24711163Sjulian	return ENOEXEC;
2489313Ssos
2499313Ssos    /*
2509313Ssos     * Set file/virtual offset based on a.out variant.
2519313Ssos     */
2529313Ssos    switch ((int)(a_out->a_magic & 0xffff)) {
2539313Ssos    case 0413:	/* ZMAGIC */
2549313Ssos	virtual_offset = 0;
2559313Ssos	file_offset = 1024;
2569313Ssos	break;
2579313Ssos    case 0314:	/* QMAGIC */
2589313Ssos	virtual_offset = 4096;
2599313Ssos	file_offset = 0;
2609313Ssos	break;
2619313Ssos    default:
26211163Sjulian	return ENOEXEC;
2639313Ssos    }
2649313Ssos
26512130Sdg    vp->v_flag |= VTEXT;
2669313Ssos    bss_size = round_page(a_out->a_bss);
2679313Ssos    /*
2689313Ssos     * Check if file_offset page aligned,.
2699313Ssos     * Currently we cannot handle misalinged file offsets,
2709313Ssos     * and so we read in the entire image (what a waste).
2719313Ssos     */
2729313Ssos    if (file_offset & PGOFSET) {
2739313Ssos#ifdef DEBUG
2749313Ssosprintf("uselib: Non page aligned binary %d\n", file_offset);
2759313Ssos#endif
2769313Ssos	/*
2779313Ssos	 * Map text+data read/write/execute
2789313Ssos	 */
2799313Ssos	vmaddr = virtual_offset + round_page(a_out->a_entry);
2809313Ssos	error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
2819313Ssos		    	    round_page(a_out->a_text + a_out->a_data), FALSE);
2829313Ssos	if (error)
2839313Ssos	    return error;
2849313Ssos
2859313Ssos	error = vm_mmap(kernel_map, &buffer,
2869313Ssos			round_page(a_out->a_text + a_out->a_data + file_offset),
2879313Ssos		   	VM_PROT_READ, VM_PROT_READ, MAP_FILE,
28812130Sdg			(caddr_t)vp, trunc_page(file_offset));
2899313Ssos	if (error)
2909313Ssos	    return error;
2919313Ssos
2929313Ssos	error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
2939313Ssos			a_out->a_text + a_out->a_data);
2949313Ssos	if (error)
2959313Ssos	    return error;
2969313Ssos
2979313Ssos	vm_map_remove(kernel_map, trunc_page(vmaddr),
2989313Ssos		      round_page(a_out->a_text + a_out->a_data + file_offset));
2999313Ssos
3009313Ssos	error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr,
3019313Ssos		   	       round_page(a_out->a_text + a_out->a_data),
3029313Ssos		   	       VM_PROT_ALL, TRUE);
3039313Ssos	if (error)
3049313Ssos	    return error;
3059313Ssos    }
3069313Ssos    else {
3079313Ssos#ifdef DEBUG
3089313Ssosprintf("uselib: Page aligned binary %d\n", file_offset);
3099313Ssos#endif
3109313Ssos	vmaddr = virtual_offset + round_page(a_out->a_entry);
3119313Ssos	error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr,
3129313Ssos			a_out->a_text + a_out->a_data,
3139313Ssos			VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED,
31412130Sdg			(caddr_t)vp, file_offset);
3159313Ssos	if (error)
3169313Ssos	    return (error);
3179313Ssos    }
3189313Ssos#ifdef DEBUG
3199313Ssosprintf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
3209313Ssos#endif
3219313Ssos    if (bss_size != 0) {
3229313Ssos	vmaddr = virtual_offset + round_page(a_out->a_entry) +
3239313Ssos		 round_page(a_out->a_text + a_out->a_data);
3249313Ssos	error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
3259313Ssos			    bss_size, FALSE);
3269313Ssos	if (error)
3279313Ssos	    return error;
3289313Ssos	error = vm_map_protect(&p->p_vmspace->vm_map, vmaddr, bss_size,
3299313Ssos		   	       VM_PROT_ALL, TRUE);
3309313Ssos	if (error)
3319313Ssos	    return error;
3329313Ssos    }
3339313Ssos    return 0;
3349313Ssos}
3359313Ssos
3369313Ssosstruct linux_select_args {
3379313Ssos    void *ptr;
3389313Ssos};
3399313Ssos
3409313Ssosint
3419313Ssoslinux_select(struct proc *p, struct linux_select_args *args, int *retval)
3429313Ssos{
3439313Ssos    struct {
3449313Ssos	int nfds;
3459313Ssos	fd_set *readfds;
3469313Ssos	fd_set *writefds;
3479313Ssos	fd_set *exceptfds;
3489313Ssos	struct timeval *timeout;
3499313Ssos    } linux_args;
3509313Ssos    struct {
3519313Ssos	unsigned int nd;
3529313Ssos	fd_set *in;
3539313Ssos	fd_set *ou;
3549313Ssos	fd_set *ex;
3559313Ssos	struct timeval *tv;
3569313Ssos    } bsd_args;
3579313Ssos    int error;
3589313Ssos
3599313Ssos    if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
3609313Ssos			sizeof(linux_args))))
3619313Ssos	return error;
3629313Ssos#ifdef DEBUG
3639313Ssos    printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n",
3649313Ssos	   p->p_pid, linux_args.nfds, linux_args.readfds,
3659313Ssos	   linux_args.writefds, linux_args.exceptfds,
3669313Ssos	   linux_args.timeout);
3679313Ssos#endif
3689313Ssos    bsd_args.nd = linux_args.nfds;
3699313Ssos    bsd_args.in = linux_args.readfds;
3709313Ssos    bsd_args.ou = linux_args.writefds;
3719313Ssos    bsd_args.ex = linux_args.exceptfds;
3729313Ssos    bsd_args.tv = linux_args.timeout;
3739313Ssos    return select(p, &bsd_args, retval);
3749313Ssos}
3759313Ssos
3769313Ssosstruct linux_getpgid_args {
3779313Ssos    int pid;
3789313Ssos};
3799313Ssos
3809313Ssosint
3819313Ssoslinux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
3829313Ssos{
3839313Ssos    struct proc *curproc;
3849313Ssos
3859313Ssos#ifdef DEBUG
3869313Ssos    printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid);
3879313Ssos#endif
3889313Ssos    if (args->pid != p->p_pid) {
3899313Ssos	if (!(curproc = pfind(args->pid)))
3909313Ssos	    return ESRCH;
3919313Ssos    }
3929313Ssos    else
3939313Ssos	curproc = p;
3949313Ssos    *retval = curproc->p_pgid;
3959313Ssos    return 0;
3969313Ssos}
3979313Ssos
3989313Ssosint
3999313Ssoslinux_fork(struct proc *p, void *args, int *retval)
4009313Ssos{
4019313Ssos    int error;
4029313Ssos
4039313Ssos#ifdef DEBUG
4049313Ssos    printf("Linux-emul(%d): fork()\n", p->p_pid);
4059313Ssos#endif
4069313Ssos    if (error = fork(p, args, retval))
4079313Ssos	return error;
4089313Ssos    if (retval[1] == 1)
4099313Ssos	retval[0] = 0;
4109313Ssos    return 0;
4119313Ssos}
4129313Ssos
4139313Ssosstruct linux_mmap_args {
4149313Ssos    void *ptr;
4159313Ssos};
4169313Ssos
4179313Ssosint
4189313Ssoslinux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
4199313Ssos{
4209313Ssos    struct {
4219313Ssos	linux_caddr_t addr;
4229313Ssos	int len;
4239313Ssos	int prot;
4249313Ssos	int flags;
4259313Ssos	int fd;
4269313Ssos	int pos;
4279313Ssos    } linux_args;
4289313Ssos    struct {
4299313Ssos	caddr_t addr;
4309313Ssos	size_t len;
4319313Ssos	int prot;
4329313Ssos	int flags;
4339313Ssos	int fd;
4349313Ssos	long pad;
4359313Ssos	off_t pos;
4369313Ssos    } bsd_args;
4379313Ssos    int error;
4389313Ssos
4399313Ssos    if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
4409313Ssos			sizeof(linux_args))))
4419313Ssos	return error;
4429313Ssos#ifdef DEBUG
4439313Ssos    printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
4449313Ssos	   p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
4459313Ssos	   linux_args.flags, linux_args.fd, linux_args.pos);
4469313Ssos#endif
4479313Ssos    bsd_args.flags = 0;
4489313Ssos    if (linux_args.flags & LINUX_MAP_SHARED)
4499313Ssos	bsd_args.flags |= MAP_SHARED;
4509313Ssos    if (linux_args.flags & LINUX_MAP_PRIVATE)
4519313Ssos	bsd_args.flags |= MAP_PRIVATE;
4529313Ssos    if (linux_args.flags & LINUX_MAP_FIXED)
4539313Ssos	bsd_args.flags |= MAP_FIXED;
4549313Ssos    if (linux_args.flags & LINUX_MAP_ANON)
4559313Ssos	bsd_args.flags |= MAP_ANON;
4569313Ssos    bsd_args.addr = linux_args.addr;
4579313Ssos    bsd_args.len = linux_args.len;
4589313Ssos    bsd_args.prot = linux_args.prot;
4599313Ssos    bsd_args.fd = linux_args.fd;
4609313Ssos    bsd_args.pos = linux_args.pos;
4619313Ssos    bsd_args.pad = 0;
4629313Ssos    return mmap(p, &bsd_args, retval);
4639313Ssos}
4649313Ssos
4659313Ssosstruct linux_pipe_args {
4669313Ssos    int *pipefds;
4679313Ssos};
4689313Ssos
4699313Ssosint
4709313Ssoslinux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
4719313Ssos{
4729313Ssos    int error;
4739313Ssos
4749313Ssos#ifdef DEBUG
4759313Ssos    printf("Linux-emul(%d): pipe(*)\n", p->p_pid);
4769313Ssos#endif
4779313Ssos    if (error = pipe(p, 0, retval))
4789313Ssos	return error;
4799313Ssos    if (error = copyout(retval, args->pipefds, 2*sizeof(int)))
4809313Ssos	return error;
4819313Ssos    *retval = 0;
4829313Ssos    return 0;
4839313Ssos}
4849313Ssos
4859313Ssosstruct linux_time_args {
4869313Ssos    linux_time_t *tm;
4879313Ssos};
4889313Ssos
4899313Ssosint
4909313Ssoslinux_time(struct proc *p, struct linux_time_args *args, int *retval)
4919313Ssos{
4929313Ssos    struct timeval tv;
4939313Ssos    linux_time_t tm;
4949313Ssos    int error;
4959313Ssos
4969313Ssos#ifdef DEBUG
4979313Ssos    printf("Linux-emul(%d): time(*)\n", p->p_pid);
4989313Ssos#endif
4999313Ssos    microtime(&tv);
5009313Ssos    tm = tv.tv_sec;
5019313Ssos    if (error = copyout(&tm, args->tm, sizeof(linux_time_t)))
5029313Ssos	return error;
5039313Ssos    *retval = tv.tv_sec;
5049313Ssos    return 0;
5059313Ssos}
5069313Ssos
5079313Ssosstruct linux_tms {
5089313Ssos    long    tms_utime;
5099313Ssos    long    tms_stime;
5109313Ssos    long    tms_cutime;
5119313Ssos    long    tms_cstime;
5129313Ssos};
5139313Ssos
5149313Ssosstruct linux_tms_args {
5159313Ssos    char *buf;
5169313Ssos};
5179313Ssos
5189313Ssosint
5199313Ssoslinux_times(struct proc *p, struct linux_tms_args *args, int *retval)
5209313Ssos{
5219313Ssos    struct timeval tv;
5229313Ssos    struct linux_tms tms;
5239313Ssos
5249313Ssos#ifdef DEBUG
5259313Ssos    printf("Linux-emul(%d): times(*)\n", p->p_pid);
5269313Ssos#endif
5279313Ssos    tms.tms_utime = p->p_uticks;
5289313Ssos    tms.tms_stime = p->p_sticks;
5299313Ssos    tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz +
5309313Ssos	    ((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000);
5319313Ssos    tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz +
5329313Ssos	    ((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000);
5339313Ssos    microtime(&tv);
5349313Ssos    *retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
5359313Ssos    return (copyout((caddr_t)&tms, (caddr_t)args->buf,
5369313Ssos	    	    sizeof(struct linux_tms)));
5379313Ssos}
5389313Ssos
5399313Ssosstruct linux_newuname_t {
5409313Ssos    char sysname[65];
5419313Ssos    char nodename[65];
5429313Ssos    char release[65];
5439313Ssos    char version[65];
5449313Ssos    char machine[65];
5459313Ssos    char domainname[65];
5469313Ssos};
5479313Ssos
5489313Ssosstruct linux_newuname_args {
5499313Ssos    char *buf;
5509313Ssos};
5519313Ssos
5529313Ssosint
5539313Ssoslinux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
5549313Ssos{
5559313Ssos    struct linux_newuname_t linux_newuname;
5569313Ssos
5579313Ssos#ifdef DEBUG
5589313Ssos    printf("Linux-emul(%d): newuname(*)\n", p->p_pid);
5599313Ssos#endif
5609313Ssos    bzero(&linux_newuname, sizeof(struct linux_newuname_args));
5619313Ssos    strncpy(linux_newuname.sysname, ostype, 64);
5629313Ssos    strncpy(linux_newuname.nodename, hostname, 64);
5639313Ssos    strncpy(linux_newuname.release, osrelease, 64);
5649313Ssos    strncpy(linux_newuname.version, version, 64);
5659313Ssos    strncpy(linux_newuname.machine, machine, 64);
5669313Ssos    strncpy(linux_newuname.domainname, domainname, 64);
5679313Ssos    return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf,
5689313Ssos	    	    sizeof(struct linux_newuname_t)));
5699313Ssos}
5709313Ssos
5719313Ssosstruct linux_utime_args {
5729313Ssos    char	*fname;
5739313Ssos    linux_time_t    *timeptr;
5749313Ssos};
5759313Ssos
5769313Ssosint
5779313Ssoslinux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
5789313Ssos{
5799313Ssos    struct bsd_utimes_args {
5809313Ssos	char	*fname;
5819313Ssos	struct	timeval *tptr;
5829313Ssos    } bsdutimes;
5839313Ssos    struct timeval tv;
5849313Ssos
5859313Ssos#ifdef DEBUG
5869313Ssos    printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
5879313Ssos#endif
5889313Ssos    tv.tv_sec = (long)args->timeptr;
5899313Ssos    tv.tv_usec = 0;
5909313Ssos    bsdutimes.tptr = &tv;
5919313Ssos    bsdutimes.fname = args->fname;
5929313Ssos    return utimes(p, &bsdutimes, retval);
5939313Ssos}
5949313Ssos
5959313Ssosstruct linux_waitpid_args {
5969313Ssos    int pid;
5979313Ssos    int *status;
5989313Ssos    int options;
5999313Ssos};
6009313Ssos
6019313Ssosint
6029313Ssoslinux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
6039313Ssos{
6049313Ssos    struct wait4_args {
6059313Ssos	int pid;
6069313Ssos	int *status;
6079313Ssos	int options;
6089313Ssos	struct	rusage *rusage;
6099313Ssos	int compat;
6109313Ssos    } tmp;
6119313Ssos    int error, tmpstat;
6129313Ssos
6139313Ssos#ifdef DEBUG
6149313Ssos    printf("Linux-emul(%d): waitpid(%d, *, %d)\n",
6159313Ssos	   p->p_pid, args->pid, args->options);
6169313Ssos#endif
6179313Ssos    tmp.pid = args->pid;
6189313Ssos    tmp.status = args->status;
6199313Ssos    tmp.options = args->options;
6209313Ssos    tmp.rusage = NULL;
6219313Ssos    tmp.compat = 0;
6229313Ssos
6239313Ssos    if (error = wait4(p, &tmp, retval))
6249313Ssos	return error;
6259313Ssos    if (error = copyin(args->status, &tmpstat, sizeof(int)))
6269313Ssos	return error;
6279313Ssos    if (WIFSIGNALED(tmpstat))
6289313Ssos	tmpstat = (tmpstat & 0xffffff80) |
6299313Ssos		  bsd_to_linux_signal[WTERMSIG(tmpstat)];
6309313Ssos    else if (WIFSTOPPED(tmpstat))
6319313Ssos	tmpstat = (tmpstat & 0xffff00ff) |
6329313Ssos	      	  (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
6339313Ssos    return copyout(&tmpstat, args->status, sizeof(int));
6349313Ssos}
6359313Ssos
6369313Ssosstruct linux_wait4_args {
6379313Ssos    int pid;
6389313Ssos    int *status;
6399313Ssos    int options;
6409313Ssos    struct rusage *rusage;
6419313Ssos};
6429313Ssos
6439313Ssosint
6449313Ssoslinux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
6459313Ssos{
6469313Ssos    struct wait4_args {
6479313Ssos	int pid;
6489313Ssos	int *status;
6499313Ssos	int options;
6509313Ssos	struct	rusage *rusage;
6519313Ssos	int compat;
6529313Ssos    } tmp;
6539313Ssos    int error, tmpstat;
6549313Ssos
6559313Ssos#ifdef DEBUG
6569313Ssos    printf("Linux-emul(%d): wait4(%d, *, %d, *)\n",
6579313Ssos	   p->p_pid, args->pid, args->options);
6589313Ssos#endif
6599313Ssos    tmp.pid = args->pid;
6609313Ssos    tmp.status = args->status;
6619313Ssos    tmp.options = args->options;
6629313Ssos    tmp.rusage = args->rusage;
6639313Ssos    tmp.compat = 0;
6649313Ssos
6659313Ssos    if (error = wait4(p, &tmp, retval))
6669313Ssos	return error;
6679313Ssos    if (error = copyin(args->status, &tmpstat, sizeof(int)))
6689313Ssos	return error;
6699313Ssos    if (WIFSIGNALED(tmpstat))
6709313Ssos	tmpstat = (tmpstat & 0xffffff80) |
6719313Ssos	      bsd_to_linux_signal[WTERMSIG(tmpstat)];
6729313Ssos    else if (WIFSTOPPED(tmpstat))
6739313Ssos	tmpstat = (tmpstat & 0xffff00ff) |
6749313Ssos	      (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
6759313Ssos    return copyout(&tmpstat, args->status, sizeof(int));
6769313Ssos}
677