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