1139799Simp/*-
211734Sswallace * Copyright (c) 1995 Steven Wallace
311397Sswallace * Copyright (c) 1994, 1995 Scott Bartram
411397Sswallace * Copyright (c) 1992, 1993
511397Sswallace *	The Regents of the University of California.  All rights reserved.
63584Ssos *
711397Sswallace * This software was developed by the Computer Systems Engineering group
811397Sswallace * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
911397Sswallace * contributed to Berkeley.
103584Ssos *
1111397Sswallace * All advertising materials mentioning features or use of this software
1211397Sswallace * must display the following acknowledgement:
1311397Sswallace *	This product includes software developed by the University of
1411397Sswallace *	California, Lawrence Berkeley Laboratory.
1511397Sswallace *
163584Ssos * Redistribution and use in source and binary forms, with or without
173584Ssos * modification, are permitted provided that the following conditions
183584Ssos * are met:
193584Ssos * 1. Redistributions of source code must retain the above copyright
2011397Sswallace *    notice, this list of conditions and the following disclaimer.
213584Ssos * 2. Redistributions in binary form must reproduce the above copyright
223584Ssos *    notice, this list of conditions and the following disclaimer in the
233584Ssos *    documentation and/or other materials provided with the distribution.
243584Ssos * 3. All advertising materials mentioning features or use of this software
253584Ssos *    must display the following acknowledgement:
263584Ssos *	This product includes software developed by the University of
273584Ssos *	California, Berkeley and its contributors.
283584Ssos * 4. Neither the name of the University nor the names of its contributors
293584Ssos *    may be used to endorse or promote products derived from this software
303584Ssos *    without specific prior written permission.
313584Ssos *
323584Ssos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
333584Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
343584Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
353584Ssos * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
363584Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
373584Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
383584Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
393584Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
403584Ssos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
413584Ssos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
423584Ssos * SUCH DAMAGE.
433584Ssos *
4411397Sswallace * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
4511397Sswallace *
4611397Sswallace *	@(#)sun_misc.c	8.1 (Berkeley) 6/18/93
473584Ssos */
483584Ssos
49115684Sobrien#include <sys/cdefs.h>
50115684Sobrien__FBSDID("$FreeBSD$");
51115684Sobrien
5211397Sswallace/*
5311397Sswallace * IBCS2 compatibility module.
5411397Sswallace *
5511397Sswallace * IBCS2 system calls that are implemented differently in BSD are
5611397Sswallace * handled here.
5711397Sswallace */
583584Ssos#include <sys/param.h>
5976166Smarkm#include <sys/systm.h>
60224778Srwatson#include <sys/capability.h>
6138404Sbde#include <sys/dirent.h>
6224131Sbde#include <sys/fcntl.h>
6311397Sswallace#include <sys/filedesc.h>
64141488Sjhb#include <sys/imgact.h>
6511397Sswallace#include <sys/kernel.h>
6631561Sbde#include <sys/lock.h>
6711397Sswallace#include <sys/malloc.h>
6876166Smarkm#include <sys/file.h>			/* Must come after sys/malloc.h */
6976166Smarkm#include <sys/mutex.h>
70195458Strasz#include <sys/namei.h>
71164033Srwatson#include <sys/priv.h>
7211397Sswallace#include <sys/reboot.h>
733584Ssos#include <sys/resourcevar.h>
743584Ssos#include <sys/stat.h>
7538404Sbde#include <sys/sysctl.h>
76139739Sjhb#include <sys/syscallsubr.h>
7738404Sbde#include <sys/sysproto.h>
783584Ssos#include <sys/time.h>
793584Ssos#include <sys/times.h>
8011397Sswallace#include <sys/vnode.h>
8111397Sswallace#include <sys/wait.h>
8211397Sswallace
833584Ssos#include <machine/cpu.h>
843584Ssos
8511397Sswallace#include <i386/ibcs2/ibcs2_dirent.h>
8611397Sswallace#include <i386/ibcs2/ibcs2_signal.h>
8738404Sbde#include <i386/ibcs2/ibcs2_proto.h>
8811397Sswallace#include <i386/ibcs2/ibcs2_unistd.h>
8911397Sswallace#include <i386/ibcs2/ibcs2_util.h>
9011397Sswallace#include <i386/ibcs2/ibcs2_utime.h>
9111397Sswallace#include <i386/ibcs2/ibcs2_xenix.h>
923584Ssos
93163606Srwatson#include <security/mac/mac_framework.h>
94163606Srwatson
953584Ssosint
9683366Sjulianibcs2_ulimit(td, uap)
9783366Sjulian	struct thread *td;
9811397Sswallace	struct ibcs2_ulimit_args *uap;
993584Ssos{
100125454Sjhb	struct rlimit rl;
101125454Sjhb	struct proc *p;
10211397Sswallace	int error;
10311397Sswallace#define IBCS2_GETFSIZE		1
10411397Sswallace#define IBCS2_SETFSIZE		2
10511397Sswallace#define IBCS2_GETPSIZE		3
10611397Sswallace#define IBCS2_GETDTABLESIZE	4
107125454Sjhb
108125454Sjhb	p = td->td_proc;
109107849Salfred	switch (uap->cmd) {
11011397Sswallace	case IBCS2_GETFSIZE:
111125454Sjhb		PROC_LOCK(p);
112125454Sjhb		td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE);
113125454Sjhb		PROC_UNLOCK(p);
114125454Sjhb		if (td->td_retval[0] == -1)
115125454Sjhb			td->td_retval[0] = 0x7fffffff;
11611397Sswallace		return 0;
117125454Sjhb	case IBCS2_SETFSIZE:
118125454Sjhb		PROC_LOCK(p);
119125454Sjhb		rl.rlim_max = lim_max(p, RLIMIT_FSIZE);
120125454Sjhb		PROC_UNLOCK(p);
121107849Salfred		rl.rlim_cur = uap->newlimit;
122125454Sjhb		error = kern_setrlimit(td, RLIMIT_FSIZE, &rl);
123125454Sjhb		if (!error) {
124125454Sjhb			PROC_LOCK(p);
125125454Sjhb			td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE);
126125454Sjhb			PROC_UNLOCK(p);
127125454Sjhb		} else {
12811397Sswallace			DPRINTF(("failed "));
129125454Sjhb		}
13011397Sswallace		return error;
13111397Sswallace	case IBCS2_GETPSIZE:
132125454Sjhb		PROC_LOCK(p);
133125454Sjhb		td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */
134125454Sjhb		PROC_UNLOCK(p);
13511397Sswallace		return 0;
13611397Sswallace	case IBCS2_GETDTABLESIZE:
13711397Sswallace		uap->cmd = IBCS2_SC_OPEN_MAX;
13883366Sjulian		return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap);
13911397Sswallace	default:
14011397Sswallace		return ENOSYS;
14111397Sswallace	}
1423584Ssos}
1433584Ssos
14411734Sswallace#define IBCS2_WSTOPPED       0177
14511734Sswallace#define IBCS2_STOPCODE(sig)  ((sig) << 8 | IBCS2_WSTOPPED)
1463584Ssosint
14783366Sjulianibcs2_wait(td, uap)
14883366Sjulian	struct thread *td;
14911397Sswallace	struct ibcs2_wait_args *uap;
1503584Ssos{
151127140Sjhb	int error, options, status;
152127140Sjhb	int *statusp;
153127140Sjhb	pid_t pid;
15483366Sjulian        struct trapframe *tf = td->td_frame;
15511397Sswallace
156127140Sjhb	if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
15711397Sswallace            == (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
15811397Sswallace		/* waitpid */
159127140Sjhb		pid = uap->a1;
160127140Sjhb		statusp = (int *)uap->a2;
161127140Sjhb		options = uap->a3;
16211397Sswallace	} else {
16311397Sswallace		/* wait */
164127140Sjhb		pid = WAIT_ANY;
165127140Sjhb		statusp = (int *)uap->a1;
166127140Sjhb		options = 0;
1673584Ssos	}
168127140Sjhb	error = kern_wait(td, pid, &status, options, NULL);
169127140Sjhb	if (error)
17011397Sswallace		return error;
171127140Sjhb	if (statusp) {
172121016Stjr		/*
173127140Sjhb		 * Convert status/signal result.
174121016Stjr		 */
175121016Stjr		if (WIFSTOPPED(status)) {
176121016Stjr			if (WSTOPSIG(status) <= 0 ||
177121016Stjr			    WSTOPSIG(status) > IBCS2_SIGTBLSZ)
178121016Stjr				return (EINVAL);
17911734Sswallace			status =
18051793Smarcel			  IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]);
181121016Stjr		} else if (WIFSIGNALED(status)) {
182121016Stjr			if (WTERMSIG(status) <= 0 ||
183121016Stjr			    WTERMSIG(status) > IBCS2_SIGTBLSZ)
184121016Stjr				return (EINVAL);
18551793Smarcel			status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))];
186121016Stjr		}
18711734Sswallace		/* else exit status -- identical */
18811734Sswallace
18911734Sswallace		/* record result/status */
19083366Sjulian		td->td_retval[1] = status;
191127140Sjhb		return copyout(&status, statusp, sizeof(status));
19211734Sswallace	}
19311734Sswallace
1943584Ssos	return 0;
1953584Ssos}
1963584Ssos
1973584Ssosint
19883366Sjulianibcs2_execv(td, uap)
19983366Sjulian	struct thread *td;
20011397Sswallace	struct ibcs2_execv_args *uap;
2013584Ssos{
202141488Sjhb	struct image_args eargs;
203141488Sjhb	char *path;
204141488Sjhb	int error;
2053584Ssos
206141488Sjhb        CHECKALTEXIST(td, uap->path, &path);
207141488Sjhb
208141488Sjhb	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
209141488Sjhb	free(path, M_TEMP);
210141488Sjhb	if (error == 0)
211141488Sjhb		error = kern_execve(td, &eargs, NULL);
212141488Sjhb	return (error);
2133584Ssos}
2143584Ssos
2153584Ssosint
21683366Sjulianibcs2_execve(td, uap)
21783366Sjulian        struct thread *td;
21811397Sswallace        struct ibcs2_execve_args *uap;
2193584Ssos{
220141488Sjhb	struct image_args eargs;
221141488Sjhb	char *path;
222141488Sjhb	int error;
223141488Sjhb
224141488Sjhb        CHECKALTEXIST(td, uap->path, &path);
225141488Sjhb
226141488Sjhb	error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
227141488Sjhb	    uap->envp);
228141488Sjhb	free(path, M_TEMP);
229141488Sjhb	if (error == 0)
230141488Sjhb		error = kern_execve(td, &eargs, NULL);
231141488Sjhb	return (error);
2323584Ssos}
2333584Ssos
2343584Ssosint
23583366Sjulianibcs2_umount(td, uap)
23683366Sjulian	struct thread *td;
23711397Sswallace	struct ibcs2_umount_args *uap;
2383584Ssos{
23911397Sswallace	struct unmount_args um;
2403584Ssos
241107849Salfred	um.path = uap->name;
242107849Salfred	um.flags = 0;
243225617Skmacy	return sys_unmount(td, &um);
2443584Ssos}
2453584Ssos
2463584Ssosint
24783366Sjulianibcs2_mount(td, uap)
24883366Sjulian	struct thread *td;
24911397Sswallace	struct ibcs2_mount_args *uap;
2503584Ssos{
25111397Sswallace#ifdef notyet
252107849Salfred	int oflags = uap->flags, nflags, error;
25311397Sswallace	char fsname[MFSNAMELEN];
2543584Ssos
25511397Sswallace	if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5))
25611397Sswallace		return (EINVAL);
25711397Sswallace	if ((oflags & IBCS2_MS_NEWTYPE) == 0)
25811397Sswallace		return (EINVAL);
25911397Sswallace	nflags = 0;
26011397Sswallace	if (oflags & IBCS2_MS_RDONLY)
26111397Sswallace		nflags |= MNT_RDONLY;
26211397Sswallace	if (oflags & IBCS2_MS_NOSUID)
26311397Sswallace		nflags |= MNT_NOSUID;
26411397Sswallace	if (oflags & IBCS2_MS_REMOUNT)
26511397Sswallace		nflags |= MNT_UPDATE;
266107849Salfred	uap->flags = nflags;
2673584Ssos
268107849Salfred	if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname,
26911397Sswallace			      (u_int *)0))
27011397Sswallace		return (error);
2713584Ssos
27211397Sswallace	if (strcmp(fsname, "4.2") == 0) {
273107849Salfred		uap->type = (caddr_t)STACK_ALLOC();
274107849Salfred		if (error = copyout("ufs", uap->type, sizeof("ufs")))
27511397Sswallace			return (error);
27611397Sswallace	} else if (strcmp(fsname, "nfs") == 0) {
27711397Sswallace		struct ibcs2_nfs_args sna;
27811397Sswallace		struct sockaddr_in sain;
27911397Sswallace		struct nfs_args na;
28011397Sswallace		struct sockaddr sa;
28111397Sswallace
282107849Salfred		if (error = copyin(uap->data, &sna, sizeof sna))
28311397Sswallace			return (error);
28411397Sswallace		if (error = copyin(sna.addr, &sain, sizeof sain))
28511397Sswallace			return (error);
28611397Sswallace		bcopy(&sain, &sa, sizeof sa);
28711397Sswallace		sa.sa_len = sizeof(sain);
288107849Salfred		uap->data = (caddr_t)STACK_ALLOC();
289107849Salfred		na.addr = (struct sockaddr *)((int)uap->data + sizeof na);
29011397Sswallace		na.sotype = SOCK_DGRAM;
29111397Sswallace		na.proto = IPPROTO_UDP;
29211397Sswallace		na.fh = (nfsv2fh_t *)sna.fh;
29311397Sswallace		na.flags = sna.flags;
29411397Sswallace		na.wsize = sna.wsize;
29511397Sswallace		na.rsize = sna.rsize;
29611397Sswallace		na.timeo = sna.timeo;
29711397Sswallace		na.retrans = sna.retrans;
29811397Sswallace		na.hostname = sna.hostname;
29911397Sswallace
30011397Sswallace		if (error = copyout(&sa, na.addr, sizeof sa))
30111397Sswallace			return (error);
302107849Salfred		if (error = copyout(&na, uap->data, sizeof na))
30311397Sswallace			return (error);
30411397Sswallace	}
30583366Sjulian	return (mount(td, uap));
30611397Sswallace#else
30711397Sswallace	return EINVAL;
30811397Sswallace#endif
3093584Ssos}
3103584Ssos
31111397Sswallace/*
31211397Sswallace * Read iBCS2-style directory entries.  We suck them into kernel space so
31311397Sswallace * that they can be massaged before being copied out to user code.  Like
31411397Sswallace * SunOS, we squish out `empty' entries.
31511397Sswallace *
31611397Sswallace * This is quite ugly, but what do you expect from compatibility code?
31711397Sswallace */
3183584Ssos
3193584Ssosint
32083366Sjulianibcs2_getdents(td, uap)
32183366Sjulian	struct thread *td;
32211397Sswallace	register struct ibcs2_getdents_args *uap;
3233584Ssos{
32411397Sswallace	register struct vnode *vp;
32511397Sswallace	register caddr_t inp, buf;	/* BSD-format */
32611397Sswallace	register int len, reclen;	/* BSD-format */
32711397Sswallace	register caddr_t outp;		/* iBCS2-format */
32811397Sswallace	register int resid;		/* iBCS2-format */
329255219Spjd	cap_rights_t rights;
33011397Sswallace	struct file *fp;
33111397Sswallace	struct uio auio;
33211397Sswallace	struct iovec aiov;
33311397Sswallace	struct ibcs2_dirent idb;
33411397Sswallace	off_t off;			/* true file offset */
335241896Skib	int buflen, error, eofflag;
33624677Sdfr	u_long *cookies = NULL, *cookiep;
33724677Sdfr	int ncookies;
33824677Sdfr#define	BSD_DIRENT(cp)		((struct dirent *)(cp))
33911397Sswallace#define	IBCS2_RECLEN(reclen)	(reclen + sizeof(u_short))
34011397Sswallace
341255219Spjd	error = getvnode(td->td_proc->p_fd, uap->fd,
342255219Spjd	    cap_rights_init(&rights, CAP_READ), &fp);
343255219Spjd	if (error != 0)
34411397Sswallace		return (error);
34589306Salfred	if ((fp->f_flag & FREAD) == 0) {
34689306Salfred		fdrop(fp, td);
34711397Sswallace		return (EBADF);
34889306Salfred	}
349116678Sphk	vp = fp->f_vnode;
35089306Salfred	if (vp->v_type != VDIR) {	/* XXX  vnode readdir op should do this */
35189306Salfred		fdrop(fp, td);
35211397Sswallace		return (EINVAL);
35389306Salfred	}
35411417Sswallace
35511417Sswallace	off = fp->f_offset;
35624677Sdfr#define	DIRBLKSIZ	512		/* XXX we used to use ufs's DIRBLKSIZ */
357107849Salfred	buflen = max(DIRBLKSIZ, uap->nbytes);
35811417Sswallace	buflen = min(buflen, MAXBSIZE);
359111119Simp	buf = malloc(buflen, M_TEMP, M_WAITOK);
360188588Sjhb	vn_lock(vp, LK_SHARED | LK_RETRY);
36111397Sswallaceagain:
36211397Sswallace	aiov.iov_base = buf;
36311397Sswallace	aiov.iov_len = buflen;
36411397Sswallace	auio.uio_iov = &aiov;
36511397Sswallace	auio.uio_iovcnt = 1;
36611397Sswallace	auio.uio_rw = UIO_READ;
36711397Sswallace	auio.uio_segflg = UIO_SYSSPACE;
36883366Sjulian	auio.uio_td = td;
36911397Sswallace	auio.uio_resid = buflen;
37024677Sdfr	auio.uio_offset = off;
37124677Sdfr
37224677Sdfr	if (cookies) {
37324677Sdfr		free(cookies, M_TEMP);
37424677Sdfr		cookies = NULL;
37524677Sdfr	}
37624677Sdfr
377101710Srwatson#ifdef MAC
378172930Srwatson	error = mac_vnode_check_readdir(td->td_ucred, vp);
379101710Srwatson	if (error)
380101710Srwatson		goto out;
381101710Srwatson#endif
382101710Srwatson
38311397Sswallace	/*
38411397Sswallace	 * First we read into the malloc'ed buffer, then
38511397Sswallace	 * we massage it into user space, one record at a time.
38611397Sswallace	 */
38743314Sdillon	if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0)
38811397Sswallace		goto out;
38911397Sswallace	inp = buf;
390107849Salfred	outp = uap->buf;
391107849Salfred	resid = uap->nbytes;
39224677Sdfr	if ((len = buflen - auio.uio_resid) <= 0)
39311397Sswallace		goto eof;
39424677Sdfr
39524677Sdfr	cookiep = cookies;
39624677Sdfr
39724677Sdfr	if (cookies) {
39824677Sdfr		/*
39924677Sdfr		 * When using cookies, the vfs has the option of reading from
40024677Sdfr		 * a different offset than that supplied (UFS truncates the
40124677Sdfr		 * offset to a block boundary to make sure that it never reads
40224677Sdfr		 * partway through a directory entry, even if the directory
40324677Sdfr		 * has been compacted).
40424677Sdfr		 */
40524677Sdfr		while (len > 0 && ncookies > 0 && *cookiep <= off) {
40624677Sdfr			len -= BSD_DIRENT(inp)->d_reclen;
40724677Sdfr			inp += BSD_DIRENT(inp)->d_reclen;
40824677Sdfr			cookiep++;
40924677Sdfr			ncookies--;
41024677Sdfr		}
41124677Sdfr	}
41224677Sdfr
41311397Sswallace	for (; len > 0; len -= reclen) {
41424677Sdfr		if (cookiep && ncookies == 0)
41524677Sdfr			break;
41611397Sswallace		reclen = BSD_DIRENT(inp)->d_reclen;
41711417Sswallace		if (reclen & 3) {
41811417Sswallace		        printf("ibcs2_getdents: reclen=%d\n", reclen);
41911417Sswallace		        error = EFAULT;
42011417Sswallace			goto out;
42111417Sswallace		}
42224677Sdfr		if (BSD_DIRENT(inp)->d_fileno == 0) {
42311397Sswallace			inp += reclen;	/* it is a hole; squish it out */
42424677Sdfr			if (cookiep) {
42524677Sdfr				off = *cookiep++;
42624677Sdfr				ncookies--;
42724677Sdfr			} else
42824677Sdfr				off += reclen;
42911397Sswallace			continue;
43011397Sswallace		}
43111397Sswallace		if (reclen > len || resid < IBCS2_RECLEN(reclen)) {
43211397Sswallace			/* entry too big for buffer, so just stop */
43311397Sswallace			outp++;
43411397Sswallace			break;
43511397Sswallace		}
43611397Sswallace		/*
437108533Sschweikh		 * Massage in place to make an iBCS2-shaped dirent (otherwise
43811397Sswallace		 * we have to worry about touching user memory outside of
43911397Sswallace		 * the copyout() call).
44011397Sswallace		 */
44124677Sdfr		idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno;
44211397Sswallace		idb.d_off = (ibcs2_off_t)off;
44311397Sswallace		idb.d_reclen = (u_short)IBCS2_RECLEN(reclen);
44411397Sswallace		if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 ||
44511397Sswallace		    (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10,
44611397Sswallace				     BSD_DIRENT(inp)->d_namlen + 1)) != 0)
44711397Sswallace			goto out;
44811397Sswallace		/* advance past this real entry */
44924677Sdfr		if (cookiep) {
45024677Sdfr			off = *cookiep++;
45124677Sdfr			ncookies--;
45224677Sdfr		} else
45324677Sdfr			off += reclen;
45411397Sswallace		inp += reclen;
45511397Sswallace		/* advance output past iBCS2-shaped entry */
45611397Sswallace		outp += IBCS2_RECLEN(reclen);
45711397Sswallace		resid -= IBCS2_RECLEN(reclen);
45811397Sswallace	}
45911397Sswallace	/* if we squished out the whole block, try again */
460107849Salfred	if (outp == uap->buf)
46111397Sswallace		goto again;
46211397Sswallace	fp->f_offset = off;		/* update the vnode offset */
46311397Sswallaceeof:
464107849Salfred	td->td_retval[0] = uap->nbytes - resid;
46511397Sswallaceout:
466175294Sattilio	VOP_UNLOCK(vp, 0);
46789306Salfred	fdrop(fp, td);
46824677Sdfr	if (cookies)
46924677Sdfr		free(cookies, M_TEMP);
47011397Sswallace	free(buf, M_TEMP);
47111397Sswallace	return (error);
4723584Ssos}
4733584Ssos
4743584Ssosint
47583366Sjulianibcs2_read(td, uap)
47683366Sjulian	struct thread *td;
47711397Sswallace	struct ibcs2_read_args *uap;
4783584Ssos{
47911397Sswallace	register struct vnode *vp;
48011397Sswallace	register caddr_t inp, buf;	/* BSD-format */
48111397Sswallace	register int len, reclen;	/* BSD-format */
48211397Sswallace	register caddr_t outp;		/* iBCS2-format */
48311397Sswallace	register int resid;		/* iBCS2-format */
484255219Spjd	cap_rights_t rights;
48511397Sswallace	struct file *fp;
48611397Sswallace	struct uio auio;
48711397Sswallace	struct iovec aiov;
48811397Sswallace	struct ibcs2_direct {
48911397Sswallace		ibcs2_ino_t ino;
49011397Sswallace		char name[14];
49111397Sswallace	} idb;
49211397Sswallace	off_t off;			/* true file offset */
493241896Skib	int buflen, error, eofflag, size;
49424677Sdfr	u_long *cookies = NULL, *cookiep;
49524677Sdfr	int ncookies;
49611397Sswallace
497255219Spjd	error = getvnode(td->td_proc->p_fd, uap->fd,
498255219Spjd	    cap_rights_init(&rights, CAP_READ), &fp);
499255219Spjd	if (error != 0) {
50011397Sswallace		if (error == EINVAL)
501225617Skmacy			return sys_read(td, (struct read_args *)uap);
50211397Sswallace		else
50311397Sswallace			return error;
50411397Sswallace	}
50589306Salfred	if ((fp->f_flag & FREAD) == 0) {
50689306Salfred		fdrop(fp, td);
50711397Sswallace		return (EBADF);
50889306Salfred	}
509116678Sphk	vp = fp->f_vnode;
51089306Salfred	if (vp->v_type != VDIR) {
51189306Salfred		fdrop(fp, td);
512225617Skmacy		return sys_read(td, (struct read_args *)uap);
51389306Salfred	}
51489306Salfred
51589306Salfred	off = fp->f_offset;
51611417Sswallace
51711397Sswallace	DPRINTF(("ibcs2_read: read directory\n"));
51811417Sswallace
519107849Salfred	buflen = max(DIRBLKSIZ, uap->nbytes);
52011417Sswallace	buflen = min(buflen, MAXBSIZE);
521111119Simp	buf = malloc(buflen, M_TEMP, M_WAITOK);
522188588Sjhb	vn_lock(vp, LK_SHARED | LK_RETRY);
52311397Sswallaceagain:
52411397Sswallace	aiov.iov_base = buf;
52511397Sswallace	aiov.iov_len = buflen;
52611397Sswallace	auio.uio_iov = &aiov;
52711397Sswallace	auio.uio_iovcnt = 1;
52811397Sswallace	auio.uio_rw = UIO_READ;
52911397Sswallace	auio.uio_segflg = UIO_SYSSPACE;
53083366Sjulian	auio.uio_td = td;
53111397Sswallace	auio.uio_resid = buflen;
53224677Sdfr	auio.uio_offset = off;
53324677Sdfr
53424677Sdfr	if (cookies) {
53524677Sdfr		free(cookies, M_TEMP);
53624677Sdfr		cookies = NULL;
53724677Sdfr	}
53824677Sdfr
539101710Srwatson#ifdef MAC
540172930Srwatson	error = mac_vnode_check_readdir(td->td_ucred, vp);
541101710Srwatson	if (error)
542101710Srwatson		goto out;
543101710Srwatson#endif
544101710Srwatson
54511397Sswallace	/*
54611397Sswallace	 * First we read into the malloc'ed buffer, then
54711397Sswallace	 * we massage it into user space, one record at a time.
54811397Sswallace	 */
54943314Sdillon	if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) {
55011397Sswallace		DPRINTF(("VOP_READDIR failed: %d\n", error));
55111397Sswallace		goto out;
55211397Sswallace	}
55311417Sswallace	inp = buf;
554107849Salfred	outp = uap->buf;
555107849Salfred	resid = uap->nbytes;
55624677Sdfr	if ((len = buflen - auio.uio_resid) <= 0)
55711397Sswallace		goto eof;
55824677Sdfr
55924677Sdfr	cookiep = cookies;
56024677Sdfr
56124677Sdfr	if (cookies) {
56224677Sdfr		/*
56324677Sdfr		 * When using cookies, the vfs has the option of reading from
56424677Sdfr		 * a different offset than that supplied (UFS truncates the
56524677Sdfr		 * offset to a block boundary to make sure that it never reads
56624677Sdfr		 * partway through a directory entry, even if the directory
56724677Sdfr		 * has been compacted).
56824677Sdfr		 */
56924677Sdfr		while (len > 0 && ncookies > 0 && *cookiep <= off) {
57024677Sdfr			len -= BSD_DIRENT(inp)->d_reclen;
57124677Sdfr			inp += BSD_DIRENT(inp)->d_reclen;
57224677Sdfr			cookiep++;
57324677Sdfr			ncookies--;
57424677Sdfr		}
57524677Sdfr	}
57624677Sdfr
57711397Sswallace	for (; len > 0 && resid > 0; len -= reclen) {
57824677Sdfr		if (cookiep && ncookies == 0)
57924677Sdfr			break;
58011397Sswallace		reclen = BSD_DIRENT(inp)->d_reclen;
58111417Sswallace		if (reclen & 3) {
58211417Sswallace		        printf("ibcs2_read: reclen=%d\n", reclen);
58311417Sswallace		        error = EFAULT;
58411417Sswallace			goto out;
58511417Sswallace		}
58624677Sdfr		if (BSD_DIRENT(inp)->d_fileno == 0) {
58711397Sswallace			inp += reclen;	/* it is a hole; squish it out */
58824677Sdfr			if (cookiep) {
58924677Sdfr				off = *cookiep++;
59024677Sdfr				ncookies--;
59124677Sdfr			} else
59224677Sdfr				off += reclen;
59311397Sswallace			continue;
59411397Sswallace		}
59511397Sswallace		if (reclen > len || resid < sizeof(struct ibcs2_direct)) {
59611397Sswallace			/* entry too big for buffer, so just stop */
59711397Sswallace			outp++;
59811397Sswallace			break;
59911397Sswallace		}
60011397Sswallace		/*
601108533Sschweikh		 * Massage in place to make an iBCS2-shaped dirent (otherwise
60211397Sswallace		 * we have to worry about touching user memory outside of
60311397Sswallace		 * the copyout() call).
60411397Sswallace		 *
60511397Sswallace		 * TODO: if length(filename) > 14, then break filename into
60611397Sswallace		 * multiple entries and set inode = 0xffff except last
60711397Sswallace		 */
60824677Sdfr		idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe :
60924677Sdfr			BSD_DIRENT(inp)->d_fileno;
61011397Sswallace		(void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size);
61111397Sswallace		bzero(idb.name + size, 14 - size);
61243314Sdillon		if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0)
61311397Sswallace			goto out;
61411397Sswallace		/* advance past this real entry */
61524677Sdfr		if (cookiep) {
61624677Sdfr			off = *cookiep++;
61724677Sdfr			ncookies--;
61824677Sdfr		} else
61924677Sdfr			off += reclen;
62011397Sswallace		inp += reclen;
62111397Sswallace		/* advance output past iBCS2-shaped entry */
62211397Sswallace		outp += sizeof(struct ibcs2_direct);
62311397Sswallace		resid -= sizeof(struct ibcs2_direct);
62411397Sswallace	}
62511397Sswallace	/* if we squished out the whole block, try again */
626107849Salfred	if (outp == uap->buf)
62711397Sswallace		goto again;
62811397Sswallace	fp->f_offset = off;		/* update the vnode offset */
62911397Sswallaceeof:
630107849Salfred	td->td_retval[0] = uap->nbytes - resid;
63111397Sswallaceout:
632175294Sattilio	VOP_UNLOCK(vp, 0);
63389306Salfred	fdrop(fp, td);
63424677Sdfr	if (cookies)
63524677Sdfr		free(cookies, M_TEMP);
63611397Sswallace	free(buf, M_TEMP);
63711397Sswallace	return (error);
6383584Ssos}
6393584Ssos
6403584Ssosint
64183366Sjulianibcs2_mknod(td, uap)
64283366Sjulian	struct thread *td;
64311397Sswallace	struct ibcs2_mknod_args *uap;
6443584Ssos{
645141488Sjhb	char *path;
646141488Sjhb	int error;
64711397Sswallace
648141488Sjhb        CHECKALTCREAT(td, uap->path, &path);
649141488Sjhb	if (S_ISFIFO(uap->mode))
650141488Sjhb		error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode);
651141488Sjhb	else
652141488Sjhb		error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev);
653141488Sjhb	free(path, M_TEMP);
654141488Sjhb	return (error);
6553584Ssos}
6563584Ssos
6573584Ssosint
65883366Sjulianibcs2_getgroups(td, uap)
65983366Sjulian	struct thread *td;
66011397Sswallace	struct ibcs2_getgroups_args *uap;
6613584Ssos{
662194498Sbrooks	ibcs2_gid_t *iset;
663194498Sbrooks	gid_t *gp;
664160139Sjhb	u_int i, ngrp;
665160139Sjhb	int error;
66611397Sswallace
667202342Sbrooks	if (uap->gidsetsize < td->td_ucred->cr_ngroups) {
668202342Sbrooks		if (uap->gidsetsize == 0)
669202342Sbrooks			ngrp = 0;
670202342Sbrooks		else
671202342Sbrooks			return (EINVAL);
672202342Sbrooks	} else
673202342Sbrooks		ngrp = td->td_ucred->cr_ngroups;
674194498Sbrooks	gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK);
675160139Sjhb	error = kern_getgroups(td, &ngrp, gp);
676160139Sjhb	if (error)
677194498Sbrooks		goto out;
678160139Sjhb	if (uap->gidsetsize > 0) {
679194498Sbrooks		iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK);
680160139Sjhb		for (i = 0; i < ngrp; i++)
681160139Sjhb			iset[i] = (ibcs2_gid_t)gp[i];
682160139Sjhb		error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
683194498Sbrooks		free(iset, M_TEMP);
68411397Sswallace	}
685160139Sjhb	if (error == 0)
686160139Sjhb		td->td_retval[0] = ngrp;
687194498Sbrooksout:
688194498Sbrooks	free(gp, M_TEMP);
689160139Sjhb	return (error);
6903584Ssos}
6913584Ssos
6923584Ssosint
69383366Sjulianibcs2_setgroups(td, uap)
69483366Sjulian	struct thread *td;
69511397Sswallace	struct ibcs2_setgroups_args *uap;
6963584Ssos{
697194498Sbrooks	ibcs2_gid_t *iset;
698194498Sbrooks	gid_t *gp;
69911397Sswallace	int error, i;
70011397Sswallace
701202143Sbrooks	if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1)
702121016Stjr		return (EINVAL);
703194498Sbrooks	if (uap->gidsetsize && uap->gidset == NULL)
704194498Sbrooks		return (EINVAL);
705194498Sbrooks	gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK);
706194498Sbrooks	if (uap->gidsetsize) {
707194498Sbrooks		iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK);
708160139Sjhb		error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) *
709160139Sjhb		    uap->gidsetsize);
710194498Sbrooks		if (error) {
711194498Sbrooks			free(iset, M_TEMP);
712194498Sbrooks			goto out;
713194498Sbrooks		}
714160139Sjhb		for (i = 0; i < uap->gidsetsize; i++)
715160139Sjhb			gp[i] = (gid_t)iset[i];
71611397Sswallace	}
717194498Sbrooks
718194498Sbrooks	error = kern_setgroups(td, uap->gidsetsize, gp);
719194498Sbrooksout:
720194498Sbrooks	free(gp, M_TEMP);
721194498Sbrooks	return (error);
7223584Ssos}
7233584Ssos
7243584Ssosint
72583366Sjulianibcs2_setuid(td, uap)
72683366Sjulian	struct thread *td;
72711397Sswallace	struct ibcs2_setuid_args *uap;
7283584Ssos{
72911397Sswallace	struct setuid_args sa;
7303584Ssos
731107849Salfred	sa.uid = (uid_t)uap->uid;
732225617Skmacy	return sys_setuid(td, &sa);
7333584Ssos}
7343584Ssos
7353584Ssosint
73683366Sjulianibcs2_setgid(td, uap)
73783366Sjulian	struct thread *td;
73811397Sswallace	struct ibcs2_setgid_args *uap;
7393584Ssos{
74011397Sswallace	struct setgid_args sa;
7413584Ssos
742107849Salfred	sa.gid = (gid_t)uap->gid;
743225617Skmacy	return sys_setgid(td, &sa);
7443584Ssos}
7453584Ssos
7463584Ssosint
74783366Sjulianibcs2_time(td, uap)
74883366Sjulian	struct thread *td;
74911397Sswallace	struct ibcs2_time_args *uap;
7503584Ssos{
7513584Ssos	struct timeval tv;
7523584Ssos
75338403Sbde	microtime(&tv);
75483366Sjulian	td->td_retval[0] = tv.tv_sec;
755107849Salfred	if (uap->tp)
756107849Salfred		return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp,
75711397Sswallace			       sizeof(ibcs2_time_t));
75811397Sswallace	else
75911397Sswallace		return 0;
7603584Ssos}
7613584Ssos
7623584Ssosint
76383366Sjulianibcs2_pathconf(td, uap)
76483366Sjulian	struct thread *td;
76511397Sswallace	struct ibcs2_pathconf_args *uap;
7663584Ssos{
767141488Sjhb	char *path;
768141488Sjhb	int error;
769141488Sjhb
770141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
771107849Salfred	uap->name++;	/* iBCS2 _PC_* defines are offset by one */
772195458Strasz	error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW);
773141488Sjhb	free(path, M_TEMP);
774141488Sjhb	return (error);
7753584Ssos}
7763584Ssos
7773584Ssosint
77883366Sjulianibcs2_fpathconf(td, uap)
77983366Sjulian	struct thread *td;
78011397Sswallace	struct ibcs2_fpathconf_args *uap;
7813584Ssos{
782107849Salfred	uap->name++;	/* iBCS2 _PC_* defines are offset by one */
783225617Skmacy        return sys_fpathconf(td, (struct fpathconf_args *)uap);
7843584Ssos}
7853584Ssos
7863584Ssosint
78783366Sjulianibcs2_sysconf(td, uap)
78883366Sjulian	struct thread *td;
78911397Sswallace	struct ibcs2_sysconf_args *uap;
7903584Ssos{
79111397Sswallace	int mib[2], value, len, error;
792125454Sjhb	struct proc *p;
7933584Ssos
794125454Sjhb	p = td->td_proc;
795107849Salfred	switch(uap->name) {
79611397Sswallace	case IBCS2_SC_ARG_MAX:
79711397Sswallace		mib[1] = KERN_ARGMAX;
79811397Sswallace		break;
7993584Ssos
80011397Sswallace	case IBCS2_SC_CHILD_MAX:
801125454Sjhb		PROC_LOCK(p);
802125454Sjhb		td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC);
803125454Sjhb		PROC_UNLOCK(p);
80411397Sswallace		return 0;
8053584Ssos
80611397Sswallace	case IBCS2_SC_CLK_TCK:
80783366Sjulian		td->td_retval[0] = hz;
80811397Sswallace		return 0;
8093584Ssos
81011397Sswallace	case IBCS2_SC_NGROUPS_MAX:
81111397Sswallace		mib[1] = KERN_NGROUPS;
81211397Sswallace		break;
8133584Ssos
81411397Sswallace	case IBCS2_SC_OPEN_MAX:
815125454Sjhb		PROC_LOCK(p);
816125454Sjhb		td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE);
817125454Sjhb		PROC_UNLOCK(p);
81811397Sswallace		return 0;
81911397Sswallace
82011397Sswallace	case IBCS2_SC_JOB_CONTROL:
82111397Sswallace		mib[1] = KERN_JOB_CONTROL;
82211397Sswallace		break;
82311397Sswallace
82411397Sswallace	case IBCS2_SC_SAVED_IDS:
82511397Sswallace		mib[1] = KERN_SAVED_IDS;
82611397Sswallace		break;
82711397Sswallace
82811397Sswallace	case IBCS2_SC_VERSION:
82911397Sswallace		mib[1] = KERN_POSIX1;
83011397Sswallace		break;
83111397Sswallace
83211397Sswallace	case IBCS2_SC_PASS_MAX:
83383366Sjulian		td->td_retval[0] = 128;		/* XXX - should we create PASS_MAX ? */
83411397Sswallace		return 0;
8353584Ssos
83611397Sswallace	case IBCS2_SC_XOPEN_VERSION:
83783366Sjulian		td->td_retval[0] = 2;		/* XXX: What should that be? */
83811397Sswallace		return 0;
83911397Sswallace
84011397Sswallace	default:
84111397Sswallace		return EINVAL;
84211397Sswallace	}
8433584Ssos
84411397Sswallace	mib[0] = CTL_KERN;
84511397Sswallace	len = sizeof(value);
846136418Sphk	error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0);
847125454Sjhb	if (error)
84811397Sswallace		return error;
84983366Sjulian	td->td_retval[0] = value;
85011397Sswallace	return 0;
85111397Sswallace}
8523584Ssos
8533584Ssosint
85483366Sjulianibcs2_alarm(td, uap)
85583366Sjulian	struct thread *td;
85611397Sswallace	struct ibcs2_alarm_args *uap;
8573584Ssos{
858141488Sjhb	struct itimerval itv, oitv;
85911397Sswallace	int error;
8603584Ssos
861141488Sjhb	timevalclear(&itv.it_interval);
862141488Sjhb	itv.it_value.tv_sec = uap->sec;
863141488Sjhb	itv.it_value.tv_usec = 0;
864141488Sjhb	error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
86511397Sswallace	if (error)
866141488Sjhb		return (error);
867141488Sjhb	if (oitv.it_value.tv_usec != 0)
868141488Sjhb		oitv.it_value.tv_sec++;
869141488Sjhb	td->td_retval[0] = oitv.it_value.tv_sec;
870141488Sjhb	return (0);
8713584Ssos}
8723584Ssos
8733584Ssosint
87483366Sjulianibcs2_times(td, uap)
87583366Sjulian	struct thread *td;
87611397Sswallace	struct ibcs2_times_args *uap;
8773584Ssos{
878141488Sjhb	struct rusage ru;
879141488Sjhb	struct timeval t;
880141488Sjhb	struct tms tms;
88111397Sswallace	int error;
882141488Sjhb
88311397Sswallace#define CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
88411397Sswallace
885141488Sjhb	error = kern_getrusage(td, RUSAGE_SELF, &ru);
88611397Sswallace	if (error)
887141488Sjhb		return (error);
888141488Sjhb	tms.tms_utime = CONVTCK(ru.ru_utime);
889141488Sjhb	tms.tms_stime = CONVTCK(ru.ru_stime);
89011397Sswallace
891141488Sjhb	error = kern_getrusage(td, RUSAGE_CHILDREN, &ru);
89211397Sswallace	if (error)
893141488Sjhb		return (error);
894141488Sjhb	tms.tms_cutime = CONVTCK(ru.ru_utime);
895141488Sjhb	tms.tms_cstime = CONVTCK(ru.ru_stime);
89611397Sswallace
89711397Sswallace	microtime(&t);
898141488Sjhb	td->td_retval[0] = CONVTCK(t);
89911397Sswallace
900141488Sjhb	return (copyout(&tms, uap->tp, sizeof(struct tms)));
9013584Ssos}
9023584Ssos
9033584Ssosint
90483366Sjulianibcs2_stime(td, uap)
90583366Sjulian	struct thread *td;
90611397Sswallace	struct ibcs2_stime_args *uap;
9073584Ssos{
908144451Sjhb	struct timeval tv;
909144451Sjhb	long secs;
91011397Sswallace	int error;
91111397Sswallace
912144451Sjhb	error = copyin(uap->timep, &secs, sizeof(long));
913144451Sjhb	if (error)
914144451Sjhb		return (error);
915144451Sjhb	tv.tv_sec = secs;
916144451Sjhb	tv.tv_usec = 0;
917144451Sjhb	error = kern_settimeofday(td, &tv, NULL);
918144451Sjhb	if (error)
919144451Sjhb		error = EPERM;
920144451Sjhb	return (error);
9213584Ssos}
9223584Ssos
9233584Ssosint
92483366Sjulianibcs2_utime(td, uap)
92583366Sjulian	struct thread *td;
92611397Sswallace	struct ibcs2_utime_args *uap;
9273584Ssos{
928141488Sjhb	struct ibcs2_utimbuf ubuf;
929141488Sjhb	struct timeval tbuf[2], *tp;
930141488Sjhb	char *path;
93111397Sswallace	int error;
93211397Sswallace
933107849Salfred	if (uap->buf) {
934141488Sjhb		error = copyin(uap->buf, &ubuf, sizeof(ubuf));
935141488Sjhb		if (error)
936141488Sjhb			return (error);
937141488Sjhb		tbuf[0].tv_sec = ubuf.actime;
938141488Sjhb		tbuf[0].tv_usec = 0;
939141488Sjhb		tbuf[1].tv_sec = ubuf.modtime;
940141488Sjhb		tbuf[1].tv_usec = 0;
941141488Sjhb		tp = tbuf;
942141488Sjhb	} else
943141488Sjhb		tp = NULL;
94411397Sswallace
945141488Sjhb        CHECKALTEXIST(td, uap->path, &path);
946141488Sjhb	error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE);
947141488Sjhb	free(path, M_TEMP);
948141488Sjhb	return (error);
9493584Ssos}
9503584Ssos
9513584Ssosint
95283366Sjulianibcs2_nice(td, uap)
95383366Sjulian	struct thread *td;
95411397Sswallace	struct ibcs2_nice_args *uap;
9553584Ssos{
95616322Sgpalmer	int error;
95711397Sswallace	struct setpriority_args sa;
95811397Sswallace
959107849Salfred	sa.which = PRIO_PROCESS;
960107849Salfred	sa.who = 0;
961130551Sjulian	sa.prio = td->td_proc->p_nice + uap->incr;
962225617Skmacy	if ((error = sys_setpriority(td, &sa)) != 0)
96311397Sswallace		return EPERM;
964130551Sjulian	td->td_retval[0] = td->td_proc->p_nice;
96511397Sswallace	return 0;
9663584Ssos}
9673584Ssos
96811397Sswallace/*
96911397Sswallace * iBCS2 getpgrp, setpgrp, setsid, and setpgid
97011397Sswallace */
9713584Ssos
9723584Ssosint
97383366Sjulianibcs2_pgrpsys(td, uap)
97483366Sjulian	struct thread *td;
97511397Sswallace	struct ibcs2_pgrpsys_args *uap;
9763584Ssos{
97783366Sjulian	struct proc *p = td->td_proc;
978107849Salfred	switch (uap->type) {
97911397Sswallace	case 0:			/* getpgrp */
98071489Sjhb		PROC_LOCK(p);
98183366Sjulian		td->td_retval[0] = p->p_pgrp->pg_id;
98271489Sjhb		PROC_UNLOCK(p);
98311397Sswallace		return 0;
9843584Ssos
98511397Sswallace	case 1:			/* setpgrp */
98611397Sswallace	    {
98711397Sswallace		struct setpgid_args sa;
9883584Ssos
989107849Salfred		sa.pid = 0;
990107849Salfred		sa.pgid = 0;
991225617Skmacy		sys_setpgid(td, &sa);
99271489Sjhb		PROC_LOCK(p);
99383366Sjulian		td->td_retval[0] = p->p_pgrp->pg_id;
99471489Sjhb		PROC_UNLOCK(p);
99511397Sswallace		return 0;
99611397Sswallace	    }
9973584Ssos
99811397Sswallace	case 2:			/* setpgid */
99911397Sswallace	    {
100011397Sswallace		struct setpgid_args sa;
10013584Ssos
1002107849Salfred		sa.pid = uap->pid;
1003107849Salfred		sa.pgid = uap->pgid;
1004225617Skmacy		return sys_setpgid(td, &sa);
100511397Sswallace	    }
10063584Ssos
100711397Sswallace	case 3:			/* setsid */
1008225617Skmacy		return sys_setsid(td, NULL);
100911397Sswallace
10103584Ssos	default:
101111397Sswallace		return EINVAL;
10123584Ssos	}
10133584Ssos}
10143584Ssos
101511397Sswallace/*
101611397Sswallace * XXX - need to check for nested calls
101711397Sswallace */
10183584Ssos
10193584Ssosint
102083366Sjulianibcs2_plock(td, uap)
102183366Sjulian	struct thread *td;
102211397Sswallace	struct ibcs2_plock_args *uap;
10233584Ssos{
102411397Sswallace	int error;
102511397Sswallace#define IBCS2_UNLOCK	0
102611397Sswallace#define IBCS2_PROCLOCK	1
102711397Sswallace#define IBCS2_TEXTLOCK	2
102811397Sswallace#define IBCS2_DATALOCK	4
10293584Ssos
103011397Sswallace
1031107849Salfred	switch(uap->cmd) {
103211397Sswallace	case IBCS2_UNLOCK:
1033164033Srwatson        	error = priv_check(td, PRIV_VM_MUNLOCK);
1034164033Srwatson		if (error)
1035164033Srwatson			return (error);
1036164033Srwatson		/* XXX - TODO */
1037164033Srwatson		return (0);
1038164033Srwatson
103911397Sswallace	case IBCS2_PROCLOCK:
104011397Sswallace	case IBCS2_TEXTLOCK:
104111397Sswallace	case IBCS2_DATALOCK:
1042164033Srwatson        	error = priv_check(td, PRIV_VM_MLOCK);
1043164033Srwatson		if (error)
1044164033Srwatson			return (error);
1045164033Srwatson		/* XXX - TODO */
1046164033Srwatson		return 0;
104711397Sswallace	}
104811397Sswallace	return EINVAL;
10493584Ssos}
10503584Ssos
10513584Ssosint
105283366Sjulianibcs2_uadmin(td, uap)
105383366Sjulian	struct thread *td;
105411397Sswallace	struct ibcs2_uadmin_args *uap;
10553584Ssos{
105611397Sswallace#define SCO_A_REBOOT        1
105711397Sswallace#define SCO_A_SHUTDOWN      2
105811397Sswallace#define SCO_A_REMOUNT       4
105911397Sswallace#define SCO_A_CLOCK         8
106011397Sswallace#define SCO_A_SETCONFIG     128
106111397Sswallace#define SCO_A_GETDEV        130
10623584Ssos
106311397Sswallace#define SCO_AD_HALT         0
106411397Sswallace#define SCO_AD_BOOT         1
106511397Sswallace#define SCO_AD_IBOOT        2
106611397Sswallace#define SCO_AD_PWRDOWN      3
106711397Sswallace#define SCO_AD_PWRNAP       4
10683584Ssos
106911397Sswallace#define SCO_AD_PANICBOOT    1
10703584Ssos
107111397Sswallace#define SCO_AD_GETBMAJ      0
107211397Sswallace#define SCO_AD_GETCMAJ      1
10733584Ssos
1074107849Salfred	switch(uap->cmd) {
107511397Sswallace	case SCO_A_REBOOT:
107611397Sswallace	case SCO_A_SHUTDOWN:
1077107849Salfred		switch(uap->func) {
107811397Sswallace			struct reboot_args r;
107911397Sswallace		case SCO_AD_HALT:
108011397Sswallace		case SCO_AD_PWRDOWN:
108111397Sswallace		case SCO_AD_PWRNAP:
108211397Sswallace			r.opt = RB_HALT;
1083225617Skmacy			return (sys_reboot(td, &r));
108411397Sswallace		case SCO_AD_BOOT:
108511397Sswallace		case SCO_AD_IBOOT:
108611397Sswallace			r.opt = RB_AUTOBOOT;
1087225617Skmacy			return (sys_reboot(td, &r));
108811397Sswallace		}
108911397Sswallace		return EINVAL;
109011397Sswallace	case SCO_A_REMOUNT:
109111397Sswallace	case SCO_A_CLOCK:
109211397Sswallace	case SCO_A_SETCONFIG:
109311397Sswallace		return 0;
109411397Sswallace	case SCO_A_GETDEV:
109511397Sswallace		return EINVAL;	/* XXX - TODO */
109611397Sswallace	}
109711397Sswallace	return EINVAL;
10983584Ssos}
10993584Ssos
11003584Ssosint
110183366Sjulianibcs2_sysfs(td, uap)
110283366Sjulian	struct thread *td;
110311397Sswallace	struct ibcs2_sysfs_args *uap;
11043584Ssos{
110511397Sswallace#define IBCS2_GETFSIND        1
110611397Sswallace#define IBCS2_GETFSTYP        2
110711397Sswallace#define IBCS2_GETNFSTYP       3
11088876Srgrimes
1109107849Salfred	switch(uap->cmd) {
111011397Sswallace	case IBCS2_GETFSIND:
111111397Sswallace	case IBCS2_GETFSTYP:
111211397Sswallace	case IBCS2_GETNFSTYP:
111328748Sbde		break;
11143584Ssos	}
111511397Sswallace	return EINVAL;		/* XXX - TODO */
11163584Ssos}
11173584Ssos
11183584Ssosint
111983366Sjulianibcs2_unlink(td, uap)
112083366Sjulian	struct thread *td;
112111397Sswallace	struct ibcs2_unlink_args *uap;
11223584Ssos{
1123141488Sjhb	char *path;
1124141488Sjhb	int error;
112511397Sswallace
1126141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1127141488Sjhb	error = kern_unlink(td, path, UIO_SYSSPACE);
1128141488Sjhb	free(path, M_TEMP);
1129141488Sjhb	return (error);
11303584Ssos}
11313584Ssos
11323584Ssosint
113383366Sjulianibcs2_chdir(td, uap)
113483366Sjulian	struct thread *td;
113511397Sswallace	struct ibcs2_chdir_args *uap;
11363584Ssos{
1137141488Sjhb	char *path;
1138141488Sjhb	int error;
113911397Sswallace
1140141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1141141488Sjhb	error = kern_chdir(td, path, UIO_SYSSPACE);
1142141488Sjhb	free(path, M_TEMP);
1143141488Sjhb	return (error);
11443584Ssos}
11453584Ssos
11463584Ssosint
114783366Sjulianibcs2_chmod(td, uap)
114883366Sjulian	struct thread *td;
114911397Sswallace	struct ibcs2_chmod_args *uap;
11503584Ssos{
1151141488Sjhb	char *path;
1152141488Sjhb	int error;
11533584Ssos
1154141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1155141488Sjhb	error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode);
1156141488Sjhb	free(path, M_TEMP);
1157141488Sjhb	return (error);
11583584Ssos}
11593584Ssos
11603584Ssosint
116183366Sjulianibcs2_chown(td, uap)
116283366Sjulian	struct thread *td;
116311397Sswallace	struct ibcs2_chown_args *uap;
11643584Ssos{
1165141488Sjhb	char *path;
1166141488Sjhb	int error;
11673584Ssos
1168141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1169141488Sjhb	error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid);
1170141488Sjhb	free(path, M_TEMP);
1171141488Sjhb	return (error);
11723584Ssos}
11733584Ssos
11743584Ssosint
117583366Sjulianibcs2_rmdir(td, uap)
117683366Sjulian	struct thread *td;
117711397Sswallace	struct ibcs2_rmdir_args *uap;
11783584Ssos{
1179141488Sjhb	char *path;
1180141488Sjhb	int error;
11813584Ssos
1182141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1183141488Sjhb	error = kern_rmdir(td, path, UIO_SYSSPACE);
1184141488Sjhb	free(path, M_TEMP);
1185141488Sjhb	return (error);
11863584Ssos}
11873584Ssos
11883584Ssosint
118983366Sjulianibcs2_mkdir(td, uap)
119083366Sjulian	struct thread *td;
119111397Sswallace	struct ibcs2_mkdir_args *uap;
11923584Ssos{
1193141488Sjhb	char *path;
1194141488Sjhb	int error;
11953584Ssos
1196141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1197141488Sjhb	error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode);
1198141488Sjhb	free(path, M_TEMP);
1199141488Sjhb	return (error);
12003584Ssos}
12013584Ssos
12023584Ssosint
120383366Sjulianibcs2_symlink(td, uap)
120483366Sjulian	struct thread *td;
120511397Sswallace	struct ibcs2_symlink_args *uap;
12063584Ssos{
1207141488Sjhb	char *path, *link;
1208141488Sjhb	int error;
12093584Ssos
1210141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1211141488Sjhb
1212141488Sjhb	/*
1213141488Sjhb	 * Have to expand CHECKALTCREAT() so that 'path' can be freed on
1214141488Sjhb	 * errors.
1215141488Sjhb	 */
1216141488Sjhb	error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1);
1217141488Sjhb	if (link == NULL) {
1218141488Sjhb		free(path, M_TEMP);
1219141488Sjhb		return (error);
1220141488Sjhb	}
1221141488Sjhb	error = kern_symlink(td, path, link, UIO_SYSSPACE);
1222141488Sjhb	free(path, M_TEMP);
1223141488Sjhb	free(link, M_TEMP);
1224141488Sjhb	return (error);
12253584Ssos}
12263584Ssos
12273584Ssosint
122883366Sjulianibcs2_rename(td, uap)
122983366Sjulian	struct thread *td;
123011397Sswallace	struct ibcs2_rename_args *uap;
12313584Ssos{
1232141488Sjhb	char *from, *to;
1233141488Sjhb	int error;
12343584Ssos
1235141488Sjhb	CHECKALTEXIST(td, uap->from, &from);
1236141488Sjhb
1237141488Sjhb	/*
1238141488Sjhb	 * Have to expand CHECKALTCREAT() so that 'from' can be freed on
1239141488Sjhb	 * errors.
1240141488Sjhb	 */
1241141488Sjhb	error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1);
1242167900Sjhb	if (to == NULL) {
1243141488Sjhb		free(from, M_TEMP);
1244141488Sjhb		return (error);
1245141488Sjhb	}
1246141488Sjhb	error = kern_rename(td, from, to, UIO_SYSSPACE);
1247141488Sjhb	free(from, M_TEMP);
1248141488Sjhb	free(to, M_TEMP);
1249141488Sjhb	return (error);
12503584Ssos}
12513584Ssos
12523584Ssosint
125383366Sjulianibcs2_readlink(td, uap)
125483366Sjulian	struct thread *td;
125511397Sswallace	struct ibcs2_readlink_args *uap;
12563584Ssos{
1257141488Sjhb	char *path;
1258141488Sjhb	int error;
12593584Ssos
1260141488Sjhb	CHECKALTEXIST(td, uap->path, &path);
1261141488Sjhb	error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE,
1262141488Sjhb		uap->count);
1263141488Sjhb	free(path, M_TEMP);
1264141488Sjhb	return (error);
12653584Ssos}
1266