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