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