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