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