1/*	$NetBSD: ibcs2_misc.c,v 1.110 2010/03/03 08:20:39 he Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 *	This product includes software developed by the University of
14 *	California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 *    may be used to endorse or promote products derived from this software
26 *    without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
41 *
42 *	@(#)sun_misc.c	8.1 (Berkeley) 6/18/93
43 */
44
45/*
46 * Copyright (c) 1994, 1995, 1998 Scott Bartram
47 *
48 * This software was developed by the Computer Systems Engineering group
49 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
50 * contributed to Berkeley.
51 *
52 * All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 *	This product includes software developed by the University of
55 *	California, Lawrence Berkeley Laboratory.
56 *
57 * Redistribution and use in source and binary forms, with or without
58 * modification, are permitted provided that the following conditions
59 * are met:
60 * 1. Redistributions of source code must retain the above copyright
61 *    notice, this list of conditions and the following disclaimer.
62 * 2. Redistributions in binary form must reproduce the above copyright
63 *    notice, this list of conditions and the following disclaimer in the
64 *    documentation and/or other materials provided with the distribution.
65 * 3. All advertising materials mentioning features or use of this software
66 *    must display the following acknowledgement:
67 *	This product includes software developed by the University of
68 *	California, Berkeley and its contributors.
69 * 4. Neither the name of the University nor the names of its contributors
70 *    may be used to endorse or promote products derived from this software
71 *    without specific prior written permission.
72 *
73 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
74 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
77 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
79 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83 * SUCH DAMAGE.
84 *
85 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
86 *
87 *	@(#)sun_misc.c	8.1 (Berkeley) 6/18/93
88 */
89
90/*
91 * IBCS2 compatibility module.
92 *
93 * IBCS2 system calls that are implemented differently in BSD are
94 * handled here.
95 */
96
97#include <sys/cdefs.h>
98__KERNEL_RCSID(0, "$NetBSD: ibcs2_misc.c,v 1.110 2010/03/03 08:20:39 he Exp $");
99
100#include <sys/param.h>
101#include <sys/systm.h>
102#include <sys/namei.h>
103#include <sys/dirent.h>
104#include <sys/proc.h>
105#include <sys/file.h>
106#include <sys/filedesc.h>
107#include <sys/ioctl.h>
108#include <sys/kernel.h>
109#include <sys/malloc.h>
110#include <sys/mbuf.h>
111#include <sys/mman.h>
112#include <sys/mount.h>
113#include <sys/prot.h>
114#include <sys/reboot.h>
115#include <sys/resource.h>
116#include <sys/resourcevar.h>
117#include <sys/socket.h>
118#include <sys/stat.h>
119#include <sys/syslog.h>
120#include <sys/time.h>
121#include <sys/times.h>
122#include <sys/vnode.h>
123#include <sys/uio.h>
124#include <sys/wait.h>
125#include <sys/utsname.h>
126#include <sys/unistd.h>
127#include <sys/kauth.h>
128#include <sys/vfs_syscalls.h>
129
130#include <netinet/in.h>
131#include <sys/syscallargs.h>
132
133#include <miscfs/specfs/specdev.h>
134
135#include <uvm/uvm_extern.h>
136#include <sys/sysctl.h>
137
138#if defined(__i386__)
139#include <i386/include/reg.h>
140#endif
141
142#include <compat/ibcs2/ibcs2_types.h>
143#include <compat/ibcs2/ibcs2_dirent.h>
144#include <compat/ibcs2/ibcs2_fcntl.h>
145#include <compat/ibcs2/ibcs2_mman.h>
146#include <compat/ibcs2/ibcs2_time.h>
147#include <compat/ibcs2/ibcs2_signal.h>
148#include <compat/ibcs2/ibcs2_timeb.h>
149#include <compat/ibcs2/ibcs2_unistd.h>
150#include <compat/ibcs2/ibcs2_utsname.h>
151#include <compat/ibcs2/ibcs2_util.h>
152#include <compat/ibcs2/ibcs2_utime.h>
153#include <compat/ibcs2/ibcs2_syscallargs.h>
154#include <compat/ibcs2/ibcs2_sysi86.h>
155#include <compat/ibcs2/ibcs2_exec.h>
156
157#include <compat/sys/mount.h>
158
159int
160ibcs2_sys_ulimit(struct lwp *l, const struct ibcs2_sys_ulimit_args *uap, register_t *retval)
161{
162	/* {
163		syscallarg(int) cmd;
164		syscallarg(int) newlimit;
165	} */
166	struct proc *p = l->l_proc;
167	struct ibcs2_sys_sysconf_args sysconf_ua;
168#ifdef notyet
169	int error;
170	struct rlimit rl;
171	struct sys_setrlimit_args sra;
172#endif
173#define IBCS2_GETFSIZE		1
174#define IBCS2_SETFSIZE		2
175#define IBCS2_GETPSIZE		3
176#define IBCS2_GETDTABLESIZE	4
177
178	switch (SCARG(uap, cmd)) {
179	case IBCS2_GETFSIZE:
180		*retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
181		return 0;
182	case IBCS2_SETFSIZE:	/* XXX - fix this */
183#ifdef notyet
184		rl.rlim_cur = SCARG(uap, newlimit);
185		SCARG(&sra, which) = RLIMIT_FSIZE;
186		SCARG(&sra, rlp) = &rl;
187		error = setrlimit(p, &sra, retval);
188		if (!error)
189			*retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
190		else
191			DPRINTF(("failed "));
192		return error;
193#else
194		*retval = SCARG(uap, newlimit);
195		return 0;
196#endif
197	case IBCS2_GETPSIZE:
198		*retval = p->p_rlimit[RLIMIT_RSS].rlim_cur; /* XXX */
199		return 0;
200	case IBCS2_GETDTABLESIZE:
201		SCARG(&sysconf_ua, name) = IBCS2_SC_OPEN_MAX;
202		return ibcs2_sys_sysconf(l, &sysconf_ua, retval);
203	default:
204		return ENOSYS;
205	}
206}
207
208int
209ibcs2_sys_waitsys(struct lwp *l, const struct ibcs2_sys_waitsys_args *uap, register_t *retval)
210{
211#if defined(__i386__)
212	/* {
213		syscallarg(int) a1;
214		syscallarg(int) a2;
215		syscallarg(int) a3;
216	} */
217#endif
218	int error, options, status, pid;
219
220#if defined(__i386__)
221#define WAITPID_EFLAGS	0x8c4	/* OF, SF, ZF, PF */
222	if ((l->l_md.md_regs->tf_eflags & WAITPID_EFLAGS) == WAITPID_EFLAGS) {
223		/* waitpid */
224		pid = SCARG(uap, a1);
225		options = SCARG(uap, a3);
226	} else {
227#endif
228		/* wait */
229		pid = WAIT_ANY;
230		options = 0;
231#if defined(__i386__)
232	}
233#endif
234
235	error = do_sys_wait(&pid, &status, options, NULL);
236	retval[0] = pid;
237	retval[1] = status;
238	return error;
239}
240
241int
242ibcs2_sys_execv(struct lwp *l, const struct ibcs2_sys_execv_args *uap, register_t *retval)
243{
244	/* {
245		syscallarg(const char *) path;
246		syscallarg(char **) argp;
247	} */
248	struct sys_execve_args ap;
249
250	SCARG(&ap, path) = SCARG(uap, path);
251	SCARG(&ap, argp) = SCARG(uap, argp);
252	SCARG(&ap, envp) = NULL;
253
254	return sys_execve(l, &ap, retval);
255}
256
257int
258ibcs2_sys_execve(struct lwp *l, const struct ibcs2_sys_execve_args *uap, register_t *retval)
259{
260	/* {
261		syscallarg(const char *) path;
262		syscallarg(char **) argp;
263		syscallarg(char **) envp;
264	} */
265	struct sys_execve_args ap;
266
267	SCARG(&ap, path) = SCARG(uap, path);
268	SCARG(&ap, argp) = SCARG(uap, argp);
269	SCARG(&ap, envp) = SCARG(uap, envp);
270
271	return sys_execve(l, &ap, retval);
272}
273
274int
275ibcs2_sys_umount(struct lwp *l, const struct ibcs2_sys_umount_args *uap, register_t *retval)
276{
277	/* {
278		syscallarg(char *) name;
279	} */
280	struct sys_unmount_args um;
281
282	SCARG(&um, path) = SCARG(uap, name);
283	SCARG(&um, flags) = 0;
284	return sys_unmount(l, &um, retval);
285}
286
287int
288ibcs2_sys_mount(struct lwp *l, const struct ibcs2_sys_mount_args *uap, register_t *retval)
289{
290#ifdef notyet
291	/* {
292		syscallarg(char *) special;
293		syscallarg(char *) dir;
294		syscallarg(int) flags;
295		syscallarg(int) fstype;
296		syscallarg(char *) data;
297		syscallarg(int) len;
298	} */
299	int oflags = SCARG(uap, flags), nflags, error;
300	char fsname[MFSNAMELEN];
301
302	if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5))
303		return EINVAL;
304	if ((oflags & IBCS2_MS_NEWTYPE) == 0)
305		return EINVAL;
306	nflags = 0;
307	if (oflags & IBCS2_MS_RDONLY)
308		nflags |= MNT_RDONLY;
309	if (oflags & IBCS2_MS_NOSUID)
310		nflags |= MNT_NOSUID;
311	if (oflags & IBCS2_MS_REMOUNT)
312		nflags |= MNT_UPDATE;
313	SCARG(uap, flags) = nflags;
314
315	if (error = copyinstr(SCARG(uap, type), fsname, sizeof fsname, NULL))
316		return error;
317
318	if (strncmp(fsname, "4.2", sizeof fsname) == 0) {
319		SCARG(uap, type) = (void *)STACK_ALLOC();
320		if (error = copyout("ffs", SCARG(uap, type), sizeof("ffs")))
321			return error;
322	} else if (strncmp(fsname, "nfs", sizeof fsname) == 0) {
323		struct ibcs2_nfs_args sna;
324		struct sockaddr_in sain;
325		struct nfs_args na;
326		struct sockaddr sa;
327
328		if (error = copyin(SCARG(uap, data), &sna, sizeof sna))
329			return error;
330		if (error = copyin(sna.addr, &sain, sizeof sain))
331			return error;
332		memcpy(&sa, &sain, sizeof sa);
333		sa.sa_len = sizeof(sain);
334		SCARG(uap, data) = STACK_ALLOC();
335		na.addr = (void *)((unsigned long)SCARG(uap, data) + sizeof na);
336		na.sotype = SOCK_DGRAM;
337		na.proto = IPPROTO_UDP;
338		na.fh = (nfsv2fh_t *)sna.fh;
339		na.flags = sna.flags;
340		na.wsize = sna.wsize;
341		na.rsize = sna.rsize;
342		na.timeo = sna.timeo;
343		na.retrans = sna.retrans;
344		na.hostname = sna.hostname;
345
346		if (error = copyout(&sa, na.addr, sizeof sa))
347			return error;
348		if (error = copyout(&na, SCARG(uap, data), sizeof na))
349			return error;
350	}
351	return sys_mount(p, uap, retval);
352#else
353	return EINVAL;
354#endif
355}
356
357/*
358 * Read iBCS2-style directory entries.  We suck them into kernel space so
359 * that they can be massaged before being copied out to user code.  Like
360 * SunOS, we squish out `empty' entries.
361 *
362 * This is quite ugly, but what do you expect from compatibility code?
363 */
364
365int
366ibcs2_sys_getdents(struct lwp *l, const struct ibcs2_sys_getdents_args *uap, register_t *retval)
367{
368	/* {
369		syscallarg(int) fd;
370		syscallarg(char *) buf;
371		syscallarg(int) nbytes;
372	} */
373	struct dirent *bdp;
374	struct vnode *vp;
375	char *inp, *tbuf;	/* BSD-format */
376	int len, reclen;	/* BSD-format */
377	char *outp;		/* iBCS2-format */
378	int resid, ibcs2_reclen;/* iBCS2-format */
379	file_t *fp;
380	struct uio auio;
381	struct iovec aiov;
382	struct ibcs2_dirent idb;
383	off_t off;			/* true file offset */
384	size_t buflen;
385	int error, eofflag;
386	off_t *cookiebuf = NULL, *cookie;
387	int ncookies;
388
389	/* fd_getvnode() will use the descriptor for us */
390	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
391		return (error);
392	if ((fp->f_flag & FREAD) == 0) {
393		error = EBADF;
394		goto out1;
395	}
396	vp = fp->f_data;
397	if (vp->v_type != VDIR) {
398		error = EINVAL;
399		goto out1;
400	}
401	buflen = min(MAXBSIZE, (size_t)SCARG(uap, nbytes));
402	tbuf = malloc(buflen, M_TEMP, M_WAITOK);
403	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
404	off = fp->f_offset;
405again:
406	aiov.iov_base = tbuf;
407	aiov.iov_len = buflen;
408	auio.uio_iov = &aiov;
409	auio.uio_iovcnt = 1;
410	auio.uio_rw = UIO_READ;
411	auio.uio_resid = buflen;
412	auio.uio_offset = off;
413	UIO_SETUP_SYSSPACE(&auio);
414	/*
415	 * First we read into the malloc'ed buffer, then
416	 * we massage it into user space, one record at a time.
417	 */
418	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
419	    &ncookies);
420	if (error)
421		goto out;
422	inp = tbuf;
423	outp = SCARG(uap, buf);
424	resid = SCARG(uap, nbytes);
425	if ((len = buflen - auio.uio_resid) == 0)
426		goto eof;
427	for (cookie = cookiebuf; len > 0; len -= reclen) {
428		bdp = (struct dirent *)inp;
429		reclen = bdp->d_reclen;
430		if (reclen & 3)
431			panic("ibcs2_getdents: bad reclen");
432		if (cookie && (*cookie >> 32) != 0) {
433			compat_offseterr(vp, "ibcs2_getdents");
434			error = EINVAL;
435			goto out;
436		}
437		if (bdp->d_fileno == 0) {
438			inp += reclen;	/* it is a hole; squish it out */
439			if (cookie)
440				off = *cookie++;
441			else
442				off += reclen;
443			continue;
444		}
445		ibcs2_reclen = IBCS2_RECLEN(&idb, bdp->d_namlen);
446		if (reclen > len || resid < ibcs2_reclen) {
447			/* entry too big for buffer, so just stop */
448			outp++;
449			break;
450		}
451		if (cookie)
452			off = *cookie++; /* each entry points to the next */
453		else
454			off += reclen;
455		/*
456		 * Massage in place to make a iBCS2-shaped dirent (otherwise
457		 * we have to worry about touching user memory outside of
458		 * the copyout() call).
459		 */
460		idb.d_ino = (ibcs2_ino_t)bdp->d_fileno;
461		idb.d_off = (ibcs2_off_t)off;
462		idb.d_reclen = (u_short)ibcs2_reclen;
463		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
464		error = copyout(&idb, outp, ibcs2_reclen);
465		if (error)
466			goto out;
467		/* advance past this real entry */
468		inp += reclen;
469		/* advance output past iBCS2-shaped entry */
470		outp += ibcs2_reclen;
471		resid -= ibcs2_reclen;
472	}
473
474	/* if we squished out the whole block, try again */
475	if (outp == SCARG(uap, buf)) {
476		if (cookiebuf)
477			free(cookiebuf, M_TEMP);
478		cookiebuf = NULL;
479		goto again;
480	}
481	fp->f_offset = off;	/* update the vnode offset */
482
483eof:
484	*retval = SCARG(uap, nbytes) - resid;
485out:
486	VOP_UNLOCK(vp);
487	if (cookiebuf)
488		free(cookiebuf, M_TEMP);
489	free(tbuf, M_TEMP);
490out1:
491	fd_putfile(SCARG(uap, fd));
492	return (error);
493}
494
495int
496ibcs2_sys_read(struct lwp *l, const struct ibcs2_sys_read_args *uap, register_t *retval)
497{
498	/* {
499		syscallarg(int) fd;
500		syscallarg(char *) buf;
501		syscallarg(u_int) nbytes;
502	} */
503	struct dirent *bdp;
504	struct vnode *vp;
505	char *inp, *tbuf;	/* BSD-format */
506	int len, reclen;	/* BSD-format */
507	char *outp;		/* iBCS2-format */
508	int resid, ibcs2_reclen;/* iBCS2-format */
509	file_t *fp;
510	struct uio auio;
511	struct iovec aiov;
512	struct ibcs2_direct {
513		ibcs2_ino_t ino;
514		char name[14];
515	} idb;
516	size_t buflen;
517	int error, eofflag;
518	size_t size;
519	off_t *cookiebuf = NULL, *cookie;
520	off_t off;			/* true file offset */
521	int ncookies;
522
523	/* fd_getvnode() will use the descriptor for us */
524	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0) {
525		if (error == EINVAL)
526			return sys_read(l, (const void *)uap, retval);
527		else
528			return error;
529	}
530	if ((fp->f_flag & FREAD) == 0) {
531		error = EBADF;
532		goto out1;
533	}
534	vp = fp->f_data;
535	if (vp->v_type != VDIR) {
536		fd_putfile(SCARG(uap, fd));
537		return sys_read(l, (const void *)uap, retval);
538	}
539	buflen = min(MAXBSIZE, max(DEV_BSIZE, (size_t)SCARG(uap, nbytes)));
540	tbuf = malloc(buflen, M_TEMP, M_WAITOK);
541	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
542	off = fp->f_offset;
543again:
544	aiov.iov_base = tbuf;
545	aiov.iov_len = buflen;
546	auio.uio_iov = &aiov;
547	auio.uio_iovcnt = 1;
548	auio.uio_rw = UIO_READ;
549	auio.uio_resid = buflen;
550	auio.uio_offset = off;
551	UIO_SETUP_SYSSPACE(&auio);
552	/*
553	 * First we read into the malloc'ed buffer, then
554	 * we massage it into user space, one record at a time.
555	 */
556	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
557	    &ncookies);
558	if (error)
559		goto out;
560	inp = tbuf;
561	outp = SCARG(uap, buf);
562	resid = SCARG(uap, nbytes);
563	if ((len = buflen - auio.uio_resid) == 0)
564		goto eof;
565	for (cookie = cookiebuf; len > 0 && resid > 0; len -= reclen) {
566		bdp = (struct dirent *)inp;
567		reclen = bdp->d_reclen;
568		if (reclen & 3)
569			panic("ibcs2_sys_read");
570		if (cookie)
571			off = *cookie++; /* each entry points to the next */
572		else
573			off += reclen;
574		if ((off >> 32) != 0) {
575			error = EINVAL;
576			goto out;
577		}
578		if (bdp->d_fileno == 0) {
579			inp += reclen;	/* it is a hole; squish it out */
580			continue;
581		}
582		ibcs2_reclen = 16;
583		if (reclen > len || resid < ibcs2_reclen) {
584			/* entry too big for buffer, so just stop */
585			outp++;
586			break;
587		}
588		/*
589		 * Massage in place to make a iBCS2-shaped dirent (otherwise
590		 * we have to worry about touching user memory outside of
591		 * the copyout() call).
592		 *
593		 * TODO: if length(filename) > 14, then break filename into
594		 * multiple entries and set inode = 0xffff except last
595		 */
596		idb.ino = (bdp->d_fileno > 0xfffe) ? 0xfffe : bdp->d_fileno;
597		(void)copystr(bdp->d_name, idb.name, 14, &size);
598		memset(idb.name + size, 0, 14 - size);
599		error = copyout(&idb, outp, ibcs2_reclen);
600		if (error)
601			goto out;
602		/* advance past this real entry */
603		inp += reclen;
604		/* advance output past iBCS2-shaped entry */
605		outp += ibcs2_reclen;
606		resid -= ibcs2_reclen;
607	}
608	/* if we squished out the whole block, try again */
609	if (outp == SCARG(uap, buf)) {
610		if (cookiebuf)
611			free(cookiebuf, M_TEMP);
612		cookiebuf = NULL;
613		goto again;
614	}
615	fp->f_offset = off;		/* update the vnode offset */
616eof:
617	*retval = SCARG(uap, nbytes) - resid;
618out:
619	VOP_UNLOCK(vp);
620	if (cookiebuf)
621		free(cookiebuf, M_TEMP);
622	free(tbuf, M_TEMP);
623out1:
624	fd_putfile(SCARG(uap, fd));
625	return (error);
626}
627
628int
629ibcs2_sys_mknod(struct lwp *l, const struct ibcs2_sys_mknod_args *uap, register_t *retval)
630{
631	/* {
632		syscallarg(const char *) path;
633		syscallarg(int) mode;
634		syscallarg(int) dev;
635	} */
636
637	if (S_ISFIFO(SCARG(uap, mode))) {
638		struct sys_mkfifo_args ap;
639		SCARG(&ap, path) = SCARG(uap, path);
640		SCARG(&ap, mode) = SCARG(uap, mode);
641		return sys_mkfifo(l, &ap, retval);
642	} else {
643		return do_sys_mknod(l, SCARG(uap, path), SCARG(uap, mode),
644		    SCARG(uap, dev), retval, UIO_USERSPACE);
645	}
646}
647
648int
649ibcs2_sys_getgroups(struct lwp *l, const struct ibcs2_sys_getgroups_args *uap, register_t *retval)
650{
651	/* {
652		syscallarg(int) gidsetsize;
653		syscallarg(ibcs2_gid_t *) gidset;
654	} */
655	ibcs2_gid_t iset[16];
656	ibcs2_gid_t *gidset;
657	unsigned int ngrps;
658	int i, n, j;
659	int error;
660
661	ngrps = kauth_cred_ngroups(l->l_cred);
662	*retval = ngrps;
663	if (SCARG(uap, gidsetsize) == 0)
664		return 0;
665	if (SCARG(uap, gidsetsize) < ngrps)
666		return EINVAL;
667
668	gidset = SCARG(uap, gidset);
669	for (i = 0; i < (n = ngrps); i += n, gidset += n) {
670		n -= i;
671		if (n > __arraycount(iset))
672			n = __arraycount(iset);
673		for (j = 0; j < n; j++)
674			iset[j] = kauth_cred_group(l->l_cred, i + j);
675		error = copyout(iset, gidset, n * sizeof(iset[0]));
676		if (error != 0)
677			return error;
678	}
679
680	return 0;
681}
682
683/*
684 * It is very unlikly that any problem using 16bit groups is written
685 * to allow for more than 16 of them, so don't bother trying to
686 * support that.
687 */
688#define COMPAT_NGROUPS16 16
689
690int
691ibcs2_sys_setgroups(struct lwp *l, const struct ibcs2_sys_setgroups_args *uap, register_t *retval)
692{
693	/* {
694		syscallarg(int) gidsetsize;
695		syscallarg(ibcs2_gid_t *) gidset;
696	} */
697
698	ibcs2_gid_t iset[COMPAT_NGROUPS16];
699	kauth_cred_t ncred;
700	int error;
701	gid_t grbuf[COMPAT_NGROUPS16];
702	unsigned int i, ngroups = SCARG(uap, gidsetsize);
703
704	if (ngroups > COMPAT_NGROUPS16)
705		return EINVAL;
706	error = copyin(SCARG(uap, gidset), iset, ngroups);
707	if (error != 0)
708		return error;
709
710	for (i = 0; i < ngroups; i++)
711		grbuf[i] = iset[i];
712
713	ncred = kauth_cred_alloc();
714	error = kauth_cred_setgroups(ncred, grbuf, SCARG(uap, gidsetsize),
715	    -1, UIO_SYSSPACE);
716	if (error != 0) {
717		kauth_cred_free(ncred);
718		return error;
719	}
720
721	return kauth_proc_setgroups(l, ncred);
722}
723
724int
725ibcs2_sys_setuid(struct lwp *l, const struct ibcs2_sys_setuid_args *uap, register_t *retval)
726{
727	/* {
728		syscallarg(int) uid;
729	} */
730	struct sys_setuid_args sa;
731
732	SCARG(&sa, uid) = (uid_t)SCARG(uap, uid);
733	return sys_setuid(l, &sa, retval);
734}
735
736int
737ibcs2_sys_setgid(struct lwp *l, const struct ibcs2_sys_setgid_args *uap, register_t *retval)
738{
739	/* {
740		syscallarg(int) gid;
741	} */
742	struct sys_setgid_args sa;
743
744	SCARG(&sa, gid) = (gid_t)SCARG(uap, gid);
745	return sys_setgid(l, &sa, retval);
746}
747
748int
749xenix_sys_ftime(struct lwp *l, const struct xenix_sys_ftime_args *uap, register_t *retval)
750{
751	/* {
752		syscallarg(struct xenix_timeb *) tp;
753	} */
754	struct timeval tv;
755	struct xenix_timeb itb;
756
757	microtime(&tv);
758	itb.time = tv.tv_sec;
759	itb.millitm = (tv.tv_usec / 1000);
760	/* NetBSD has no kernel notion of timezone -- fake it. */
761	itb.timezone = 0;
762	itb.dstflag = 0;
763	return copyout(&itb, SCARG(uap, tp), xenix_timeb_len);
764}
765
766int
767ibcs2_sys_time(struct lwp *l, const struct ibcs2_sys_time_args *uap, register_t *retval)
768{
769	/* {
770		syscallarg(ibcs2_time_t *) tp;
771	} */
772	struct proc *p = l->l_proc;
773	struct timeval tv;
774
775	microtime(&tv);
776	*retval = tv.tv_sec;
777	if (p->p_emuldata == IBCS2_EXEC_XENIX && SCARG(uap, tp))
778		return copyout(&tv.tv_sec, SCARG(uap, tp),
779		    sizeof(ibcs2_time_t));
780	else
781		return 0;
782}
783
784int
785ibcs2_sys_pathconf(struct lwp *l, const struct ibcs2_sys_pathconf_args *uap, register_t *retval)
786{
787	/* {
788		syscallarg(char *) path;
789		syscallarg(int) name;
790	} */
791	struct sys_pathconf_args bsd_ua;
792
793	SCARG(&bsd_ua, path) = SCARG(uap, path);
794	/* iBCS2 _PC_* defines are offset by one */
795	SCARG(&bsd_ua, name) = SCARG(uap, name) + 1;
796	return sys_pathconf(l, &bsd_ua, retval);
797}
798
799int
800ibcs2_sys_fpathconf(struct lwp *l, const struct ibcs2_sys_fpathconf_args *uap, register_t *retval)
801{
802	/* {
803		syscallarg(int) fd;
804		syscallarg(int) name;
805	} */
806	struct sys_fpathconf_args bsd_ua;
807
808	SCARG(&bsd_ua, fd) = SCARG(uap, fd);
809	/* iBCS2 _PC_* defines are offset by one */
810	SCARG(&bsd_ua, name) = SCARG(uap, name) + 1;
811	return sys_fpathconf(l, &bsd_ua, retval);
812}
813
814int
815ibcs2_sys_sysconf(struct lwp *l, const struct ibcs2_sys_sysconf_args *uap, register_t *retval)
816{
817	/* {
818		syscallarg(int) name;
819	} */
820	struct proc *p = l->l_proc;
821	int mib[2], value, error;
822	size_t len;
823
824	switch(SCARG(uap, name)) {
825	case IBCS2_SC_ARG_MAX:
826		mib[1] = KERN_ARGMAX;
827		break;
828
829	case IBCS2_SC_CHILD_MAX:
830		*retval = p->p_rlimit[RLIMIT_NPROC].rlim_cur;
831		return 0;
832
833	case IBCS2_SC_CLK_TCK:
834		*retval = hz;
835		return 0;
836
837	case IBCS2_SC_NGROUPS_MAX:
838		mib[1] = KERN_NGROUPS;
839		break;
840
841	case IBCS2_SC_OPEN_MAX:
842		*retval = p->p_rlimit[RLIMIT_NPROC].rlim_cur;
843		return 0;
844
845	case IBCS2_SC_JOB_CONTROL:
846		mib[1] = KERN_JOB_CONTROL;
847		break;
848
849	case IBCS2_SC_SAVED_IDS:
850		mib[1] = KERN_SAVED_IDS;
851		break;
852
853	case IBCS2_SC_VERSION:
854		mib[1] = KERN_POSIX1;
855		break;
856
857	case IBCS2_SC_PASS_MAX:
858		*retval = 128;		/* XXX - should we create PASS_MAX ? */
859		return 0;
860
861	case IBCS2_SC_XOPEN_VERSION:
862		*retval = 2;		/* XXX: What should that be? */
863		return 0;
864
865	default:
866		return EINVAL;
867	}
868
869	mib[0] = CTL_KERN;
870	len = sizeof(value);
871	/*
872	 * calling into sysctl with superuser privs, but we don't mind,
873	 * 'cause we're only querying a value.
874	 */
875	error = old_sysctl(&mib[0], 2, &value, &len, NULL, 0, NULL);
876	if (error)
877		return (error);
878	*retval = value;
879	return 0;
880}
881
882int
883ibcs2_sys_alarm(struct lwp *l, const struct ibcs2_sys_alarm_args *uap, register_t *retval)
884{
885	/* {
886		syscallarg(unsigned) sec;
887	} */
888	struct proc *p = l->l_proc;
889	struct itimerval it, oit;
890	int error;
891
892	error = dogetitimer(p, ITIMER_REAL, &oit);
893	if (error != 0)
894		return error;
895
896	timerclear(&it.it_interval);
897	it.it_value.tv_sec = SCARG(uap, sec);
898	it.it_value.tv_usec = 0;
899
900	error = dosetitimer(p, ITIMER_REAL, &it);
901	if (error)
902		return error;
903
904	if (oit.it_value.tv_usec)
905		oit.it_value.tv_sec++;
906	*retval = oit.it_value.tv_sec;
907	return 0;
908}
909
910int
911ibcs2_sys_getmsg(struct lwp *l, const struct ibcs2_sys_getmsg_args *uap, register_t *retval)
912{
913#ifdef notyet
914	/* {
915		syscallarg(int) fd;
916		syscallarg(struct ibcs2_stropts *) ctl;
917		syscallarg(struct ibcs2_stropts *) dat;
918		syscallarg(int *) flags;
919	} */
920#endif
921
922	return 0;
923}
924
925int
926ibcs2_sys_putmsg(struct lwp *l, const struct ibcs2_sys_putmsg_args *uap, register_t *retval)
927{
928#ifdef notyet
929	/* {
930		syscallarg(int) fd;
931		syscallarg(struct ibcs2_stropts *) ctl;
932		syscallarg(struct ibcs2_stropts *) dat;
933		syscallarg(int) flags;
934	} */
935#endif
936
937	return 0;
938}
939
940int
941ibcs2_sys_times(struct lwp *l, const struct ibcs2_sys_times_args *uap, register_t *retval)
942{
943	/* {
944		syscallarg(struct tms *) tp;
945	} */
946	struct tms tms;
947	struct timeval t;
948	struct rusage ru, *rup;
949#define CONVTCK(r)      (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
950
951	ru = l->l_proc->p_stats->p_ru;
952	mutex_enter(l->l_proc->p_lock);
953	calcru(l->l_proc, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
954	rulwps(l->l_proc, &ru);
955	mutex_exit(l->l_proc->p_lock);
956	tms.tms_utime = CONVTCK(ru.ru_utime);
957	tms.tms_stime = CONVTCK(ru.ru_stime);
958
959	rup = &l->l_proc->p_stats->p_cru;
960	tms.tms_cutime = CONVTCK(rup->ru_utime);
961	tms.tms_cstime = CONVTCK(rup->ru_stime);
962
963	microtime(&t);
964	*retval = CONVTCK(t);
965
966	return copyout(&tms, SCARG(uap, tp), sizeof(tms));
967}
968
969int
970ibcs2_sys_stime(struct lwp *l, const struct ibcs2_sys_stime_args *uap, register_t *retval)
971{
972	/* {
973		syscallarg(long *) timep;
974	} */
975	struct timeval tv;
976	int error;
977
978	error = copyin(SCARG(uap, timep), &tv.tv_sec, sizeof(long));
979	if (error)
980		return error;
981	tv.tv_usec = 0;
982	return settimeofday1(&tv, false, NULL, l, true);
983}
984
985int
986ibcs2_sys_utime(struct lwp *l, const struct ibcs2_sys_utime_args *uap, register_t *retval)
987{
988	/* {
989		syscallarg(const char *) path;
990		syscallarg(struct ibcs2_utimbuf *) buf;
991	} */
992	int error;
993	struct timeval *tptr;
994	struct timeval tp[2];
995
996	if (SCARG(uap, buf)) {
997		struct ibcs2_utimbuf ubuf;
998
999		error = copyin(SCARG(uap, buf), &ubuf, sizeof(ubuf));
1000		if (error)
1001			return error;
1002		tp[0].tv_sec = ubuf.actime;
1003		tp[0].tv_usec = 0;
1004		tp[1].tv_sec = ubuf.modtime;
1005		tp[1].tv_usec = 0;
1006		tptr = tp;
1007	} else
1008		tptr = NULL;
1009
1010	return do_sys_utimes(l, NULL, SCARG(uap, path), FOLLOW,
1011			    tptr, UIO_SYSSPACE);
1012}
1013
1014int
1015ibcs2_sys_nice(struct lwp *l, const struct ibcs2_sys_nice_args *uap, register_t *retval)
1016{
1017	/* {
1018		syscallarg(int) incr;
1019	} */
1020	struct proc *p = l->l_proc;
1021	struct sys_setpriority_args sa;
1022
1023	SCARG(&sa, which) = PRIO_PROCESS;
1024	SCARG(&sa, who) = 0;
1025	SCARG(&sa, prio) = p->p_nice - NZERO + SCARG(uap, incr);
1026	if (sys_setpriority(l, &sa, retval) != 0)
1027		return EPERM;
1028	*retval = p->p_nice - NZERO;
1029	return 0;
1030}
1031
1032/*
1033 * iBCS2 getpgrp, setpgrp, setsid, and setpgid
1034 */
1035
1036int
1037ibcs2_sys_pgrpsys(struct lwp *l, const struct ibcs2_sys_pgrpsys_args *uap, register_t *retval)
1038{
1039	/* {
1040		syscallarg(int) type;
1041		syscallarg(void *) dummy;
1042		syscallarg(int) pid;
1043		syscallarg(int) pgid;
1044	} */
1045	struct proc *p = l->l_proc;
1046
1047	switch (SCARG(uap, type)) {
1048	case 0:			/* getpgrp */
1049		mutex_enter(proc_lock);
1050		*retval = p->p_pgrp->pg_id;
1051		mutex_exit(proc_lock);
1052		return 0;
1053
1054	case 1:			/* setpgrp */
1055	    {
1056		struct sys_setpgid_args sa;
1057
1058		SCARG(&sa, pid) = 0;
1059		SCARG(&sa, pgid) = 0;
1060		sys_setpgid(l, &sa, retval);
1061		mutex_enter(proc_lock);
1062		*retval = p->p_pgrp->pg_id;
1063		mutex_exit(proc_lock);
1064		return 0;
1065	    }
1066
1067	case 2:			/* setpgid */
1068	    {
1069		struct sys_setpgid_args sa;
1070
1071		SCARG(&sa, pid) = SCARG(uap, pid);
1072		SCARG(&sa, pgid) = SCARG(uap, pgid);
1073		return sys_setpgid(l, &sa, retval);
1074	    }
1075
1076	case 3:			/* setsid */
1077		return sys_setsid(l, NULL, retval);
1078
1079	default:
1080		return EINVAL;
1081	}
1082}
1083
1084/*
1085 * See http://docsrv.sco.com:507/en/man/html.S/plock.S.html
1086 *
1087 * XXX - need to check for nested calls
1088 */
1089
1090int
1091ibcs2_sys_plock(struct lwp *l, const struct ibcs2_sys_plock_args *uap, register_t *retval)
1092{
1093	/* {
1094		syscallarg(int) cmd;
1095	} */
1096#define IBCS2_UNLOCK	0
1097#define IBCS2_PROCLOCK	1
1098#define IBCS2_TEXTLOCK	2
1099#define IBCS2_DATALOCK	4
1100
1101	/*
1102	 * NOTE: This is a privileged operation. Normally it would require root
1103	 * access. When implementing, please make sure to use an appropriate
1104	 * kauth(9) request. See the man-page for more information.
1105	 */
1106
1107	switch(SCARG(uap, cmd)) {
1108	case IBCS2_UNLOCK:
1109	case IBCS2_PROCLOCK:
1110	case IBCS2_TEXTLOCK:
1111	case IBCS2_DATALOCK:
1112		return 0;	/* XXX - TODO */
1113	}
1114	return EINVAL;
1115}
1116
1117/*
1118 * See http://docsrv.sco.com:507/en/man/html.S/uadmin.S.html
1119 */
1120int
1121ibcs2_sys_uadmin(struct lwp *l, const struct ibcs2_sys_uadmin_args *uap, register_t *retval)
1122{
1123	/* {
1124		syscallarg(int) cmd;
1125		syscallarg(int) func;
1126		syscallarg(void *) data;
1127	} */
1128	int error;
1129
1130#define SCO_A_REBOOT        1
1131#define SCO_A_SHUTDOWN      2
1132#define SCO_A_REMOUNT       4
1133#define SCO_A_CLOCK         8
1134#define SCO_A_SETCONFIG     128
1135#define SCO_A_GETDEV        130
1136
1137#define SCO_AD_HALT         0
1138#define SCO_AD_BOOT         1
1139#define SCO_AD_IBOOT        2
1140#define SCO_AD_PWRDOWN      3
1141#define SCO_AD_PWRNAP       4
1142
1143#define SCO_AD_PANICBOOT    1
1144
1145#define SCO_AD_GETBMAJ      0
1146#define SCO_AD_GETCMAJ      1
1147
1148
1149	switch(SCARG(uap, cmd)) {
1150	case SCO_A_REBOOT:
1151	case SCO_A_SHUTDOWN:
1152		error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_REBOOT,
1153		    0, NULL, NULL, NULL);
1154		if (error)
1155			return (error);
1156
1157		switch(SCARG(uap, func)) {
1158		case SCO_AD_HALT:
1159		case SCO_AD_PWRDOWN:
1160		case SCO_AD_PWRNAP:
1161			cpu_reboot(RB_HALT, NULL);
1162		case SCO_AD_BOOT:
1163		case SCO_AD_IBOOT:
1164			cpu_reboot(RB_AUTOBOOT, NULL);
1165		}
1166		return EINVAL;
1167	case SCO_A_REMOUNT:
1168	case SCO_A_CLOCK:
1169	case SCO_A_SETCONFIG:
1170	case SCO_A_GETDEV:
1171		/*
1172		 * NOTE: These are all privileged operations, that otherwise
1173		 * would require root access or similar. When implementing,
1174		 * please use appropriate kauth(9) requests. See the man-page
1175		 * for more information.
1176		 */
1177
1178		if (SCARG(uap, cmd) != SCO_A_GETDEV)
1179			return 0;
1180		else
1181			return EINVAL;	/* XXX - TODO */
1182	}
1183	return EINVAL;
1184}
1185
1186int
1187ibcs2_sys_sysfs(struct lwp *l, const struct ibcs2_sys_sysfs_args *uap, register_t *retval)
1188{
1189	/* {
1190		syscallarg(int) cmd;
1191		syscallarg(void *) d1;
1192		syscallarg(char *) buf;
1193	} */
1194
1195#define IBCS2_GETFSIND        1
1196#define IBCS2_GETFSTYP        2
1197#define IBCS2_GETNFSTYP       3
1198
1199	switch(SCARG(uap, cmd)) {
1200	case IBCS2_GETFSIND:
1201	case IBCS2_GETFSTYP:
1202	case IBCS2_GETNFSTYP:
1203		break;
1204	}
1205	return EINVAL;		/* XXX - TODO */
1206}
1207
1208int
1209xenix_sys_rdchk(struct lwp *l, const struct xenix_sys_rdchk_args *uap, register_t *retval)
1210{
1211	/* {
1212		syscallarg(int) fd;
1213	} */
1214	file_t *fp;
1215	int nbytes;
1216	int error;
1217
1218	if ((fp = fd_getfile(SCARG(uap, fd))) == NULL)
1219		return (EBADF);
1220	error = (*fp->f_ops->fo_ioctl)(fp, FIONREAD, &nbytes);
1221	fd_putfile(SCARG(uap, fd));
1222
1223	if (error != 0)
1224		return error;
1225
1226	*retval = nbytes ? 1 : 0;
1227	return 0;
1228}
1229
1230int
1231xenix_sys_chsize(struct lwp *l, const struct xenix_sys_chsize_args *uap, register_t *retval)
1232{
1233	/* {
1234		syscallarg(int) fd;
1235		syscallarg(long) size;
1236	} */
1237	struct sys_ftruncate_args sa;
1238
1239	SCARG(&sa, fd) = SCARG(uap, fd);
1240	SCARG(&sa, PAD) = 0;
1241	SCARG(&sa, length) = SCARG(uap, size);
1242	return sys_ftruncate(l, &sa, retval);
1243}
1244
1245int
1246xenix_sys_nap(struct lwp *l, const struct xenix_sys_nap_args *uap, register_t *retval)
1247{
1248	/* {
1249		syscallarg(long) millisec;
1250	} */
1251	int error;
1252	struct timespec rqt;
1253	struct timespec rmt;
1254
1255	rqt.tv_sec = 0;
1256	rqt.tv_nsec = SCARG(uap, millisec) * 1000;
1257	error = nanosleep1(l, &rqt, &rmt);
1258	/* If interrupted we can either report EINTR, or the time left */
1259	if (error != 0 && error != EINTR)
1260		return error;
1261	*retval = rmt.tv_nsec / 1000;
1262	return 0;
1263}
1264
1265/*
1266 * mmap compat code borrowed from svr4/svr4_misc.c
1267 */
1268
1269int
1270ibcs2_sys_mmap(struct lwp *l, const struct ibcs2_sys_mmap_args *uap, register_t *retval)
1271{
1272	/* {
1273		syscallarg(ibcs2_void *) addr;
1274		syscallarg(ibcs2_size_t) len;
1275		syscallarg(int) prot;
1276		syscallarg(int) flags;
1277		syscallarg(int) fd;
1278		syscallarg(ibcs2_off_t) off;
1279	} */
1280	struct sys_mmap_args mm;
1281
1282#define _MAP_NEW	0x80000000 /* XXX why? */
1283
1284	if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
1285		return EINVAL;
1286	if (SCARG(uap, len) == 0)
1287		return EINVAL;
1288
1289	SCARG(&mm, prot) = SCARG(uap, prot);
1290	SCARG(&mm, len) = SCARG(uap, len);
1291	SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW;
1292	SCARG(&mm, fd) = SCARG(uap, fd);
1293	SCARG(&mm, addr) = SCARG(uap, addr);
1294	SCARG(&mm, pos) = SCARG(uap, off);
1295
1296	return sys_mmap(l, &mm, retval);
1297}
1298
1299int
1300ibcs2_sys_memcntl(struct lwp *l, const struct ibcs2_sys_memcntl_args *uap, register_t *retval)
1301{
1302	/* {
1303		syscallarg(ibcs2_void *) addr;
1304		syscallarg(ibcs2_size_t) len;
1305		syscallarg(int) cmd;
1306		syscallarg(ibcs2_void *) arg;
1307		syscallarg(int) attr;
1308		syscallarg(int) mask;
1309	} */
1310
1311	switch (SCARG(uap, cmd)) {
1312	case IBCS2_MC_SYNC:
1313		{
1314			struct sys___msync13_args msa;
1315
1316			SCARG(&msa, addr) = SCARG(uap, addr);
1317			SCARG(&msa, len) = SCARG(uap, len);
1318			SCARG(&msa, flags) = (int)SCARG(uap, arg);
1319
1320			return sys___msync13(l, &msa, retval);
1321		}
1322#ifdef IBCS2_MC_ADVISE		/* supported? */
1323	case IBCS2_MC_ADVISE:
1324		{
1325			struct sys_madvise_args maa;
1326
1327			SCARG(&maa, addr) = SCARG(uap, addr);
1328			SCARG(&maa, len) = SCARG(uap, len);
1329			SCARG(&maa, behav) = (int)SCARG(uap, arg);
1330
1331			return sys_madvise(l, &maa, retval);
1332		}
1333#endif
1334	case IBCS2_MC_LOCK:
1335	case IBCS2_MC_UNLOCK:
1336	case IBCS2_MC_LOCKAS:
1337	case IBCS2_MC_UNLOCKAS:
1338		return EOPNOTSUPP;
1339	default:
1340		return ENOSYS;
1341	}
1342}
1343
1344int
1345ibcs2_sys_gettimeofday(struct lwp *l, const struct ibcs2_sys_gettimeofday_args *uap, register_t *retval)
1346{
1347	/* {
1348		syscallarg(struct timeval *) tp;
1349	} */
1350
1351	if (SCARG(uap, tp)) {
1352		struct timeval atv;
1353
1354		microtime(&atv);
1355		return copyout(&atv, SCARG(uap, tp), sizeof (atv));
1356	}
1357
1358	return 0;
1359}
1360
1361int
1362ibcs2_sys_settimeofday(struct lwp *l, const struct ibcs2_sys_settimeofday_args *uap, register_t *retval)
1363{
1364	/* {
1365		syscallarg(struct timeval *) tp;
1366	} */
1367	struct compat_50_sys_settimeofday_args ap;
1368
1369	SCARG(&ap, tv) = SCARG(uap, tp);
1370	SCARG(&ap, tzp) = NULL;
1371	return compat_50_sys_settimeofday(l, &ap, retval);
1372}
1373
1374int
1375ibcs2_sys_scoinfo(struct lwp *l, const struct ibcs2_sys_scoinfo_args *uap, register_t *retval)
1376{
1377	/* {
1378		syscallarg(struct scoutsname *) bp;
1379		syscallarg(int) len;
1380	} */
1381	struct scoutsname uts;
1382
1383	(void)memset(&uts, 0, sizeof(uts));
1384	(void)strncpy(uts.sysname, ostype, 8);
1385	(void)strncpy(uts.nodename, hostname, 8);
1386	(void)strncpy(uts.release, osrelease, 15);
1387	(void)strncpy(uts.kid, "kernel id 1", 19);
1388	(void)strncpy(uts.machine, machine, 8);
1389	(void)strncpy(uts.bustype, "pci", 8);
1390	(void)strncpy(uts.serial, "1234", 9);
1391	uts.origin = 0;
1392	uts.oem = 0;
1393	(void)strncpy(uts.nusers, "unlim", 8);
1394	uts.ncpu = 1;
1395
1396	return copyout(&uts, SCARG(uap, bp), sizeof(uts));
1397}
1398
1399#define X_LK_UNLCK  0
1400#define X_LK_LOCK   1
1401#define X_LK_NBLCK 20
1402#define X_LK_RLCK   3
1403#define X_LK_NBRLCK 4
1404#define X_LK_GETLK  5
1405#define X_LK_SETLK  6
1406#define X_LK_SETLKW 7
1407#define X_LK_TESTLK 8
1408
1409int
1410xenix_sys_locking(struct lwp *l, const struct xenix_sys_locking_args *uap, register_t *retval)
1411{
1412	/* {
1413	      syscallarg(int) fd;
1414	      syscallarg(int) blk;
1415	      syscallarg(int) size;
1416	} */
1417	struct flock fl;
1418	int cmd;
1419
1420	switch SCARG(uap, blk) {
1421	case X_LK_GETLK:
1422	case X_LK_SETLK:
1423	case X_LK_SETLKW:
1424		return ibcs2_sys_fcntl(l, (const void *)uap, retval);
1425	}
1426
1427	switch SCARG(uap, blk) {
1428	case X_LK_UNLCK:
1429		cmd = F_SETLK;
1430		fl.l_type = F_UNLCK;
1431		break;
1432	case X_LK_LOCK:
1433		cmd = F_SETLKW;
1434		fl.l_type = F_WRLCK;
1435		break;
1436	case X_LK_RLCK:
1437		cmd = F_SETLKW;
1438		fl.l_type = F_RDLCK;
1439		break;
1440	case X_LK_NBRLCK:
1441		cmd = F_SETLK;
1442		fl.l_type = F_RDLCK;
1443		break;
1444	case X_LK_NBLCK:
1445		cmd = F_SETLK;
1446		fl.l_type = F_WRLCK;
1447		break;
1448	default:
1449		return EINVAL;
1450	}
1451	fl.l_len = SCARG(uap, size);
1452	fl.l_start = 0;
1453	fl.l_whence = SEEK_CUR;
1454
1455	return do_fcntl_lock(SCARG(uap, fd), cmd, &fl);
1456}
1457