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