1 /*	$NetBSD: ibcs2_misc.c,v 1.113 2014/09/05 09:21:54 matt 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.113 2014/09/05 09:21:54 matt 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 
159 int
ibcs2_sys_ulimit(struct lwp * l,const struct ibcs2_sys_ulimit_args * uap,register_t * retval)160 ibcs2_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 
208 int
ibcs2_sys_waitsys(struct lwp * l,const struct ibcs2_sys_waitsys_args * uap,register_t * retval)209 ibcs2_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 
241 int
ibcs2_sys_execv(struct lwp * l,const struct ibcs2_sys_execv_args * uap,register_t * retval)242 ibcs2_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 
257 int
ibcs2_sys_execve(struct lwp * l,const struct ibcs2_sys_execve_args * uap,register_t * retval)258 ibcs2_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 
274 int
ibcs2_sys_umount(struct lwp * l,const struct ibcs2_sys_umount_args * uap,register_t * retval)275 ibcs2_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 
287 int
ibcs2_sys_mount(struct lwp * l,const struct ibcs2_sys_mount_args * uap,register_t * retval)288 ibcs2_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 
365 int
ibcs2_sys_getdents(struct lwp * l,const struct ibcs2_sys_getdents_args * uap,register_t * retval)366 ibcs2_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_vnode;
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;
405 again:
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 
483 eof:
484 	*retval = SCARG(uap, nbytes) - resid;
485 out:
486 	VOP_UNLOCK(vp);
487 	if (cookiebuf)
488 		free(cookiebuf, M_TEMP);
489 	free(tbuf, M_TEMP);
490 out1:
491 	fd_putfile(SCARG(uap, fd));
492 	return (error);
493 }
494 
495 int
ibcs2_sys_read(struct lwp * l,const struct ibcs2_sys_read_args * uap,register_t * retval)496 ibcs2_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_vnode;
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;
543 again:
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 */
616 eof:
617 	*retval = SCARG(uap, nbytes) - resid;
618 out:
619 	VOP_UNLOCK(vp);
620 	if (cookiebuf)
621 		free(cookiebuf, M_TEMP);
622 	free(tbuf, M_TEMP);
623 out1:
624 	fd_putfile(SCARG(uap, fd));
625 	return (error);
626 }
627 
628 int
ibcs2_sys_mknod(struct lwp * l,const struct ibcs2_sys_mknod_args * uap,register_t * retval)629 ibcs2_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 
648 int
ibcs2_sys_getgroups(struct lwp * l,const struct ibcs2_sys_getgroups_args * uap,register_t * retval)649 ibcs2_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 
690 int
ibcs2_sys_setgroups(struct lwp * l,const struct ibcs2_sys_setgroups_args * uap,register_t * retval)691 ibcs2_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 
724 int
ibcs2_sys_setuid(struct lwp * l,const struct ibcs2_sys_setuid_args * uap,register_t * retval)725 ibcs2_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 
736 int
ibcs2_sys_setgid(struct lwp * l,const struct ibcs2_sys_setgid_args * uap,register_t * retval)737 ibcs2_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 
748 int
xenix_sys_ftime(struct lwp * l,const struct xenix_sys_ftime_args * uap,register_t * retval)749 xenix_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 
766 int
ibcs2_sys_time(struct lwp * l,const struct ibcs2_sys_time_args * uap,register_t * retval)767 ibcs2_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 
784 int
ibcs2_sys_pathconf(struct lwp * l,const struct ibcs2_sys_pathconf_args * uap,register_t * retval)785 ibcs2_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 
799 int
ibcs2_sys_fpathconf(struct lwp * l,const struct ibcs2_sys_fpathconf_args * uap,register_t * retval)800 ibcs2_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 
814 int
ibcs2_sys_sysconf(struct lwp * l,const struct ibcs2_sys_sysconf_args * uap,register_t * retval)815 ibcs2_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 
882 int
ibcs2_sys_alarm(struct lwp * l,const struct ibcs2_sys_alarm_args * uap,register_t * retval)883 ibcs2_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 
910 int
ibcs2_sys_getmsg(struct lwp * l,const struct ibcs2_sys_getmsg_args * uap,register_t * retval)911 ibcs2_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 
925 int
ibcs2_sys_putmsg(struct lwp * l,const struct ibcs2_sys_putmsg_args * uap,register_t * retval)926 ibcs2_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 
940 int
ibcs2_sys_times(struct lwp * l,const struct ibcs2_sys_times_args * uap,register_t * retval)941 ibcs2_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 
969 int
ibcs2_sys_stime(struct lwp * l,const struct ibcs2_sys_stime_args * uap,register_t * retval)970 ibcs2_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 
985 int
ibcs2_sys_utime(struct lwp * l,const struct ibcs2_sys_utime_args * uap,register_t * retval)986 ibcs2_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 
1014 int
ibcs2_sys_nice(struct lwp * l,const struct ibcs2_sys_nice_args * uap,register_t * retval)1015 ibcs2_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 
1036 int
ibcs2_sys_pgrpsys(struct lwp * l,const struct ibcs2_sys_pgrpsys_args * uap,register_t * retval)1037 ibcs2_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 
1090 int
ibcs2_sys_plock(struct lwp * l,const struct ibcs2_sys_plock_args * uap,register_t * retval)1091 ibcs2_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  */
1120 int
ibcs2_sys_uadmin(struct lwp * l,const struct ibcs2_sys_uadmin_args * uap,register_t * retval)1121 ibcs2_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 
1186 int
ibcs2_sys_sysfs(struct lwp * l,const struct ibcs2_sys_sysfs_args * uap,register_t * retval)1187 ibcs2_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 
1208 int
xenix_sys_rdchk(struct lwp * l,const struct xenix_sys_rdchk_args * uap,register_t * retval)1209 xenix_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 
1230 int
xenix_sys_chsize(struct lwp * l,const struct xenix_sys_chsize_args * uap,register_t * retval)1231 xenix_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 
1245 int
xenix_sys_nap(struct lwp * l,const struct xenix_sys_nap_args * uap,register_t * retval)1246 xenix_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, CLOCK_MONOTONIC, 0, &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 
1269 int
ibcs2_sys_mmap(struct lwp * l,const struct ibcs2_sys_mmap_args * uap,register_t * retval)1270 ibcs2_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 
1299 int
ibcs2_sys_memcntl(struct lwp * l,const struct ibcs2_sys_memcntl_args * uap,register_t * retval)1300 ibcs2_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 
1344 int
ibcs2_sys_gettimeofday(struct lwp * l,const struct ibcs2_sys_gettimeofday_args * uap,register_t * retval)1345 ibcs2_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 
1361 int
ibcs2_sys_settimeofday(struct lwp * l,const struct ibcs2_sys_settimeofday_args * uap,register_t * retval)1362 ibcs2_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 
1374 int
ibcs2_sys_scoinfo(struct lwp * l,const struct ibcs2_sys_scoinfo_args * uap,register_t * retval)1375 ibcs2_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 
1409 int
xenix_sys_locking(struct lwp * l,const struct xenix_sys_locking_args * uap,register_t * retval)1410 xenix_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