Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / svr4 / svr4_misc.c
blobfdc185fb10b74d99ce7a5a663e905b4266795524
1 /* $NetBSD: svr4_misc.c,v 1.147 2009/11/04 21:23:03 rmind Exp $ */
3 /*-
4 * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * SVR4 compatibility module.
35 * SVR4 system calls that are implemented differently in BSD are
36 * handled here.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: svr4_misc.c,v 1.147 2009/11/04 21:23:03 rmind Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/namei.h>
45 #include <sys/dirent.h>
46 #include <sys/proc.h>
47 #include <sys/file.h>
48 #include <sys/stat.h>
49 #include <sys/time.h>
50 #include <sys/filedesc.h>
51 #include <sys/ioctl.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
54 #include <sys/pool.h>
55 #include <sys/mbuf.h>
56 #include <sys/mman.h>
57 #include <sys/mount.h>
58 #include <sys/resource.h>
59 #include <sys/resourcevar.h>
60 #include <sys/socket.h>
61 #include <sys/vnode.h>
62 #include <sys/uio.h>
63 #include <sys/wait.h>
64 #include <sys/utsname.h>
65 #include <sys/unistd.h>
66 #include <sys/vfs_syscalls.h>
67 #include <sys/times.h>
68 #include <sys/sem.h>
69 #include <sys/msg.h>
70 #include <sys/ptrace.h>
71 #include <sys/signalvar.h>
73 #include <netinet/in.h>
74 #include <sys/syscallargs.h>
76 #include <miscfs/specfs/specdev.h>
78 #include <compat/svr4/svr4_types.h>
79 #include <compat/svr4/svr4_signal.h>
80 #include <compat/svr4/svr4_lwp.h>
81 #include <compat/svr4/svr4_ucontext.h>
82 #include <compat/svr4/svr4_syscallargs.h>
83 #include <compat/svr4/svr4_util.h>
84 #include <compat/svr4/svr4_time.h>
85 #include <compat/svr4/svr4_dirent.h>
86 #include <compat/svr4/svr4_ulimit.h>
87 #include <compat/svr4/svr4_hrt.h>
88 #include <compat/svr4/svr4_wait.h>
89 #include <compat/svr4/svr4_statvfs.h>
90 #include <compat/svr4/svr4_sysconfig.h>
91 #include <compat/svr4/svr4_acl.h>
92 #include <compat/svr4/svr4_mman.h>
94 #include <sys/cpu.h>
96 #include <uvm/uvm_extern.h>
98 static int svr4_to_bsd_mmap_flags(int);
100 static inline clock_t timeval_to_clock_t(struct timeval *);
101 static void svr4_setinfo(int, struct rusage *, int, svr4_siginfo_t *);
103 struct svr4_hrtcntl_args;
104 static int svr4_hrtcntl(struct lwp *, const struct svr4_hrtcntl_args *,
105 register_t *);
106 #define svr4_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE)
108 static int svr4_mknod(struct lwp *, register_t *, const char *,
109 svr4_mode_t, svr4_dev_t);
112 svr4_sys_wait(struct lwp *l, const struct svr4_sys_wait_args *uap,
113 register_t *retval)
115 int error, st, sig, pid = WAIT_ANY;
117 error = do_sys_wait(&pid, &st, 0, NULL);
119 retval[0] = pid;
120 if (pid == 0)
121 return error;
123 if (WIFSIGNALED(st)) {
124 sig = WTERMSIG(st);
125 if (sig >= 0 && sig < NSIG)
126 st = (st & ~0177) | native_to_svr4_signo[sig];
127 } else if (WIFSTOPPED(st)) {
128 sig = WSTOPSIG(st);
129 if (sig >= 0 && sig < NSIG)
130 st = (st & ~0xff00) | (native_to_svr4_signo[sig] << 8);
134 * It looks like wait(2) on svr4/solaris/2.4 returns
135 * the status in retval[1], and the pid on retval[0].
137 retval[1] = st;
139 if (SCARG(uap, status))
140 error = copyout(&st, SCARG(uap, status), sizeof(st));
142 return error;
147 svr4_sys_execv(struct lwp *l, const struct svr4_sys_execv_args *uap, register_t *retval)
149 /* {
150 syscallarg(char *) path;
151 syscallarg(char **) argv;
152 } */
153 struct sys_execve_args ap;
155 SCARG(&ap, path) = SCARG(uap, path);
156 SCARG(&ap, argp) = SCARG(uap, argp);
157 SCARG(&ap, envp) = NULL;
159 return sys_execve(l, &ap, retval);
164 svr4_sys_execve(struct lwp *l, const struct svr4_sys_execve_args *uap, register_t *retval)
166 /* {
167 syscallarg(const char *) path;
168 syscallarg(char **) argv;
169 syscallarg(char **) envp;
170 } */
171 struct sys_execve_args ap;
173 SCARG(&ap, path) = SCARG(uap, path);
174 SCARG(&ap, argp) = SCARG(uap, argp);
175 SCARG(&ap, envp) = SCARG(uap, envp);
177 return sys_execve(l, &ap, retval);
182 svr4_sys_time(struct lwp *l, const struct svr4_sys_time_args *uap, register_t *retval)
184 int error = 0;
185 struct timeval tv;
187 microtime(&tv);
188 if (SCARG(uap, t))
189 error = copyout(&tv.tv_sec, SCARG(uap, t),
190 sizeof(*(SCARG(uap, t))));
191 *retval = (int) tv.tv_sec;
193 return error;
198 * Read SVR4-style directory entries. We suck them into kernel space so
199 * that they can be massaged before being copied out to user code. Like
200 * SunOS, we squish out `empty' entries.
202 * This is quite ugly, but what do you expect from compatibility code?
205 svr4_sys_getdents64(struct lwp *l, const struct svr4_sys_getdents64_args *uap, register_t *retval)
207 struct dirent *bdp;
208 struct vnode *vp;
209 char *inp, *tbuf; /* BSD-format */
210 int len, reclen; /* BSD-format */
211 char *outp; /* SVR4-format */
212 int resid, svr4_reclen; /* SVR4-format */
213 struct file *fp;
214 struct uio auio;
215 struct iovec aiov;
216 struct svr4_dirent64 idb;
217 off_t off; /* true file offset */
218 int buflen, error, eofflag;
219 off_t *cookiebuf = NULL, *cookie;
220 int ncookies;
222 /* fd_getvnode() will use the descriptor for us */
223 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
224 return (error);
226 if ((fp->f_flag & FREAD) == 0) {
227 error = EBADF;
228 goto out1;
231 vp = (struct vnode *)fp->f_data;
232 if (vp->v_type != VDIR) {
233 error = EINVAL;
234 goto out1;
237 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
238 tbuf = malloc(buflen, M_TEMP, M_WAITOK);
239 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
240 off = fp->f_offset;
241 again:
242 aiov.iov_base = tbuf;
243 aiov.iov_len = buflen;
244 auio.uio_iov = &aiov;
245 auio.uio_iovcnt = 1;
246 auio.uio_rw = UIO_READ;
247 auio.uio_resid = buflen;
248 auio.uio_offset = off;
249 UIO_SETUP_SYSSPACE(&auio);
251 * First we read into the malloc'ed buffer, then
252 * we massage it into user space, one record at a time.
254 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
255 &ncookies);
256 if (error)
257 goto out;
259 inp = tbuf;
260 outp = (char *) SCARG(uap, dp);
261 resid = SCARG(uap, nbytes);
262 if ((len = buflen - auio.uio_resid) == 0)
263 goto eof;
265 for (cookie = cookiebuf; len > 0; len -= reclen) {
266 bdp = (struct dirent *)inp;
267 reclen = bdp->d_reclen;
268 if (reclen & 3)
269 panic("svr4_getdents64: bad reclen");
270 if (bdp->d_fileno == 0) {
271 inp += reclen; /* it is a hole; squish it out */
272 if (cookie)
273 off = *cookie++;
274 else
275 off += reclen;
276 continue;
278 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
279 if (reclen > len || resid < svr4_reclen) {
280 /* entry too big for buffer, so just stop */
281 outp++;
282 break;
284 if (cookie)
285 off = *cookie++; /* each entry points to the next */
286 else
287 off += reclen;
289 * Massage in place to make a SVR4-shaped dirent (otherwise
290 * we have to worry about touching user memory outside of
291 * the copyout() call).
293 idb.d_ino = (svr4_ino64_t)bdp->d_fileno;
294 idb.d_off = (svr4_off64_t)off;
295 idb.d_reclen = (u_short)svr4_reclen;
296 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
297 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
298 goto out;
299 /* advance past this real entry */
300 inp += reclen;
301 /* advance output past SVR4-shaped entry */
302 outp += svr4_reclen;
303 resid -= svr4_reclen;
306 /* if we squished out the whole block, try again */
307 if (outp == (char *) SCARG(uap, dp))
308 goto again;
309 fp->f_offset = off; /* update the vnode offset */
311 eof:
312 *retval = SCARG(uap, nbytes) - resid;
313 out:
314 VOP_UNLOCK(vp, 0);
315 if (cookiebuf)
316 free(cookiebuf, M_TEMP);
317 free(tbuf, M_TEMP);
318 out1:
319 fd_putfile(SCARG(uap, fd));
320 return error;
325 svr4_sys_getdents(struct lwp *l, const struct svr4_sys_getdents_args *uap, register_t *retval)
327 struct dirent *bdp;
328 struct vnode *vp;
329 char *inp, *tbuf; /* BSD-format */
330 int len, reclen; /* BSD-format */
331 char *outp; /* SVR4-format */
332 int resid, svr4_reclen; /* SVR4-format */
333 struct file *fp;
334 struct uio auio;
335 struct iovec aiov;
336 struct svr4_dirent idb;
337 off_t off; /* true file offset */
338 int buflen, error, eofflag;
339 off_t *cookiebuf = NULL, *cookie;
340 int ncookies;
342 /* fd_getvnode() will use the descriptor for us */
343 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
344 return (error);
346 if ((fp->f_flag & FREAD) == 0) {
347 error = EBADF;
348 goto out1;
351 vp = (struct vnode *)fp->f_data;
352 if (vp->v_type != VDIR) {
353 error = EINVAL;
354 goto out1;
357 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
358 tbuf = malloc(buflen, M_TEMP, M_WAITOK);
359 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
360 off = fp->f_offset;
361 again:
362 aiov.iov_base = tbuf;
363 aiov.iov_len = buflen;
364 auio.uio_iov = &aiov;
365 auio.uio_iovcnt = 1;
366 auio.uio_rw = UIO_READ;
367 auio.uio_resid = buflen;
368 auio.uio_offset = off;
369 UIO_SETUP_SYSSPACE(&auio);
371 * First we read into the malloc'ed buffer, then
372 * we massage it into user space, one record at a time.
374 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
375 &ncookies);
376 if (error)
377 goto out;
379 inp = tbuf;
380 outp = SCARG(uap, buf);
381 resid = SCARG(uap, nbytes);
382 if ((len = buflen - auio.uio_resid) == 0)
383 goto eof;
385 for (cookie = cookiebuf; len > 0; len -= reclen) {
386 bdp = (struct dirent *)inp;
387 reclen = bdp->d_reclen;
388 if (reclen & 3)
389 panic("svr4_getdents: bad reclen");
390 if (cookie)
391 off = *cookie++; /* each entry points to the next */
392 else
393 off += reclen;
394 if ((off >> 32) != 0) {
395 compat_offseterr(vp, "svr4_getdents");
396 error = EINVAL;
397 goto out;
399 if (bdp->d_fileno == 0) {
400 inp += reclen; /* it is a hole; squish it out */
401 continue;
403 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
404 if (reclen > len || resid < svr4_reclen) {
405 /* entry too big for buffer, so just stop */
406 outp++;
407 break;
410 * Massage in place to make a SVR4-shaped dirent (otherwise
411 * we have to worry about touching user memory outside of
412 * the copyout() call).
414 idb.d_ino = (svr4_ino_t)bdp->d_fileno;
415 idb.d_off = (svr4_off_t)off;
416 idb.d_reclen = (u_short)svr4_reclen;
417 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
418 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
419 goto out;
420 /* advance past this real entry */
421 inp += reclen;
422 /* advance output past SVR4-shaped entry */
423 outp += svr4_reclen;
424 resid -= svr4_reclen;
427 /* if we squished out the whole block, try again */
428 if (outp == SCARG(uap, buf))
429 goto again;
430 fp->f_offset = off; /* update the vnode offset */
432 eof:
433 *retval = SCARG(uap, nbytes) - resid;
434 out:
435 VOP_UNLOCK(vp, 0);
436 if (cookiebuf)
437 free(cookiebuf, M_TEMP);
438 free(tbuf, M_TEMP);
439 out1:
440 fd_putfile(SCARG(uap, fd));
441 return error;
445 static int
446 svr4_to_bsd_mmap_flags(int f)
448 int type = f & SVR4_MAP_TYPE;
449 int nf;
451 if (type != MAP_PRIVATE && type != MAP_SHARED)
452 return -1;
454 nf = f & SVR4_MAP_COPYFLAGS;
455 if (f & SVR4_MAP_ANON)
456 nf |= MAP_ANON;
458 return nf;
463 svr4_sys_mmap(struct lwp *l, const struct svr4_sys_mmap_args *uap, register_t *retval)
465 struct sys_mmap_args mm;
467 * Verify the arguments.
469 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
470 return EINVAL; /* XXX still needed? */
472 if (SCARG(uap, len) == 0)
473 return EINVAL;
475 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
476 return EINVAL;
478 SCARG(&mm, prot) = SCARG(uap, prot);
479 SCARG(&mm, len) = SCARG(uap, len);
480 SCARG(&mm, fd) = SCARG(uap, fd);
481 SCARG(&mm, addr) = SCARG(uap, addr);
482 SCARG(&mm, pos) = SCARG(uap, pos);
484 return sys_mmap(l, &mm, retval);
489 svr4_sys_mmap64(struct lwp *l, const struct svr4_sys_mmap64_args *uap, register_t *retval)
491 struct sys_mmap_args mm;
493 * Verify the arguments.
495 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
496 return EINVAL; /* XXX still needed? */
498 if (SCARG(uap, len) == 0)
499 return EINVAL;
501 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
502 return EINVAL;
504 SCARG(&mm, prot) = SCARG(uap, prot);
505 SCARG(&mm, len) = SCARG(uap, len);
506 SCARG(&mm, fd) = SCARG(uap, fd);
507 SCARG(&mm, addr) = SCARG(uap, addr);
508 SCARG(&mm, pos) = SCARG(uap, pos);
510 return sys_mmap(l, &mm, retval);
514 static int
515 svr4_mknod(struct lwp *l, register_t *retval, const char *path, svr4_mode_t mode, svr4_dev_t dev)
517 if (S_ISFIFO(mode)) {
518 struct sys_mkfifo_args ap;
519 SCARG(&ap, path) = path;
520 SCARG(&ap, mode) = mode;
521 return sys_mkfifo(l, &ap, retval);
522 } else {
523 return do_sys_mknod(l, path, mode, dev, retval, UIO_USERSPACE);
529 svr4_sys_mknod(struct lwp *l, const struct svr4_sys_mknod_args *uap, register_t *retval)
531 return svr4_mknod(l, retval,
532 SCARG(uap, path), SCARG(uap, mode),
533 svr4_to_bsd_odev_t(SCARG(uap, dev)));
538 svr4_sys_xmknod(struct lwp *l, const struct svr4_sys_xmknod_args *uap, register_t *retval)
540 return svr4_mknod(l, retval,
541 SCARG(uap, path), SCARG(uap, mode),
542 svr4_to_bsd_dev_t(SCARG(uap, dev)));
547 svr4_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
549 return 0;
554 svr4_sys_sysconfig(struct lwp *l, const struct svr4_sys_sysconfig_args *uap, register_t *retval)
556 int active;
558 switch (SCARG(uap, name)) {
559 case SVR4_CONFIG_NGROUPS:
560 *retval = NGROUPS_MAX;
561 break;
562 case SVR4_CONFIG_CHILD_MAX:
563 *retval = maxproc;
564 break;
565 case SVR4_CONFIG_OPEN_FILES:
566 *retval = maxfiles;
567 break;
568 case SVR4_CONFIG_POSIX_VER:
569 *retval = 198808;
570 break;
571 case SVR4_CONFIG_PAGESIZE:
572 *retval = PAGE_SIZE;
573 break;
574 case SVR4_CONFIG_CLK_TCK:
575 *retval = 60; /* should this be `hz', ie. 100? */
576 break;
577 case SVR4_CONFIG_XOPEN_VER:
578 *retval = 2; /* XXX: What should that be? */
579 break;
580 case SVR4_CONFIG_PROF_TCK:
581 *retval = 60; /* XXX: What should that be? */
582 break;
583 case SVR4_CONFIG_NPROC_CONF:
584 *retval = 1; /* Only one processor for now */
585 break;
586 case SVR4_CONFIG_NPROC_ONLN:
587 *retval = 1; /* And it better be online */
588 break;
589 case SVR4_CONFIG_AIO_LISTIO_MAX:
590 case SVR4_CONFIG_AIO_MAX:
591 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
592 *retval = 0; /* No aio support */
593 break;
594 case SVR4_CONFIG_DELAYTIMER_MAX:
595 *retval = 0; /* No delaytimer support */
596 break;
597 case SVR4_CONFIG_MQ_OPEN_MAX:
598 #ifdef SYSVMSG
599 *retval = msginfo.msgmni;
600 #else
601 *retval = 0;
602 #endif
603 break;
604 case SVR4_CONFIG_MQ_PRIO_MAX:
605 *retval = 0; /* XXX: Don't know */
606 break;
607 case SVR4_CONFIG_RTSIG_MAX:
608 *retval = 0;
609 break;
610 case SVR4_CONFIG_SEM_NSEMS_MAX:
611 #ifdef SYSVSEM
612 *retval = seminfo.semmni;
613 #else
614 *retval = 0;
615 #endif
616 break;
617 case SVR4_CONFIG_SEM_VALUE_MAX:
618 #ifdef SYSVSEM
619 *retval = seminfo.semvmx;
620 #else
621 *retval = 0;
622 #endif
623 break;
624 case SVR4_CONFIG_SIGQUEUE_MAX:
625 *retval = 0; /* XXX: Don't know */
626 break;
627 case SVR4_CONFIG_SIGRT_MIN:
628 case SVR4_CONFIG_SIGRT_MAX:
629 *retval = 0; /* No real time signals */
630 break;
631 case SVR4_CONFIG_TIMER_MAX:
632 *retval = 3; /* XXX: real, virtual, profiling */
633 break;
634 case SVR4_CONFIG_PHYS_PAGES:
635 *retval = uvmexp.free; /* XXX: free instead of total */
636 break;
637 case SVR4_CONFIG_AVPHYS_PAGES:
638 uvm_estimatepageable(&active, NULL);
639 *retval = active; /* XXX: active instead of avg */
640 break;
641 case SVR4_CONFIG_COHERENCY:
642 *retval = 0; /* XXX */
643 break;
644 case SVR4_CONFIG_SPLIT_CACHE:
645 *retval = 0; /* XXX */
646 break;
647 case SVR4_CONFIG_ICACHESZ:
648 *retval = 256; /* XXX */
649 break;
650 case SVR4_CONFIG_DCACHESZ:
651 *retval = 256; /* XXX */
652 break;
653 case SVR4_CONFIG_ICACHELINESZ:
654 *retval = 64; /* XXX */
655 break;
656 case SVR4_CONFIG_DCACHELINESZ:
657 *retval = 64; /* XXX */
658 break;
659 case SVR4_CONFIG_ICACHEBLKSZ:
660 *retval = 64; /* XXX */
661 break;
662 case SVR4_CONFIG_DCACHEBLKSZ:
663 *retval = 64; /* XXX */
664 break;
665 case SVR4_CONFIG_DCACHETBLKSZ:
666 *retval = 64; /* XXX */
667 break;
668 case SVR4_CONFIG_ICACHE_ASSOC:
669 *retval = 1; /* XXX */
670 break;
671 case SVR4_CONFIG_DCACHE_ASSOC:
672 *retval = 1; /* XXX */
673 break;
674 case SVR4_CONFIG_MAXPID:
675 *retval = PID_MAX;
676 break;
677 case SVR4_CONFIG_STACK_PROT:
678 *retval = PROT_READ|PROT_WRITE|PROT_EXEC;
679 break;
680 default:
681 return EINVAL;
683 return 0;
686 /* ARGSUSED */
688 svr4_sys_break(struct lwp *l, const struct svr4_sys_break_args *uap, register_t *retval)
690 struct proc *p = l->l_proc;
691 struct vmspace *vm = p->p_vmspace;
692 vaddr_t new, old;
693 int error;
695 old = (vaddr_t) vm->vm_daddr;
696 new = round_page((vaddr_t)SCARG(uap, nsize));
698 if (new - old > p->p_rlimit[RLIMIT_DATA].rlim_cur && new > old)
699 return ENOMEM;
701 old = round_page(old + ctob(vm->vm_dsize));
702 DPRINTF(("break(2): dsize = %x ctob %x\n",
703 vm->vm_dsize, ctob(vm->vm_dsize)));
705 if (new > old) {
706 error = uvm_map(&vm->vm_map, &old, new - old, NULL,
707 UVM_UNKNOWN_OFFSET, 0,
708 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
709 UVM_ADV_NORMAL,
710 UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
711 UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
712 if (error) {
713 uprintf("sbrk: grow failed, error = %d\n", error);
714 return error;
716 vm->vm_dsize += btoc(new - old);
717 } else if (new < old) {
718 uvm_deallocate(&vm->vm_map, new, old - new);
719 vm->vm_dsize -= btoc(old - new);
721 return 0;
725 static inline clock_t
726 timeval_to_clock_t(struct timeval *tv)
728 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
733 svr4_sys_times(struct lwp *l, const struct svr4_sys_times_args *uap, register_t *retval)
735 struct tms tms;
736 struct timeval t;
737 struct rusage ru, *rup;
738 struct proc *p = l->l_proc;
740 ru = p->p_stats->p_ru;
741 mutex_enter(p->p_lock);
742 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
743 rulwps(p, &ru);
744 mutex_exit(p->p_lock);
746 tms.tms_utime = timeval_to_clock_t(&ru.ru_utime);
747 tms.tms_stime = timeval_to_clock_t(&ru.ru_stime);
749 rup = &p->p_stats->p_cru;
750 tms.tms_cutime = timeval_to_clock_t(&rup->ru_utime);
751 tms.tms_cstime = timeval_to_clock_t(&rup->ru_stime);
753 microtime(&t);
754 *retval = timeval_to_clock_t(&t);
756 return copyout(&tms, SCARG(uap, tp), sizeof(tms));
761 svr4_sys_ulimit(struct lwp *l, const struct svr4_sys_ulimit_args *uap, register_t *retval)
763 struct proc *p = l->l_proc;
764 int error;
765 struct rlimit krl;
766 register_t r;
768 switch (SCARG(uap, cmd)) {
769 case SVR4_GFILLIM:
770 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
771 break;
773 case SVR4_SFILLIM:
774 krl.rlim_cur = SCARG(uap, newlimit) * 512;
775 krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;
777 error = dosetrlimit(l, l->l_proc, RLIMIT_FSIZE, &krl);
778 if (error)
779 return error;
781 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
782 break;
784 case SVR4_GMEMLIM:
785 r = p->p_rlimit[RLIMIT_DATA].rlim_cur;
786 if (r > 0x7fffffff)
787 r = 0x7fffffff;
788 r += (long)p->p_vmspace->vm_daddr;
789 break;
791 case SVR4_GDESLIM:
792 r = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
793 break;
795 default:
796 return EINVAL;
799 *retval = r > 0x7fffffff ? 0x7fffffff : r;
800 return 0;
805 svr4_sys_pgrpsys(struct lwp *l, const struct svr4_sys_pgrpsys_args *uap, register_t *retval)
807 struct proc *p = l->l_proc;
809 switch (SCARG(uap, cmd)) {
810 case 1: /* setpgrp() */
812 * SVR4 setpgrp() (which takes no arguments) has the
813 * semantics that the session ID is also created anew, so
814 * in almost every sense, setpgrp() is identical to
815 * setsid() for SVR4. (Under BSD, the difference is that
816 * a setpgid(0,0) will not create a new session.)
818 sys_setsid(l, NULL, retval);
819 /*FALLTHROUGH*/
821 case 0: /* getpgrp() */
822 mutex_enter(proc_lock);
823 *retval = p->p_pgrp->pg_id;
824 mutex_exit(proc_lock);
825 return 0;
827 case 2: /* getsid(pid) */
828 mutex_enter(proc_lock);
829 if (SCARG(uap, pid) != 0 &&
830 (p = p_find(SCARG(uap, pid), PFIND_LOCKED | PFIND_ZOMBIE)) == NULL) {
831 mutex_exit(proc_lock);
832 return ESRCH;
835 * This has already been initialized to the pid of
836 * the session leader.
838 *retval = (register_t) p->p_session->s_sid;
839 mutex_exit(proc_lock);
840 return 0;
842 case 3: /* setsid() */
843 return sys_setsid(l, NULL, retval);
845 case 4: /* getpgid(pid) */
846 mutex_enter(proc_lock);
847 if (SCARG(uap, pid) != 0 &&
848 (p = p_find(SCARG(uap, pid), PFIND_LOCKED | PFIND_ZOMBIE)) == NULL) {
849 mutex_exit(proc_lock);
850 return ESRCH;
853 *retval = (int) p->p_pgrp->pg_id;
854 mutex_exit(proc_lock);
855 return 0;
857 case 5: /* setpgid(pid, pgid); */
859 struct sys_setpgid_args sa;
861 SCARG(&sa, pid) = SCARG(uap, pid);
862 SCARG(&sa, pgid) = SCARG(uap, pgid);
863 return sys_setpgid(l, &sa, retval);
866 default:
867 return EINVAL;
871 struct svr4_hrtcntl_args {
872 syscallarg(int) cmd;
873 syscallarg(int) fun;
874 syscallarg(int) clk;
875 syscallarg(svr4_hrt_interval_t *) iv;
876 syscallarg(svr4_hrt_time_t *) ti;
880 static int
881 svr4_hrtcntl(struct lwp *l, const struct svr4_hrtcntl_args *uap,
882 register_t *retval)
884 switch (SCARG(uap, fun)) {
885 case SVR4_HRT_CNTL_RES:
886 DPRINTF(("htrcntl(RES)\n"));
887 *retval = SVR4_HRT_USEC;
888 return 0;
890 case SVR4_HRT_CNTL_TOFD:
891 DPRINTF(("htrcntl(TOFD)\n"));
893 struct timeval tv;
894 svr4_hrt_time_t t;
895 if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) {
896 DPRINTF(("clk == %d\n", SCARG(uap, clk)));
897 return EINVAL;
899 if (SCARG(uap, ti) == NULL) {
900 DPRINTF(("ti NULL\n"));
901 return EINVAL;
903 microtime(&tv);
904 t.h_sec = tv.tv_sec;
905 t.h_rem = tv.tv_usec;
906 t.h_res = SVR4_HRT_USEC;
907 return copyout(&t, SCARG(uap, ti), sizeof(t));
910 case SVR4_HRT_CNTL_START:
911 DPRINTF(("htrcntl(START)\n"));
912 return ENOSYS;
914 case SVR4_HRT_CNTL_GET:
915 DPRINTF(("htrcntl(GET)\n"));
916 return ENOSYS;
917 default:
918 DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun)));
919 return ENOSYS;
925 svr4_sys_hrtsys(struct lwp *l, const struct svr4_sys_hrtsys_args *uap, register_t *retval)
928 switch (SCARG(uap, cmd)) {
929 case SVR4_HRT_CNTL:
930 return svr4_hrtcntl(l, (const struct svr4_hrtcntl_args *) uap,
931 retval);
933 case SVR4_HRT_ALRM:
934 DPRINTF(("hrtalarm\n"));
935 return ENOSYS;
937 case SVR4_HRT_SLP:
938 DPRINTF(("hrtsleep\n"));
939 return ENOSYS;
941 case SVR4_HRT_CAN:
942 DPRINTF(("hrtcancel\n"));
943 return ENOSYS;
945 default:
946 DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd)));
947 return EINVAL;
952 static void
953 svr4_setinfo(int pid, struct rusage *ru, int st, svr4_siginfo_t *s)
955 int sig;
957 memset(s, 0, sizeof(*s));
959 s->si_signo = SVR4_SIGCHLD;
960 s->si_errno = 0; /* XXX? */
962 if (pid != 0) {
963 s->si_pid = pid;
964 s->si_stime = ru->ru_stime.tv_sec;
965 s->si_utime = ru->ru_utime.tv_sec;
968 if (WIFEXITED(st)) {
969 s->si_status = WEXITSTATUS(st);
970 s->si_code = SVR4_CLD_EXITED;
971 } else if (WIFSTOPPED(st)) {
972 sig = WSTOPSIG(st);
973 if (sig >= 0 && sig < NSIG)
974 s->si_status = native_to_svr4_signo[sig];
976 if (s->si_status == SVR4_SIGCONT)
977 s->si_code = SVR4_CLD_CONTINUED;
978 else
979 s->si_code = SVR4_CLD_STOPPED;
980 } else {
981 sig = WTERMSIG(st);
982 if (sig >= 0 && sig < NSIG)
983 s->si_status = native_to_svr4_signo[sig];
985 if (WCOREDUMP(st))
986 s->si_code = SVR4_CLD_DUMPED;
987 else
988 s->si_code = SVR4_CLD_KILLED;
991 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
992 (long) s->si_pid,
993 s->si_signo, s->si_code, s->si_errno, s->si_status));
998 svr4_sys_waitsys(struct lwp *l, const struct svr4_sys_waitsys_args *uap, register_t *retval)
1000 int options, status;
1001 int error;
1002 struct rusage ru;
1003 svr4_siginfo_t i;
1004 int id = SCARG(uap, id);
1006 switch (SCARG(uap, grp)) {
1007 case SVR4_P_PID:
1008 break;
1010 case SVR4_P_PGID:
1011 mutex_enter(proc_lock);
1012 id = -l->l_proc->p_pgid;
1013 mutex_exit(proc_lock);
1014 break;
1016 case SVR4_P_ALL:
1017 id = WAIT_ANY;
1018 break;
1020 default:
1021 return EINVAL;
1024 /* Translate options */
1025 options = WOPTSCHECKED;
1026 if (SCARG(uap, options) & SVR4_WNOWAIT)
1027 options |= WNOWAIT;
1028 if (SCARG(uap, options) & SVR4_WNOHANG)
1029 options |= WNOHANG;
1030 if ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)) == 0)
1031 options |= WNOZOMBIE;
1032 if (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED))
1033 options |= WUNTRACED;
1035 DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1036 SCARG(uap, grp), id,
1037 SCARG(uap, info), SCARG(uap, options)));
1039 error = do_sys_wait(&id, &status, options, &ru);
1041 retval[0] = id;
1042 if (error != 0)
1043 return error;
1045 svr4_setinfo(id, &ru, status, &i);
1046 return copyout(&i, SCARG(uap, info), sizeof(i));
1050 static int
1051 svr4_copyout_statvfs(const struct statvfs *bfs, struct svr4_statvfs *sufs)
1053 struct svr4_statvfs *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1054 int error;
1056 sfs->f_bsize = bfs->f_bsize;
1057 sfs->f_frsize = bfs->f_frsize;
1058 sfs->f_blocks = bfs->f_blocks;
1059 sfs->f_bfree = bfs->f_bfree;
1060 sfs->f_bavail = bfs->f_bavail;
1061 sfs->f_files = bfs->f_files;
1062 sfs->f_ffree = bfs->f_ffree;
1063 sfs->f_favail = bfs->f_favail;
1064 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1065 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1066 sfs->f_flag = 0;
1067 if (bfs->f_flag & MNT_RDONLY)
1068 sfs->f_flag |= SVR4_ST_RDONLY;
1069 if (bfs->f_flag & MNT_NOSUID)
1070 sfs->f_flag |= SVR4_ST_NOSUID;
1071 sfs->f_namemax = MAXNAMLEN;
1072 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1073 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1075 error = copyout(sfs, sufs, sizeof(*sfs));
1077 free(sfs, M_TEMP);
1078 return error;
1082 static int
1083 svr4_copyout_statvfs64(const struct statvfs *bfs, struct svr4_statvfs64 *sufs)
1085 struct svr4_statvfs64 *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1086 int error;
1088 sfs->f_bsize = bfs->f_bsize;
1089 sfs->f_frsize = bfs->f_frsize;
1090 sfs->f_blocks = bfs->f_blocks;
1091 sfs->f_bfree = bfs->f_bfree;
1092 sfs->f_bavail = bfs->f_bavail;
1093 sfs->f_files = bfs->f_files;
1094 sfs->f_ffree = bfs->f_ffree;
1095 sfs->f_favail = bfs->f_ffree;
1096 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1097 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1098 sfs->f_flag = 0;
1099 if (bfs->f_flag & MNT_RDONLY)
1100 sfs->f_flag |= SVR4_ST_RDONLY;
1101 if (bfs->f_flag & MNT_NOSUID)
1102 sfs->f_flag |= SVR4_ST_NOSUID;
1103 sfs->f_namemax = MAXNAMLEN;
1104 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1105 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1107 error = copyout(sfs, sufs, sizeof(*sfs));
1109 free(sfs, M_TEMP);
1110 return error;
1115 svr4_sys_statvfs(struct lwp *l, const struct svr4_sys_statvfs_args *uap, register_t *retval)
1117 struct statvfs *sb;
1118 int error;
1120 sb = STATVFSBUF_GET();
1121 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
1122 if (error == 0)
1123 error = svr4_copyout_statvfs(sb, SCARG(uap, fs));
1124 STATVFSBUF_PUT(sb);
1125 return error;
1130 svr4_sys_fstatvfs(struct lwp *l, const struct svr4_sys_fstatvfs_args *uap, register_t *retval)
1132 struct statvfs *sb;
1133 int error;
1135 sb = STATVFSBUF_GET();
1136 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1137 if (error == 0)
1138 error = svr4_copyout_statvfs(sb, SCARG(uap, fs));
1139 STATVFSBUF_PUT(sb);
1140 return error;
1145 svr4_sys_statvfs64(struct lwp *l, const struct svr4_sys_statvfs64_args *uap, register_t *retval)
1147 struct statvfs *sb;
1148 int error;
1150 sb = STATVFSBUF_GET();
1151 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
1152 if (error == 0)
1153 error = svr4_copyout_statvfs64(sb, SCARG(uap, fs));
1154 STATVFSBUF_PUT(sb);
1155 return error;
1160 svr4_sys_fstatvfs64(struct lwp *l, const struct svr4_sys_fstatvfs64_args *uap, register_t *retval)
1162 struct statvfs *sb;
1163 int error;
1165 sb = STATVFSBUF_GET();
1166 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1167 if (error == 0)
1168 error = svr4_copyout_statvfs64(sb, SCARG(uap, fs));
1169 STATVFSBUF_PUT(sb);
1170 return error;
1174 svr4_sys_alarm(struct lwp *l, const struct svr4_sys_alarm_args *uap, register_t *retval)
1176 struct itimerval tp;
1178 dogetitimer(l->l_proc, ITIMER_REAL, &tp);
1179 if (tp.it_value.tv_usec)
1180 tp.it_value.tv_sec++;
1181 *retval = (register_t)tp.it_value.tv_sec;
1183 timerclear(&tp.it_interval);
1184 tp.it_value.tv_sec = SCARG(uap, sec);
1185 tp.it_value.tv_usec = 0;
1187 return dosetitimer(l->l_proc, ITIMER_REAL, &tp);
1192 svr4_sys_gettimeofday(struct lwp *l, const struct svr4_sys_gettimeofday_args *uap, register_t *retval)
1195 if (SCARG(uap, tp)) {
1196 struct timeval atv;
1198 microtime(&atv);
1199 return copyout(&atv, SCARG(uap, tp), sizeof (atv));
1202 return 0;
1207 svr4_sys_facl(struct lwp *l, const struct svr4_sys_facl_args *uap, register_t *retval)
1210 *retval = 0;
1212 switch (SCARG(uap, cmd)) {
1213 case SVR4_SYS_SETACL:
1214 /* We don't support acls on any filesystem */
1215 return ENOSYS;
1217 case SVR4_SYS_GETACL:
1218 #if 1
1219 return ENOSYS;
1220 #else
1222 * XXX This code is completly borked, no idea what it was
1223 * trying to do.
1225 return copyout(retval, &SCARG(uap, num),
1226 sizeof(SCARG(uap, num)));
1227 #endif
1229 case SVR4_SYS_GETACLCNT:
1230 return 0;
1232 default:
1233 return EINVAL;
1239 svr4_sys_acl(struct lwp *l, const struct svr4_sys_acl_args *uap, register_t *retval)
1241 return svr4_sys_facl(l, (const void *)uap, retval); /* XXX: for now the same */
1246 svr4_sys_auditsys(struct lwp *l, const struct svr4_sys_auditsys_args *uap, register_t *retval)
1249 * XXX: Big brother is *not* watching.
1251 return 0;
1256 svr4_sys_memcntl(struct lwp *l, const struct svr4_sys_memcntl_args *uap, register_t *retval)
1258 switch (SCARG(uap, cmd)) {
1259 case SVR4_MC_SYNC:
1261 struct sys___msync13_args msa;
1263 SCARG(&msa, addr) = SCARG(uap, addr);
1264 SCARG(&msa, len) = SCARG(uap, len);
1265 SCARG(&msa, flags) = (int)(u_long)SCARG(uap, arg);
1267 return sys___msync13(l, &msa, retval);
1269 case SVR4_MC_ADVISE:
1271 struct sys_madvise_args maa;
1273 SCARG(&maa, addr) = SCARG(uap, addr);
1274 SCARG(&maa, len) = SCARG(uap, len);
1275 SCARG(&maa, behav) = (int)(u_long)SCARG(uap, arg);
1277 return sys_madvise(l, &maa, retval);
1279 case SVR4_MC_LOCK:
1280 case SVR4_MC_UNLOCK:
1281 case SVR4_MC_LOCKAS:
1282 case SVR4_MC_UNLOCKAS:
1283 return EOPNOTSUPP;
1284 default:
1285 return ENOSYS;
1291 svr4_sys_nice(struct lwp *l, const struct svr4_sys_nice_args *uap, register_t *retval)
1293 struct sys_setpriority_args ap;
1294 int error;
1296 SCARG(&ap, which) = PRIO_PROCESS;
1297 SCARG(&ap, who) = 0;
1298 SCARG(&ap, prio) = SCARG(uap, prio);
1300 if ((error = sys_setpriority(l, &ap, retval)) != 0)
1301 return error;
1303 if ((error = sys_getpriority(l, (const void *)&ap, retval)) != 0)
1304 return error;
1306 return 0;
1311 svr4_sys_resolvepath(struct lwp *l, const struct svr4_sys_resolvepath_args *uap, register_t *retval)
1313 struct nameidata nd;
1314 int error;
1315 size_t len;
1317 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | TRYEMULROOT, UIO_USERSPACE,
1318 SCARG(uap, path));
1320 if ((error = namei(&nd)) != 0)
1321 return error;
1323 if ((error = copyoutstr(nd.ni_cnd.cn_pnbuf, SCARG(uap, buf),
1324 SCARG(uap, bufsiz), &len)) != 0)
1325 goto bad;
1327 *retval = len;
1328 bad:
1329 vrele(nd.ni_vp);
1330 PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
1331 return error;