1139743Simp/*-
243412Snewton * Copyright (c) 1998 Mark Newton
343412Snewton * Copyright (c) 1994 Christos Zoulas
443412Snewton * All rights reserved.
543412Snewton *
643412Snewton * Redistribution and use in source and binary forms, with or without
743412Snewton * modification, are permitted provided that the following conditions
843412Snewton * are met:
943412Snewton * 1. Redistributions of source code must retain the above copyright
1043412Snewton *    notice, this list of conditions and the following disclaimer.
1143412Snewton * 2. Redistributions in binary form must reproduce the above copyright
1243412Snewton *    notice, this list of conditions and the following disclaimer in the
1343412Snewton *    documentation and/or other materials provided with the distribution.
1443412Snewton * 3. The name of the author may not be used to endorse or promote products
1543412Snewton *    derived from this software without specific prior written permission
1643412Snewton *
1743412Snewton * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1843412Snewton * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1943412Snewton * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2043412Snewton * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2143412Snewton * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2243412Snewton * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343412Snewton * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443412Snewton * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543412Snewton * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2643412Snewton * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743412Snewton */
2843412Snewton/*
2943412Snewton * SVR4 compatibility module.
3043412Snewton *
3143412Snewton * SVR4 system calls that are implemented differently in BSD are
3243412Snewton * handled here.
3343412Snewton */
3443412Snewton
35116174Sobrien#include <sys/cdefs.h>
36116174Sobrien__FBSDID("$FreeBSD$");
37116174Sobrien
3843412Snewton#include <sys/param.h>
3943412Snewton#include <sys/systm.h>
40224778Srwatson#include <sys/capability.h>
4143412Snewton#include <sys/dirent.h>
4276166Smarkm#include <sys/fcntl.h>
4343412Snewton#include <sys/filedesc.h>
44141486Sjhb#include <sys/imgact.h>
4543412Snewton#include <sys/kernel.h>
4676166Smarkm#include <sys/lock.h>
4776166Smarkm#include <sys/malloc.h>
4876166Smarkm#include <sys/file.h>		/* Must come after sys/malloc.h */
4943412Snewton#include <sys/mman.h>
5043412Snewton#include <sys/mount.h>
5176166Smarkm#include <sys/msg.h>
5276166Smarkm#include <sys/mutex.h>
5376166Smarkm#include <sys/namei.h>
54164033Srwatson#include <sys/priv.h>
5576166Smarkm#include <sys/proc.h>
5676166Smarkm#include <sys/ptrace.h>
5743412Snewton#include <sys/resource.h>
5843412Snewton#include <sys/resourcevar.h>
5976166Smarkm#include <sys/sem.h>
60138129Sdas#include <sys/signalvar.h>
6176166Smarkm#include <sys/stat.h>
6274940Sjhb#include <sys/sx.h>
63139739Sjhb#include <sys/syscallsubr.h>
6476166Smarkm#include <sys/sysproto.h>
6576166Smarkm#include <sys/time.h>
6676166Smarkm#include <sys/times.h>
6743412Snewton#include <sys/uio.h>
6876166Smarkm#include <sys/vnode.h>
6943412Snewton#include <sys/wait.h>
7043412Snewton
7165302Sobrien#include <compat/svr4/svr4.h>
7265302Sobrien#include <compat/svr4/svr4_types.h>
7365302Sobrien#include <compat/svr4/svr4_signal.h>
7465302Sobrien#include <compat/svr4/svr4_proto.h>
7565302Sobrien#include <compat/svr4/svr4_util.h>
7665302Sobrien#include <compat/svr4/svr4_sysconfig.h>
7765302Sobrien#include <compat/svr4/svr4_dirent.h>
7865302Sobrien#include <compat/svr4/svr4_acl.h>
7965302Sobrien#include <compat/svr4/svr4_ulimit.h>
8065302Sobrien#include <compat/svr4/svr4_statvfs.h>
8165302Sobrien#include <compat/svr4/svr4_hrt.h>
8265302Sobrien#include <compat/svr4/svr4_mman.h>
8365302Sobrien#include <compat/svr4/svr4_wait.h>
8443412Snewton
85163606Srwatson#include <security/mac/mac_framework.h>
86163606Srwatson
8743412Snewton#include <machine/vmparam.h>
8843412Snewton#include <vm/vm.h>
8943412Snewton#include <vm/vm_param.h>
9043412Snewton#include <vm/vm_map.h>
9171452Sjhb#if defined(__FreeBSD__)
9292787Sjeff#include <vm/uma.h>
93109254Sdillon#include <vm/vm_extern.h>
9471452Sjhb#endif
9543412Snewton
9643412Snewton#if defined(NetBSD)
9743412Snewton# if defined(UVM)
9843412Snewton#  include <uvm/uvm_extern.h>
9943412Snewton# endif
10043412Snewton#endif
10143412Snewton
10243412Snewton#define	BSD_DIRENT(cp)		((struct dirent *)(cp))
10343412Snewton
10492761Salfredstatic int svr4_mknod(struct thread *, register_t *, char *,
10592761Salfred    svr4_mode_t, svr4_dev_t);
10643412Snewton
10792761Salfredstatic __inline clock_t timeval_to_clock_t(struct timeval *);
108160510Sjhbstatic int svr4_setinfo	(pid_t , struct rusage *, int, svr4_siginfo_t *);
10943412Snewton
11043412Snewtonstruct svr4_hrtcntl_args;
11192761Salfredstatic int svr4_hrtcntl	(struct thread *, struct svr4_hrtcntl_args *,
11292761Salfred    register_t *);
11392761Salfredstatic void bsd_statfs_to_svr4_statvfs(const struct statfs *,
11492761Salfred    struct svr4_statvfs *);
11592761Salfredstatic void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
11692761Salfred    struct svr4_statvfs64 *);
11792761Salfredstatic struct proc *svr4_pfind(pid_t pid);
11843412Snewton
11943412Snewton/* BOGUS noop */
12043412Snewton#if defined(BOGUS)
12143412Snewtonint
12283366Sjuliansvr4_sys_setitimer(td, uap)
123193014Sdelphij        struct thread *td;
12443412Snewton	struct svr4_sys_setitimer_args *uap;
12543412Snewton{
12683366Sjulian        td->td_retval[0] = 0;
12743412Snewton	return 0;
12843412Snewton}
12943412Snewton#endif
13043412Snewton
13143412Snewtonint
13283366Sjuliansvr4_sys_wait(td, uap)
13383366Sjulian	struct thread *td;
13443412Snewton	struct svr4_sys_wait_args *uap;
13543412Snewton{
136127140Sjhb	int error, st, sig;
13743412Snewton
138127140Sjhb	error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
139127140Sjhb	if (error)
140127140Sjhb		return (error);
14143412Snewton
14243412Snewton	if (WIFSIGNALED(st)) {
14343412Snewton		sig = WTERMSIG(st);
14443412Snewton		if (sig >= 0 && sig < NSIG)
14551793Smarcel			st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
14643412Snewton	} else if (WIFSTOPPED(st)) {
14743412Snewton		sig = WSTOPSIG(st);
14843412Snewton		if (sig >= 0 && sig < NSIG)
14951793Smarcel			st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
15043412Snewton	}
15143412Snewton
15243412Snewton	/*
15343412Snewton	 * It looks like wait(2) on svr4/solaris/2.4 returns
15443412Snewton	 * the status in retval[1], and the pid on retval[0].
15543412Snewton	 */
156127140Sjhb	td->td_retval[1] = st;
15743412Snewton
158107849Salfred	if (uap->status)
159127140Sjhb		error = copyout(&st, uap->status, sizeof(st));
16043412Snewton
161127140Sjhb	return (error);
16243412Snewton}
16343412Snewton
16443412Snewtonint
16583366Sjuliansvr4_sys_execv(td, uap)
16683366Sjulian	struct thread *td;
16743412Snewton	struct svr4_sys_execv_args *uap;
16843412Snewton{
169141486Sjhb	struct image_args eargs;
170141486Sjhb	char *path;
171141486Sjhb	int error;
17243412Snewton
173141486Sjhb	CHECKALTEXIST(td, uap->path, &path);
17443412Snewton
175141486Sjhb	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
176141486Sjhb	free(path, M_TEMP);
177141486Sjhb	if (error == 0)
178141486Sjhb		error = kern_execve(td, &eargs, NULL);
179141486Sjhb	return (error);
18043412Snewton}
18143412Snewton
18243412Snewtonint
18383366Sjuliansvr4_sys_execve(td, uap)
18483366Sjulian	struct thread *td;
18543412Snewton	struct svr4_sys_execve_args *uap;
18643412Snewton{
187141486Sjhb	struct image_args eargs;
188141486Sjhb	char *path;
189141486Sjhb	int error;
19043412Snewton
191141486Sjhb	CHECKALTEXIST(td, uap->path, &path);
19243412Snewton
193141486Sjhb	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
194141486Sjhb	    uap->envp);
195141486Sjhb	free(path, M_TEMP);
196141486Sjhb	if (error == 0)
197141486Sjhb		error = kern_execve(td, &eargs, NULL);
198141486Sjhb	return (error);
19943412Snewton}
20043412Snewton
20143412Snewtonint
20283366Sjuliansvr4_sys_time(td, v)
20383366Sjulian	struct thread *td;
20443412Snewton	struct svr4_sys_time_args *v;
20543412Snewton{
20643412Snewton	struct svr4_sys_time_args *uap = v;
20743412Snewton	int error = 0;
20843412Snewton	struct timeval tv;
20943412Snewton
21043412Snewton	microtime(&tv);
211107849Salfred	if (uap->t)
212107849Salfred		error = copyout(&tv.tv_sec, uap->t,
213107849Salfred				sizeof(*(uap->t)));
21483366Sjulian	td->td_retval[0] = (int) tv.tv_sec;
21543412Snewton
21643412Snewton	return error;
21743412Snewton}
21843412Snewton
21943412Snewton
22043412Snewton/*
22143412Snewton * Read SVR4-style directory entries.  We suck them into kernel space so
22254494Snewton * that they can be massaged before being copied out to user code.
22343412Snewton *
22454494Snewton * This code is ported from the Linux emulator:  Changes to the VFS interface
22554494Snewton * between FreeBSD and NetBSD have made it simpler to port it from there than
22654494Snewton * to adapt the NetBSD version.
22743412Snewton */
22843412Snewtonint
22983366Sjuliansvr4_sys_getdents64(td, uap)
23083366Sjulian	struct thread *td;
23143412Snewton	struct svr4_sys_getdents64_args *uap;
23243412Snewton{
233193014Sdelphij	struct dirent *bdp;
23443412Snewton	struct vnode *vp;
23554494Snewton	caddr_t inp, buf;		/* BSD-format */
23654494Snewton	int len, reclen;		/* BSD-format */
23754494Snewton	caddr_t outp;			/* SVR4-format */
23854494Snewton	int resid, svr4reclen=0;	/* SVR4-format */
23943412Snewton	struct file *fp;
24043412Snewton	struct uio auio;
24143412Snewton	struct iovec aiov;
24254494Snewton	off_t off;
24354494Snewton	struct svr4_dirent64 svr4_dirent;
244160276Sjhb	int buflen, error, eofflag, nbytes, justone, vfslocked;
24554494Snewton	u_long *cookies = NULL, *cookiep;
24654494Snewton	int ncookies;
24743412Snewton
24854494Snewton	DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
249107849Salfred		uap->fd, uap->nbytes));
250224778Srwatson	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
251224778Srwatson	    CAP_READ | CAP_SEEK, &fp)) != 0) {
25243412Snewton		return (error);
25354494Snewton	}
25443412Snewton
25589306Salfred	if ((fp->f_flag & FREAD) == 0) {
25689306Salfred		fdrop(fp, td);
25743412Snewton		return (EBADF);
25889306Salfred	}
25943412Snewton
260116678Sphk	vp = fp->f_vnode;
261160276Sjhb	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
26289306Salfred	if (vp->v_type != VDIR) {
263160276Sjhb		VFS_UNLOCK_GIANT(vfslocked);
26489306Salfred		fdrop(fp, td);
26543412Snewton		return (EINVAL);
26689306Salfred	}
26743412Snewton
268107849Salfred	nbytes = uap->nbytes;
26954494Snewton	if (nbytes == 1) {
27054494Snewton		nbytes = sizeof (struct svr4_dirent64);
27154494Snewton		justone = 1;
27254494Snewton	}
27354494Snewton	else
27454494Snewton		justone = 0;
27554494Snewton
27654494Snewton	off = fp->f_offset;
27754494Snewton#define	DIRBLKSIZ	512		/* XXX we used to use ufs's DIRBLKSIZ */
27854494Snewton	buflen = max(DIRBLKSIZ, nbytes);
27954494Snewton	buflen = min(buflen, MAXBSIZE);
280111119Simp	buf = malloc(buflen, M_TEMP, M_WAITOK);
281188588Sjhb	vn_lock(vp, LK_SHARED | LK_RETRY);
28243412Snewtonagain:
28343412Snewton	aiov.iov_base = buf;
28443412Snewton	aiov.iov_len = buflen;
28543412Snewton	auio.uio_iov = &aiov;
28643412Snewton	auio.uio_iovcnt = 1;
28743412Snewton	auio.uio_rw = UIO_READ;
28843412Snewton	auio.uio_segflg = UIO_SYSSPACE;
28983366Sjulian	auio.uio_td = td;
29043412Snewton	auio.uio_resid = buflen;
29143412Snewton	auio.uio_offset = off;
29243412Snewton
29354494Snewton	if (cookies) {
29454494Snewton		free(cookies, M_TEMP);
29554494Snewton		cookies = NULL;
29654494Snewton	}
29754494Snewton
298101709Srwatson#ifdef MAC
299172930Srwatson	error = mac_vnode_check_readdir(td->td_ucred, vp);
300101709Srwatson	if (error)
301101924Srwatson		goto out;
302101709Srwatson#endif
303101709Srwatson
30454494Snewton	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
30554494Snewton						&ncookies, &cookies);
30654494Snewton	if (error) {
30743412Snewton		goto out;
30854494Snewton	}
30943412Snewton
31043412Snewton	inp = buf;
311107849Salfred	outp = (caddr_t) uap->dp;
31254494Snewton	resid = nbytes;
31354494Snewton	if ((len = buflen - auio.uio_resid) <= 0) {
31443412Snewton		goto eof;
31554494Snewton	}
31643412Snewton
31754494Snewton	cookiep = cookies;
31854494Snewton
31954494Snewton	if (cookies) {
32054494Snewton		/*
32154494Snewton		 * When using cookies, the vfs has the option of reading from
32254494Snewton		 * a different offset than that supplied (UFS truncates the
32354494Snewton		 * offset to a block boundary to make sure that it never reads
32454494Snewton		 * partway through a directory entry, even if the directory
32554494Snewton		 * has been compacted).
32654494Snewton		 */
32754494Snewton		while (len > 0 && ncookies > 0 && *cookiep <= off) {
32854494Snewton			bdp = (struct dirent *) inp;
32954494Snewton			len -= bdp->d_reclen;
33054494Snewton			inp += bdp->d_reclen;
33154494Snewton			cookiep++;
33254494Snewton			ncookies--;
33354494Snewton		}
33454494Snewton	}
33554494Snewton
33654494Snewton	while (len > 0) {
33754494Snewton		if (cookiep && ncookies == 0)
33854494Snewton			break;
33954494Snewton		bdp = (struct dirent *) inp;
34043412Snewton		reclen = bdp->d_reclen;
34154494Snewton		if (reclen & 3) {
34254494Snewton			DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
34354494Snewton			error = EFAULT;
34454494Snewton			goto out;
34554494Snewton		}
34654494Snewton
34743412Snewton		if (bdp->d_fileno == 0) {
34854494Snewton	    		inp += reclen;
34954494Snewton			if (cookiep) {
35054494Snewton				off = *cookiep++;
35154494Snewton				ncookies--;
35254494Snewton			} else
35354494Snewton				off += reclen;
35454494Snewton			len -= reclen;
35543412Snewton			continue;
35643412Snewton		}
35754494Snewton		svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
35854494Snewton		if (reclen > len || resid < svr4reclen) {
35943412Snewton			outp++;
36043412Snewton			break;
36143412Snewton		}
36254494Snewton		svr4_dirent.d_ino = (long) bdp->d_fileno;
36354494Snewton		if (justone) {
36454494Snewton			/*
36554494Snewton			 * old svr4-style readdir usage.
36654494Snewton			 */
36754494Snewton			svr4_dirent.d_off = (svr4_off_t) svr4reclen;
36854494Snewton			svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
36954494Snewton		} else {
37054494Snewton			svr4_dirent.d_off = (svr4_off_t)(off + reclen);
37154494Snewton			svr4_dirent.d_reclen = (u_short) svr4reclen;
37254494Snewton		}
373192994Sdelphij		strlcpy(svr4_dirent.d_name, bdp->d_name, sizeof(svr4_dirent.d_name));
37454494Snewton		if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
37543412Snewton			goto out;
37643412Snewton		inp += reclen;
37754494Snewton		if (cookiep) {
37854494Snewton			off = *cookiep++;
37954494Snewton			ncookies--;
38054494Snewton		} else
38154494Snewton			off += reclen;
38254494Snewton		outp += svr4reclen;
38354494Snewton		resid -= svr4reclen;
38454494Snewton		len -= reclen;
38554494Snewton		if (justone)
38654494Snewton			break;
38754494Snewton    	}
38854494Snewton
389107849Salfred	if (outp == (caddr_t) uap->dp)
39043412Snewton		goto again;
39154494Snewton	fp->f_offset = off;
39243412Snewton
39354494Snewton	if (justone)
39454494Snewton		nbytes = resid + svr4reclen;
39554494Snewton
39643412Snewtoneof:
39783366Sjulian	td->td_retval[0] = nbytes - resid;
39843412Snewtonout:
399175294Sattilio	VOP_UNLOCK(vp, 0);
400160276Sjhb	VFS_UNLOCK_GIANT(vfslocked);
40189306Salfred	fdrop(fp, td);
40254494Snewton	if (cookies)
40354494Snewton		free(cookies, M_TEMP);
40443412Snewton	free(buf, M_TEMP);
40543412Snewton	return error;
40643412Snewton}
40743412Snewton
40843412Snewton
40943412Snewtonint
41083366Sjuliansvr4_sys_getdents(td, uap)
41183366Sjulian	struct thread *td;
41243412Snewton	struct svr4_sys_getdents_args *uap;
41343412Snewton{
41443412Snewton	struct dirent *bdp;
41543412Snewton	struct vnode *vp;
41643412Snewton	caddr_t inp, buf;	/* BSD-format */
41743412Snewton	int len, reclen;	/* BSD-format */
41843412Snewton	caddr_t outp;		/* SVR4-format */
41943412Snewton	int resid, svr4_reclen;	/* SVR4-format */
42043412Snewton	struct file *fp;
42143412Snewton	struct uio auio;
42243412Snewton	struct iovec aiov;
42343412Snewton	struct svr4_dirent idb;
42443412Snewton	off_t off;		/* true file offset */
425160276Sjhb	int buflen, error, eofflag, vfslocked;
42643412Snewton	u_long *cookiebuf = NULL, *cookie;
42783366Sjulian	int ncookies = 0, *retval = td->td_retval;
42843412Snewton
429121275Stjr	if (uap->nbytes < 0)
430121275Stjr		return (EINVAL);
431121275Stjr
432224778Srwatson	if ((error = getvnode(td->td_proc->p_fd, uap->fd,
433224778Srwatson	    CAP_READ | CAP_SEEK, &fp)) != 0)
43443412Snewton		return (error);
43543412Snewton
43689306Salfred	if ((fp->f_flag & FREAD) == 0) {
43789306Salfred		fdrop(fp, td);
43843412Snewton		return (EBADF);
43989306Salfred	}
44043412Snewton
441116678Sphk	vp = fp->f_vnode;
442160276Sjhb	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
44389306Salfred	if (vp->v_type != VDIR) {
444160276Sjhb		VFS_UNLOCK_GIANT(vfslocked);
44589306Salfred		fdrop(fp, td);
44643412Snewton		return (EINVAL);
44789306Salfred	}
44843412Snewton
449107849Salfred	buflen = min(MAXBSIZE, uap->nbytes);
450111119Simp	buf = malloc(buflen, M_TEMP, M_WAITOK);
451188588Sjhb	vn_lock(vp, LK_SHARED | LK_RETRY);
45243412Snewton	off = fp->f_offset;
45343412Snewtonagain:
45443412Snewton	aiov.iov_base = buf;
45543412Snewton	aiov.iov_len = buflen;
45643412Snewton	auio.uio_iov = &aiov;
45743412Snewton	auio.uio_iovcnt = 1;
45843412Snewton	auio.uio_rw = UIO_READ;
45943412Snewton	auio.uio_segflg = UIO_SYSSPACE;
46083366Sjulian	auio.uio_td = td;
46143412Snewton	auio.uio_resid = buflen;
46243412Snewton	auio.uio_offset = off;
463101709Srwatson
464101709Srwatson#ifdef MAC
465172930Srwatson	error = mac_vnode_check_readdir(td->td_ucred, vp);
466101709Srwatson	if (error)
467101709Srwatson		goto out;
468101709Srwatson#endif
469101709Srwatson
47043412Snewton	/*
47143412Snewton         * First we read into the malloc'ed buffer, then
47243412Snewton         * we massage it into user space, one record at a time.
47343412Snewton         */
47443412Snewton	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
47543412Snewton	    &cookiebuf);
47689306Salfred	if (error) {
47743412Snewton		goto out;
47889306Salfred	}
47943412Snewton
48043412Snewton	inp = buf;
481107849Salfred	outp = uap->buf;
482107849Salfred	resid = uap->nbytes;
48343412Snewton	if ((len = buflen - auio.uio_resid) == 0)
48443412Snewton		goto eof;
48543412Snewton
48643412Snewton	for (cookie = cookiebuf; len > 0; len -= reclen) {
48743412Snewton		bdp = (struct dirent *)inp;
48843412Snewton		reclen = bdp->d_reclen;
48943412Snewton		if (reclen & 3)
49054494Snewton			panic("svr4_sys_getdents64: bad reclen");
491193013Sdelphij		if (cookie)
492193013Sdelphij			off = *cookie++; /* each entry points to the next */
493193013Sdelphij		else
494193013Sdelphij			off += reclen;
49543412Snewton		if ((off >> 32) != 0) {
49654494Snewton			uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
49743412Snewton			error = EINVAL;
49843412Snewton			goto out;
49943412Snewton		}
50043412Snewton		if (bdp->d_fileno == 0) {
50143412Snewton			inp += reclen;	/* it is a hole; squish it out */
50243412Snewton			continue;
50343412Snewton		}
50443412Snewton		svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
50543412Snewton		if (reclen > len || resid < svr4_reclen) {
50643412Snewton			/* entry too big for buffer, so just stop */
50743412Snewton			outp++;
50843412Snewton			break;
50943412Snewton		}
51043412Snewton		/*
51143412Snewton		 * Massage in place to make a SVR4-shaped dirent (otherwise
51243412Snewton		 * we have to worry about touching user memory outside of
51343412Snewton		 * the copyout() call).
51443412Snewton		 */
51543412Snewton		idb.d_ino = (svr4_ino_t)bdp->d_fileno;
51643412Snewton		idb.d_off = (svr4_off_t)off;
51743412Snewton		idb.d_reclen = (u_short)svr4_reclen;
518192994Sdelphij		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
51943412Snewton		if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
52043412Snewton			goto out;
52143412Snewton		/* advance past this real entry */
52243412Snewton		inp += reclen;
52343412Snewton		/* advance output past SVR4-shaped entry */
52443412Snewton		outp += svr4_reclen;
52543412Snewton		resid -= svr4_reclen;
52643412Snewton	}
52743412Snewton
52843412Snewton	/* if we squished out the whole block, try again */
529107849Salfred	if (outp == uap->buf)
53043412Snewton		goto again;
53143412Snewton	fp->f_offset = off;	/* update the vnode offset */
53243412Snewton
53343412Snewtoneof:
534107849Salfred	*retval = uap->nbytes - resid;
53543412Snewtonout:
536175294Sattilio	VOP_UNLOCK(vp, 0);
537160276Sjhb	VFS_UNLOCK_GIANT(vfslocked);
53889306Salfred	fdrop(fp, td);
53943412Snewton	if (cookiebuf)
54043412Snewton		free(cookiebuf, M_TEMP);
54143412Snewton	free(buf, M_TEMP);
54243412Snewton	return error;
54343412Snewton}
54443412Snewton
54543412Snewton
54643412Snewtonint
54783366Sjuliansvr4_sys_mmap(td, uap)
54883366Sjulian	struct thread *td;
54943412Snewton	struct svr4_sys_mmap_args *uap;
55043412Snewton{
55143412Snewton	struct mmap_args	 mm;
55243412Snewton	int             *retval;
55343412Snewton
55483366Sjulian	retval = td->td_retval;
55543412Snewton#define _MAP_NEW	0x80000000
55643412Snewton	/*
55743412Snewton         * Verify the arguments.
55843412Snewton         */
559107849Salfred	if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
56043412Snewton		return EINVAL;	/* XXX still needed? */
56143412Snewton
562107849Salfred	if (uap->len == 0)
56343412Snewton		return EINVAL;
56443412Snewton
565107849Salfred	mm.prot = uap->prot;
566107849Salfred	mm.len = uap->len;
567107849Salfred	mm.flags = uap->flags & ~_MAP_NEW;
568107849Salfred	mm.fd = uap->fd;
569107849Salfred	mm.addr = uap->addr;
570107849Salfred	mm.pos = uap->pos;
57143412Snewton
572225617Skmacy	return sys_mmap(td, &mm);
57343412Snewton}
57443412Snewton
57543412Snewtonint
57683366Sjuliansvr4_sys_mmap64(td, uap)
57783366Sjulian	struct thread *td;
57843412Snewton	struct svr4_sys_mmap64_args *uap;
57943412Snewton{
58043412Snewton	struct mmap_args	 mm;
58143412Snewton	void		*rp;
58243412Snewton
58343412Snewton#define _MAP_NEW	0x80000000
58443412Snewton	/*
58543412Snewton         * Verify the arguments.
58643412Snewton         */
587107849Salfred	if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
58843412Snewton		return EINVAL;	/* XXX still needed? */
58943412Snewton
590107849Salfred	if (uap->len == 0)
59143412Snewton		return EINVAL;
59243412Snewton
593107849Salfred	mm.prot = uap->prot;
594107849Salfred	mm.len = uap->len;
595107849Salfred	mm.flags = uap->flags & ~_MAP_NEW;
596107849Salfred	mm.fd = uap->fd;
597107849Salfred	mm.addr = uap->addr;
598107849Salfred	mm.pos = uap->pos;
59943412Snewton
60084783Sps	rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
601107849Salfred	if ((mm.flags & MAP_FIXED) == 0 &&
602107849Salfred	    mm.addr != 0 && (void *)mm.addr < rp)
603107849Salfred		mm.addr = rp;
60443412Snewton
605225617Skmacy	return sys_mmap(td, &mm);
60643412Snewton}
60743412Snewton
60843412Snewton
60943412Snewtonint
61083366Sjuliansvr4_sys_fchroot(td, uap)
61183366Sjulian	struct thread *td;
61243412Snewton	struct svr4_sys_fchroot_args *uap;
61343412Snewton{
61483366Sjulian	struct filedesc	*fdp = td->td_proc->p_fd;
615160557Sjhb	struct vnode	*vp;
61643412Snewton	struct file	*fp;
617160557Sjhb	int		 error, vfslocked;
61843412Snewton
619170587Srwatson	if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
62043412Snewton		return error;
621224778Srwatson	/* XXX: we have the chroot priv... what cap might we need? all? */
622224778Srwatson	if ((error = getvnode(fdp, uap->fd, 0, &fp)) != 0)
62343412Snewton		return error;
624116678Sphk	vp = fp->f_vnode;
625160557Sjhb	VREF(vp);
626160557Sjhb	fdrop(fp, td);
627160557Sjhb	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
628175202Sattilio	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
629160557Sjhb	error = change_dir(vp, td);
630160557Sjhb	if (error)
631160557Sjhb		goto fail;
632160557Sjhb#ifdef MAC
633172930Srwatson	error = mac_vnode_check_chroot(td->td_ucred, vp);
634160557Sjhb	if (error)
635160557Sjhb		goto fail;
636160557Sjhb#endif
637175294Sattilio	VOP_UNLOCK(vp, 0);
638160557Sjhb	error = change_root(vp, td);
639160557Sjhb	vrele(vp);
640160557Sjhb	VFS_UNLOCK_GIANT(vfslocked);
641160557Sjhb	return (error);
642160557Sjhbfail:
643160557Sjhb	vput(vp);
644160557Sjhb	VFS_UNLOCK_GIANT(vfslocked);
645160557Sjhb	return (error);
64643412Snewton}
64743412Snewton
64843412Snewton
64943412Snewtonstatic int
65083366Sjuliansvr4_mknod(td, retval, path, mode, dev)
65183366Sjulian	struct thread *td;
65243412Snewton	register_t *retval;
65343412Snewton	char *path;
65443412Snewton	svr4_mode_t mode;
65543412Snewton	svr4_dev_t dev;
65643412Snewton{
657141486Sjhb	char *newpath;
658141486Sjhb	int error;
65943412Snewton
660141486Sjhb	CHECKALTEXIST(td, path, &newpath);
66143412Snewton
662141486Sjhb	if (S_ISFIFO(mode))
663141486Sjhb		error = kern_mkfifo(td, newpath, UIO_SYSSPACE, mode);
664141486Sjhb	else
665141486Sjhb		error = kern_mknod(td, newpath, UIO_SYSSPACE, mode, dev);
666141486Sjhb	free(newpath, M_TEMP);
667141486Sjhb	return (error);
66843412Snewton}
66943412Snewton
67043412Snewton
67143412Snewtonint
67283366Sjuliansvr4_sys_mknod(td, uap)
673193014Sdelphij	struct thread *td;
67443412Snewton	struct svr4_sys_mknod_args *uap;
67543412Snewton{
67683366Sjulian        int *retval = td->td_retval;
67783366Sjulian	return svr4_mknod(td, retval,
678107849Salfred			  uap->path, uap->mode,
679107849Salfred			  (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
68043412Snewton}
68143412Snewton
68243412Snewton
68343412Snewtonint
68483366Sjuliansvr4_sys_xmknod(td, uap)
68583366Sjulian	struct thread *td;
68643412Snewton	struct svr4_sys_xmknod_args *uap;
68743412Snewton{
68883366Sjulian        int *retval = td->td_retval;
68983366Sjulian	return svr4_mknod(td, retval,
690107849Salfred			  uap->path, uap->mode,
691107849Salfred			  (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
69243412Snewton}
69343412Snewton
69443412Snewton
69543412Snewtonint
69683366Sjuliansvr4_sys_vhangup(td, uap)
69783366Sjulian	struct thread *td;
69843412Snewton	struct svr4_sys_vhangup_args *uap;
69943412Snewton{
70043412Snewton	return 0;
70143412Snewton}
70243412Snewton
70343412Snewton
70443412Snewtonint
70583366Sjuliansvr4_sys_sysconfig(td, uap)
70683366Sjulian	struct thread *td;
70743412Snewton	struct svr4_sys_sysconfig_args *uap;
70843412Snewton{
70943412Snewton	int *retval;
71043412Snewton
71183366Sjulian	retval = &(td->td_retval[0]);
71243412Snewton
713107849Salfred	switch (uap->name) {
71443412Snewton	case SVR4_CONFIG_NGROUPS:
715202143Sbrooks		*retval = ngroups_max;
71643412Snewton		break;
71743412Snewton	case SVR4_CONFIG_CHILD_MAX:
71843412Snewton		*retval = maxproc;
71943412Snewton		break;
72043412Snewton	case SVR4_CONFIG_OPEN_FILES:
72143412Snewton		*retval = maxfiles;
72243412Snewton		break;
72343412Snewton	case SVR4_CONFIG_POSIX_VER:
72443412Snewton		*retval = 198808;
72543412Snewton		break;
72643412Snewton	case SVR4_CONFIG_PAGESIZE:
72743412Snewton		*retval = PAGE_SIZE;
72843412Snewton		break;
72943412Snewton	case SVR4_CONFIG_CLK_TCK:
73043412Snewton		*retval = 60;	/* should this be `hz', ie. 100? */
73143412Snewton		break;
73243412Snewton	case SVR4_CONFIG_XOPEN_VER:
73343412Snewton		*retval = 2;	/* XXX: What should that be? */
73443412Snewton		break;
73543412Snewton	case SVR4_CONFIG_PROF_TCK:
73643412Snewton		*retval = 60;	/* XXX: What should that be? */
73743412Snewton		break;
73843412Snewton	case SVR4_CONFIG_NPROC_CONF:
73943412Snewton		*retval = 1;	/* Only one processor for now */
74043412Snewton		break;
74143412Snewton	case SVR4_CONFIG_NPROC_ONLN:
74243412Snewton		*retval = 1;	/* And it better be online */
74343412Snewton		break;
74443412Snewton	case SVR4_CONFIG_AIO_LISTIO_MAX:
74543412Snewton	case SVR4_CONFIG_AIO_MAX:
74643412Snewton	case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
74743412Snewton		*retval = 0;	/* No aio support */
74843412Snewton		break;
74943412Snewton	case SVR4_CONFIG_DELAYTIMER_MAX:
75043412Snewton		*retval = 0;	/* No delaytimer support */
75143412Snewton		break;
75243412Snewton	case SVR4_CONFIG_MQ_OPEN_MAX:
75343412Snewton		*retval = msginfo.msgmni;
75443412Snewton		break;
75543412Snewton	case SVR4_CONFIG_MQ_PRIO_MAX:
75643412Snewton		*retval = 0;	/* XXX: Don't know */
75743412Snewton		break;
75843412Snewton	case SVR4_CONFIG_RTSIG_MAX:
75943412Snewton		*retval = 0;
76043412Snewton		break;
76143412Snewton	case SVR4_CONFIG_SEM_NSEMS_MAX:
76243412Snewton		*retval = seminfo.semmni;
76343412Snewton		break;
76443412Snewton	case SVR4_CONFIG_SEM_VALUE_MAX:
76543412Snewton		*retval = seminfo.semvmx;
76643412Snewton		break;
76743412Snewton	case SVR4_CONFIG_SIGQUEUE_MAX:
76843412Snewton		*retval = 0;	/* XXX: Don't know */
76943412Snewton		break;
77043412Snewton	case SVR4_CONFIG_SIGRT_MIN:
77143412Snewton	case SVR4_CONFIG_SIGRT_MAX:
77243412Snewton		*retval = 0;	/* No real time signals */
77343412Snewton		break;
77443412Snewton	case SVR4_CONFIG_TIMER_MAX:
77543412Snewton		*retval = 3;	/* XXX: real, virtual, profiling */
77643412Snewton		break;
77743412Snewton#if defined(NOTYET)
77843412Snewton	case SVR4_CONFIG_PHYS_PAGES:
77943412Snewton#if defined(UVM)
78043412Snewton		*retval = uvmexp.free;	/* XXX: free instead of total */
78143412Snewton#else
782170170Sattilio		*retval = cnt.v_free_count;	/* XXX: free instead of total */
78343412Snewton#endif
78443412Snewton		break;
78543412Snewton	case SVR4_CONFIG_AVPHYS_PAGES:
78643412Snewton#if defined(UVM)
78743412Snewton		*retval = uvmexp.active;	/* XXX: active instead of avg */
78843412Snewton#else
789170170Sattilio		*retval = cnt.v_active_count;	/* XXX: active instead of avg */
79043412Snewton#endif
79143412Snewton		break;
79243412Snewton#endif /* NOTYET */
793193012Sdelphij	case SVR4_CONFIG_COHERENCY:
794193012Sdelphij		*retval = 0;	/* XXX */
795193012Sdelphij		break;
796193012Sdelphij	case SVR4_CONFIG_SPLIT_CACHE:
797193012Sdelphij		*retval = 0;	/* XXX */
798193012Sdelphij		break;
799193012Sdelphij	case SVR4_CONFIG_ICACHESZ:
800193012Sdelphij		*retval = 256;	/* XXX */
801193012Sdelphij		break;
802193012Sdelphij	case SVR4_CONFIG_DCACHESZ:
803193012Sdelphij		*retval = 256;	/* XXX */
804193012Sdelphij		break;
805193012Sdelphij	case SVR4_CONFIG_ICACHELINESZ:
806193012Sdelphij		*retval = 64;	/* XXX */
807193012Sdelphij		break;
808193012Sdelphij	case SVR4_CONFIG_DCACHELINESZ:
809193012Sdelphij		*retval = 64;	/* XXX */
810193012Sdelphij		break;
811193012Sdelphij	case SVR4_CONFIG_ICACHEBLKSZ:
812193012Sdelphij		*retval = 64;	/* XXX */
813193012Sdelphij		break;
814193012Sdelphij	case SVR4_CONFIG_DCACHEBLKSZ:
815193012Sdelphij		*retval = 64;	/* XXX */
816193012Sdelphij		break;
817193012Sdelphij	case SVR4_CONFIG_DCACHETBLKSZ:
818193012Sdelphij		*retval = 64;	/* XXX */
819193012Sdelphij		break;
820193012Sdelphij	case SVR4_CONFIG_ICACHE_ASSOC:
821193012Sdelphij		*retval = 1;	/* XXX */
822193012Sdelphij		break;
823193012Sdelphij	case SVR4_CONFIG_DCACHE_ASSOC:
824193012Sdelphij		*retval = 1;	/* XXX */
825193012Sdelphij		break;
826193012Sdelphij	case SVR4_CONFIG_MAXPID:
827193012Sdelphij		*retval = PID_MAX;
828193012Sdelphij		break;
829193012Sdelphij	case SVR4_CONFIG_STACK_PROT:
830193012Sdelphij		*retval = PROT_READ|PROT_WRITE|PROT_EXEC;
831193012Sdelphij		break;
83243412Snewton	default:
83343412Snewton		return EINVAL;
83443412Snewton	}
83543412Snewton	return 0;
83643412Snewton}
83743412Snewton
83843412Snewton/* ARGSUSED */
83943412Snewtonint
84083366Sjuliansvr4_sys_break(td, uap)
84183366Sjulian	struct thread *td;
84243412Snewton	struct svr4_sys_break_args *uap;
84343412Snewton{
844159960Sjhb	struct obreak_args ap;
84543412Snewton
846159960Sjhb	ap.nsize = uap->nsize;
847225617Skmacy	return (sys_obreak(td, &ap));
84843412Snewton}
84943412Snewton
85043412Snewtonstatic __inline clock_t
85143412Snewtontimeval_to_clock_t(tv)
85243412Snewton	struct timeval *tv;
85343412Snewton{
85443412Snewton	return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
85543412Snewton}
85643412Snewton
85743412Snewton
85843412Snewtonint
85983366Sjuliansvr4_sys_times(td, uap)
86083366Sjulian	struct thread *td;
86143412Snewton	struct svr4_sys_times_args *uap;
86243412Snewton{
863136152Sjhb	struct timeval tv, utime, stime, cutime, cstime;
864136152Sjhb	struct tms tms;
865136152Sjhb	struct proc *p;
866136152Sjhb	int error;
86743412Snewton
868136152Sjhb	p = td->td_proc;
869136152Sjhb	PROC_LOCK(p);
870170472Sattilio	PROC_SLOCK(p);
871136152Sjhb	calcru(p, &utime, &stime);
872170472Sattilio	PROC_SUNLOCK(p);
873136152Sjhb	calccru(p, &cutime, &cstime);
874136152Sjhb	PROC_UNLOCK(p);
87543412Snewton
876136152Sjhb	tms.tms_utime = timeval_to_clock_t(&utime);
877136152Sjhb	tms.tms_stime = timeval_to_clock_t(&stime);
87843412Snewton
879136152Sjhb	tms.tms_cutime = timeval_to_clock_t(&cutime);
880136152Sjhb	tms.tms_cstime = timeval_to_clock_t(&cstime);
88143412Snewton
882136152Sjhb	error = copyout(&tms, uap->tp, sizeof(tms));
88343412Snewton	if (error)
884136152Sjhb		return (error);
88543412Snewton
886136152Sjhb	microtime(&tv);
887136152Sjhb	td->td_retval[0] = (int)timeval_to_clock_t(&tv);
888136152Sjhb	return (0);
88943412Snewton}
89043412Snewton
89143412Snewton
89243412Snewtonint
89383366Sjuliansvr4_sys_ulimit(td, uap)
89483366Sjulian	struct thread *td;
89543412Snewton	struct svr4_sys_ulimit_args *uap;
89643412Snewton{
89783366Sjulian        int *retval = td->td_retval;
898125454Sjhb	int error;
89943412Snewton
900107849Salfred	switch (uap->cmd) {
90143412Snewton	case SVR4_GFILLIM:
902125454Sjhb		PROC_LOCK(td->td_proc);
903125454Sjhb		*retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512;
904125454Sjhb		PROC_UNLOCK(td->td_proc);
90543412Snewton		if (*retval == -1)
90643412Snewton			*retval = 0x7fffffff;
90743412Snewton		return 0;
90843412Snewton
90943412Snewton	case SVR4_SFILLIM:
91043412Snewton		{
91143412Snewton			struct rlimit krl;
91243412Snewton
913107849Salfred			krl.rlim_cur = uap->newlimit * 512;
914125454Sjhb			PROC_LOCK(td->td_proc);
915125454Sjhb			krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE);
916125454Sjhb			PROC_UNLOCK(td->td_proc);
91743412Snewton
918125454Sjhb			error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
91943412Snewton			if (error)
92043412Snewton				return error;
92143412Snewton
922125454Sjhb			PROC_LOCK(td->td_proc);
923125454Sjhb			*retval = lim_cur(td->td_proc, RLIMIT_FSIZE);
924125454Sjhb			PROC_UNLOCK(td->td_proc);
92543412Snewton			if (*retval == -1)
92643412Snewton				*retval = 0x7fffffff;
92743412Snewton			return 0;
92843412Snewton		}
92943412Snewton
93043412Snewton	case SVR4_GMEMLIM:
93143412Snewton		{
93283366Sjulian			struct vmspace *vm = td->td_proc->p_vmspace;
93371452Sjhb			register_t r;
93443412Snewton
935125454Sjhb			PROC_LOCK(td->td_proc);
936125454Sjhb			r = lim_cur(td->td_proc, RLIMIT_DATA);
937125454Sjhb			PROC_UNLOCK(td->td_proc);
93871452Sjhb
93943412Snewton			if (r == -1)
94043412Snewton				r = 0x7fffffff;
94143412Snewton			r += (long) vm->vm_daddr;
94243412Snewton			if (r < 0)
94343412Snewton				r = 0x7fffffff;
94443412Snewton			*retval = r;
94543412Snewton			return 0;
94643412Snewton		}
94743412Snewton
94843412Snewton	case SVR4_GDESLIM:
949125454Sjhb		PROC_LOCK(td->td_proc);
950125454Sjhb		*retval = lim_cur(td->td_proc, RLIMIT_NOFILE);
951125454Sjhb		PROC_UNLOCK(td->td_proc);
95243412Snewton		if (*retval == -1)
95343412Snewton			*retval = 0x7fffffff;
95443412Snewton		return 0;
95543412Snewton
95643412Snewton	default:
95743412Snewton		return EINVAL;
95843412Snewton	}
95943412Snewton}
96043412Snewton
96143412Snewtonstatic struct proc *
96243412Snewtonsvr4_pfind(pid)
96343412Snewton	pid_t pid;
96443412Snewton{
96543412Snewton	struct proc *p;
96643412Snewton
96743412Snewton	/* look in the live processes */
96871452Sjhb	if ((p = pfind(pid)) == NULL)
96971452Sjhb		/* look in the zombies */
97071452Sjhb		p = zpfind(pid);
97143412Snewton
97269947Sjake	return p;
97343412Snewton}
97443412Snewton
97543412Snewton
97643412Snewtonint
97783366Sjuliansvr4_sys_pgrpsys(td, uap)
97883366Sjulian	struct thread *td;
97943412Snewton	struct svr4_sys_pgrpsys_args *uap;
98043412Snewton{
98183366Sjulian        int *retval = td->td_retval;
98283366Sjulian	struct proc *p = td->td_proc;
98343412Snewton
984107849Salfred	switch (uap->cmd) {
98543412Snewton	case 1:			/* setpgrp() */
98643412Snewton		/*
98743412Snewton		 * SVR4 setpgrp() (which takes no arguments) has the
98843412Snewton		 * semantics that the session ID is also created anew, so
98943412Snewton		 * in almost every sense, setpgrp() is identical to
99043412Snewton		 * setsid() for SVR4.  (Under BSD, the difference is that
99143412Snewton		 * a setpgid(0,0) will not create a new session.)
99243412Snewton		 */
993225617Skmacy		sys_setsid(td, NULL);
99443412Snewton		/*FALLTHROUGH*/
99543412Snewton
99643412Snewton	case 0:			/* getpgrp() */
99791140Stanimura		PROC_LOCK(p);
99843412Snewton		*retval = p->p_pgrp->pg_id;
99991140Stanimura		PROC_UNLOCK(p);
100043412Snewton		return 0;
100143412Snewton
100243412Snewton	case 2:			/* getsid(pid) */
1003107849Salfred		if (uap->pid == 0)
100489545Stanimura			PROC_LOCK(p);
1005107849Salfred		else if ((p = svr4_pfind(uap->pid)) == NULL)
100643412Snewton			return ESRCH;
100743412Snewton		/*
100843412Snewton		 * This has already been initialized to the pid of
100943412Snewton		 * the session leader.
101043412Snewton		 */
101189541Stanimura		*retval = (register_t) p->p_session->s_sid;
101275893Sjhb		PROC_UNLOCK(p);
101343412Snewton		return 0;
101443412Snewton
101543412Snewton	case 3:			/* setsid() */
1016225617Skmacy		return sys_setsid(td, NULL);
101743412Snewton
101843412Snewton	case 4:			/* getpgid(pid) */
101943412Snewton
1020107849Salfred		if (uap->pid == 0)
102189545Stanimura			PROC_LOCK(p);
1022107849Salfred		else if ((p = svr4_pfind(uap->pid)) == NULL)
102343412Snewton			return ESRCH;
102443412Snewton
102543412Snewton		*retval = (int) p->p_pgrp->pg_id;
102675893Sjhb		PROC_UNLOCK(p);
102743412Snewton		return 0;
102843412Snewton
102943412Snewton	case 5:			/* setpgid(pid, pgid); */
103043412Snewton		{
103143412Snewton			struct setpgid_args sa;
103243412Snewton
1033107849Salfred			sa.pid = uap->pid;
1034107849Salfred			sa.pgid = uap->pgid;
1035225617Skmacy			return sys_setpgid(td, &sa);
103643412Snewton		}
103743412Snewton
103843412Snewton	default:
103943412Snewton		return EINVAL;
104043412Snewton	}
104143412Snewton}
104243412Snewton
104343412Snewtonstruct svr4_hrtcntl_args {
104443412Snewton	int 			cmd;
104543412Snewton	int 			fun;
104643412Snewton	int 			clk;
104743412Snewton	svr4_hrt_interval_t *	iv;
104843412Snewton	svr4_hrt_time_t *	ti;
104943412Snewton};
105043412Snewton
105143412Snewton
105243412Snewtonstatic int
105383366Sjuliansvr4_hrtcntl(td, uap, retval)
105483366Sjulian	struct thread *td;
105543412Snewton	struct svr4_hrtcntl_args *uap;
105643412Snewton	register_t *retval;
105743412Snewton{
1058107849Salfred	switch (uap->fun) {
105943412Snewton	case SVR4_HRT_CNTL_RES:
106043412Snewton		DPRINTF(("htrcntl(RES)\n"));
106143412Snewton		*retval = SVR4_HRT_USEC;
106243412Snewton		return 0;
106343412Snewton
106443412Snewton	case SVR4_HRT_CNTL_TOFD:
106543412Snewton		DPRINTF(("htrcntl(TOFD)\n"));
106643412Snewton		{
106743412Snewton			struct timeval tv;
106843412Snewton			svr4_hrt_time_t t;
1069107849Salfred			if (uap->clk != SVR4_HRT_CLK_STD) {
1070107849Salfred				DPRINTF(("clk == %d\n", uap->clk));
107143412Snewton				return EINVAL;
107243412Snewton			}
1073107849Salfred			if (uap->ti == NULL) {
107443412Snewton				DPRINTF(("ti NULL\n"));
107543412Snewton				return EINVAL;
107643412Snewton			}
107743412Snewton			microtime(&tv);
107843412Snewton			t.h_sec = tv.tv_sec;
107943412Snewton			t.h_rem = tv.tv_usec;
108043412Snewton			t.h_res = SVR4_HRT_USEC;
1081107849Salfred			return copyout(&t, uap->ti, sizeof(t));
108243412Snewton		}
108343412Snewton
108443412Snewton	case SVR4_HRT_CNTL_START:
108543412Snewton		DPRINTF(("htrcntl(START)\n"));
108643412Snewton		return ENOSYS;
108743412Snewton
108843412Snewton	case SVR4_HRT_CNTL_GET:
108943412Snewton		DPRINTF(("htrcntl(GET)\n"));
109043412Snewton		return ENOSYS;
109143412Snewton	default:
1092107849Salfred		DPRINTF(("Bad htrcntl command %d\n", uap->fun));
109343412Snewton		return ENOSYS;
109443412Snewton	}
109543412Snewton}
109643412Snewton
109743412Snewton
109843412Snewtonint
109983366Sjuliansvr4_sys_hrtsys(td, uap)
110083366Sjulian	struct thread *td;
110143412Snewton	struct svr4_sys_hrtsys_args *uap;
110243412Snewton{
110383366Sjulian        int *retval = td->td_retval;
110443412Snewton
1105107849Salfred	switch (uap->cmd) {
110643412Snewton	case SVR4_HRT_CNTL:
110783366Sjulian		return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
110843412Snewton				    retval);
110943412Snewton
111043412Snewton	case SVR4_HRT_ALRM:
111143412Snewton		DPRINTF(("hrtalarm\n"));
111243412Snewton		return ENOSYS;
111343412Snewton
111443412Snewton	case SVR4_HRT_SLP:
111543412Snewton		DPRINTF(("hrtsleep\n"));
111643412Snewton		return ENOSYS;
111743412Snewton
111843412Snewton	case SVR4_HRT_CAN:
111943412Snewton		DPRINTF(("hrtcancel\n"));
112043412Snewton		return ENOSYS;
112143412Snewton
112243412Snewton	default:
1123107849Salfred		DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
112443412Snewton		return EINVAL;
112543412Snewton	}
112643412Snewton}
112743412Snewton
112843412Snewton
112943412Snewtonstatic int
1130160510Sjhbsvr4_setinfo(pid, ru, st, s)
1131160510Sjhb	pid_t pid;
1132160510Sjhb	struct rusage *ru;
113343412Snewton	int st;
113443412Snewton	svr4_siginfo_t *s;
113543412Snewton{
113643412Snewton	svr4_siginfo_t i;
113743412Snewton	int sig;
113843412Snewton
113943412Snewton	memset(&i, 0, sizeof(i));
114043412Snewton
1141151463Sdavidxu	i.svr4_si_signo = SVR4_SIGCHLD;
1142151463Sdavidxu	i.svr4_si_errno = 0;	/* XXX? */
114343412Snewton
1144160510Sjhb	i.svr4_si_pid = pid;
1145160510Sjhb	if (ru) {
1146160510Sjhb		i.svr4_si_stime = ru->ru_stime.tv_sec;
1147160510Sjhb		i.svr4_si_utime = ru->ru_utime.tv_sec;
114843412Snewton	}
114943412Snewton
115043412Snewton	if (WIFEXITED(st)) {
1151151463Sdavidxu		i.svr4_si_status = WEXITSTATUS(st);
1152151463Sdavidxu		i.svr4_si_code = SVR4_CLD_EXITED;
115343412Snewton	} else if (WIFSTOPPED(st)) {
115443412Snewton		sig = WSTOPSIG(st);
115543412Snewton		if (sig >= 0 && sig < NSIG)
1156151463Sdavidxu			i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
115743412Snewton
1158151463Sdavidxu		if (i.svr4_si_status == SVR4_SIGCONT)
1159151463Sdavidxu			i.svr4_si_code = SVR4_CLD_CONTINUED;
116043412Snewton		else
1161151463Sdavidxu			i.svr4_si_code = SVR4_CLD_STOPPED;
116243412Snewton	} else {
116343412Snewton		sig = WTERMSIG(st);
116443412Snewton		if (sig >= 0 && sig < NSIG)
1165151463Sdavidxu			i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
116643412Snewton
116743412Snewton		if (WCOREDUMP(st))
1168151463Sdavidxu			i.svr4_si_code = SVR4_CLD_DUMPED;
116943412Snewton		else
1170151463Sdavidxu			i.svr4_si_code = SVR4_CLD_KILLED;
117143412Snewton	}
117243412Snewton
117343412Snewton	DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1174151463Sdavidxu		 i.svr4_si_pid, i.svr4_si_signo, i.svr4_si_code, i.svr4_si_errno,
1175151463Sdavidxu		 i.svr4_si_status));
117643412Snewton
117743412Snewton	return copyout(&i, s, sizeof(i));
117843412Snewton}
117943412Snewton
118043412Snewton
118143412Snewtonint
118283366Sjuliansvr4_sys_waitsys(td, uap)
118383366Sjulian	struct thread *td;
118443412Snewton	struct svr4_sys_waitsys_args *uap;
118543412Snewton{
1186160510Sjhb	struct rusage ru;
1187160510Sjhb	pid_t pid;
1188160510Sjhb	int nfound, status;
118983366Sjulian	int error, *retval = td->td_retval;
1190160510Sjhb	struct proc *p, *q;
119143412Snewton
1192160510Sjhb	DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1193160510Sjhb	         uap->grp, uap->id,
1194160510Sjhb		 uap->info, uap->options));
1195160510Sjhb
1196160510Sjhb	q = td->td_proc;
1197107849Salfred	switch (uap->grp) {
1198160510Sjhb	case SVR4_P_PID:
1199160510Sjhb		pid = uap->id;
120043412Snewton		break;
120143412Snewton
120243412Snewton	case SVR4_P_PGID:
1203160510Sjhb		PROC_LOCK(q);
1204160510Sjhb		pid = -q->p_pgid;
1205160510Sjhb		PROC_UNLOCK(q);
120643412Snewton		break;
120743412Snewton
120843412Snewton	case SVR4_P_ALL:
1209160510Sjhb		pid = WAIT_ANY;
121043412Snewton		break;
121143412Snewton
121243412Snewton	default:
121343412Snewton		return EINVAL;
121443412Snewton	}
121543412Snewton
1216160510Sjhb	/* Hand off the easy cases to kern_wait(). */
1217160510Sjhb	if (!(uap->options & (SVR4_WNOWAIT)) &&
1218160510Sjhb	    (uap->options & (SVR4_WEXITED | SVR4_WTRAPPED))) {
1219160510Sjhb		int options;
122043412Snewton
1221160510Sjhb		options = 0;
1222160510Sjhb		if (uap->options & SVR4_WSTOPPED)
1223160510Sjhb			options |= WUNTRACED;
1224160510Sjhb		if (uap->options & SVR4_WCONTINUED)
1225160510Sjhb			options |= WCONTINUED;
1226160510Sjhb		if (uap->options & SVR4_WNOHANG)
1227160510Sjhb			options |= WNOHANG;
1228160510Sjhb
1229160510Sjhb		error = kern_wait(td, pid, &status, options, &ru);
1230160510Sjhb		if (error)
1231160510Sjhb			return (error);
1232160510Sjhb		if (uap->options & SVR4_WNOHANG && *retval == 0)
1233160510Sjhb			error = svr4_setinfo(*retval, NULL, 0, uap->info);
1234160510Sjhb		else
1235160510Sjhb			error = svr4_setinfo(*retval, &ru, status, uap->info);
1236160510Sjhb		*retval = 0;
1237160510Sjhb		return (error);
1238160510Sjhb	}
1239160510Sjhb
1240160510Sjhb	/*
1241160510Sjhb	 * Ok, handle the weird cases.  Either WNOWAIT is set (meaning we
1242192459Sjhb	 * just want to see if there is a process to harvest, we don't
1243160510Sjhb	 * want to actually harvest it), or WEXIT and WTRAPPED are clear
1244160510Sjhb	 * meaning we want to ignore zombies.  Either way, we don't have
1245160510Sjhb	 * to handle harvesting zombies here.  We do have to duplicate the
1246192459Sjhb	 * other portions of kern_wait() though, especially for WCONTINUED
1247192459Sjhb	 * and WSTOPPED.
1248160510Sjhb	 */
124943412Snewtonloop:
125043412Snewton	nfound = 0;
125174927Sjhb	sx_slock(&proctree_lock);
1252160510Sjhb	LIST_FOREACH(p, &q->p_children, p_sibling) {
1253160510Sjhb		PROC_LOCK(p);
1254160510Sjhb		if (pid != WAIT_ANY &&
1255160510Sjhb		    p->p_pid != pid && p->p_pgid != -pid) {
1256160510Sjhb			PROC_UNLOCK(p);
1257160510Sjhb			DPRINTF(("pid %d pgid %d != %d\n", p->p_pid,
1258160510Sjhb				 p->p_pgid, pid));
125943412Snewton			continue;
126043412Snewton		}
1261160510Sjhb		if (p_canwait(td, p)) {
1262160510Sjhb			PROC_UNLOCK(p);
1263160510Sjhb			continue;
1264160510Sjhb		}
1265160510Sjhb
126643412Snewton		nfound++;
1267160510Sjhb
1268170466Sattilio		PROC_SLOCK(p);
1269160510Sjhb		/*
1270160510Sjhb		 * See if we have a zombie.  If so, WNOWAIT should be set,
1271160510Sjhb		 * as otherwise we should have called kern_wait() up above.
1272160510Sjhb		 */
1273160510Sjhb		if ((p->p_state == PRS_ZOMBIE) &&
1274107849Salfred		    ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
1275170466Sattilio			PROC_SUNLOCK(p);
1276160510Sjhb			KASSERT(uap->options & SVR4_WNOWAIT,
1277160510Sjhb			    ("WNOWAIT is clear"));
1278160510Sjhb
1279160510Sjhb			/* Found a zombie, so cache info in local variables. */
1280160510Sjhb			pid = p->p_pid;
1281160510Sjhb			status = p->p_xstat;
1282170466Sattilio			ru = p->p_ru;
1283170472Sattilio			PROC_SLOCK(p);
1284160510Sjhb			calcru(p, &ru.ru_utime, &ru.ru_stime);
1285170472Sattilio			PROC_SUNLOCK(p);
1286160510Sjhb			PROC_UNLOCK(p);
128774927Sjhb			sx_sunlock(&proctree_lock);
1288160510Sjhb
1289160510Sjhb			/* Copy the info out to userland. */
129043412Snewton			*retval = 0;
1291160510Sjhb			DPRINTF(("found %d\n", pid));
1292160510Sjhb			return (svr4_setinfo(pid, &ru, status, uap->info));
1293160510Sjhb		}
129443412Snewton
1295160510Sjhb		/*
1296160510Sjhb		 * See if we have a stopped or continued process.
1297160510Sjhb		 * XXX: This duplicates the same code in kern_wait().
1298160510Sjhb		 */
1299160510Sjhb		if ((p->p_flag & P_STOPPED_SIG) &&
1300160510Sjhb		    (p->p_suspcount == p->p_numthreads) &&
1301160510Sjhb		    (p->p_flag & P_WAITED) == 0 &&
1302160510Sjhb		    (p->p_flag & P_TRACED || uap->options & SVR4_WSTOPPED)) {
1303170307Sjeff			PROC_SUNLOCK(p);
1304160510Sjhb		        if (((uap->options & SVR4_WNOWAIT)) == 0)
1305160510Sjhb				p->p_flag |= P_WAITED;
1306160510Sjhb			sx_sunlock(&proctree_lock);
1307160510Sjhb			pid = p->p_pid;
1308160510Sjhb			status = W_STOPCODE(p->p_xstat);
1309170466Sattilio			ru = p->p_ru;
1310170472Sattilio			PROC_SLOCK(p);
1311160510Sjhb			calcru(p, &ru.ru_utime, &ru.ru_stime);
1312170472Sattilio			PROC_SUNLOCK(p);
1313160510Sjhb			PROC_UNLOCK(p);
131443412Snewton
1315160510Sjhb		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
1316160510Sjhb				PROC_LOCK(q);
1317160510Sjhb				sigqueue_take(p->p_ksi);
1318160510Sjhb				PROC_UNLOCK(q);
131943412Snewton			}
132043412Snewton
1321160510Sjhb			*retval = 0;
1322160510Sjhb			DPRINTF(("jobcontrol %d\n", pid));
1323160510Sjhb			return (svr4_setinfo(pid, &ru, status, uap->info));
1324160510Sjhb		}
1325170307Sjeff		PROC_SUNLOCK(p);
1326160510Sjhb		if (uap->options & SVR4_WCONTINUED &&
1327160510Sjhb		    (p->p_flag & P_CONTINUED)) {
1328160510Sjhb			sx_sunlock(&proctree_lock);
1329160510Sjhb		        if (((uap->options & SVR4_WNOWAIT)) == 0)
1330160510Sjhb				p->p_flag &= ~P_CONTINUED;
1331160510Sjhb			pid = p->p_pid;
1332170466Sattilio			ru = p->p_ru;
1333160510Sjhb			status = SIGCONT;
1334170472Sattilio			PROC_SLOCK(p);
1335160510Sjhb			calcru(p, &ru.ru_utime, &ru.ru_stime);
1336170472Sattilio			PROC_SUNLOCK(p);
1337160510Sjhb			PROC_UNLOCK(p);
1338160510Sjhb
1339160510Sjhb		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
1340160510Sjhb				PROC_LOCK(q);
1341160510Sjhb				sigqueue_take(p->p_ksi);
1342160510Sjhb				PROC_UNLOCK(q);
134373907Sjhb			}
134443412Snewton
134543412Snewton			*retval = 0;
1346160510Sjhb			DPRINTF(("jobcontrol %d\n", pid));
1347160510Sjhb			return (svr4_setinfo(pid, &ru, status, uap->info));
134843412Snewton		}
1349160510Sjhb		PROC_UNLOCK(p);
135043412Snewton	}
135143412Snewton
1352160510Sjhb	if (nfound == 0) {
1353160510Sjhb		sx_sunlock(&proctree_lock);
1354160510Sjhb		return (ECHILD);
1355160510Sjhb	}
135643412Snewton
1357107849Salfred	if (uap->options & SVR4_WNOHANG) {
1358160510Sjhb		sx_sunlock(&proctree_lock);
135943412Snewton		*retval = 0;
1360160510Sjhb		return (svr4_setinfo(0, NULL, 0, uap->info));
136143412Snewton	}
136243412Snewton
1363160510Sjhb	PROC_LOCK(q);
1364160510Sjhb	sx_sunlock(&proctree_lock);
1365160510Sjhb	if (q->p_flag & P_STATCHILD) {
1366160510Sjhb		q->p_flag &= ~P_STATCHILD;
1367160510Sjhb		error = 0;
1368160510Sjhb	} else
1369160510Sjhb		error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "svr4_wait", 0);
1370160510Sjhb	PROC_UNLOCK(q);
1371160510Sjhb	if (error)
137243412Snewton		return error;
137343412Snewton	goto loop;
137443412Snewton}
137543412Snewton
137643412Snewton
137743412Snewtonstatic void
137843412Snewtonbsd_statfs_to_svr4_statvfs(bfs, sfs)
137943412Snewton	const struct statfs *bfs;
138043412Snewton	struct svr4_statvfs *sfs;
138143412Snewton{
138243412Snewton	sfs->f_bsize = bfs->f_iosize; /* XXX */
138343412Snewton	sfs->f_frsize = bfs->f_bsize;
138443412Snewton	sfs->f_blocks = bfs->f_blocks;
138543412Snewton	sfs->f_bfree = bfs->f_bfree;
138643412Snewton	sfs->f_bavail = bfs->f_bavail;
138743412Snewton	sfs->f_files = bfs->f_files;
138843412Snewton	sfs->f_ffree = bfs->f_ffree;
138943412Snewton	sfs->f_favail = bfs->f_ffree;
139043412Snewton	sfs->f_fsid = bfs->f_fsid.val[0];
139143412Snewton	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
139243412Snewton	sfs->f_flag = 0;
139343412Snewton	if (bfs->f_flags & MNT_RDONLY)
139443412Snewton		sfs->f_flag |= SVR4_ST_RDONLY;
139543412Snewton	if (bfs->f_flags & MNT_NOSUID)
139643412Snewton		sfs->f_flag |= SVR4_ST_NOSUID;
139743412Snewton	sfs->f_namemax = MAXNAMLEN;
139843412Snewton	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
139943412Snewton	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
140043412Snewton}
140143412Snewton
140243412Snewton
140343412Snewtonstatic void
140443412Snewtonbsd_statfs_to_svr4_statvfs64(bfs, sfs)
140543412Snewton	const struct statfs *bfs;
140643412Snewton	struct svr4_statvfs64 *sfs;
140743412Snewton{
140843412Snewton	sfs->f_bsize = bfs->f_iosize; /* XXX */
140943412Snewton	sfs->f_frsize = bfs->f_bsize;
141043412Snewton	sfs->f_blocks = bfs->f_blocks;
141143412Snewton	sfs->f_bfree = bfs->f_bfree;
141243412Snewton	sfs->f_bavail = bfs->f_bavail;
141343412Snewton	sfs->f_files = bfs->f_files;
141443412Snewton	sfs->f_ffree = bfs->f_ffree;
141543412Snewton	sfs->f_favail = bfs->f_ffree;
141643412Snewton	sfs->f_fsid = bfs->f_fsid.val[0];
141743412Snewton	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
141843412Snewton	sfs->f_flag = 0;
141943412Snewton	if (bfs->f_flags & MNT_RDONLY)
142043412Snewton		sfs->f_flag |= SVR4_ST_RDONLY;
142143412Snewton	if (bfs->f_flags & MNT_NOSUID)
142243412Snewton		sfs->f_flag |= SVR4_ST_NOSUID;
142343412Snewton	sfs->f_namemax = MAXNAMLEN;
142443412Snewton	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
142543412Snewton	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
142643412Snewton}
142743412Snewton
142843412Snewton
142943412Snewtonint
143083366Sjuliansvr4_sys_statvfs(td, uap)
143183366Sjulian	struct thread *td;
143243412Snewton	struct svr4_sys_statvfs_args *uap;
143343412Snewton{
1434141486Sjhb	struct svr4_statvfs sfs;
143543412Snewton	struct statfs bfs;
1436141486Sjhb	char *path;
143743412Snewton	int error;
143843412Snewton
1439141486Sjhb	CHECKALTEXIST(td, uap->path, &path);
144043412Snewton
1441141486Sjhb	error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1442141486Sjhb	free(path, M_TEMP);
1443141486Sjhb	if (error)
1444141486Sjhb		return (error);
144543412Snewton	bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1446107849Salfred	return copyout(&sfs, uap->fs, sizeof(sfs));
144743412Snewton}
144843412Snewton
144943412Snewton
145043412Snewtonint
145183366Sjuliansvr4_sys_fstatvfs(td, uap)
145283366Sjulian	struct thread *td;
145343412Snewton	struct svr4_sys_fstatvfs_args *uap;
145443412Snewton{
1455141486Sjhb	struct svr4_statvfs sfs;
145643412Snewton	struct statfs bfs;
145743412Snewton	int error;
145843412Snewton
1459141486Sjhb	error = kern_fstatfs(td, uap->fd, &bfs);
1460141486Sjhb	if (error)
1461141486Sjhb		return (error);
146243412Snewton	bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1463107849Salfred	return copyout(&sfs, uap->fs, sizeof(sfs));
146443412Snewton}
146543412Snewton
146643412Snewton
146743412Snewtonint
146883366Sjuliansvr4_sys_statvfs64(td, uap)
146983366Sjulian	struct thread *td;
147043412Snewton	struct svr4_sys_statvfs64_args *uap;
147143412Snewton{
1472141486Sjhb	struct svr4_statvfs64 sfs;
147343412Snewton	struct statfs bfs;
1474141486Sjhb	char *path;
147543412Snewton	int error;
147643412Snewton
1477141486Sjhb	CHECKALTEXIST(td, uap->path, &path);
147843412Snewton
1479141486Sjhb	error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1480141486Sjhb	free(path, M_TEMP);
1481141486Sjhb	if (error)
1482141486Sjhb		return (error);
148343412Snewton	bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1484107849Salfred	return copyout(&sfs, uap->fs, sizeof(sfs));
148543412Snewton}
148643412Snewton
148743412Snewton
148843412Snewtonint
148983366Sjuliansvr4_sys_fstatvfs64(td, uap)
149083366Sjulian	struct thread *td;
149143412Snewton	struct svr4_sys_fstatvfs64_args *uap;
149243412Snewton{
1493141486Sjhb	struct svr4_statvfs64 sfs;
149443412Snewton	struct statfs bfs;
149543412Snewton	int error;
149643412Snewton
1497141486Sjhb	error = kern_fstatfs(td, uap->fd, &bfs);
1498141486Sjhb	if (error)
1499141486Sjhb		return (error);
150043412Snewton	bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1501107849Salfred	return copyout(&sfs, uap->fs, sizeof(sfs));
150243412Snewton}
150343412Snewton
150443412Snewtonint
150583366Sjuliansvr4_sys_alarm(td, uap)
150683366Sjulian	struct thread *td;
150743412Snewton	struct svr4_sys_alarm_args *uap;
150843412Snewton{
1509141486Sjhb        struct itimerval itv, oitv;
151043412Snewton	int error;
151143412Snewton
1512141486Sjhb	timevalclear(&itv.it_interval);
1513141486Sjhb	itv.it_value.tv_sec = uap->sec;
1514141486Sjhb	itv.it_value.tv_usec = 0;
1515141486Sjhb	error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
151643412Snewton	if (error)
1517141486Sjhb		return (error);
1518141486Sjhb	if (oitv.it_value.tv_usec != 0)
1519141486Sjhb		oitv.it_value.tv_sec++;
1520141486Sjhb	td->td_retval[0] = oitv.it_value.tv_sec;
1521141486Sjhb	return (0);
152243412Snewton}
152343412Snewton
152443412Snewtonint
152583366Sjuliansvr4_sys_gettimeofday(td, uap)
152683366Sjulian	struct thread *td;
152743412Snewton	struct svr4_sys_gettimeofday_args *uap;
152843412Snewton{
1529107849Salfred	if (uap->tp) {
153043412Snewton		struct timeval atv;
153143412Snewton
153243412Snewton		microtime(&atv);
1533107849Salfred		return copyout(&atv, uap->tp, sizeof (atv));
153443412Snewton	}
153543412Snewton
153643412Snewton	return 0;
153743412Snewton}
153843412Snewton
153943412Snewtonint
154083366Sjuliansvr4_sys_facl(td, uap)
154183366Sjulian	struct thread *td;
154243412Snewton	struct svr4_sys_facl_args *uap;
154343412Snewton{
154443412Snewton	int *retval;
154543412Snewton
154683366Sjulian	retval = td->td_retval;
154743412Snewton	*retval = 0;
154843412Snewton
1549107849Salfred	switch (uap->cmd) {
155043412Snewton	case SVR4_SYS_SETACL:
155143412Snewton		/* We don't support acls on any filesystem */
155243412Snewton		return ENOSYS;
155343412Snewton
155443412Snewton	case SVR4_SYS_GETACL:
1555107849Salfred		return copyout(retval, &uap->num,
1556107849Salfred		    sizeof(uap->num));
155743412Snewton
155843412Snewton	case SVR4_SYS_GETACLCNT:
155943412Snewton		return 0;
156043412Snewton
156143412Snewton	default:
156243412Snewton		return EINVAL;
156343412Snewton	}
156443412Snewton}
156543412Snewton
156643412Snewton
156743412Snewtonint
156883366Sjuliansvr4_sys_acl(td, uap)
156983366Sjulian	struct thread *td;
157043412Snewton	struct svr4_sys_acl_args *uap;
157143412Snewton{
157243412Snewton	/* XXX: for now the same */
157383366Sjulian	return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
157443412Snewton}
157543412Snewton
157643412Snewtonint
157783366Sjuliansvr4_sys_auditsys(td, uap)
157883366Sjulian	struct thread *td;
157943412Snewton	struct svr4_sys_auditsys_args *uap;
158043412Snewton{
158143412Snewton	/*
158243412Snewton	 * XXX: Big brother is *not* watching.
158343412Snewton	 */
158443412Snewton	return 0;
158543412Snewton}
158643412Snewton
158743412Snewtonint
158883366Sjuliansvr4_sys_memcntl(td, uap)
158983366Sjulian	struct thread *td;
159043412Snewton	struct svr4_sys_memcntl_args *uap;
159143412Snewton{
1592107849Salfred	switch (uap->cmd) {
159343412Snewton	case SVR4_MC_SYNC:
159443412Snewton		{
159543412Snewton			struct msync_args msa;
159643412Snewton
1597107849Salfred			msa.addr = uap->addr;
1598107849Salfred			msa.len = uap->len;
1599107849Salfred			msa.flags = (int)uap->arg;
160043412Snewton
1601225617Skmacy			return sys_msync(td, &msa);
160243412Snewton		}
160343412Snewton	case SVR4_MC_ADVISE:
160443412Snewton		{
160543412Snewton			struct madvise_args maa;
160643412Snewton
1607107849Salfred			maa.addr = uap->addr;
1608107849Salfred			maa.len = uap->len;
1609107849Salfred			maa.behav = (int)uap->arg;
161043412Snewton
1611225617Skmacy			return sys_madvise(td, &maa);
161243412Snewton		}
161343412Snewton	case SVR4_MC_LOCK:
161443412Snewton	case SVR4_MC_UNLOCK:
161543412Snewton	case SVR4_MC_LOCKAS:
161643412Snewton	case SVR4_MC_UNLOCKAS:
161743412Snewton		return EOPNOTSUPP;
161843412Snewton	default:
161943412Snewton		return ENOSYS;
162043412Snewton	}
162143412Snewton}
162243412Snewton
162343412Snewton
162443412Snewtonint
162583366Sjuliansvr4_sys_nice(td, uap)
162683366Sjulian	struct thread *td;
162743412Snewton	struct svr4_sys_nice_args *uap;
162843412Snewton{
162943412Snewton	struct setpriority_args ap;
163043412Snewton	int error;
163143412Snewton
1632107849Salfred	ap.which = PRIO_PROCESS;
1633107849Salfred	ap.who = 0;
1634107849Salfred	ap.prio = uap->prio;
163543412Snewton
1636225617Skmacy	if ((error = sys_setpriority(td, &ap)) != 0)
163743412Snewton		return error;
163843412Snewton
163943412Snewton	/* the cast is stupid, but the structures are the same */
1640225617Skmacy	if ((error = sys_getpriority(td, (struct getpriority_args *)&ap)) != 0)
164143412Snewton		return error;
164243412Snewton
164343412Snewton	return 0;
164443412Snewton}
164543412Snewton
164643412Snewtonint
164783366Sjuliansvr4_sys_resolvepath(td, uap)
164883366Sjulian	struct thread *td;
164943412Snewton	struct svr4_sys_resolvepath_args *uap;
165043412Snewton{
165143412Snewton	struct nameidata nd;
165283366Sjulian	int error, *retval = td->td_retval;
1653121275Stjr	unsigned int ncopy;
165443412Snewton
1655160511Sjhb	NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | MPSAFE, UIO_USERSPACE,
1656107849Salfred	    uap->path, td);
165743412Snewton
165843412Snewton	if ((error = namei(&nd)) != 0)
1659192455Sjhb		return (error);
1660192455Sjhb	NDFREE(&nd, NDF_NO_FREE_PNBUF);
1661192455Sjhb	VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
166243412Snewton
1663121275Stjr	ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
1664121275Stjr	if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
166543412Snewton		goto bad;
166643412Snewton
1667121275Stjr	*retval = ncopy;
166843412Snewtonbad:
166954655Seivind	NDFREE(&nd, NDF_ONLY_PNBUF);
167043412Snewton	return error;
167143412Snewton}
1672