2 * Copyright (c) 1995 Steven Wallace
3 * Copyright (c) 1994, 1995 Scott Bartram
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93
49 #include <sys/cdefs.h>
50 __FBSDID("$FreeBSD$");
53 * IBCS2 compatibility module.
55 * IBCS2 system calls that are implemented differently in BSD are
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/capsicum.h>
61 #include <sys/dirent.h>
62 #include <sys/fcntl.h>
63 #include <sys/filedesc.h>
64 #include <sys/imgact.h>
65 #include <sys/kernel.h>
67 #include <sys/malloc.h>
68 #include <sys/file.h> /* Must come after sys/malloc.h */
69 #include <sys/mutex.h>
70 #include <sys/namei.h>
72 #include <sys/reboot.h>
73 #include <sys/resourcevar.h>
75 #include <sys/sysctl.h>
76 #include <sys/syscallsubr.h>
77 #include <sys/sysproto.h>
79 #include <sys/times.h>
80 #include <sys/vnode.h>
83 #include <machine/cpu.h>
85 #include <i386/ibcs2/ibcs2_dirent.h>
86 #include <i386/ibcs2/ibcs2_signal.h>
87 #include <i386/ibcs2/ibcs2_proto.h>
88 #include <i386/ibcs2/ibcs2_unistd.h>
89 #include <i386/ibcs2/ibcs2_util.h>
90 #include <i386/ibcs2/ibcs2_utime.h>
91 #include <i386/ibcs2/ibcs2_xenix.h>
93 #include <security/mac/mac_framework.h>
98 struct ibcs2_ulimit_args
*uap
;
102 #define IBCS2_GETFSIZE 1
103 #define IBCS2_SETFSIZE 2
104 #define IBCS2_GETPSIZE 3
105 #define IBCS2_GETDTABLESIZE 4
109 td
->td_retval
[0] = lim_cur(td
, RLIMIT_FSIZE
);
110 if (td
->td_retval
[0] == -1)
111 td
->td_retval
[0] = 0x7fffffff;
114 rl
.rlim_max
= lim_max(td
, RLIMIT_FSIZE
);
115 rl
.rlim_cur
= uap
->newlimit
;
116 error
= kern_setrlimit(td
, RLIMIT_FSIZE
, &rl
);
118 td
->td_retval
[0] = lim_cur(td
, RLIMIT_FSIZE
);
120 DPRINTF(("failed "));
124 td
->td_retval
[0] = lim_cur(td
, RLIMIT_RSS
); /* XXX */
126 case IBCS2_GETDTABLESIZE
:
127 uap
->cmd
= IBCS2_SC_OPEN_MAX
;
128 return ibcs2_sysconf(td
, (struct ibcs2_sysconf_args
*)uap
);
134 #define IBCS2_WSTOPPED 0177
135 #define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED)
139 struct ibcs2_wait_args
*uap
;
141 int error
, options
, status
;
144 struct trapframe
*tf
= td
->td_frame
;
146 if ((tf
->tf_eflags
& (PSL_Z
|PSL_PF
|PSL_N
|PSL_V
))
147 == (PSL_Z
|PSL_PF
|PSL_N
|PSL_V
)) {
150 statusp
= (int *)uap
->a2
;
155 statusp
= (int *)uap
->a1
;
158 error
= kern_wait(td
, pid
, &status
, options
, NULL
);
163 * Convert status/signal result.
165 if (WIFSTOPPED(status
)) {
166 if (WSTOPSIG(status
) <= 0 ||
167 WSTOPSIG(status
) > IBCS2_SIGTBLSZ
)
170 IBCS2_STOPCODE(bsd_to_ibcs2_sig
[_SIG_IDX(WSTOPSIG(status
))]);
171 } else if (WIFSIGNALED(status
)) {
172 if (WTERMSIG(status
) <= 0 ||
173 WTERMSIG(status
) > IBCS2_SIGTBLSZ
)
175 status
= bsd_to_ibcs2_sig
[_SIG_IDX(WTERMSIG(status
))];
177 /* else exit status -- identical */
179 /* record result/status */
180 td
->td_retval
[1] = status
;
181 return copyout(&status
, statusp
, sizeof(status
));
190 struct ibcs2_execv_args
*uap
;
192 struct image_args eargs
;
193 struct vmspace
*oldvmspace
;
197 CHECKALTEXIST(td
, uap
->path
, &path
);
199 error
= pre_execve(td
, &oldvmspace
);
204 error
= exec_copyin_args(&eargs
, path
, UIO_SYSSPACE
, uap
->argp
, NULL
);
207 error
= kern_execve(td
, &eargs
, NULL
);
208 post_execve(td
, error
, oldvmspace
);
213 ibcs2_execve(td
, uap
)
215 struct ibcs2_execve_args
*uap
;
217 struct image_args eargs
;
218 struct vmspace
*oldvmspace
;
222 CHECKALTEXIST(td
, uap
->path
, &path
);
224 error
= pre_execve(td
, &oldvmspace
);
229 error
= exec_copyin_args(&eargs
, path
, UIO_SYSSPACE
, uap
->argp
,
233 error
= kern_execve(td
, &eargs
, NULL
);
234 post_execve(td
, error
, oldvmspace
);
239 ibcs2_umount(td
, uap
)
241 struct ibcs2_umount_args
*uap
;
243 struct unmount_args um
;
247 return sys_unmount(td
, &um
);
253 struct ibcs2_mount_args
*uap
;
256 int oflags
= uap
->flags
, nflags
, error
;
257 char fsname
[MFSNAMELEN
];
259 if (oflags
& (IBCS2_MS_NOSUB
| IBCS2_MS_SYS5
))
261 if ((oflags
& IBCS2_MS_NEWTYPE
) == 0)
264 if (oflags
& IBCS2_MS_RDONLY
)
265 nflags
|= MNT_RDONLY
;
266 if (oflags
& IBCS2_MS_NOSUID
)
267 nflags
|= MNT_NOSUID
;
268 if (oflags
& IBCS2_MS_REMOUNT
)
269 nflags
|= MNT_UPDATE
;
272 if (error
= copyinstr((caddr_t
)uap
->type
, fsname
, sizeof fsname
,
276 if (strcmp(fsname
, "4.2") == 0) {
277 uap
->type
= (caddr_t
)STACK_ALLOC();
278 if (error
= copyout("ufs", uap
->type
, sizeof("ufs")))
280 } else if (strcmp(fsname
, "nfs") == 0) {
281 struct ibcs2_nfs_args sna
;
282 struct sockaddr_in sain
;
286 if (error
= copyin(uap
->data
, &sna
, sizeof sna
))
288 if (error
= copyin(sna
.addr
, &sain
, sizeof sain
))
290 bcopy(&sain
, &sa
, sizeof sa
);
291 sa
.sa_len
= sizeof(sain
);
292 uap
->data
= (caddr_t
)STACK_ALLOC();
293 na
.addr
= (struct sockaddr
*)((int)uap
->data
+ sizeof na
);
294 na
.sotype
= SOCK_DGRAM
;
295 na
.proto
= IPPROTO_UDP
;
296 na
.fh
= (nfsv2fh_t
*)sna
.fh
;
297 na
.flags
= sna
.flags
;
298 na
.wsize
= sna
.wsize
;
299 na
.rsize
= sna
.rsize
;
300 na
.timeo
= sna
.timeo
;
301 na
.retrans
= sna
.retrans
;
302 na
.hostname
= sna
.hostname
;
304 if (error
= copyout(&sa
, na
.addr
, sizeof sa
))
306 if (error
= copyout(&na
, uap
->data
, sizeof na
))
309 return (mount(td
, uap
));
316 * Read iBCS2-style directory entries. We suck them into kernel space so
317 * that they can be massaged before being copied out to user code. Like
318 * SunOS, we squish out `empty' entries.
320 * This is quite ugly, but what do you expect from compatibility code?
324 ibcs2_getdents(td
, uap
)
326 register struct ibcs2_getdents_args
*uap
;
328 register struct vnode
*vp
;
329 register caddr_t inp
, buf
; /* BSD-format */
330 register int len
, reclen
; /* BSD-format */
331 register caddr_t outp
; /* iBCS2-format */
332 register int resid
; /* iBCS2-format */
337 struct ibcs2_dirent idb
;
338 off_t off
; /* true file offset */
339 int buflen
, error
, eofflag
;
340 u_long
*cookies
= NULL
, *cookiep
;
342 #define BSD_DIRENT(cp) ((struct dirent *)(cp))
343 #define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short))
345 error
= getvnode(td
, uap
->fd
, cap_rights_init(&rights
, CAP_READ
), &fp
);
348 if ((fp
->f_flag
& FREAD
) == 0) {
353 if (vp
->v_type
!= VDIR
) { /* XXX vnode readdir op should do this */
359 #define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
360 buflen
= max(DIRBLKSIZ
, uap
->nbytes
);
361 buflen
= min(buflen
, MAXBSIZE
);
362 buf
= malloc(buflen
, M_TEMP
, M_WAITOK
);
363 vn_lock(vp
, LK_SHARED
| LK_RETRY
);
366 aiov
.iov_len
= buflen
;
367 auio
.uio_iov
= &aiov
;
369 auio
.uio_rw
= UIO_READ
;
370 auio
.uio_segflg
= UIO_SYSSPACE
;
372 auio
.uio_resid
= buflen
;
373 auio
.uio_offset
= off
;
376 free(cookies
, M_TEMP
);
381 error
= mac_vnode_check_readdir(td
->td_ucred
, vp
);
387 * First we read into the malloc'ed buffer, then
388 * we massage it into user space, one record at a time.
390 if ((error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, &ncookies
, &cookies
)) != 0)
395 if ((len
= buflen
- auio
.uio_resid
) <= 0)
402 * When using cookies, the vfs has the option of reading from
403 * a different offset than that supplied (UFS truncates the
404 * offset to a block boundary to make sure that it never reads
405 * partway through a directory entry, even if the directory
406 * has been compacted).
408 while (len
> 0 && ncookies
> 0 && *cookiep
<= off
) {
409 len
-= BSD_DIRENT(inp
)->d_reclen
;
410 inp
+= BSD_DIRENT(inp
)->d_reclen
;
416 for (; len
> 0; len
-= reclen
) {
417 if (cookiep
&& ncookies
== 0)
419 reclen
= BSD_DIRENT(inp
)->d_reclen
;
421 printf("ibcs2_getdents: reclen=%d\n", reclen
);
425 if (BSD_DIRENT(inp
)->d_fileno
== 0) {
426 inp
+= reclen
; /* it is a hole; squish it out */
434 if (reclen
> len
|| resid
< IBCS2_RECLEN(reclen
)) {
435 /* entry too big for buffer, so just stop */
440 * Massage in place to make an iBCS2-shaped dirent (otherwise
441 * we have to worry about touching user memory outside of
442 * the copyout() call).
444 idb
.d_ino
= (ibcs2_ino_t
)BSD_DIRENT(inp
)->d_fileno
;
445 idb
.d_off
= (ibcs2_off_t
)off
;
446 idb
.d_reclen
= (u_short
)IBCS2_RECLEN(reclen
);
447 if ((error
= copyout((caddr_t
)&idb
, outp
, 10)) != 0 ||
448 (error
= copyout(BSD_DIRENT(inp
)->d_name
, outp
+ 10,
449 BSD_DIRENT(inp
)->d_namlen
+ 1)) != 0)
451 /* advance past this real entry */
458 /* advance output past iBCS2-shaped entry */
459 outp
+= IBCS2_RECLEN(reclen
);
460 resid
-= IBCS2_RECLEN(reclen
);
462 /* if we squished out the whole block, try again */
463 if (outp
== uap
->buf
)
465 fp
->f_offset
= off
; /* update the vnode offset */
467 td
->td_retval
[0] = uap
->nbytes
- resid
;
472 free(cookies
, M_TEMP
);
480 struct ibcs2_read_args
*uap
;
482 register struct vnode
*vp
;
483 register caddr_t inp
, buf
; /* BSD-format */
484 register int len
, reclen
; /* BSD-format */
485 register caddr_t outp
; /* iBCS2-format */
486 register int resid
; /* iBCS2-format */
491 struct ibcs2_direct
{
495 off_t off
; /* true file offset */
496 int buflen
, error
, eofflag
, size
;
497 u_long
*cookies
= NULL
, *cookiep
;
500 error
= getvnode(td
, uap
->fd
, cap_rights_init(&rights
, CAP_READ
), &fp
);
503 return sys_read(td
, (struct read_args
*)uap
);
507 if ((fp
->f_flag
& FREAD
) == 0) {
512 if (vp
->v_type
!= VDIR
) {
514 return sys_read(td
, (struct read_args
*)uap
);
519 DPRINTF(("ibcs2_read: read directory\n"));
521 buflen
= max(DIRBLKSIZ
, uap
->nbytes
);
522 buflen
= min(buflen
, MAXBSIZE
);
523 buf
= malloc(buflen
, M_TEMP
, M_WAITOK
);
524 vn_lock(vp
, LK_SHARED
| LK_RETRY
);
527 aiov
.iov_len
= buflen
;
528 auio
.uio_iov
= &aiov
;
530 auio
.uio_rw
= UIO_READ
;
531 auio
.uio_segflg
= UIO_SYSSPACE
;
533 auio
.uio_resid
= buflen
;
534 auio
.uio_offset
= off
;
537 free(cookies
, M_TEMP
);
542 error
= mac_vnode_check_readdir(td
->td_ucred
, vp
);
548 * First we read into the malloc'ed buffer, then
549 * we massage it into user space, one record at a time.
551 if ((error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
, &ncookies
, &cookies
)) != 0) {
552 DPRINTF(("VOP_READDIR failed: %d\n", error
));
558 if ((len
= buflen
- auio
.uio_resid
) <= 0)
565 * When using cookies, the vfs has the option of reading from
566 * a different offset than that supplied (UFS truncates the
567 * offset to a block boundary to make sure that it never reads
568 * partway through a directory entry, even if the directory
569 * has been compacted).
571 while (len
> 0 && ncookies
> 0 && *cookiep
<= off
) {
572 len
-= BSD_DIRENT(inp
)->d_reclen
;
573 inp
+= BSD_DIRENT(inp
)->d_reclen
;
579 for (; len
> 0 && resid
> 0; len
-= reclen
) {
580 if (cookiep
&& ncookies
== 0)
582 reclen
= BSD_DIRENT(inp
)->d_reclen
;
584 printf("ibcs2_read: reclen=%d\n", reclen
);
588 if (BSD_DIRENT(inp
)->d_fileno
== 0) {
589 inp
+= reclen
; /* it is a hole; squish it out */
597 if (reclen
> len
|| resid
< sizeof(struct ibcs2_direct
)) {
598 /* entry too big for buffer, so just stop */
603 * Massage in place to make an iBCS2-shaped dirent (otherwise
604 * we have to worry about touching user memory outside of
605 * the copyout() call).
607 * TODO: if length(filename) > 14, then break filename into
608 * multiple entries and set inode = 0xffff except last
610 idb
.ino
= (BSD_DIRENT(inp
)->d_fileno
> 0xfffe) ? 0xfffe :
611 BSD_DIRENT(inp
)->d_fileno
;
612 (void)copystr(BSD_DIRENT(inp
)->d_name
, idb
.name
, 14, &size
);
613 bzero(idb
.name
+ size
, 14 - size
);
614 if ((error
= copyout(&idb
, outp
, sizeof(struct ibcs2_direct
))) != 0)
616 /* advance past this real entry */
623 /* advance output past iBCS2-shaped entry */
624 outp
+= sizeof(struct ibcs2_direct
);
625 resid
-= sizeof(struct ibcs2_direct
);
627 /* if we squished out the whole block, try again */
628 if (outp
== uap
->buf
)
630 fp
->f_offset
= off
; /* update the vnode offset */
632 td
->td_retval
[0] = uap
->nbytes
- resid
;
637 free(cookies
, M_TEMP
);
645 struct ibcs2_mknod_args
*uap
;
650 CHECKALTCREAT(td
, uap
->path
, &path
);
651 if (S_ISFIFO(uap
->mode
)) {
652 error
= kern_mkfifoat(td
, AT_FDCWD
, path
,
653 UIO_SYSSPACE
, uap
->mode
);
655 error
= kern_mknodat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
,
656 uap
->mode
, uap
->dev
);
663 ibcs2_getgroups(td
, uap
)
665 struct ibcs2_getgroups_args
*uap
;
673 ngrp
= cred
->cr_ngroups
;
675 if (uap
->gidsetsize
== 0) {
679 if (uap
->gidsetsize
< ngrp
)
682 iset
= malloc(ngrp
* sizeof(*iset
), M_TEMP
, M_WAITOK
);
683 for (i
= 0; i
< ngrp
; i
++)
684 iset
[i
] = (ibcs2_gid_t
)cred
->cr_groups
[i
];
685 error
= copyout(iset
, uap
->gidset
, ngrp
* sizeof(ibcs2_gid_t
));
688 td
->td_retval
[0] = ngrp
;
693 ibcs2_setgroups(td
, uap
)
695 struct ibcs2_setgroups_args
*uap
;
701 if (uap
->gidsetsize
< 0 || uap
->gidsetsize
> ngroups_max
+ 1)
703 if (uap
->gidsetsize
&& uap
->gidset
== NULL
)
705 gp
= malloc(uap
->gidsetsize
* sizeof(*gp
), M_TEMP
, M_WAITOK
);
706 if (uap
->gidsetsize
) {
707 iset
= malloc(uap
->gidsetsize
* sizeof(*iset
), M_TEMP
, M_WAITOK
);
708 error
= copyin(uap
->gidset
, iset
, sizeof(ibcs2_gid_t
) *
714 for (i
= 0; i
< uap
->gidsetsize
; i
++)
715 gp
[i
] = (gid_t
)iset
[i
];
718 error
= kern_setgroups(td
, uap
->gidsetsize
, gp
);
725 ibcs2_setuid(td
, uap
)
727 struct ibcs2_setuid_args
*uap
;
729 struct setuid_args sa
;
731 sa
.uid
= (uid_t
)uap
->uid
;
732 return sys_setuid(td
, &sa
);
736 ibcs2_setgid(td
, uap
)
738 struct ibcs2_setgid_args
*uap
;
740 struct setgid_args sa
;
742 sa
.gid
= (gid_t
)uap
->gid
;
743 return sys_setgid(td
, &sa
);
749 struct ibcs2_time_args
*uap
;
754 td
->td_retval
[0] = tv
.tv_sec
;
756 return copyout((caddr_t
)&tv
.tv_sec
, (caddr_t
)uap
->tp
,
757 sizeof(ibcs2_time_t
));
763 ibcs2_pathconf(td
, uap
)
765 struct ibcs2_pathconf_args
*uap
;
770 CHECKALTEXIST(td
, uap
->path
, &path
);
771 uap
->name
++; /* iBCS2 _PC_* defines are offset by one */
772 error
= kern_pathconf(td
, path
, UIO_SYSSPACE
, uap
->name
, FOLLOW
);
778 ibcs2_fpathconf(td
, uap
)
780 struct ibcs2_fpathconf_args
*uap
;
782 uap
->name
++; /* iBCS2 _PC_* defines are offset by one */
783 return sys_fpathconf(td
, (struct fpathconf_args
*)uap
);
787 ibcs2_sysconf(td
, uap
)
789 struct ibcs2_sysconf_args
*uap
;
791 int mib
[2], value
, len
, error
;
794 case IBCS2_SC_ARG_MAX
:
795 mib
[1] = KERN_ARGMAX
;
798 case IBCS2_SC_CHILD_MAX
:
799 td
->td_retval
[0] = lim_cur(td
, RLIMIT_NPROC
);
802 case IBCS2_SC_CLK_TCK
:
803 td
->td_retval
[0] = hz
;
806 case IBCS2_SC_NGROUPS_MAX
:
807 mib
[1] = KERN_NGROUPS
;
810 case IBCS2_SC_OPEN_MAX
:
811 td
->td_retval
[0] = lim_cur(td
, RLIMIT_NOFILE
);
814 case IBCS2_SC_JOB_CONTROL
:
815 mib
[1] = KERN_JOB_CONTROL
;
818 case IBCS2_SC_SAVED_IDS
:
819 mib
[1] = KERN_SAVED_IDS
;
822 case IBCS2_SC_VERSION
:
823 mib
[1] = KERN_POSIX1
;
826 case IBCS2_SC_PASS_MAX
:
827 td
->td_retval
[0] = 128; /* XXX - should we create PASS_MAX ? */
830 case IBCS2_SC_XOPEN_VERSION
:
831 td
->td_retval
[0] = 2; /* XXX: What should that be? */
840 error
= kernel_sysctl(td
, mib
, 2, &value
, &len
, NULL
, 0, NULL
, 0);
843 td
->td_retval
[0] = value
;
850 struct ibcs2_alarm_args
*uap
;
852 struct itimerval itv
, oitv
;
855 timevalclear(&itv
.it_interval
);
856 itv
.it_value
.tv_sec
= uap
->sec
;
857 itv
.it_value
.tv_usec
= 0;
858 error
= kern_setitimer(td
, ITIMER_REAL
, &itv
, &oitv
);
861 if (oitv
.it_value
.tv_usec
!= 0)
862 oitv
.it_value
.tv_sec
++;
863 td
->td_retval
[0] = oitv
.it_value
.tv_sec
;
870 struct ibcs2_times_args
*uap
;
877 #define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
879 error
= kern_getrusage(td
, RUSAGE_SELF
, &ru
);
882 tms
.tms_utime
= CONVTCK(ru
.ru_utime
);
883 tms
.tms_stime
= CONVTCK(ru
.ru_stime
);
885 error
= kern_getrusage(td
, RUSAGE_CHILDREN
, &ru
);
888 tms
.tms_cutime
= CONVTCK(ru
.ru_utime
);
889 tms
.tms_cstime
= CONVTCK(ru
.ru_stime
);
892 td
->td_retval
[0] = CONVTCK(t
);
894 return (copyout(&tms
, uap
->tp
, sizeof(struct tms
)));
900 struct ibcs2_stime_args
*uap
;
906 error
= copyin(uap
->timep
, &secs
, sizeof(long));
911 error
= kern_settimeofday(td
, &tv
, NULL
);
920 struct ibcs2_utime_args
*uap
;
922 struct ibcs2_utimbuf ubuf
;
923 struct timeval tbuf
[2], *tp
;
928 error
= copyin(uap
->buf
, &ubuf
, sizeof(ubuf
));
931 tbuf
[0].tv_sec
= ubuf
.actime
;
933 tbuf
[1].tv_sec
= ubuf
.modtime
;
939 CHECKALTEXIST(td
, uap
->path
, &path
);
940 error
= kern_utimesat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
,
949 struct ibcs2_nice_args
*uap
;
952 struct setpriority_args sa
;
954 sa
.which
= PRIO_PROCESS
;
956 sa
.prio
= td
->td_proc
->p_nice
+ uap
->incr
;
957 if ((error
= sys_setpriority(td
, &sa
)) != 0)
959 td
->td_retval
[0] = td
->td_proc
->p_nice
;
964 * iBCS2 getpgrp, setpgrp, setsid, and setpgid
968 ibcs2_pgrpsys(td
, uap
)
970 struct ibcs2_pgrpsys_args
*uap
;
972 struct proc
*p
= td
->td_proc
;
974 case 0: /* getpgrp */
976 td
->td_retval
[0] = p
->p_pgrp
->pg_id
;
980 case 1: /* setpgrp */
982 struct setpgid_args sa
;
986 sys_setpgid(td
, &sa
);
988 td
->td_retval
[0] = p
->p_pgrp
->pg_id
;
993 case 2: /* setpgid */
995 struct setpgid_args sa
;
999 return sys_setpgid(td
, &sa
);
1002 case 3: /* setsid */
1003 return sys_setsid(td
, NULL
);
1011 * XXX - need to check for nested calls
1015 ibcs2_plock(td
, uap
)
1017 struct ibcs2_plock_args
*uap
;
1020 #define IBCS2_UNLOCK 0
1021 #define IBCS2_PROCLOCK 1
1022 #define IBCS2_TEXTLOCK 2
1023 #define IBCS2_DATALOCK 4
1028 error
= priv_check(td
, PRIV_VM_MUNLOCK
);
1034 case IBCS2_PROCLOCK
:
1035 case IBCS2_TEXTLOCK
:
1036 case IBCS2_DATALOCK
:
1037 error
= priv_check(td
, PRIV_VM_MLOCK
);
1047 ibcs2_uadmin(td
, uap
)
1049 struct ibcs2_uadmin_args
*uap
;
1051 #define SCO_A_REBOOT 1
1052 #define SCO_A_SHUTDOWN 2
1053 #define SCO_A_REMOUNT 4
1054 #define SCO_A_CLOCK 8
1055 #define SCO_A_SETCONFIG 128
1056 #define SCO_A_GETDEV 130
1058 #define SCO_AD_HALT 0
1059 #define SCO_AD_BOOT 1
1060 #define SCO_AD_IBOOT 2
1061 #define SCO_AD_PWRDOWN 3
1062 #define SCO_AD_PWRNAP 4
1064 #define SCO_AD_PANICBOOT 1
1066 #define SCO_AD_GETBMAJ 0
1067 #define SCO_AD_GETCMAJ 1
1071 case SCO_A_SHUTDOWN
:
1073 struct reboot_args r
;
1075 case SCO_AD_PWRDOWN
:
1078 return (sys_reboot(td
, &r
));
1081 r
.opt
= RB_AUTOBOOT
;
1082 return (sys_reboot(td
, &r
));
1087 case SCO_A_SETCONFIG
:
1090 return EINVAL
; /* XXX - TODO */
1096 ibcs2_sysfs(td
, uap
)
1098 struct ibcs2_sysfs_args
*uap
;
1100 #define IBCS2_GETFSIND 1
1101 #define IBCS2_GETFSTYP 2
1102 #define IBCS2_GETNFSTYP 3
1105 case IBCS2_GETFSIND
:
1106 case IBCS2_GETFSTYP
:
1107 case IBCS2_GETNFSTYP
:
1110 return EINVAL
; /* XXX - TODO */
1114 ibcs2_unlink(td
, uap
)
1116 struct ibcs2_unlink_args
*uap
;
1121 CHECKALTEXIST(td
, uap
->path
, &path
);
1122 error
= kern_unlinkat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
, 0);
1128 ibcs2_chdir(td
, uap
)
1130 struct ibcs2_chdir_args
*uap
;
1135 CHECKALTEXIST(td
, uap
->path
, &path
);
1136 error
= kern_chdir(td
, path
, UIO_SYSSPACE
);
1142 ibcs2_chmod(td
, uap
)
1144 struct ibcs2_chmod_args
*uap
;
1149 CHECKALTEXIST(td
, uap
->path
, &path
);
1150 error
= kern_fchmodat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
, uap
->mode
, 0);
1156 ibcs2_chown(td
, uap
)
1158 struct ibcs2_chown_args
*uap
;
1163 CHECKALTEXIST(td
, uap
->path
, &path
);
1164 error
= kern_fchownat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
, uap
->uid
,
1171 ibcs2_rmdir(td
, uap
)
1173 struct ibcs2_rmdir_args
*uap
;
1178 CHECKALTEXIST(td
, uap
->path
, &path
);
1179 error
= kern_rmdirat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
);
1185 ibcs2_mkdir(td
, uap
)
1187 struct ibcs2_mkdir_args
*uap
;
1192 CHECKALTEXIST(td
, uap
->path
, &path
);
1193 error
= kern_mkdirat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
, uap
->mode
);
1199 ibcs2_symlink(td
, uap
)
1201 struct ibcs2_symlink_args
*uap
;
1206 CHECKALTEXIST(td
, uap
->path
, &path
);
1209 * Have to expand CHECKALTCREAT() so that 'path' can be freed on
1212 error
= ibcs2_emul_find(td
, uap
->link
, UIO_USERSPACE
, &link
, 1);
1217 error
= kern_symlinkat(td
, path
, AT_FDCWD
, link
, UIO_SYSSPACE
);
1224 ibcs2_rename(td
, uap
)
1226 struct ibcs2_rename_args
*uap
;
1231 CHECKALTEXIST(td
, uap
->from
, &from
);
1234 * Have to expand CHECKALTCREAT() so that 'from' can be freed on
1237 error
= ibcs2_emul_find(td
, uap
->to
, UIO_USERSPACE
, &to
, 1);
1242 error
= kern_renameat(td
, AT_FDCWD
, from
, AT_FDCWD
, to
, UIO_SYSSPACE
);
1249 ibcs2_readlink(td
, uap
)
1251 struct ibcs2_readlink_args
*uap
;
1256 CHECKALTEXIST(td
, uap
->path
, &path
);
1257 error
= kern_readlinkat(td
, AT_FDCWD
, path
, UIO_SYSSPACE
,
1258 uap
->buf
, UIO_USERSPACE
, uap
->count
);