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