ibcs2_misc.c revision 280258
1/*- 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. 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. 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. 31 * 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 42 * SUCH DAMAGE. 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * 46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 47 */ 48 49#include <sys/cdefs.h> 50__FBSDID("$FreeBSD: stable/10/sys/i386/ibcs2/ibcs2_misc.c 280258 2015-03-19 13:37:36Z rwatson $"); 51 52/* 53 * IBCS2 compatibility module. 54 * 55 * IBCS2 system calls that are implemented differently in BSD are 56 * handled here. 57 */ 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> 66#include <sys/lock.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> 71#include <sys/priv.h> 72#include <sys/reboot.h> 73#include <sys/resourcevar.h> 74#include <sys/stat.h> 75#include <sys/sysctl.h> 76#include <sys/syscallsubr.h> 77#include <sys/sysproto.h> 78#include <sys/time.h> 79#include <sys/times.h> 80#include <sys/vnode.h> 81#include <sys/wait.h> 82 83#include <machine/cpu.h> 84 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> 92 93#include <security/mac/mac_framework.h> 94 95int 96ibcs2_ulimit(td, uap) 97 struct thread *td; 98 struct ibcs2_ulimit_args *uap; 99{ 100 struct rlimit rl; 101 struct proc *p; 102 int error; 103#define IBCS2_GETFSIZE 1 104#define IBCS2_SETFSIZE 2 105#define IBCS2_GETPSIZE 3 106#define IBCS2_GETDTABLESIZE 4 107 108 p = td->td_proc; 109 switch (uap->cmd) { 110 case IBCS2_GETFSIZE: 111 PROC_LOCK(p); 112 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 113 PROC_UNLOCK(p); 114 if (td->td_retval[0] == -1) 115 td->td_retval[0] = 0x7fffffff; 116 return 0; 117 case IBCS2_SETFSIZE: 118 PROC_LOCK(p); 119 rl.rlim_max = lim_max(p, RLIMIT_FSIZE); 120 PROC_UNLOCK(p); 121 rl.rlim_cur = uap->newlimit; 122 error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); 123 if (!error) { 124 PROC_LOCK(p); 125 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 126 PROC_UNLOCK(p); 127 } else { 128 DPRINTF(("failed ")); 129 } 130 return error; 131 case IBCS2_GETPSIZE: 132 PROC_LOCK(p); 133 td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ 134 PROC_UNLOCK(p); 135 return 0; 136 case IBCS2_GETDTABLESIZE: 137 uap->cmd = IBCS2_SC_OPEN_MAX; 138 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap); 139 default: 140 return ENOSYS; 141 } 142} 143 144#define IBCS2_WSTOPPED 0177 145#define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED) 146int 147ibcs2_wait(td, uap) 148 struct thread *td; 149 struct ibcs2_wait_args *uap; 150{ 151 int error, options, status; 152 int *statusp; 153 pid_t pid; 154 struct trapframe *tf = td->td_frame; 155 156 if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) 157 == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { 158 /* waitpid */ 159 pid = uap->a1; 160 statusp = (int *)uap->a2; 161 options = uap->a3; 162 } else { 163 /* wait */ 164 pid = WAIT_ANY; 165 statusp = (int *)uap->a1; 166 options = 0; 167 } 168 error = kern_wait(td, pid, &status, options, NULL); 169 if (error) 170 return error; 171 if (statusp) { 172 /* 173 * Convert status/signal result. 174 */ 175 if (WIFSTOPPED(status)) { 176 if (WSTOPSIG(status) <= 0 || 177 WSTOPSIG(status) > IBCS2_SIGTBLSZ) 178 return (EINVAL); 179 status = 180 IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]); 181 } else if (WIFSIGNALED(status)) { 182 if (WTERMSIG(status) <= 0 || 183 WTERMSIG(status) > IBCS2_SIGTBLSZ) 184 return (EINVAL); 185 status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))]; 186 } 187 /* else exit status -- identical */ 188 189 /* record result/status */ 190 td->td_retval[1] = status; 191 return copyout(&status, statusp, sizeof(status)); 192 } 193 194 return 0; 195} 196 197int 198ibcs2_execv(td, uap) 199 struct thread *td; 200 struct ibcs2_execv_args *uap; 201{ 202 struct image_args eargs; 203 char *path; 204 int error; 205 206 CHECKALTEXIST(td, uap->path, &path); 207 208 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL); 209 free(path, M_TEMP); 210 if (error == 0) 211 error = kern_execve(td, &eargs, NULL); 212 return (error); 213} 214 215int 216ibcs2_execve(td, uap) 217 struct thread *td; 218 struct ibcs2_execve_args *uap; 219{ 220 struct image_args eargs; 221 char *path; 222 int error; 223 224 CHECKALTEXIST(td, uap->path, &path); 225 226 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, 227 uap->envp); 228 free(path, M_TEMP); 229 if (error == 0) 230 error = kern_execve(td, &eargs, NULL); 231 return (error); 232} 233 234int 235ibcs2_umount(td, uap) 236 struct thread *td; 237 struct ibcs2_umount_args *uap; 238{ 239 struct unmount_args um; 240 241 um.path = uap->name; 242 um.flags = 0; 243 return sys_unmount(td, &um); 244} 245 246int 247ibcs2_mount(td, uap) 248 struct thread *td; 249 struct ibcs2_mount_args *uap; 250{ 251#ifdef notyet 252 int oflags = uap->flags, nflags, error; 253 char fsname[MFSNAMELEN]; 254 255 if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5)) 256 return (EINVAL); 257 if ((oflags & IBCS2_MS_NEWTYPE) == 0) 258 return (EINVAL); 259 nflags = 0; 260 if (oflags & IBCS2_MS_RDONLY) 261 nflags |= MNT_RDONLY; 262 if (oflags & IBCS2_MS_NOSUID) 263 nflags |= MNT_NOSUID; 264 if (oflags & IBCS2_MS_REMOUNT) 265 nflags |= MNT_UPDATE; 266 uap->flags = nflags; 267 268 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, 269 (u_int *)0)) 270 return (error); 271 272 if (strcmp(fsname, "4.2") == 0) { 273 uap->type = (caddr_t)STACK_ALLOC(); 274 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 275 return (error); 276 } else if (strcmp(fsname, "nfs") == 0) { 277 struct ibcs2_nfs_args sna; 278 struct sockaddr_in sain; 279 struct nfs_args na; 280 struct sockaddr sa; 281 282 if (error = copyin(uap->data, &sna, sizeof sna)) 283 return (error); 284 if (error = copyin(sna.addr, &sain, sizeof sain)) 285 return (error); 286 bcopy(&sain, &sa, sizeof sa); 287 sa.sa_len = sizeof(sain); 288 uap->data = (caddr_t)STACK_ALLOC(); 289 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 290 na.sotype = SOCK_DGRAM; 291 na.proto = IPPROTO_UDP; 292 na.fh = (nfsv2fh_t *)sna.fh; 293 na.flags = sna.flags; 294 na.wsize = sna.wsize; 295 na.rsize = sna.rsize; 296 na.timeo = sna.timeo; 297 na.retrans = sna.retrans; 298 na.hostname = sna.hostname; 299 300 if (error = copyout(&sa, na.addr, sizeof sa)) 301 return (error); 302 if (error = copyout(&na, uap->data, sizeof na)) 303 return (error); 304 } 305 return (mount(td, uap)); 306#else 307 return EINVAL; 308#endif 309} 310 311/* 312 * Read iBCS2-style directory entries. We suck them into kernel space so 313 * that they can be massaged before being copied out to user code. Like 314 * SunOS, we squish out `empty' entries. 315 * 316 * This is quite ugly, but what do you expect from compatibility code? 317 */ 318 319int 320ibcs2_getdents(td, uap) 321 struct thread *td; 322 register struct ibcs2_getdents_args *uap; 323{ 324 register struct vnode *vp; 325 register caddr_t inp, buf; /* BSD-format */ 326 register int len, reclen; /* BSD-format */ 327 register caddr_t outp; /* iBCS2-format */ 328 register int resid; /* iBCS2-format */ 329 cap_rights_t rights; 330 struct file *fp; 331 struct uio auio; 332 struct iovec aiov; 333 struct ibcs2_dirent idb; 334 off_t off; /* true file offset */ 335 int buflen, error, eofflag; 336 u_long *cookies = NULL, *cookiep; 337 int ncookies; 338#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 339#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) 340 341 error = getvnode(td->td_proc->p_fd, uap->fd, 342 cap_rights_init(&rights, CAP_READ), &fp); 343 if (error != 0) 344 return (error); 345 if ((fp->f_flag & FREAD) == 0) { 346 fdrop(fp, td); 347 return (EBADF); 348 } 349 vp = fp->f_vnode; 350 if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 351 fdrop(fp, td); 352 return (EINVAL); 353 } 354 355 off = fp->f_offset; 356#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 357 buflen = max(DIRBLKSIZ, uap->nbytes); 358 buflen = min(buflen, MAXBSIZE); 359 buf = malloc(buflen, M_TEMP, M_WAITOK); 360 vn_lock(vp, LK_SHARED | LK_RETRY); 361again: 362 aiov.iov_base = buf; 363 aiov.iov_len = buflen; 364 auio.uio_iov = &aiov; 365 auio.uio_iovcnt = 1; 366 auio.uio_rw = UIO_READ; 367 auio.uio_segflg = UIO_SYSSPACE; 368 auio.uio_td = td; 369 auio.uio_resid = buflen; 370 auio.uio_offset = off; 371 372 if (cookies) { 373 free(cookies, M_TEMP); 374 cookies = NULL; 375 } 376 377#ifdef MAC 378 error = mac_vnode_check_readdir(td->td_ucred, vp); 379 if (error) 380 goto out; 381#endif 382 383 /* 384 * First we read into the malloc'ed buffer, then 385 * we massage it into user space, one record at a time. 386 */ 387 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 388 goto out; 389 inp = buf; 390 outp = uap->buf; 391 resid = uap->nbytes; 392 if ((len = buflen - auio.uio_resid) <= 0) 393 goto eof; 394 395 cookiep = cookies; 396 397 if (cookies) { 398 /* 399 * When using cookies, the vfs has the option of reading from 400 * a different offset than that supplied (UFS truncates the 401 * offset to a block boundary to make sure that it never reads 402 * partway through a directory entry, even if the directory 403 * has been compacted). 404 */ 405 while (len > 0 && ncookies > 0 && *cookiep <= off) { 406 len -= BSD_DIRENT(inp)->d_reclen; 407 inp += BSD_DIRENT(inp)->d_reclen; 408 cookiep++; 409 ncookies--; 410 } 411 } 412 413 for (; len > 0; len -= reclen) { 414 if (cookiep && ncookies == 0) 415 break; 416 reclen = BSD_DIRENT(inp)->d_reclen; 417 if (reclen & 3) { 418 printf("ibcs2_getdents: reclen=%d\n", reclen); 419 error = EFAULT; 420 goto out; 421 } 422 if (BSD_DIRENT(inp)->d_fileno == 0) { 423 inp += reclen; /* it is a hole; squish it out */ 424 if (cookiep) { 425 off = *cookiep++; 426 ncookies--; 427 } else 428 off += reclen; 429 continue; 430 } 431 if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 432 /* entry too big for buffer, so just stop */ 433 outp++; 434 break; 435 } 436 /* 437 * Massage in place to make an iBCS2-shaped dirent (otherwise 438 * we have to worry about touching user memory outside of 439 * the copyout() call). 440 */ 441 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 442 idb.d_off = (ibcs2_off_t)off; 443 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 444 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 445 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 446 BSD_DIRENT(inp)->d_namlen + 1)) != 0) 447 goto out; 448 /* advance past this real entry */ 449 if (cookiep) { 450 off = *cookiep++; 451 ncookies--; 452 } else 453 off += reclen; 454 inp += reclen; 455 /* advance output past iBCS2-shaped entry */ 456 outp += IBCS2_RECLEN(reclen); 457 resid -= IBCS2_RECLEN(reclen); 458 } 459 /* if we squished out the whole block, try again */ 460 if (outp == uap->buf) 461 goto again; 462 fp->f_offset = off; /* update the vnode offset */ 463eof: 464 td->td_retval[0] = uap->nbytes - resid; 465out: 466 VOP_UNLOCK(vp, 0); 467 fdrop(fp, td); 468 if (cookies) 469 free(cookies, M_TEMP); 470 free(buf, M_TEMP); 471 return (error); 472} 473 474int 475ibcs2_read(td, uap) 476 struct thread *td; 477 struct ibcs2_read_args *uap; 478{ 479 register struct vnode *vp; 480 register caddr_t inp, buf; /* BSD-format */ 481 register int len, reclen; /* BSD-format */ 482 register caddr_t outp; /* iBCS2-format */ 483 register int resid; /* iBCS2-format */ 484 cap_rights_t rights; 485 struct file *fp; 486 struct uio auio; 487 struct iovec aiov; 488 struct ibcs2_direct { 489 ibcs2_ino_t ino; 490 char name[14]; 491 } idb; 492 off_t off; /* true file offset */ 493 int buflen, error, eofflag, size; 494 u_long *cookies = NULL, *cookiep; 495 int ncookies; 496 497 error = getvnode(td->td_proc->p_fd, uap->fd, 498 cap_rights_init(&rights, CAP_READ), &fp); 499 if (error != 0) { 500 if (error == EINVAL) 501 return sys_read(td, (struct read_args *)uap); 502 else 503 return error; 504 } 505 if ((fp->f_flag & FREAD) == 0) { 506 fdrop(fp, td); 507 return (EBADF); 508 } 509 vp = fp->f_vnode; 510 if (vp->v_type != VDIR) { 511 fdrop(fp, td); 512 return sys_read(td, (struct read_args *)uap); 513 } 514 515 off = fp->f_offset; 516 517 DPRINTF(("ibcs2_read: read directory\n")); 518 519 buflen = max(DIRBLKSIZ, uap->nbytes); 520 buflen = min(buflen, MAXBSIZE); 521 buf = malloc(buflen, M_TEMP, M_WAITOK); 522 vn_lock(vp, LK_SHARED | LK_RETRY); 523again: 524 aiov.iov_base = buf; 525 aiov.iov_len = buflen; 526 auio.uio_iov = &aiov; 527 auio.uio_iovcnt = 1; 528 auio.uio_rw = UIO_READ; 529 auio.uio_segflg = UIO_SYSSPACE; 530 auio.uio_td = td; 531 auio.uio_resid = buflen; 532 auio.uio_offset = off; 533 534 if (cookies) { 535 free(cookies, M_TEMP); 536 cookies = NULL; 537 } 538 539#ifdef MAC 540 error = mac_vnode_check_readdir(td->td_ucred, vp); 541 if (error) 542 goto out; 543#endif 544 545 /* 546 * First we read into the malloc'ed buffer, then 547 * we massage it into user space, one record at a time. 548 */ 549 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 550 DPRINTF(("VOP_READDIR failed: %d\n", error)); 551 goto out; 552 } 553 inp = buf; 554 outp = uap->buf; 555 resid = uap->nbytes; 556 if ((len = buflen - auio.uio_resid) <= 0) 557 goto eof; 558 559 cookiep = cookies; 560 561 if (cookies) { 562 /* 563 * When using cookies, the vfs has the option of reading from 564 * a different offset than that supplied (UFS truncates the 565 * offset to a block boundary to make sure that it never reads 566 * partway through a directory entry, even if the directory 567 * has been compacted). 568 */ 569 while (len > 0 && ncookies > 0 && *cookiep <= off) { 570 len -= BSD_DIRENT(inp)->d_reclen; 571 inp += BSD_DIRENT(inp)->d_reclen; 572 cookiep++; 573 ncookies--; 574 } 575 } 576 577 for (; len > 0 && resid > 0; len -= reclen) { 578 if (cookiep && ncookies == 0) 579 break; 580 reclen = BSD_DIRENT(inp)->d_reclen; 581 if (reclen & 3) { 582 printf("ibcs2_read: reclen=%d\n", reclen); 583 error = EFAULT; 584 goto out; 585 } 586 if (BSD_DIRENT(inp)->d_fileno == 0) { 587 inp += reclen; /* it is a hole; squish it out */ 588 if (cookiep) { 589 off = *cookiep++; 590 ncookies--; 591 } else 592 off += reclen; 593 continue; 594 } 595 if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 596 /* entry too big for buffer, so just stop */ 597 outp++; 598 break; 599 } 600 /* 601 * Massage in place to make an iBCS2-shaped dirent (otherwise 602 * we have to worry about touching user memory outside of 603 * the copyout() call). 604 * 605 * TODO: if length(filename) > 14, then break filename into 606 * multiple entries and set inode = 0xffff except last 607 */ 608 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 609 BSD_DIRENT(inp)->d_fileno; 610 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 611 bzero(idb.name + size, 14 - size); 612 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 613 goto out; 614 /* advance past this real entry */ 615 if (cookiep) { 616 off = *cookiep++; 617 ncookies--; 618 } else 619 off += reclen; 620 inp += reclen; 621 /* advance output past iBCS2-shaped entry */ 622 outp += sizeof(struct ibcs2_direct); 623 resid -= sizeof(struct ibcs2_direct); 624 } 625 /* if we squished out the whole block, try again */ 626 if (outp == uap->buf) 627 goto again; 628 fp->f_offset = off; /* update the vnode offset */ 629eof: 630 td->td_retval[0] = uap->nbytes - resid; 631out: 632 VOP_UNLOCK(vp, 0); 633 fdrop(fp, td); 634 if (cookies) 635 free(cookies, M_TEMP); 636 free(buf, M_TEMP); 637 return (error); 638} 639 640int 641ibcs2_mknod(td, uap) 642 struct thread *td; 643 struct ibcs2_mknod_args *uap; 644{ 645 char *path; 646 int error; 647 648 CHECKALTCREAT(td, uap->path, &path); 649 if (S_ISFIFO(uap->mode)) 650 error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 651 else 652 error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 653 free(path, M_TEMP); 654 return (error); 655} 656 657int 658ibcs2_getgroups(td, uap) 659 struct thread *td; 660 struct ibcs2_getgroups_args *uap; 661{ 662 ibcs2_gid_t *iset; 663 gid_t *gp; 664 u_int i, ngrp; 665 int error; 666 667 if (uap->gidsetsize < td->td_ucred->cr_ngroups) { 668 if (uap->gidsetsize == 0) 669 ngrp = 0; 670 else 671 return (EINVAL); 672 } else 673 ngrp = td->td_ucred->cr_ngroups; 674 gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); 675 error = kern_getgroups(td, &ngrp, gp); 676 if (error) 677 goto out; 678 if (uap->gidsetsize > 0) { 679 iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); 680 for (i = 0; i < ngrp; i++) 681 iset[i] = (ibcs2_gid_t)gp[i]; 682 error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); 683 free(iset, M_TEMP); 684 } 685 if (error == 0) 686 td->td_retval[0] = ngrp; 687out: 688 free(gp, M_TEMP); 689 return (error); 690} 691 692int 693ibcs2_setgroups(td, uap) 694 struct thread *td; 695 struct ibcs2_setgroups_args *uap; 696{ 697 ibcs2_gid_t *iset; 698 gid_t *gp; 699 int error, i; 700 701 if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1) 702 return (EINVAL); 703 if (uap->gidsetsize && uap->gidset == NULL) 704 return (EINVAL); 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) * 709 uap->gidsetsize); 710 if (error) { 711 free(iset, M_TEMP); 712 goto out; 713 } 714 for (i = 0; i < uap->gidsetsize; i++) 715 gp[i] = (gid_t)iset[i]; 716 } 717 718 error = kern_setgroups(td, uap->gidsetsize, gp); 719out: 720 free(gp, M_TEMP); 721 return (error); 722} 723 724int 725ibcs2_setuid(td, uap) 726 struct thread *td; 727 struct ibcs2_setuid_args *uap; 728{ 729 struct setuid_args sa; 730 731 sa.uid = (uid_t)uap->uid; 732 return sys_setuid(td, &sa); 733} 734 735int 736ibcs2_setgid(td, uap) 737 struct thread *td; 738 struct ibcs2_setgid_args *uap; 739{ 740 struct setgid_args sa; 741 742 sa.gid = (gid_t)uap->gid; 743 return sys_setgid(td, &sa); 744} 745 746int 747ibcs2_time(td, uap) 748 struct thread *td; 749 struct ibcs2_time_args *uap; 750{ 751 struct timeval tv; 752 753 microtime(&tv); 754 td->td_retval[0] = tv.tv_sec; 755 if (uap->tp) 756 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 757 sizeof(ibcs2_time_t)); 758 else 759 return 0; 760} 761 762int 763ibcs2_pathconf(td, uap) 764 struct thread *td; 765 struct ibcs2_pathconf_args *uap; 766{ 767 char *path; 768 int error; 769 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); 773 free(path, M_TEMP); 774 return (error); 775} 776 777int 778ibcs2_fpathconf(td, uap) 779 struct thread *td; 780 struct ibcs2_fpathconf_args *uap; 781{ 782 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 783 return sys_fpathconf(td, (struct fpathconf_args *)uap); 784} 785 786int 787ibcs2_sysconf(td, uap) 788 struct thread *td; 789 struct ibcs2_sysconf_args *uap; 790{ 791 int mib[2], value, len, error; 792 struct proc *p; 793 794 p = td->td_proc; 795 switch(uap->name) { 796 case IBCS2_SC_ARG_MAX: 797 mib[1] = KERN_ARGMAX; 798 break; 799 800 case IBCS2_SC_CHILD_MAX: 801 PROC_LOCK(p); 802 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 803 PROC_UNLOCK(p); 804 return 0; 805 806 case IBCS2_SC_CLK_TCK: 807 td->td_retval[0] = hz; 808 return 0; 809 810 case IBCS2_SC_NGROUPS_MAX: 811 mib[1] = KERN_NGROUPS; 812 break; 813 814 case IBCS2_SC_OPEN_MAX: 815 PROC_LOCK(p); 816 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 817 PROC_UNLOCK(p); 818 return 0; 819 820 case IBCS2_SC_JOB_CONTROL: 821 mib[1] = KERN_JOB_CONTROL; 822 break; 823 824 case IBCS2_SC_SAVED_IDS: 825 mib[1] = KERN_SAVED_IDS; 826 break; 827 828 case IBCS2_SC_VERSION: 829 mib[1] = KERN_POSIX1; 830 break; 831 832 case IBCS2_SC_PASS_MAX: 833 td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 834 return 0; 835 836 case IBCS2_SC_XOPEN_VERSION: 837 td->td_retval[0] = 2; /* XXX: What should that be? */ 838 return 0; 839 840 default: 841 return EINVAL; 842 } 843 844 mib[0] = CTL_KERN; 845 len = sizeof(value); 846 error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 847 if (error) 848 return error; 849 td->td_retval[0] = value; 850 return 0; 851} 852 853int 854ibcs2_alarm(td, uap) 855 struct thread *td; 856 struct ibcs2_alarm_args *uap; 857{ 858 struct itimerval itv, oitv; 859 int error; 860 861 timevalclear(&itv.it_interval); 862 itv.it_value.tv_sec = uap->sec; 863 itv.it_value.tv_usec = 0; 864 error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 865 if (error) 866 return (error); 867 if (oitv.it_value.tv_usec != 0) 868 oitv.it_value.tv_sec++; 869 td->td_retval[0] = oitv.it_value.tv_sec; 870 return (0); 871} 872 873int 874ibcs2_times(td, uap) 875 struct thread *td; 876 struct ibcs2_times_args *uap; 877{ 878 struct rusage ru; 879 struct timeval t; 880 struct tms tms; 881 int error; 882 883#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 884 885 error = kern_getrusage(td, RUSAGE_SELF, &ru); 886 if (error) 887 return (error); 888 tms.tms_utime = CONVTCK(ru.ru_utime); 889 tms.tms_stime = CONVTCK(ru.ru_stime); 890 891 error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 892 if (error) 893 return (error); 894 tms.tms_cutime = CONVTCK(ru.ru_utime); 895 tms.tms_cstime = CONVTCK(ru.ru_stime); 896 897 microtime(&t); 898 td->td_retval[0] = CONVTCK(t); 899 900 return (copyout(&tms, uap->tp, sizeof(struct tms))); 901} 902 903int 904ibcs2_stime(td, uap) 905 struct thread *td; 906 struct ibcs2_stime_args *uap; 907{ 908 struct timeval tv; 909 long secs; 910 int error; 911 912 error = copyin(uap->timep, &secs, sizeof(long)); 913 if (error) 914 return (error); 915 tv.tv_sec = secs; 916 tv.tv_usec = 0; 917 error = kern_settimeofday(td, &tv, NULL); 918 if (error) 919 error = EPERM; 920 return (error); 921} 922 923int 924ibcs2_utime(td, uap) 925 struct thread *td; 926 struct ibcs2_utime_args *uap; 927{ 928 struct ibcs2_utimbuf ubuf; 929 struct timeval tbuf[2], *tp; 930 char *path; 931 int error; 932 933 if (uap->buf) { 934 error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 935 if (error) 936 return (error); 937 tbuf[0].tv_sec = ubuf.actime; 938 tbuf[0].tv_usec = 0; 939 tbuf[1].tv_sec = ubuf.modtime; 940 tbuf[1].tv_usec = 0; 941 tp = tbuf; 942 } else 943 tp = NULL; 944 945 CHECKALTEXIST(td, uap->path, &path); 946 error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 947 free(path, M_TEMP); 948 return (error); 949} 950 951int 952ibcs2_nice(td, uap) 953 struct thread *td; 954 struct ibcs2_nice_args *uap; 955{ 956 int error; 957 struct setpriority_args sa; 958 959 sa.which = PRIO_PROCESS; 960 sa.who = 0; 961 sa.prio = td->td_proc->p_nice + uap->incr; 962 if ((error = sys_setpriority(td, &sa)) != 0) 963 return EPERM; 964 td->td_retval[0] = td->td_proc->p_nice; 965 return 0; 966} 967 968/* 969 * iBCS2 getpgrp, setpgrp, setsid, and setpgid 970 */ 971 972int 973ibcs2_pgrpsys(td, uap) 974 struct thread *td; 975 struct ibcs2_pgrpsys_args *uap; 976{ 977 struct proc *p = td->td_proc; 978 switch (uap->type) { 979 case 0: /* getpgrp */ 980 PROC_LOCK(p); 981 td->td_retval[0] = p->p_pgrp->pg_id; 982 PROC_UNLOCK(p); 983 return 0; 984 985 case 1: /* setpgrp */ 986 { 987 struct setpgid_args sa; 988 989 sa.pid = 0; 990 sa.pgid = 0; 991 sys_setpgid(td, &sa); 992 PROC_LOCK(p); 993 td->td_retval[0] = p->p_pgrp->pg_id; 994 PROC_UNLOCK(p); 995 return 0; 996 } 997 998 case 2: /* setpgid */ 999 { 1000 struct setpgid_args sa; 1001 1002 sa.pid = uap->pid; 1003 sa.pgid = uap->pgid; 1004 return sys_setpgid(td, &sa); 1005 } 1006 1007 case 3: /* setsid */ 1008 return sys_setsid(td, NULL); 1009 1010 default: 1011 return EINVAL; 1012 } 1013} 1014 1015/* 1016 * XXX - need to check for nested calls 1017 */ 1018 1019int 1020ibcs2_plock(td, uap) 1021 struct thread *td; 1022 struct ibcs2_plock_args *uap; 1023{ 1024 int error; 1025#define IBCS2_UNLOCK 0 1026#define IBCS2_PROCLOCK 1 1027#define IBCS2_TEXTLOCK 2 1028#define IBCS2_DATALOCK 4 1029 1030 1031 switch(uap->cmd) { 1032 case IBCS2_UNLOCK: 1033 error = priv_check(td, PRIV_VM_MUNLOCK); 1034 if (error) 1035 return (error); 1036 /* XXX - TODO */ 1037 return (0); 1038 1039 case IBCS2_PROCLOCK: 1040 case IBCS2_TEXTLOCK: 1041 case IBCS2_DATALOCK: 1042 error = priv_check(td, PRIV_VM_MLOCK); 1043 if (error) 1044 return (error); 1045 /* XXX - TODO */ 1046 return 0; 1047 } 1048 return EINVAL; 1049} 1050 1051int 1052ibcs2_uadmin(td, uap) 1053 struct thread *td; 1054 struct ibcs2_uadmin_args *uap; 1055{ 1056#define SCO_A_REBOOT 1 1057#define SCO_A_SHUTDOWN 2 1058#define SCO_A_REMOUNT 4 1059#define SCO_A_CLOCK 8 1060#define SCO_A_SETCONFIG 128 1061#define SCO_A_GETDEV 130 1062 1063#define SCO_AD_HALT 0 1064#define SCO_AD_BOOT 1 1065#define SCO_AD_IBOOT 2 1066#define SCO_AD_PWRDOWN 3 1067#define SCO_AD_PWRNAP 4 1068 1069#define SCO_AD_PANICBOOT 1 1070 1071#define SCO_AD_GETBMAJ 0 1072#define SCO_AD_GETCMAJ 1 1073 1074 switch(uap->cmd) { 1075 case SCO_A_REBOOT: 1076 case SCO_A_SHUTDOWN: 1077 switch(uap->func) { 1078 struct reboot_args r; 1079 case SCO_AD_HALT: 1080 case SCO_AD_PWRDOWN: 1081 case SCO_AD_PWRNAP: 1082 r.opt = RB_HALT; 1083 return (sys_reboot(td, &r)); 1084 case SCO_AD_BOOT: 1085 case SCO_AD_IBOOT: 1086 r.opt = RB_AUTOBOOT; 1087 return (sys_reboot(td, &r)); 1088 } 1089 return EINVAL; 1090 case SCO_A_REMOUNT: 1091 case SCO_A_CLOCK: 1092 case SCO_A_SETCONFIG: 1093 return 0; 1094 case SCO_A_GETDEV: 1095 return EINVAL; /* XXX - TODO */ 1096 } 1097 return EINVAL; 1098} 1099 1100int 1101ibcs2_sysfs(td, uap) 1102 struct thread *td; 1103 struct ibcs2_sysfs_args *uap; 1104{ 1105#define IBCS2_GETFSIND 1 1106#define IBCS2_GETFSTYP 2 1107#define IBCS2_GETNFSTYP 3 1108 1109 switch(uap->cmd) { 1110 case IBCS2_GETFSIND: 1111 case IBCS2_GETFSTYP: 1112 case IBCS2_GETNFSTYP: 1113 break; 1114 } 1115 return EINVAL; /* XXX - TODO */ 1116} 1117 1118int 1119ibcs2_unlink(td, uap) 1120 struct thread *td; 1121 struct ibcs2_unlink_args *uap; 1122{ 1123 char *path; 1124 int error; 1125 1126 CHECKALTEXIST(td, uap->path, &path); 1127 error = kern_unlink(td, path, UIO_SYSSPACE); 1128 free(path, M_TEMP); 1129 return (error); 1130} 1131 1132int 1133ibcs2_chdir(td, uap) 1134 struct thread *td; 1135 struct ibcs2_chdir_args *uap; 1136{ 1137 char *path; 1138 int error; 1139 1140 CHECKALTEXIST(td, uap->path, &path); 1141 error = kern_chdir(td, path, UIO_SYSSPACE); 1142 free(path, M_TEMP); 1143 return (error); 1144} 1145 1146int 1147ibcs2_chmod(td, uap) 1148 struct thread *td; 1149 struct ibcs2_chmod_args *uap; 1150{ 1151 char *path; 1152 int error; 1153 1154 CHECKALTEXIST(td, uap->path, &path); 1155 error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1156 free(path, M_TEMP); 1157 return (error); 1158} 1159 1160int 1161ibcs2_chown(td, uap) 1162 struct thread *td; 1163 struct ibcs2_chown_args *uap; 1164{ 1165 char *path; 1166 int error; 1167 1168 CHECKALTEXIST(td, uap->path, &path); 1169 error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1170 free(path, M_TEMP); 1171 return (error); 1172} 1173 1174int 1175ibcs2_rmdir(td, uap) 1176 struct thread *td; 1177 struct ibcs2_rmdir_args *uap; 1178{ 1179 char *path; 1180 int error; 1181 1182 CHECKALTEXIST(td, uap->path, &path); 1183 error = kern_rmdir(td, path, UIO_SYSSPACE); 1184 free(path, M_TEMP); 1185 return (error); 1186} 1187 1188int 1189ibcs2_mkdir(td, uap) 1190 struct thread *td; 1191 struct ibcs2_mkdir_args *uap; 1192{ 1193 char *path; 1194 int error; 1195 1196 CHECKALTEXIST(td, uap->path, &path); 1197 error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1198 free(path, M_TEMP); 1199 return (error); 1200} 1201 1202int 1203ibcs2_symlink(td, uap) 1204 struct thread *td; 1205 struct ibcs2_symlink_args *uap; 1206{ 1207 char *path, *link; 1208 int error; 1209 1210 CHECKALTEXIST(td, uap->path, &path); 1211 1212 /* 1213 * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1214 * errors. 1215 */ 1216 error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1217 if (link == NULL) { 1218 free(path, M_TEMP); 1219 return (error); 1220 } 1221 error = kern_symlink(td, path, link, UIO_SYSSPACE); 1222 free(path, M_TEMP); 1223 free(link, M_TEMP); 1224 return (error); 1225} 1226 1227int 1228ibcs2_rename(td, uap) 1229 struct thread *td; 1230 struct ibcs2_rename_args *uap; 1231{ 1232 char *from, *to; 1233 int error; 1234 1235 CHECKALTEXIST(td, uap->from, &from); 1236 1237 /* 1238 * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1239 * errors. 1240 */ 1241 error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1242 if (to == NULL) { 1243 free(from, M_TEMP); 1244 return (error); 1245 } 1246 error = kern_rename(td, from, to, UIO_SYSSPACE); 1247 free(from, M_TEMP); 1248 free(to, M_TEMP); 1249 return (error); 1250} 1251 1252int 1253ibcs2_readlink(td, uap) 1254 struct thread *td; 1255 struct ibcs2_readlink_args *uap; 1256{ 1257 char *path; 1258 int error; 1259 1260 CHECKALTEXIST(td, uap->path, &path); 1261 error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1262 uap->count); 1263 free(path, M_TEMP); 1264 return (error); 1265} 1266