1/*-
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/*
29 * SVR4 compatibility module.
30 *
31 * SVR4 system calls that are implemented differently in BSD are
32 * handled here.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: stable/11/sys/compat/svr4/svr4_misc.c 366288 2020-09-30 12:16:36Z kib $");
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/capsicum.h>
41#include <sys/dirent.h>
42#include <sys/fcntl.h>
43#include <sys/filedesc.h>
44#include <sys/imgact.h>
45#include <sys/kernel.h>
46#include <sys/lock.h>
47#include <sys/malloc.h>
48#include <sys/file.h>		/* Must come after sys/malloc.h */
49#include <sys/mman.h>
50#include <sys/mount.h>
51#include <sys/msg.h>
52#include <sys/mutex.h>
53#include <sys/namei.h>
54#include <sys/priv.h>
55#include <sys/proc.h>
56#include <sys/ptrace.h>
57#include <sys/resource.h>
58#include <sys/resourcevar.h>
59#include <sys/sem.h>
60#include <sys/signalvar.h>
61#include <sys/stat.h>
62#include <sys/sx.h>
63#include <sys/syscallsubr.h>
64#include <sys/sysproto.h>
65#include <sys/time.h>
66#include <sys/times.h>
67#include <sys/uio.h>
68#include <sys/vnode.h>
69#include <sys/wait.h>
70
71#include <compat/svr4/svr4.h>
72#include <compat/svr4/svr4_types.h>
73#include <compat/svr4/svr4_signal.h>
74#include <compat/svr4/svr4_proto.h>
75#include <compat/svr4/svr4_util.h>
76#include <compat/svr4/svr4_sysconfig.h>
77#include <compat/svr4/svr4_dirent.h>
78#include <compat/svr4/svr4_acl.h>
79#include <compat/svr4/svr4_ulimit.h>
80#include <compat/svr4/svr4_statvfs.h>
81#include <compat/svr4/svr4_hrt.h>
82#include <compat/svr4/svr4_mman.h>
83#include <compat/svr4/svr4_wait.h>
84
85#include <security/mac/mac_framework.h>
86
87#include <vm/vm.h>
88#include <vm/vm_param.h>
89#include <vm/vm_map.h>
90#if defined(__FreeBSD__)
91#include <vm/uma.h>
92#include <vm/vm_extern.h>
93#endif
94
95#if defined(NetBSD)
96# if defined(UVM)
97#  include <uvm/uvm_extern.h>
98# endif
99#endif
100
101#define	BSD_DIRENT(cp)		((struct dirent *)(cp))
102
103static int svr4_mknod(struct thread *, register_t *, char *,
104    svr4_mode_t, svr4_dev_t);
105
106static __inline clock_t timeval_to_clock_t(struct timeval *);
107static int svr4_setinfo	(pid_t , struct rusage *, int, svr4_siginfo_t *);
108
109struct svr4_hrtcntl_args;
110static int svr4_hrtcntl	(struct thread *, struct svr4_hrtcntl_args *,
111    register_t *);
112static void bsd_statfs_to_svr4_statvfs(const struct statfs *,
113    struct svr4_statvfs *);
114static void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
115    struct svr4_statvfs64 *);
116static struct proc *svr4_pfind(pid_t pid);
117
118/* BOGUS noop */
119#if defined(BOGUS)
120int
121svr4_sys_setitimer(td, uap)
122        struct thread *td;
123	struct svr4_sys_setitimer_args *uap;
124{
125        td->td_retval[0] = 0;
126	return 0;
127}
128#endif
129
130int
131svr4_sys_wait(td, uap)
132	struct thread *td;
133	struct svr4_sys_wait_args *uap;
134{
135	int error, st, sig;
136
137	error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
138	if (error)
139		return (error);
140
141	if (WIFSIGNALED(st)) {
142		sig = WTERMSIG(st);
143		if (sig >= 0 && sig < NSIG)
144			st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
145	} else if (WIFSTOPPED(st)) {
146		sig = WSTOPSIG(st);
147		if (sig >= 0 && sig < NSIG)
148			st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
149	}
150
151	/*
152	 * It looks like wait(2) on svr4/solaris/2.4 returns
153	 * the status in retval[1], and the pid on retval[0].
154	 */
155	td->td_retval[1] = st;
156
157	if (uap->status)
158		error = copyout(&st, uap->status, sizeof(st));
159
160	return (error);
161}
162
163int
164svr4_sys_execv(td, uap)
165	struct thread *td;
166	struct svr4_sys_execv_args *uap;
167{
168	struct image_args eargs;
169	struct vmspace *oldvmspace;
170	char *path;
171	int error;
172
173	CHECKALTEXIST(td, uap->path, &path);
174
175	error = pre_execve(td, &oldvmspace);
176	if (error != 0) {
177		free(path, M_TEMP);
178		return (error);
179	}
180	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
181	free(path, M_TEMP);
182	if (error == 0)
183		error = kern_execve(td, &eargs, NULL, oldvmspace);
184	post_execve(td, error, oldvmspace);
185	return (error);
186}
187
188int
189svr4_sys_execve(td, uap)
190	struct thread *td;
191	struct svr4_sys_execve_args *uap;
192{
193	struct image_args eargs;
194	struct vmspace *oldvmspace;
195	char *path;
196	int error;
197
198	CHECKALTEXIST(td, uap->path, &path);
199
200	error = pre_execve(td, &oldvmspace);
201	if (error != 0) {
202		free(path, M_TEMP);
203		return (error);
204	}
205	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
206	    uap->envp);
207	free(path, M_TEMP);
208	if (error == 0)
209		error = kern_execve(td, &eargs, NULL, oldvmspace);
210	post_execve(td, error, oldvmspace);
211	return (error);
212}
213
214int
215svr4_sys_time(td, v)
216	struct thread *td;
217	struct svr4_sys_time_args *v;
218{
219	struct svr4_sys_time_args *uap = v;
220	int error = 0;
221	struct timeval tv;
222
223	microtime(&tv);
224	if (uap->t)
225		error = copyout(&tv.tv_sec, uap->t,
226				sizeof(*(uap->t)));
227	td->td_retval[0] = (int) tv.tv_sec;
228
229	return error;
230}
231
232
233/*
234 * Read SVR4-style directory entries.  We suck them into kernel space so
235 * that they can be massaged before being copied out to user code.
236 *
237 * This code is ported from the Linux emulator:  Changes to the VFS interface
238 * between FreeBSD and NetBSD have made it simpler to port it from there than
239 * to adapt the NetBSD version.
240 */
241int
242svr4_sys_getdents64(td, uap)
243	struct thread *td;
244	struct svr4_sys_getdents64_args *uap;
245{
246	struct dirent *bdp;
247	struct vnode *vp;
248	caddr_t inp, buf;		/* BSD-format */
249	int len, reclen;		/* BSD-format */
250	caddr_t outp;			/* SVR4-format */
251	int resid, svr4reclen=0;	/* SVR4-format */
252	cap_rights_t rights;
253	struct file *fp;
254	struct uio auio;
255	struct iovec aiov;
256	off_t off;
257	struct svr4_dirent64 svr4_dirent;
258	int buflen, error, eofflag, nbytes, justone;
259	u_long *cookies = NULL, *cookiep;
260	int ncookies;
261
262	memset(&svr4_dirent, 0, sizeof(svr4_dirent));
263	DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
264		uap->fd, uap->nbytes));
265	error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
266	if (error != 0)
267		return (error);
268
269	if ((fp->f_flag & FREAD) == 0) {
270		fdrop(fp, td);
271		return (EBADF);
272	}
273
274	vp = fp->f_vnode;
275	if (vp->v_type != VDIR) {
276		fdrop(fp, td);
277		return (EINVAL);
278	}
279
280	nbytes = uap->nbytes;
281	if (nbytes == 1) {
282		nbytes = sizeof (struct svr4_dirent64);
283		justone = 1;
284	}
285	else
286		justone = 0;
287
288	off = fp->f_offset;
289#define	DIRBLKSIZ	512		/* XXX we used to use ufs's DIRBLKSIZ */
290	buflen = max(DIRBLKSIZ, nbytes);
291	buflen = min(buflen, MAXBSIZE);
292	buf = malloc(buflen, M_TEMP, M_WAITOK);
293	vn_lock(vp, LK_SHARED | LK_RETRY);
294again:
295	aiov.iov_base = buf;
296	aiov.iov_len = buflen;
297	auio.uio_iov = &aiov;
298	auio.uio_iovcnt = 1;
299	auio.uio_rw = UIO_READ;
300	auio.uio_segflg = UIO_SYSSPACE;
301	auio.uio_td = td;
302	auio.uio_resid = buflen;
303	auio.uio_offset = off;
304
305	if (cookies) {
306		free(cookies, M_TEMP);
307		cookies = NULL;
308	}
309
310#ifdef MAC
311	error = mac_vnode_check_readdir(td->td_ucred, vp);
312	if (error)
313		goto out;
314#endif
315
316	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
317						&ncookies, &cookies);
318	if (error) {
319		goto out;
320	}
321
322	inp = buf;
323	outp = (caddr_t) uap->dp;
324	resid = nbytes;
325	if ((len = buflen - auio.uio_resid) <= 0) {
326		goto eof;
327	}
328
329	cookiep = cookies;
330
331	if (cookies) {
332		/*
333		 * When using cookies, the vfs has the option of reading from
334		 * a different offset than that supplied (UFS truncates the
335		 * offset to a block boundary to make sure that it never reads
336		 * partway through a directory entry, even if the directory
337		 * has been compacted).
338		 */
339		while (len > 0 && ncookies > 0 && *cookiep <= off) {
340			bdp = (struct dirent *) inp;
341			len -= bdp->d_reclen;
342			inp += bdp->d_reclen;
343			cookiep++;
344			ncookies--;
345		}
346	}
347
348	while (len > 0) {
349		if (cookiep && ncookies == 0)
350			break;
351		bdp = (struct dirent *) inp;
352		reclen = bdp->d_reclen;
353		if (reclen & 3) {
354			DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
355			error = EFAULT;
356			goto out;
357		}
358
359		if (bdp->d_fileno == 0) {
360	    		inp += reclen;
361			if (cookiep) {
362				off = *cookiep++;
363				ncookies--;
364			} else
365				off += reclen;
366			len -= reclen;
367			continue;
368		}
369		svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
370		if (reclen > len || resid < svr4reclen) {
371			outp++;
372			break;
373		}
374		svr4_dirent.d_ino = (long) bdp->d_fileno;
375		if (justone) {
376			/*
377			 * old svr4-style readdir usage.
378			 */
379			svr4_dirent.d_off = (svr4_off_t) svr4reclen;
380			svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
381		} else {
382			svr4_dirent.d_off = (svr4_off_t)(off + reclen);
383			svr4_dirent.d_reclen = (u_short) svr4reclen;
384		}
385		strlcpy(svr4_dirent.d_name, bdp->d_name, sizeof(svr4_dirent.d_name));
386		if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
387			goto out;
388		inp += reclen;
389		if (cookiep) {
390			off = *cookiep++;
391			ncookies--;
392		} else
393			off += reclen;
394		outp += svr4reclen;
395		resid -= svr4reclen;
396		len -= reclen;
397		if (justone)
398			break;
399    	}
400
401	if (outp == (caddr_t) uap->dp)
402		goto again;
403	fp->f_offset = off;
404
405	if (justone)
406		nbytes = resid + svr4reclen;
407
408eof:
409	td->td_retval[0] = nbytes - resid;
410out:
411	VOP_UNLOCK(vp, 0);
412	fdrop(fp, td);
413	if (cookies)
414		free(cookies, M_TEMP);
415	free(buf, M_TEMP);
416	return error;
417}
418
419
420int
421svr4_sys_getdents(td, uap)
422	struct thread *td;
423	struct svr4_sys_getdents_args *uap;
424{
425	struct dirent *bdp;
426	struct vnode *vp;
427	caddr_t inp, buf;	/* BSD-format */
428	int len, reclen;	/* BSD-format */
429	caddr_t outp;		/* SVR4-format */
430	int resid, svr4_reclen;	/* SVR4-format */
431	cap_rights_t rights;
432	struct file *fp;
433	struct uio auio;
434	struct iovec aiov;
435	struct svr4_dirent idb;
436	off_t off;		/* true file offset */
437	int buflen, error, eofflag;
438	u_long *cookiebuf = NULL, *cookie;
439	int ncookies = 0, *retval = td->td_retval;
440
441	if (uap->nbytes < 0)
442		return (EINVAL);
443
444	error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
445	if (error != 0)
446		return (error);
447
448	if ((fp->f_flag & FREAD) == 0) {
449		fdrop(fp, td);
450		return (EBADF);
451	}
452
453	vp = fp->f_vnode;
454	if (vp->v_type != VDIR) {
455		fdrop(fp, td);
456		return (EINVAL);
457	}
458
459	buflen = min(MAXBSIZE, uap->nbytes);
460	buf = malloc(buflen, M_TEMP, M_WAITOK);
461	vn_lock(vp, LK_SHARED | LK_RETRY);
462	off = fp->f_offset;
463again:
464	aiov.iov_base = buf;
465	aiov.iov_len = buflen;
466	auio.uio_iov = &aiov;
467	auio.uio_iovcnt = 1;
468	auio.uio_rw = UIO_READ;
469	auio.uio_segflg = UIO_SYSSPACE;
470	auio.uio_td = td;
471	auio.uio_resid = buflen;
472	auio.uio_offset = off;
473
474#ifdef MAC
475	error = mac_vnode_check_readdir(td->td_ucred, vp);
476	if (error)
477		goto out;
478#endif
479
480	/*
481         * First we read into the malloc'ed buffer, then
482         * we massage it into user space, one record at a time.
483         */
484	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
485	    &cookiebuf);
486	if (error) {
487		goto out;
488	}
489
490	inp = buf;
491	outp = uap->buf;
492	resid = uap->nbytes;
493	if ((len = buflen - auio.uio_resid) == 0)
494		goto eof;
495
496	for (cookie = cookiebuf; len > 0; len -= reclen) {
497		bdp = (struct dirent *)inp;
498		reclen = bdp->d_reclen;
499		if (reclen & 3)
500			panic("svr4_sys_getdents64: bad reclen");
501		if (cookie)
502			off = *cookie++; /* each entry points to the next */
503		else
504			off += reclen;
505		if ((off >> 32) != 0) {
506			uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
507			error = EINVAL;
508			goto out;
509		}
510		if (bdp->d_fileno == 0) {
511			inp += reclen;	/* it is a hole; squish it out */
512			continue;
513		}
514		svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
515		if (reclen > len || resid < svr4_reclen) {
516			/* entry too big for buffer, so just stop */
517			outp++;
518			break;
519		}
520		/*
521		 * Massage in place to make a SVR4-shaped dirent (otherwise
522		 * we have to worry about touching user memory outside of
523		 * the copyout() call).
524		 */
525		idb.d_ino = (svr4_ino_t)bdp->d_fileno;
526		idb.d_off = (svr4_off_t)off;
527		idb.d_reclen = (u_short)svr4_reclen;
528		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
529		if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
530			goto out;
531		/* advance past this real entry */
532		inp += reclen;
533		/* advance output past SVR4-shaped entry */
534		outp += svr4_reclen;
535		resid -= svr4_reclen;
536	}
537
538	/* if we squished out the whole block, try again */
539	if (outp == uap->buf)
540		goto again;
541	fp->f_offset = off;	/* update the vnode offset */
542
543eof:
544	*retval = uap->nbytes - resid;
545out:
546	VOP_UNLOCK(vp, 0);
547	fdrop(fp, td);
548	if (cookiebuf)
549		free(cookiebuf, M_TEMP);
550	free(buf, M_TEMP);
551	return error;
552}
553
554
555int
556svr4_sys_mmap(td, uap)
557	struct thread *td;
558	struct svr4_sys_mmap_args *uap;
559{
560	struct mmap_args	 mm;
561	int             *retval;
562
563	retval = td->td_retval;
564#define _MAP_NEW	0x80000000
565	/*
566         * Verify the arguments.
567         */
568	if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
569		return EINVAL;	/* XXX still needed? */
570
571	if (uap->len == 0)
572		return EINVAL;
573
574	mm.prot = uap->prot;
575	mm.len = uap->len;
576	mm.flags = uap->flags & ~_MAP_NEW;
577	mm.fd = uap->fd;
578	mm.addr = uap->addr;
579	mm.pos = uap->pos;
580
581	return sys_mmap(td, &mm);
582}
583
584int
585svr4_sys_mmap64(td, uap)
586	struct thread *td;
587	struct svr4_sys_mmap64_args *uap;
588{
589	struct mmap_args	 mm;
590	void		*rp;
591
592#define _MAP_NEW	0x80000000
593	/*
594         * Verify the arguments.
595         */
596	if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
597		return EINVAL;	/* XXX still needed? */
598
599	if (uap->len == 0)
600		return EINVAL;
601
602	mm.prot = uap->prot;
603	mm.len = uap->len;
604	mm.flags = uap->flags & ~_MAP_NEW;
605	mm.fd = uap->fd;
606	mm.addr = uap->addr;
607	mm.pos = uap->pos;
608
609	rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
610	if ((mm.flags & MAP_FIXED) == 0 &&
611	    mm.addr != 0 && (void *)mm.addr < rp)
612		mm.addr = rp;
613
614	return sys_mmap(td, &mm);
615}
616
617
618int
619svr4_sys_fchroot(td, uap)
620	struct thread *td;
621	struct svr4_sys_fchroot_args *uap;
622{
623	cap_rights_t rights;
624	struct vnode	*vp;
625	struct file	*fp;
626	int		 error;
627
628	if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
629		return error;
630	/* XXX: we have the chroot priv... what cap might we need? all? */
631	if ((error = getvnode(td, uap->fd, cap_rights_init(&rights), &fp)) != 0)
632		return error;
633	vp = fp->f_vnode;
634	VREF(vp);
635	fdrop(fp, td);
636	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
637	error = change_dir(vp, td);
638	if (error)
639		goto fail;
640#ifdef MAC
641	error = mac_vnode_check_chroot(td->td_ucred, vp);
642	if (error)
643		goto fail;
644#endif
645	VOP_UNLOCK(vp, 0);
646	error = pwd_chroot(td, vp);
647	vrele(vp);
648	return (error);
649fail:
650	vput(vp);
651	return (error);
652}
653
654
655static int
656svr4_mknod(td, retval, path, mode, dev)
657	struct thread *td;
658	register_t *retval;
659	char *path;
660	svr4_mode_t mode;
661	svr4_dev_t dev;
662{
663	char *newpath;
664	int error;
665
666	CHECKALTEXIST(td, path, &newpath);
667
668	if (S_ISFIFO(mode)) {
669		error = kern_mkfifoat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
670		    mode);
671	} else {
672		error = kern_mknodat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
673		    mode, dev);
674	}
675	free(newpath, M_TEMP);
676	return (error);
677}
678
679
680int
681svr4_sys_mknod(td, uap)
682	struct thread *td;
683	struct svr4_sys_mknod_args *uap;
684{
685        int *retval = td->td_retval;
686	return svr4_mknod(td, retval,
687			  uap->path, uap->mode,
688			  (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
689}
690
691
692int
693svr4_sys_xmknod(td, uap)
694	struct thread *td;
695	struct svr4_sys_xmknod_args *uap;
696{
697        int *retval = td->td_retval;
698	return svr4_mknod(td, retval,
699			  uap->path, uap->mode,
700			  (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
701}
702
703
704int
705svr4_sys_vhangup(td, uap)
706	struct thread *td;
707	struct svr4_sys_vhangup_args *uap;
708{
709	return 0;
710}
711
712
713int
714svr4_sys_sysconfig(td, uap)
715	struct thread *td;
716	struct svr4_sys_sysconfig_args *uap;
717{
718	int *retval;
719
720	retval = &(td->td_retval[0]);
721
722	switch (uap->name) {
723	case SVR4_CONFIG_NGROUPS:
724		*retval = ngroups_max;
725		break;
726	case SVR4_CONFIG_CHILD_MAX:
727		*retval = maxproc;
728		break;
729	case SVR4_CONFIG_OPEN_FILES:
730		*retval = maxfiles;
731		break;
732	case SVR4_CONFIG_POSIX_VER:
733		*retval = 198808;
734		break;
735	case SVR4_CONFIG_PAGESIZE:
736		*retval = PAGE_SIZE;
737		break;
738	case SVR4_CONFIG_CLK_TCK:
739		*retval = 60;	/* should this be `hz', ie. 100? */
740		break;
741	case SVR4_CONFIG_XOPEN_VER:
742		*retval = 2;	/* XXX: What should that be? */
743		break;
744	case SVR4_CONFIG_PROF_TCK:
745		*retval = 60;	/* XXX: What should that be? */
746		break;
747	case SVR4_CONFIG_NPROC_CONF:
748		*retval = 1;	/* Only one processor for now */
749		break;
750	case SVR4_CONFIG_NPROC_ONLN:
751		*retval = 1;	/* And it better be online */
752		break;
753	case SVR4_CONFIG_AIO_LISTIO_MAX:
754	case SVR4_CONFIG_AIO_MAX:
755	case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
756		*retval = 0;	/* No aio support */
757		break;
758	case SVR4_CONFIG_DELAYTIMER_MAX:
759		*retval = 0;	/* No delaytimer support */
760		break;
761	case SVR4_CONFIG_MQ_OPEN_MAX:
762		*retval = msginfo.msgmni;
763		break;
764	case SVR4_CONFIG_MQ_PRIO_MAX:
765		*retval = 0;	/* XXX: Don't know */
766		break;
767	case SVR4_CONFIG_RTSIG_MAX:
768		*retval = 0;
769		break;
770	case SVR4_CONFIG_SEM_NSEMS_MAX:
771		*retval = seminfo.semmni;
772		break;
773	case SVR4_CONFIG_SEM_VALUE_MAX:
774		*retval = seminfo.semvmx;
775		break;
776	case SVR4_CONFIG_SIGQUEUE_MAX:
777		*retval = 0;	/* XXX: Don't know */
778		break;
779	case SVR4_CONFIG_SIGRT_MIN:
780	case SVR4_CONFIG_SIGRT_MAX:
781		*retval = 0;	/* No real time signals */
782		break;
783	case SVR4_CONFIG_TIMER_MAX:
784		*retval = 3;	/* XXX: real, virtual, profiling */
785		break;
786#if defined(NOTYET)
787	case SVR4_CONFIG_PHYS_PAGES:
788#if defined(UVM)
789		*retval = uvmexp.free;	/* XXX: free instead of total */
790#else
791		*retval = vm_cnt.v_free_count;	/* XXX: free instead of total */
792#endif
793		break;
794	case SVR4_CONFIG_AVPHYS_PAGES:
795#if defined(UVM)
796		*retval = uvmexp.active;	/* XXX: active instead of avg */
797#else
798		*retval = vm_cnt.v_active_count;/* XXX: active instead of avg */
799#endif
800		break;
801#endif /* NOTYET */
802	case SVR4_CONFIG_COHERENCY:
803		*retval = 0;	/* XXX */
804		break;
805	case SVR4_CONFIG_SPLIT_CACHE:
806		*retval = 0;	/* XXX */
807		break;
808	case SVR4_CONFIG_ICACHESZ:
809		*retval = 256;	/* XXX */
810		break;
811	case SVR4_CONFIG_DCACHESZ:
812		*retval = 256;	/* XXX */
813		break;
814	case SVR4_CONFIG_ICACHELINESZ:
815		*retval = 64;	/* XXX */
816		break;
817	case SVR4_CONFIG_DCACHELINESZ:
818		*retval = 64;	/* XXX */
819		break;
820	case SVR4_CONFIG_ICACHEBLKSZ:
821		*retval = 64;	/* XXX */
822		break;
823	case SVR4_CONFIG_DCACHEBLKSZ:
824		*retval = 64;	/* XXX */
825		break;
826	case SVR4_CONFIG_DCACHETBLKSZ:
827		*retval = 64;	/* XXX */
828		break;
829	case SVR4_CONFIG_ICACHE_ASSOC:
830		*retval = 1;	/* XXX */
831		break;
832	case SVR4_CONFIG_DCACHE_ASSOC:
833		*retval = 1;	/* XXX */
834		break;
835	case SVR4_CONFIG_MAXPID:
836		*retval = PID_MAX;
837		break;
838	case SVR4_CONFIG_STACK_PROT:
839		*retval = PROT_READ|PROT_WRITE|PROT_EXEC;
840		break;
841	default:
842		return EINVAL;
843	}
844	return 0;
845}
846
847/* ARGSUSED */
848int
849svr4_sys_break(td, uap)
850	struct thread *td;
851	struct svr4_sys_break_args *uap;
852{
853	struct obreak_args ap;
854
855	ap.nsize = uap->nsize;
856	return (sys_obreak(td, &ap));
857}
858
859static __inline clock_t
860timeval_to_clock_t(tv)
861	struct timeval *tv;
862{
863	return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
864}
865
866
867int
868svr4_sys_times(td, uap)
869	struct thread *td;
870	struct svr4_sys_times_args *uap;
871{
872	struct timeval tv, utime, stime, cutime, cstime;
873	struct tms tms;
874	struct proc *p;
875	int error;
876
877	p = td->td_proc;
878	PROC_LOCK(p);
879	PROC_STATLOCK(p);
880	calcru(p, &utime, &stime);
881	PROC_STATUNLOCK(p);
882	calccru(p, &cutime, &cstime);
883	PROC_UNLOCK(p);
884
885	tms.tms_utime = timeval_to_clock_t(&utime);
886	tms.tms_stime = timeval_to_clock_t(&stime);
887
888	tms.tms_cutime = timeval_to_clock_t(&cutime);
889	tms.tms_cstime = timeval_to_clock_t(&cstime);
890
891	error = copyout(&tms, uap->tp, sizeof(tms));
892	if (error)
893		return (error);
894
895	microtime(&tv);
896	td->td_retval[0] = (int)timeval_to_clock_t(&tv);
897	return (0);
898}
899
900
901int
902svr4_sys_ulimit(td, uap)
903	struct thread *td;
904	struct svr4_sys_ulimit_args *uap;
905{
906        int *retval = td->td_retval;
907	int error;
908
909	switch (uap->cmd) {
910	case SVR4_GFILLIM:
911		*retval = lim_cur(td, RLIMIT_FSIZE) / 512;
912		if (*retval == -1)
913			*retval = 0x7fffffff;
914		return 0;
915
916	case SVR4_SFILLIM:
917		{
918			struct rlimit krl;
919
920			krl.rlim_cur = uap->newlimit * 512;
921			krl.rlim_max = lim_max(td, RLIMIT_FSIZE);
922
923			error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
924			if (error)
925				return error;
926
927			*retval = lim_cur(td, RLIMIT_FSIZE);
928			if (*retval == -1)
929				*retval = 0x7fffffff;
930			return 0;
931		}
932
933	case SVR4_GMEMLIM:
934		{
935			struct vmspace *vm = td->td_proc->p_vmspace;
936			register_t r;
937
938			r = lim_cur(td, RLIMIT_DATA);
939
940			if (r == -1)
941				r = 0x7fffffff;
942			r += (long) vm->vm_daddr;
943			if (r < 0)
944				r = 0x7fffffff;
945			*retval = r;
946			return 0;
947		}
948
949	case SVR4_GDESLIM:
950		*retval = lim_cur(td, RLIMIT_NOFILE);
951		if (*retval == -1)
952			*retval = 0x7fffffff;
953		return 0;
954
955	default:
956		return EINVAL;
957	}
958}
959
960static struct proc *
961svr4_pfind(pid)
962	pid_t pid;
963{
964	struct proc *p;
965
966	/* look in the live processes */
967	if ((p = pfind(pid)) == NULL)
968		/* look in the zombies */
969		p = zpfind(pid);
970
971	return p;
972}
973
974
975int
976svr4_sys_pgrpsys(td, uap)
977	struct thread *td;
978	struct svr4_sys_pgrpsys_args *uap;
979{
980        int *retval = td->td_retval;
981	struct proc *p = td->td_proc;
982
983	switch (uap->cmd) {
984	case 1:			/* setpgrp() */
985		/*
986		 * SVR4 setpgrp() (which takes no arguments) has the
987		 * semantics that the session ID is also created anew, so
988		 * in almost every sense, setpgrp() is identical to
989		 * setsid() for SVR4.  (Under BSD, the difference is that
990		 * a setpgid(0,0) will not create a new session.)
991		 */
992		sys_setsid(td, NULL);
993		/*FALLTHROUGH*/
994
995	case 0:			/* getpgrp() */
996		PROC_LOCK(p);
997		*retval = p->p_pgrp->pg_id;
998		PROC_UNLOCK(p);
999		return 0;
1000
1001	case 2:			/* getsid(pid) */
1002		if (uap->pid == 0)
1003			PROC_LOCK(p);
1004		else if ((p = svr4_pfind(uap->pid)) == NULL)
1005			return ESRCH;
1006		/*
1007		 * This has already been initialized to the pid of
1008		 * the session leader.
1009		 */
1010		*retval = (register_t) p->p_session->s_sid;
1011		PROC_UNLOCK(p);
1012		return 0;
1013
1014	case 3:			/* setsid() */
1015		return sys_setsid(td, NULL);
1016
1017	case 4:			/* getpgid(pid) */
1018
1019		if (uap->pid == 0)
1020			PROC_LOCK(p);
1021		else if ((p = svr4_pfind(uap->pid)) == NULL)
1022			return ESRCH;
1023
1024		*retval = (int) p->p_pgrp->pg_id;
1025		PROC_UNLOCK(p);
1026		return 0;
1027
1028	case 5:			/* setpgid(pid, pgid); */
1029		{
1030			struct setpgid_args sa;
1031
1032			sa.pid = uap->pid;
1033			sa.pgid = uap->pgid;
1034			return sys_setpgid(td, &sa);
1035		}
1036
1037	default:
1038		return EINVAL;
1039	}
1040}
1041
1042struct svr4_hrtcntl_args {
1043	int 			cmd;
1044	int 			fun;
1045	int 			clk;
1046	svr4_hrt_interval_t *	iv;
1047	svr4_hrt_time_t *	ti;
1048};
1049
1050
1051static int
1052svr4_hrtcntl(td, uap, retval)
1053	struct thread *td;
1054	struct svr4_hrtcntl_args *uap;
1055	register_t *retval;
1056{
1057	switch (uap->fun) {
1058	case SVR4_HRT_CNTL_RES:
1059		DPRINTF(("htrcntl(RES)\n"));
1060		*retval = SVR4_HRT_USEC;
1061		return 0;
1062
1063	case SVR4_HRT_CNTL_TOFD:
1064		DPRINTF(("htrcntl(TOFD)\n"));
1065		{
1066			struct timeval tv;
1067			svr4_hrt_time_t t;
1068			if (uap->clk != SVR4_HRT_CLK_STD) {
1069				DPRINTF(("clk == %d\n", uap->clk));
1070				return EINVAL;
1071			}
1072			if (uap->ti == NULL) {
1073				DPRINTF(("ti NULL\n"));
1074				return EINVAL;
1075			}
1076			microtime(&tv);
1077			t.h_sec = tv.tv_sec;
1078			t.h_rem = tv.tv_usec;
1079			t.h_res = SVR4_HRT_USEC;
1080			return copyout(&t, uap->ti, sizeof(t));
1081		}
1082
1083	case SVR4_HRT_CNTL_START:
1084		DPRINTF(("htrcntl(START)\n"));
1085		return ENOSYS;
1086
1087	case SVR4_HRT_CNTL_GET:
1088		DPRINTF(("htrcntl(GET)\n"));
1089		return ENOSYS;
1090	default:
1091		DPRINTF(("Bad htrcntl command %d\n", uap->fun));
1092		return ENOSYS;
1093	}
1094}
1095
1096
1097int
1098svr4_sys_hrtsys(td, uap)
1099	struct thread *td;
1100	struct svr4_sys_hrtsys_args *uap;
1101{
1102        int *retval = td->td_retval;
1103
1104	switch (uap->cmd) {
1105	case SVR4_HRT_CNTL:
1106		return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
1107				    retval);
1108
1109	case SVR4_HRT_ALRM:
1110		DPRINTF(("hrtalarm\n"));
1111		return ENOSYS;
1112
1113	case SVR4_HRT_SLP:
1114		DPRINTF(("hrtsleep\n"));
1115		return ENOSYS;
1116
1117	case SVR4_HRT_CAN:
1118		DPRINTF(("hrtcancel\n"));
1119		return ENOSYS;
1120
1121	default:
1122		DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
1123		return EINVAL;
1124	}
1125}
1126
1127
1128static int
1129svr4_setinfo(pid, ru, st, s)
1130	pid_t pid;
1131	struct rusage *ru;
1132	int st;
1133	svr4_siginfo_t *s;
1134{
1135	svr4_siginfo_t i;
1136	int sig;
1137
1138	memset(&i, 0, sizeof(i));
1139
1140	i.svr4_si_signo = SVR4_SIGCHLD;
1141	i.svr4_si_errno = 0;	/* XXX? */
1142
1143	i.svr4_si_pid = pid;
1144	if (ru) {
1145		i.svr4_si_stime = ru->ru_stime.tv_sec;
1146		i.svr4_si_utime = ru->ru_utime.tv_sec;
1147	}
1148
1149	if (WIFEXITED(st)) {
1150		i.svr4_si_status = WEXITSTATUS(st);
1151		i.svr4_si_code = SVR4_CLD_EXITED;
1152	} else if (WIFSTOPPED(st)) {
1153		sig = WSTOPSIG(st);
1154		if (sig >= 0 && sig < NSIG)
1155			i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1156
1157		if (i.svr4_si_status == SVR4_SIGCONT)
1158			i.svr4_si_code = SVR4_CLD_CONTINUED;
1159		else
1160			i.svr4_si_code = SVR4_CLD_STOPPED;
1161	} else {
1162		sig = WTERMSIG(st);
1163		if (sig >= 0 && sig < NSIG)
1164			i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1165
1166		if (WCOREDUMP(st))
1167			i.svr4_si_code = SVR4_CLD_DUMPED;
1168		else
1169			i.svr4_si_code = SVR4_CLD_KILLED;
1170	}
1171
1172	DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1173		 i.svr4_si_pid, i.svr4_si_signo, i.svr4_si_code, i.svr4_si_errno,
1174		 i.svr4_si_status));
1175
1176	return copyout(&i, s, sizeof(i));
1177}
1178
1179
1180int
1181svr4_sys_waitsys(td, uap)
1182	struct thread *td;
1183	struct svr4_sys_waitsys_args *uap;
1184{
1185	struct rusage ru;
1186	pid_t pid;
1187	int nfound, status;
1188	int error, *retval = td->td_retval;
1189	struct proc *p, *q;
1190
1191	DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1192	         uap->grp, uap->id,
1193		 uap->info, uap->options));
1194
1195	q = td->td_proc;
1196	switch (uap->grp) {
1197	case SVR4_P_PID:
1198		pid = uap->id;
1199		break;
1200
1201	case SVR4_P_PGID:
1202		PROC_LOCK(q);
1203		pid = -q->p_pgid;
1204		PROC_UNLOCK(q);
1205		break;
1206
1207	case SVR4_P_ALL:
1208		pid = WAIT_ANY;
1209		break;
1210
1211	default:
1212		return EINVAL;
1213	}
1214
1215	/* Hand off the easy cases to kern_wait(). */
1216	if (!(uap->options & (SVR4_WNOWAIT)) &&
1217	    (uap->options & (SVR4_WEXITED | SVR4_WTRAPPED))) {
1218		int options;
1219
1220		options = 0;
1221		if (uap->options & SVR4_WSTOPPED)
1222			options |= WUNTRACED;
1223		if (uap->options & SVR4_WCONTINUED)
1224			options |= WCONTINUED;
1225		if (uap->options & SVR4_WNOHANG)
1226			options |= WNOHANG;
1227
1228		error = kern_wait(td, pid, &status, options, &ru);
1229		if (error)
1230			return (error);
1231		if (uap->options & SVR4_WNOHANG && *retval == 0)
1232			error = svr4_setinfo(*retval, NULL, 0, uap->info);
1233		else
1234			error = svr4_setinfo(*retval, &ru, status, uap->info);
1235		*retval = 0;
1236		return (error);
1237	}
1238
1239	/*
1240	 * Ok, handle the weird cases.  Either WNOWAIT is set (meaning we
1241	 * just want to see if there is a process to harvest, we don't
1242	 * want to actually harvest it), or WEXIT and WTRAPPED are clear
1243	 * meaning we want to ignore zombies.  Either way, we don't have
1244	 * to handle harvesting zombies here.  We do have to duplicate the
1245	 * other portions of kern_wait() though, especially for WCONTINUED
1246	 * and WSTOPPED.
1247	 */
1248loop:
1249	nfound = 0;
1250	sx_slock(&proctree_lock);
1251	LIST_FOREACH(p, &q->p_children, p_sibling) {
1252		PROC_LOCK(p);
1253		if (pid != WAIT_ANY &&
1254		    p->p_pid != pid && p->p_pgid != -pid) {
1255			PROC_UNLOCK(p);
1256			DPRINTF(("pid %d pgid %d != %d\n", p->p_pid,
1257				 p->p_pgid, pid));
1258			continue;
1259		}
1260		if (p_canwait(td, p)) {
1261			PROC_UNLOCK(p);
1262			continue;
1263		}
1264
1265		nfound++;
1266
1267		PROC_SLOCK(p);
1268		/*
1269		 * See if we have a zombie.  If so, WNOWAIT should be set,
1270		 * as otherwise we should have called kern_wait() up above.
1271		 */
1272		if ((p->p_state == PRS_ZOMBIE) &&
1273		    ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
1274			PROC_SUNLOCK(p);
1275			KASSERT(uap->options & SVR4_WNOWAIT,
1276			    ("WNOWAIT is clear"));
1277
1278			/* Found a zombie, so cache info in local variables. */
1279			pid = p->p_pid;
1280			status = KW_EXITCODE(p->p_xexit, p->p_xsig);
1281			ru = p->p_ru;
1282			PROC_STATLOCK(p);
1283			calcru(p, &ru.ru_utime, &ru.ru_stime);
1284			PROC_STATUNLOCK(p);
1285			PROC_UNLOCK(p);
1286			sx_sunlock(&proctree_lock);
1287
1288			/* Copy the info out to userland. */
1289			*retval = 0;
1290			DPRINTF(("found %d\n", pid));
1291			return (svr4_setinfo(pid, &ru, status, uap->info));
1292		}
1293
1294		/*
1295		 * See if we have a stopped or continued process.
1296		 * XXX: This duplicates the same code in kern_wait().
1297		 */
1298		if ((p->p_flag & P_STOPPED_SIG) &&
1299		    (p->p_suspcount == p->p_numthreads) &&
1300		    (p->p_flag & P_WAITED) == 0 &&
1301		    (p->p_flag & P_TRACED || uap->options & SVR4_WSTOPPED)) {
1302			PROC_SUNLOCK(p);
1303		        if (((uap->options & SVR4_WNOWAIT)) == 0)
1304				p->p_flag |= P_WAITED;
1305			sx_sunlock(&proctree_lock);
1306			pid = p->p_pid;
1307			status = W_STOPCODE(p->p_xsig);
1308			ru = p->p_ru;
1309			PROC_STATLOCK(p);
1310			calcru(p, &ru.ru_utime, &ru.ru_stime);
1311			PROC_STATUNLOCK(p);
1312			PROC_UNLOCK(p);
1313
1314		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
1315				PROC_LOCK(q);
1316				sigqueue_take(p->p_ksi);
1317				PROC_UNLOCK(q);
1318			}
1319
1320			*retval = 0;
1321			DPRINTF(("jobcontrol %d\n", pid));
1322			return (svr4_setinfo(pid, &ru, status, uap->info));
1323		}
1324		PROC_SUNLOCK(p);
1325		if (uap->options & SVR4_WCONTINUED &&
1326		    (p->p_flag & P_CONTINUED)) {
1327			sx_sunlock(&proctree_lock);
1328		        if (((uap->options & SVR4_WNOWAIT)) == 0)
1329				p->p_flag &= ~P_CONTINUED;
1330			pid = p->p_pid;
1331			ru = p->p_ru;
1332			status = SIGCONT;
1333			PROC_STATLOCK(p);
1334			calcru(p, &ru.ru_utime, &ru.ru_stime);
1335			PROC_STATUNLOCK(p);
1336			PROC_UNLOCK(p);
1337
1338		        if (((uap->options & SVR4_WNOWAIT)) == 0) {
1339				PROC_LOCK(q);
1340				sigqueue_take(p->p_ksi);
1341				PROC_UNLOCK(q);
1342			}
1343
1344			*retval = 0;
1345			DPRINTF(("jobcontrol %d\n", pid));
1346			return (svr4_setinfo(pid, &ru, status, uap->info));
1347		}
1348		PROC_UNLOCK(p);
1349	}
1350
1351	if (nfound == 0) {
1352		sx_sunlock(&proctree_lock);
1353		return (ECHILD);
1354	}
1355
1356	if (uap->options & SVR4_WNOHANG) {
1357		sx_sunlock(&proctree_lock);
1358		*retval = 0;
1359		return (svr4_setinfo(0, NULL, 0, uap->info));
1360	}
1361
1362	PROC_LOCK(q);
1363	sx_sunlock(&proctree_lock);
1364	if (q->p_flag & P_STATCHILD) {
1365		q->p_flag &= ~P_STATCHILD;
1366		error = 0;
1367	} else
1368		error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "svr4_wait", 0);
1369	PROC_UNLOCK(q);
1370	if (error)
1371		return error;
1372	goto loop;
1373}
1374
1375
1376static void
1377bsd_statfs_to_svr4_statvfs(bfs, sfs)
1378	const struct statfs *bfs;
1379	struct svr4_statvfs *sfs;
1380{
1381	sfs->f_bsize = bfs->f_iosize; /* XXX */
1382	sfs->f_frsize = bfs->f_bsize;
1383	sfs->f_blocks = bfs->f_blocks;
1384	sfs->f_bfree = bfs->f_bfree;
1385	sfs->f_bavail = bfs->f_bavail;
1386	sfs->f_files = bfs->f_files;
1387	sfs->f_ffree = bfs->f_ffree;
1388	sfs->f_favail = bfs->f_ffree;
1389	sfs->f_fsid = bfs->f_fsid.val[0];
1390	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1391	sfs->f_flag = 0;
1392	if (bfs->f_flags & MNT_RDONLY)
1393		sfs->f_flag |= SVR4_ST_RDONLY;
1394	if (bfs->f_flags & MNT_NOSUID)
1395		sfs->f_flag |= SVR4_ST_NOSUID;
1396	sfs->f_namemax = MAXNAMLEN;
1397	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1398	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1399}
1400
1401
1402static void
1403bsd_statfs_to_svr4_statvfs64(bfs, sfs)
1404	const struct statfs *bfs;
1405	struct svr4_statvfs64 *sfs;
1406{
1407	sfs->f_bsize = bfs->f_iosize; /* XXX */
1408	sfs->f_frsize = bfs->f_bsize;
1409	sfs->f_blocks = bfs->f_blocks;
1410	sfs->f_bfree = bfs->f_bfree;
1411	sfs->f_bavail = bfs->f_bavail;
1412	sfs->f_files = bfs->f_files;
1413	sfs->f_ffree = bfs->f_ffree;
1414	sfs->f_favail = bfs->f_ffree;
1415	sfs->f_fsid = bfs->f_fsid.val[0];
1416	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1417	sfs->f_flag = 0;
1418	if (bfs->f_flags & MNT_RDONLY)
1419		sfs->f_flag |= SVR4_ST_RDONLY;
1420	if (bfs->f_flags & MNT_NOSUID)
1421		sfs->f_flag |= SVR4_ST_NOSUID;
1422	sfs->f_namemax = MAXNAMLEN;
1423	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1424	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1425}
1426
1427
1428int
1429svr4_sys_statvfs(td, uap)
1430	struct thread *td;
1431	struct svr4_sys_statvfs_args *uap;
1432{
1433	struct svr4_statvfs sfs;
1434	struct statfs *bfs;
1435	char *path;
1436	int error;
1437
1438	CHECKALTEXIST(td, uap->path, &path);
1439
1440	bfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
1441	error = kern_statfs(td, path, UIO_SYSSPACE, bfs);
1442	free(path, M_TEMP);
1443	if (error == 0)
1444		bsd_statfs_to_svr4_statvfs(bfs, &sfs);
1445	free(bfs, M_STATFS);
1446	if (error != 0)
1447		return (error);
1448	return copyout(&sfs, uap->fs, sizeof(sfs));
1449}
1450
1451
1452int
1453svr4_sys_fstatvfs(td, uap)
1454	struct thread *td;
1455	struct svr4_sys_fstatvfs_args *uap;
1456{
1457	struct svr4_statvfs sfs;
1458	struct statfs *bfs;
1459	int error;
1460
1461	bfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
1462	error = kern_fstatfs(td, uap->fd, bfs);
1463	if (error == 0)
1464		bsd_statfs_to_svr4_statvfs(bfs, &sfs);
1465	free(bfs, M_STATFS);
1466	if (error != 0)
1467		return (error);
1468	return copyout(&sfs, uap->fs, sizeof(sfs));
1469}
1470
1471
1472int
1473svr4_sys_statvfs64(td, uap)
1474	struct thread *td;
1475	struct svr4_sys_statvfs64_args *uap;
1476{
1477	struct svr4_statvfs64 sfs;
1478	struct statfs *bfs;
1479	char *path;
1480	int error;
1481
1482	CHECKALTEXIST(td, uap->path, &path);
1483
1484	bfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
1485	error = kern_statfs(td, path, UIO_SYSSPACE, bfs);
1486	free(path, M_TEMP);
1487	if (error == 0)
1488		bsd_statfs_to_svr4_statvfs64(bfs, &sfs);
1489	free(bfs, M_STATFS);
1490	if (error != 0)
1491		return (error);
1492	return copyout(&sfs, uap->fs, sizeof(sfs));
1493}
1494
1495
1496int
1497svr4_sys_fstatvfs64(td, uap)
1498	struct thread *td;
1499	struct svr4_sys_fstatvfs64_args *uap;
1500{
1501	struct svr4_statvfs64 sfs;
1502	struct statfs *bfs;
1503	int error;
1504
1505	bfs = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
1506	error = kern_fstatfs(td, uap->fd, bfs);
1507	if (error == 0)
1508		bsd_statfs_to_svr4_statvfs64(bfs, &sfs);
1509	free(bfs, M_STATFS);
1510	if (error != 0)
1511		return (error);
1512	return copyout(&sfs, uap->fs, sizeof(sfs));
1513}
1514
1515int
1516svr4_sys_alarm(td, uap)
1517	struct thread *td;
1518	struct svr4_sys_alarm_args *uap;
1519{
1520        struct itimerval itv, oitv;
1521	int error;
1522
1523	timevalclear(&itv.it_interval);
1524	itv.it_value.tv_sec = uap->sec;
1525	itv.it_value.tv_usec = 0;
1526	error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
1527	if (error)
1528		return (error);
1529	if (oitv.it_value.tv_usec != 0)
1530		oitv.it_value.tv_sec++;
1531	td->td_retval[0] = oitv.it_value.tv_sec;
1532	return (0);
1533}
1534
1535int
1536svr4_sys_gettimeofday(td, uap)
1537	struct thread *td;
1538	struct svr4_sys_gettimeofday_args *uap;
1539{
1540	if (uap->tp) {
1541		struct timeval atv;
1542
1543		microtime(&atv);
1544		return copyout(&atv, uap->tp, sizeof (atv));
1545	}
1546
1547	return 0;
1548}
1549
1550int
1551svr4_sys_facl(td, uap)
1552	struct thread *td;
1553	struct svr4_sys_facl_args *uap;
1554{
1555	int *retval;
1556
1557	retval = td->td_retval;
1558	*retval = 0;
1559
1560	switch (uap->cmd) {
1561	case SVR4_SYS_SETACL:
1562		/* We don't support acls on any filesystem */
1563		return ENOSYS;
1564
1565	case SVR4_SYS_GETACL:
1566		return copyout(retval, &uap->num,
1567		    sizeof(uap->num));
1568
1569	case SVR4_SYS_GETACLCNT:
1570		return 0;
1571
1572	default:
1573		return EINVAL;
1574	}
1575}
1576
1577
1578int
1579svr4_sys_acl(td, uap)
1580	struct thread *td;
1581	struct svr4_sys_acl_args *uap;
1582{
1583	/* XXX: for now the same */
1584	return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
1585}
1586
1587int
1588svr4_sys_auditsys(td, uap)
1589	struct thread *td;
1590	struct svr4_sys_auditsys_args *uap;
1591{
1592	/*
1593	 * XXX: Big brother is *not* watching.
1594	 */
1595	return 0;
1596}
1597
1598int
1599svr4_sys_memcntl(td, uap)
1600	struct thread *td;
1601	struct svr4_sys_memcntl_args *uap;
1602{
1603	switch (uap->cmd) {
1604	case SVR4_MC_SYNC:
1605		{
1606			struct msync_args msa;
1607
1608			msa.addr = uap->addr;
1609			msa.len = uap->len;
1610			msa.flags = (int)uap->arg;
1611
1612			return sys_msync(td, &msa);
1613		}
1614	case SVR4_MC_ADVISE:
1615		{
1616			struct madvise_args maa;
1617
1618			maa.addr = uap->addr;
1619			maa.len = uap->len;
1620			maa.behav = (int)uap->arg;
1621
1622			return sys_madvise(td, &maa);
1623		}
1624	case SVR4_MC_LOCK:
1625	case SVR4_MC_UNLOCK:
1626	case SVR4_MC_LOCKAS:
1627	case SVR4_MC_UNLOCKAS:
1628		return EOPNOTSUPP;
1629	default:
1630		return ENOSYS;
1631	}
1632}
1633
1634
1635int
1636svr4_sys_nice(td, uap)
1637	struct thread *td;
1638	struct svr4_sys_nice_args *uap;
1639{
1640	struct setpriority_args ap;
1641	int error;
1642
1643	ap.which = PRIO_PROCESS;
1644	ap.who = 0;
1645	ap.prio = uap->prio;
1646
1647	if ((error = sys_setpriority(td, &ap)) != 0)
1648		return error;
1649
1650	/* the cast is stupid, but the structures are the same */
1651	if ((error = sys_getpriority(td, (struct getpriority_args *)&ap)) != 0)
1652		return error;
1653
1654	return 0;
1655}
1656
1657int
1658svr4_sys_resolvepath(td, uap)
1659	struct thread *td;
1660	struct svr4_sys_resolvepath_args *uap;
1661{
1662	struct nameidata nd;
1663	int error, *retval = td->td_retval;
1664	unsigned int ncopy;
1665
1666	NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE,
1667	    uap->path, td);
1668
1669	if ((error = namei(&nd)) != 0)
1670		return (error);
1671	NDFREE(&nd, NDF_NO_FREE_PNBUF);
1672
1673	ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
1674	if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
1675		goto bad;
1676
1677	*retval = ncopy;
1678bad:
1679	NDFREE(&nd, NDF_ONLY_PNBUF);
1680	return error;
1681}
1682