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