|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 University of Utah. ! 3: * Copyright (c) 1990 The Regents of the University of California. ! 4: * All rights reserved. ! 5: * ! 6: * This code is derived from software contributed to Berkeley by ! 7: * the Systems Programming Group of the University of Utah Computer ! 8: * Science Department. ! 9: * ! 10: * Redistribution and use in source and binary forms, with or without ! 11: * modification, are permitted provided that the following conditions ! 12: * are met: ! 13: * 1. Redistributions of source code must retain the above copyright ! 14: * notice, this list of conditions and the following disclaimer. ! 15: * 2. Redistributions in binary form must reproduce the above copyright ! 16: * notice, this list of conditions and the following disclaimer in the ! 17: * documentation and/or other materials provided with the distribution. ! 18: * 3. All advertising materials mentioning features or use of this software ! 19: * must display the following acknowledgement: ! 20: * This product includes software developed by the University of ! 21: * California, Berkeley and its contributors. ! 22: * 4. Neither the name of the University nor the names of its contributors ! 23: * may be used to endorse or promote products derived from this software ! 24: * without specific prior written permission. ! 25: * ! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 36: * SUCH DAMAGE. ! 37: * ! 38: * from: Utah $Hdr: hpux_compat.c 1.41 91/04/06$ ! 39: * ! 40: * @(#)hpux_compat.c 7.16 (Berkeley) 5/30/91 ! 41: */ ! 42: ! 43: /* ! 44: * Various HPUX compatibility routines ! 45: */ ! 46: ! 47: #ifdef HPUXCOMPAT ! 48: ! 49: #include "param.h" ! 50: #include "systm.h" ! 51: #include "signalvar.h" ! 52: #include "kernel.h" ! 53: #include "filedesc.h" ! 54: #include "proc.h" ! 55: #include "buf.h" ! 56: #include "wait.h" ! 57: #include "file.h" ! 58: #include "namei.h" ! 59: #include "vnode.h" ! 60: #include "ioctl.h" ! 61: #include "ptrace.h" ! 62: #include "stat.h" ! 63: #include "syslog.h" ! 64: #include "malloc.h" ! 65: #include "mount.h" ! 66: #include "ipc.h" ! 67: #include "user.h" ! 68: ! 69: #include "machine/cpu.h" ! 70: #include "machine/reg.h" ! 71: #include "machine/psl.h" ! 72: #include "machine/vmparam.h" ! 73: #include "hpux.h" ! 74: #include "hpux_termio.h" ! 75: ! 76: #ifdef DEBUG ! 77: int unimpresponse = 0; ! 78: #endif ! 79: ! 80: /* SYS5 style UTSNAME info */ ! 81: struct hpuxutsname protoutsname = { ! 82: "4.4bsd", "", "2.0", "B", "9000/3?0", "" ! 83: }; ! 84: ! 85: /* 6.0 and later style context */ ! 86: #ifdef FPCOPROC ! 87: char hpuxcontext[] = ! 88: "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; ! 89: #else ! 90: char hpuxcontext[] = ! 91: "standalone HP-MC68020 HP-MC68010 localroot default"; ! 92: #endif ! 93: ! 94: /* YP domainname */ ! 95: char domainname[MAXHOSTNAMELEN] = "unknown"; ! 96: int domainnamelen = 7; ! 97: ! 98: #define NERR 79 ! 99: #define BERR 1000 ! 100: ! 101: /* indexed by BSD errno */ ! 102: short bsdtohpuxerrnomap[NERR] = { ! 103: /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ! 104: /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, ! 105: /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, ! 106: /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, ! 107: /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, ! 108: /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, ! 109: /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, ! 110: /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR ! 111: }; ! 112: ! 113: notimp(p, uap, retval, code, nargs) ! 114: struct proc *p; ! 115: int *uap, *retval; ! 116: int code, nargs; ! 117: { ! 118: int error = 0; ! 119: #ifdef DEBUG ! 120: register int *argp = uap; ! 121: extern char *hpuxsyscallnames[]; ! 122: ! 123: printf("HPUX %s(", hpuxsyscallnames[code]); ! 124: if (nargs) ! 125: while (nargs--) ! 126: printf("%x%c", *argp++, nargs? ',' : ')'); ! 127: else ! 128: printf(")"); ! 129: printf("\n"); ! 130: switch (unimpresponse) { ! 131: case 0: ! 132: error = nosys(p, uap, retval); ! 133: break; ! 134: case 1: ! 135: error = EINVAL; ! 136: break; ! 137: } ! 138: #else ! 139: error = nosys(p, uap, retval); ! 140: #endif ! 141: uprintf("HP-UX system call %d not implemented\n", code); ! 142: return (error); ! 143: } ! 144: ! 145: hpuxexecv(p, uap, retval) ! 146: struct proc *p; ! 147: struct args { ! 148: char *fname; ! 149: char **argp; ! 150: char **envp; ! 151: } *uap; ! 152: int *retval; ! 153: { ! 154: extern int execve(); ! 155: ! 156: uap->envp = NULL; ! 157: return (execve(p, uap, retval)); ! 158: } ! 159: ! 160: /* ! 161: * HPUX versions of wait and wait3 actually pass the parameters ! 162: * (status pointer, options, rusage) into the kernel rather than ! 163: * handling it in the C library stub. We also need to map any ! 164: * termination signal from BSD to HPUX. ! 165: */ ! 166: hpuxwait3(p, uap, retval) ! 167: struct proc *p; ! 168: struct args { ! 169: int *status; ! 170: int options; ! 171: int rusage; ! 172: } *uap; ! 173: int *retval; ! 174: { ! 175: /* rusage pointer must be zero */ ! 176: if (uap->rusage) ! 177: return (EINVAL); ! 178: p->p_regs[PS] = PSL_ALLCC; ! 179: p->p_regs[R0] = uap->options; ! 180: p->p_regs[R1] = uap->rusage; ! 181: return (hpuxwait(p, uap, retval)); ! 182: } ! 183: ! 184: hpuxwait(p, uap, retval) ! 185: struct proc *p; ! 186: struct args { ! 187: int *status; ! 188: } *uap; ! 189: int *retval; ! 190: { ! 191: int sig, *statp, error; ! 192: ! 193: statp = uap->status; /* owait clobbers first arg */ ! 194: error = owait(p, uap, retval); ! 195: /* ! 196: * HP-UX wait always returns EINTR when interrupted by a signal ! 197: * (well, unless its emulating a BSD process, but we don't bother...) ! 198: */ ! 199: if (error == ERESTART) ! 200: error = EINTR; ! 201: if (error) ! 202: return (error); ! 203: sig = retval[1] & 0xFF; ! 204: if (sig == WSTOPPED) { ! 205: sig = (retval[1] >> 8) & 0xFF; ! 206: retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; ! 207: } else if (sig) ! 208: retval[1] = (retval[1] & 0xFF00) | ! 209: bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); ! 210: if (statp) ! 211: if (suword((caddr_t)statp, retval[1])) ! 212: error = EFAULT; ! 213: return (error); ! 214: } ! 215: ! 216: hpuxwaitpid(p, uap, retval) ! 217: struct proc *p; ! 218: struct args { ! 219: int pid; ! 220: int *status; ! 221: int options; ! 222: struct rusage *rusage; /* wait4 arg */ ! 223: } *uap; ! 224: int *retval; ! 225: { ! 226: int sig, *statp, error; ! 227: ! 228: uap->rusage = 0; ! 229: error = wait4(p, uap, retval); ! 230: /* ! 231: * HP-UX wait always returns EINTR when interrupted by a signal ! 232: * (well, unless its emulating a BSD process, but we don't bother...) ! 233: */ ! 234: if (error == ERESTART) ! 235: error = EINTR; ! 236: if (error) ! 237: return (error); ! 238: sig = retval[1] & 0xFF; ! 239: if (sig == WSTOPPED) { ! 240: sig = (retval[1] >> 8) & 0xFF; ! 241: retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; ! 242: } else if (sig) ! 243: retval[1] = (retval[1] & 0xFF00) | ! 244: bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); ! 245: if (statp) ! 246: if (suword((caddr_t)statp, retval[1])) ! 247: error = EFAULT; ! 248: return (error); ! 249: } ! 250: ! 251: /* ! 252: * Must remap some bits in the mode mask. ! 253: * O_CREAT, O_TRUNC, and O_EXCL must be remapped, ! 254: * O_SYNCIO (0100000) is removed entirely. ! 255: */ ! 256: hpuxopen(p, uap, retval) ! 257: struct proc *p; ! 258: register struct args { ! 259: char *fname; ! 260: int mode; ! 261: int crtmode; ! 262: } *uap; ! 263: int *retval; ! 264: { ! 265: int mode; ! 266: ! 267: mode = uap->mode; ! 268: uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); ! 269: if (mode & HPUXFCREAT) { ! 270: /* ! 271: * simulate the pre-NFS behavior that opening a ! 272: * file for READ+CREATE ignores the CREATE (unless ! 273: * EXCL is set in which case we will return the ! 274: * proper error). ! 275: */ ! 276: if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) ! 277: uap->mode |= O_CREAT; ! 278: } ! 279: if (mode & HPUXFTRUNC) ! 280: uap->mode |= O_TRUNC; ! 281: if (mode & HPUXFEXCL) ! 282: uap->mode |= O_EXCL; ! 283: return (open(p, uap, retval)); ! 284: } ! 285: ! 286: /* XXX */ ! 287: #define UF_FNDELAY_ON 0x20 ! 288: #define UF_FIONBIO_ON 0x40 ! 289: /* XXX */ ! 290: ! 291: hpuxfcntl(p, uap, retval) ! 292: struct proc *p; ! 293: register struct args { ! 294: int fdes; ! 295: int cmd; ! 296: int arg; ! 297: } *uap; ! 298: int *retval; ! 299: { ! 300: int mode, error; ! 301: char *fp; ! 302: ! 303: if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { ! 304: if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || ! 305: p->p_fd->fd_ofiles[uap->fdes] == NULL) ! 306: return (EBADF); ! 307: fp = &p->p_fd->fd_ofileflags[uap->fdes]; ! 308: } ! 309: switch (uap->cmd) { ! 310: case F_SETFL: ! 311: if (uap->arg & FNONBLOCK) ! 312: *fp |= UF_FNDELAY_ON; ! 313: else { ! 314: *fp &= ~UF_FNDELAY_ON; ! 315: if (*fp & UF_FIONBIO_ON) ! 316: uap->arg |= FNONBLOCK; ! 317: } ! 318: uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); ! 319: break; ! 320: case F_GETFL: ! 321: case F_DUPFD: ! 322: case F_GETFD: ! 323: case F_SETFD: ! 324: break; ! 325: default: ! 326: return (EINVAL); ! 327: } ! 328: error = fcntl(p, uap, retval); ! 329: if (error == 0 && uap->cmd == F_GETFL) { ! 330: mode = *retval; ! 331: *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); ! 332: if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) ! 333: *retval &= ~FNONBLOCK; ! 334: if (mode & O_CREAT) ! 335: *retval |= HPUXFCREAT; ! 336: if (mode & O_TRUNC) ! 337: *retval |= HPUXFTRUNC; ! 338: if (mode & O_EXCL) ! 339: *retval |= HPUXFEXCL; ! 340: } ! 341: return (error); ! 342: } ! 343: ! 344: /* ! 345: * Read and write should return a 0 count when an operation ! 346: * on a VNODE would block, not an error. ! 347: * ! 348: * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. ! 349: * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. ! 350: */ ! 351: hpuxread(p, uap, retval) ! 352: struct proc *p; ! 353: struct args { ! 354: int fd; ! 355: } *uap; ! 356: int *retval; ! 357: { ! 358: int error; ! 359: ! 360: error = read(p, uap, retval); ! 361: if (error == EWOULDBLOCK && ! 362: (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || ! 363: p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { ! 364: error = 0; ! 365: *retval = 0; ! 366: } ! 367: return (error); ! 368: } ! 369: ! 370: hpuxwrite(p, uap, retval) ! 371: struct proc *p; ! 372: struct args { ! 373: int fd; ! 374: } *uap; ! 375: int *retval; ! 376: { ! 377: int error; ! 378: ! 379: error = write(p, uap, retval); ! 380: if (error == EWOULDBLOCK && ! 381: (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || ! 382: p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { ! 383: error = 0; ! 384: *retval = 0; ! 385: } ! 386: return (error); ! 387: } ! 388: ! 389: hpuxreadv(p, uap, retval) ! 390: struct proc *p; ! 391: struct args { ! 392: int fd; ! 393: } *uap; ! 394: int *retval; ! 395: { ! 396: int error; ! 397: ! 398: error = readv(p, uap, retval); ! 399: if (error == EWOULDBLOCK && ! 400: (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || ! 401: p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { ! 402: error = 0; ! 403: *retval = 0; ! 404: } ! 405: return (error); ! 406: } ! 407: ! 408: hpuxwritev(p, uap, retval) ! 409: struct proc *p; ! 410: struct args { ! 411: int fd; ! 412: } *uap; ! 413: int *retval; ! 414: { ! 415: int error; ! 416: ! 417: error = writev(p, uap, retval); ! 418: if (error == EWOULDBLOCK && ! 419: (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || ! 420: p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { ! 421: error = 0; ! 422: *retval = 0; ! 423: } ! 424: return (error); ! 425: } ! 426: ! 427: /* ! 428: * 4.3bsd dup allows dup2 to come in on the same syscall entry ! 429: * and hence allows two arguments. HPUX dup has only one arg. ! 430: */ ! 431: hpuxdup(p, uap, retval) ! 432: struct proc *p; ! 433: register struct args { ! 434: int i; ! 435: } *uap; ! 436: int *retval; ! 437: { ! 438: register struct filedesc *fdp = p->p_fd; ! 439: struct file *fp; ! 440: int fd, error; ! 441: ! 442: if (((unsigned)uap->i) >= fdp->fd_nfiles || ! 443: (fp = fdp->fd_ofiles[uap->i]) == NULL) ! 444: return (EBADF); ! 445: if (error = fdalloc(p, 0, &fd)) ! 446: return (error); ! 447: fdp->fd_ofiles[fd] = fp; ! 448: fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; ! 449: fp->f_count++; ! 450: if (fd > fdp->fd_lastfile) ! 451: fdp->fd_lastfile = fd; ! 452: *retval = fd; ! 453: return (0); ! 454: } ! 455: ! 456: hpuxutssys(p, uap, retval) ! 457: struct proc *p; ! 458: register struct args { ! 459: struct hpuxutsname *uts; ! 460: int dev; ! 461: int request; ! 462: } *uap; ! 463: int *retval; ! 464: { ! 465: register int i; ! 466: int error; ! 467: ! 468: switch (uap->request) { ! 469: /* uname */ ! 470: case 0: ! 471: /* fill in machine type */ ! 472: switch (machineid) { ! 473: case HP_320: ! 474: protoutsname.machine[6] = '2'; ! 475: break; ! 476: /* includes 318 and 319 */ ! 477: case HP_330: ! 478: protoutsname.machine[6] = '3'; ! 479: break; ! 480: case HP_340: ! 481: protoutsname.machine[6] = '4'; ! 482: break; ! 483: case HP_350: ! 484: protoutsname.machine[6] = '5'; ! 485: break; ! 486: case HP_360: ! 487: protoutsname.machine[6] = '6'; ! 488: break; ! 489: case HP_370: ! 490: protoutsname.machine[6] = '7'; ! 491: break; ! 492: /* includes 345 */ ! 493: case HP_375: ! 494: protoutsname.machine[6] = '7'; ! 495: protoutsname.machine[7] = '5'; ! 496: break; ! 497: } ! 498: /* copy hostname (sans domain) to nodename */ ! 499: for (i = 0; i < 8 && hostname[i] != '.'; i++) ! 500: protoutsname.nodename[i] = hostname[i]; ! 501: protoutsname.nodename[i] = '\0'; ! 502: error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, ! 503: sizeof(struct hpuxutsname)); ! 504: break; ! 505: ! 506: /* gethostname */ ! 507: case 5: ! 508: /* uap->dev is length */ ! 509: if (uap->dev > hostnamelen + 1) ! 510: uap->dev = hostnamelen + 1; ! 511: error = copyout((caddr_t)hostname, (caddr_t)uap->uts, ! 512: uap->dev); ! 513: break; ! 514: ! 515: case 1: /* ?? */ ! 516: case 2: /* ustat */ ! 517: case 3: /* ?? */ ! 518: case 4: /* sethostname */ ! 519: default: ! 520: error = EINVAL; ! 521: break; ! 522: } ! 523: return (error); ! 524: } ! 525: ! 526: hpuxstat(p, uap, retval) ! 527: struct proc *p; ! 528: struct args { ! 529: char *fname; ! 530: struct hpuxstat *hsb; ! 531: } *uap; ! 532: int *retval; ! 533: { ! 534: return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); ! 535: } ! 536: ! 537: hpuxlstat(p, uap, retval) ! 538: struct proc *p; ! 539: struct args { ! 540: char *fname; ! 541: struct hpuxstat *hsb; ! 542: } *uap; ! 543: int *retval; ! 544: { ! 545: return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); ! 546: } ! 547: ! 548: hpuxfstat(p, uap, retval) ! 549: struct proc *p; ! 550: register struct args { ! 551: int fdes; ! 552: struct hpuxstat *hsb; ! 553: } *uap; ! 554: int *retval; ! 555: { ! 556: register struct filedesc *fdp = p->p_fd; ! 557: register struct file *fp; ! 558: struct stat sb; ! 559: int error; ! 560: ! 561: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 562: (fp = fdp->fd_ofiles[uap->fdes]) == NULL) ! 563: return (EBADF); ! 564: ! 565: switch (fp->f_type) { ! 566: ! 567: case DTYPE_VNODE: ! 568: error = vn_stat((struct vnode *)fp->f_data, &sb); ! 569: break; ! 570: ! 571: case DTYPE_SOCKET: ! 572: error = soo_stat((struct socket *)fp->f_data, &sb); ! 573: break; ! 574: ! 575: default: ! 576: panic("fstat"); ! 577: /*NOTREACHED*/ ! 578: } ! 579: /* is this right for sockets?? */ ! 580: if (error == 0) ! 581: error = bsdtohpuxstat(&sb, uap->hsb); ! 582: return (error); ! 583: } ! 584: ! 585: hpuxulimit(p, uap, retval) ! 586: struct proc *p; ! 587: register struct args { ! 588: int cmd; ! 589: long newlimit; ! 590: } *uap; ! 591: off_t *retval; ! 592: { ! 593: struct rlimit *limp; ! 594: int error = 0; ! 595: ! 596: limp = &p->p_rlimit[RLIMIT_FSIZE]; ! 597: switch (uap->cmd) { ! 598: case 2: ! 599: uap->newlimit *= 512; ! 600: if (uap->newlimit > limp->rlim_max && ! 601: (error = suser(p->p_ucred, &p->p_acflag))) ! 602: break; ! 603: limp->rlim_cur = limp->rlim_max = uap->newlimit; ! 604: /* else fall into... */ ! 605: ! 606: case 1: ! 607: *retval = limp->rlim_max / 512; ! 608: break; ! 609: ! 610: case 3: ! 611: limp = &p->p_rlimit[RLIMIT_DATA]; ! 612: *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; ! 613: break; ! 614: ! 615: default: ! 616: error = EINVAL; ! 617: break; ! 618: } ! 619: return (error); ! 620: } ! 621: ! 622: /* ! 623: * Map "real time" priorities 0 (high) thru 127 (low) into nice ! 624: * values -16 (high) thru -1 (low). ! 625: */ ! 626: hpuxrtprio(cp, uap, retval) ! 627: struct proc *cp; ! 628: register struct args { ! 629: int pid; ! 630: int prio; ! 631: } *uap; ! 632: int *retval; ! 633: { ! 634: struct proc *p; ! 635: int nice, error; ! 636: ! 637: if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && ! 638: uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) ! 639: return (EINVAL); ! 640: if (uap->pid == 0) ! 641: p = cp; ! 642: else if ((p = pfind(uap->pid)) == 0) ! 643: return (ESRCH); ! 644: nice = p->p_nice; ! 645: if (nice < NZERO) ! 646: *retval = (nice + 16) << 3; ! 647: else ! 648: *retval = RTPRIO_RTOFF; ! 649: switch (uap->prio) { ! 650: ! 651: case RTPRIO_NOCHG: ! 652: return (0); ! 653: ! 654: case RTPRIO_RTOFF: ! 655: if (nice >= NZERO) ! 656: return (0); ! 657: nice = NZERO; ! 658: break; ! 659: ! 660: default: ! 661: nice = (uap->prio >> 3) - 16; ! 662: break; ! 663: } ! 664: error = donice(cp, p, nice); ! 665: if (error == EACCES) ! 666: error = EPERM; ! 667: return (error); ! 668: } ! 669: ! 670: hpuxadvise(p, uap, retval) ! 671: struct proc *p; ! 672: struct args { ! 673: int arg; ! 674: } *uap; ! 675: int *retval; ! 676: { ! 677: int error = 0; ! 678: ! 679: switch (uap->arg) { ! 680: case 0: ! 681: p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; ! 682: break; ! 683: case 1: ! 684: ICIA(); ! 685: break; ! 686: case 2: ! 687: DCIA(); ! 688: break; ! 689: default: ! 690: error = EINVAL; ! 691: break; ! 692: } ! 693: return (error); ! 694: } ! 695: ! 696: hpuxptrace(p, uap, retval) ! 697: struct proc *p; ! 698: struct args { ! 699: int req; ! 700: int pid; ! 701: int *addr; ! 702: int data; ! 703: } *uap; ! 704: int *retval; ! 705: { ! 706: int error; ! 707: ! 708: if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { ! 709: if (uap->data) { ! 710: uap->data = hpuxtobsdsig(uap->data); ! 711: if (uap->data == 0) ! 712: uap->data = NSIG; ! 713: } ! 714: } ! 715: error = ptrace(p, uap, retval); ! 716: return (error); ! 717: } ! 718: ! 719: hpuxgetdomainname(p, uap, retval) ! 720: struct proc *p; ! 721: register struct args { ! 722: char *domainname; ! 723: u_int len; ! 724: } *uap; ! 725: int *retval; ! 726: { ! 727: if (uap->len > domainnamelen + 1) ! 728: uap->len = domainnamelen + 1; ! 729: return (copyout(domainname, uap->domainname, uap->len)); ! 730: } ! 731: ! 732: hpuxsetdomainname(p, uap, retval) ! 733: struct proc *p; ! 734: register struct args { ! 735: char *domainname; ! 736: u_int len; ! 737: } *uap; ! 738: int *retval; ! 739: { ! 740: int error; ! 741: ! 742: if (error = suser(p->p_ucred, &p->p_acflag)) ! 743: return (error); ! 744: if (uap->len > sizeof (domainname) - 1) ! 745: return (EINVAL); ! 746: domainnamelen = uap->len; ! 747: error = copyin(uap->domainname, domainname, uap->len); ! 748: domainname[domainnamelen] = 0; ! 749: return (error); ! 750: } ! 751: ! 752: #ifdef SYSVSHM ! 753: hpuxshmat(p, uap, retval) ! 754: struct proc *p; ! 755: int *uap, *retval; ! 756: { ! 757: return (shmat(p, uap, retval)); ! 758: } ! 759: ! 760: hpuxshmctl(p, uap, retval) ! 761: struct proc *p; ! 762: int *uap, *retval; ! 763: { ! 764: return (shmctl(p, uap, retval)); ! 765: } ! 766: ! 767: hpuxshmdt(p, uap, retval) ! 768: struct proc *p; ! 769: int *uap, *retval; ! 770: { ! 771: return (shmdt(p, uap, retval)); ! 772: } ! 773: ! 774: hpuxshmget(p, uap, retval) ! 775: struct proc *p; ! 776: int *uap, *retval; ! 777: { ! 778: return (shmget(p, uap, retval)); ! 779: } ! 780: #endif ! 781: ! 782: /* ! 783: * Fake semaphore routines, just don't return an error. ! 784: * Should be adequate for starbase to run. ! 785: */ ! 786: hpuxsemctl(p, uap, retval) ! 787: struct proc *p; ! 788: struct args { ! 789: int semid; ! 790: u_int semnum; ! 791: int cmd; ! 792: int arg; ! 793: } *uap; ! 794: int *retval; ! 795: { ! 796: /* XXX: should do something here */ ! 797: return (0); ! 798: } ! 799: ! 800: hpuxsemget(p, uap, retval) ! 801: struct proc *p; ! 802: struct args { ! 803: key_t key; ! 804: int nsems; ! 805: int semflg; ! 806: } *uap; ! 807: int *retval; ! 808: { ! 809: /* XXX: should do something here */ ! 810: return (0); ! 811: } ! 812: ! 813: hpuxsemop(p, uap, retval) ! 814: struct proc *p; ! 815: struct args { ! 816: int semid; ! 817: struct sembuf *sops; ! 818: u_int nsops; ! 819: } *uap; ! 820: int *retval; ! 821: { ! 822: /* XXX: should do something here */ ! 823: return (0); ! 824: } ! 825: ! 826: /* convert from BSD to HPUX errno */ ! 827: bsdtohpuxerrno(err) ! 828: int err; ! 829: { ! 830: if (err < 0 || err >= NERR) ! 831: return(BERR); ! 832: return((int)bsdtohpuxerrnomap[err]); ! 833: } ! 834: ! 835: hpuxstat1(fname, hsb, follow) ! 836: char *fname; ! 837: struct hpuxstat *hsb; ! 838: int follow; ! 839: { ! 840: register struct nameidata *ndp; ! 841: int error; ! 842: struct stat sb; ! 843: struct nameidata nd; ! 844: ! 845: ndp = &nd; ! 846: ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; ! 847: ndp->ni_segflg = UIO_USERSPACE; ! 848: ndp->ni_dirp = fname; ! 849: if (error = namei(ndp, curproc)) ! 850: return (error); ! 851: error = vn_stat(ndp->ni_vp, &sb); ! 852: vput(ndp->ni_vp); ! 853: if (error == 0) ! 854: error = bsdtohpuxstat(&sb, hsb); ! 855: return (error); ! 856: } ! 857: ! 858: #include "grf.h" ! 859: ! 860: bsdtohpuxstat(sb, hsb) ! 861: struct stat *sb; ! 862: struct hpuxstat *hsb; ! 863: { ! 864: struct hpuxstat ds; ! 865: ! 866: bzero((caddr_t)&ds, sizeof(ds)); ! 867: ds.hst_dev = sb->st_dev; ! 868: ds.hst_ino = (u_long)sb->st_ino; ! 869: ds.hst_mode = sb->st_mode; ! 870: ds.hst_nlink = sb->st_nlink; ! 871: ds.hst_uid = (u_short)sb->st_uid; ! 872: ds.hst_gid = (u_short)sb->st_gid; ! 873: #if NGRF > 0 ! 874: /* XXX: I don't want to talk about it... */ ! 875: if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) ! 876: ds.hst_rdev = grfdevno(sb->st_rdev); ! 877: else ! 878: #endif ! 879: ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); ! 880: ds.hst_size = sb->st_size; ! 881: ds.hst_atime = sb->st_atime; ! 882: ds.hst_mtime = sb->st_mtime; ! 883: ds.hst_ctime = sb->st_ctime; ! 884: ds.hst_blksize = sb->st_blksize; ! 885: ds.hst_blocks = sb->st_blocks; ! 886: return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); ! 887: } ! 888: ! 889: hpuxtobsdioctl(com) ! 890: int com; ! 891: { ! 892: switch (com) { ! 893: case HPUXTIOCSLTC: ! 894: com = TIOCSLTC; break; ! 895: case HPUXTIOCGLTC: ! 896: com = TIOCGLTC; break; ! 897: case HPUXTIOCSPGRP: ! 898: com = TIOCSPGRP; break; ! 899: case HPUXTIOCGPGRP: ! 900: com = TIOCGPGRP; break; ! 901: case HPUXTIOCLBIS: ! 902: com = TIOCLBIS; break; ! 903: case HPUXTIOCLBIC: ! 904: com = TIOCLBIC; break; ! 905: case HPUXTIOCLSET: ! 906: com = TIOCLSET; break; ! 907: case HPUXTIOCLGET: ! 908: com = TIOCLGET; break; ! 909: } ! 910: return(com); ! 911: } ! 912: ! 913: /* ! 914: * HPUX ioctl system call. The differences here are: ! 915: * IOC_IN also means IOC_VOID if the size portion is zero. ! 916: * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN ! 917: * the sgttyb struct is 2 bytes longer ! 918: */ ! 919: hpuxioctl(p, uap, retval) ! 920: struct proc *p; ! 921: register struct args { ! 922: int fdes; ! 923: int cmd; ! 924: caddr_t cmarg; ! 925: } *uap; ! 926: int *retval; ! 927: { ! 928: register struct filedesc *fdp = p->p_fd; ! 929: register struct file *fp; ! 930: register int com, error; ! 931: register u_int size; ! 932: caddr_t memp = 0; ! 933: #define STK_PARAMS 128 ! 934: char stkbuf[STK_PARAMS]; ! 935: caddr_t data = stkbuf; ! 936: ! 937: com = uap->cmd; ! 938: ! 939: /* XXX */ ! 940: if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) ! 941: return (getsettty(p, uap->fdes, com, uap->cmarg)); ! 942: ! 943: if (((unsigned)uap->fdes) >= fdp->fd_nfiles || ! 944: (fp = fdp->fd_ofiles[uap->fdes]) == NULL) ! 945: return (EBADF); ! 946: if ((fp->f_flag & (FREAD|FWRITE)) == 0) ! 947: return (EBADF); ! 948: ! 949: /* ! 950: * Interpret high order word to find ! 951: * amount of data to be copied to/from the ! 952: * user's address space. ! 953: */ ! 954: size = IOCPARM_LEN(com); ! 955: if (size > IOCPARM_MAX) ! 956: return (ENOTTY); ! 957: if (size > sizeof (stkbuf)) { ! 958: memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); ! 959: data = memp; ! 960: } ! 961: if (com&IOC_IN) { ! 962: if (size) { ! 963: error = copyin(uap->cmarg, data, (u_int)size); ! 964: if (error) { ! 965: if (memp) ! 966: free(memp, M_IOCTLOPS); ! 967: return (error); ! 968: } ! 969: } else ! 970: *(caddr_t *)data = uap->cmarg; ! 971: } else if ((com&IOC_OUT) && size) ! 972: /* ! 973: * Zero the buffer so the user always ! 974: * gets back something deterministic. ! 975: */ ! 976: bzero(data, size); ! 977: else if (com&IOC_VOID) ! 978: *(caddr_t *)data = uap->cmarg; ! 979: ! 980: switch (com) { ! 981: ! 982: case HPUXFIOSNBIO: ! 983: { ! 984: char *ofp = &fdp->fd_ofileflags[uap->fdes]; ! 985: int tmp; ! 986: ! 987: if (*(int *)data) ! 988: *ofp |= UF_FIONBIO_ON; ! 989: else ! 990: *ofp &= ~UF_FIONBIO_ON; ! 991: /* ! 992: * Only set/clear if FNONBLOCK not in effect ! 993: */ ! 994: if ((*ofp & UF_FNDELAY_ON) == 0) { ! 995: tmp = fp->f_flag & FNONBLOCK; ! 996: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, ! 997: (caddr_t)&tmp, p); ! 998: } ! 999: break; ! 1000: } ! 1001: ! 1002: case HPUXTIOCCONS: ! 1003: *(int *)data = 1; ! 1004: error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); ! 1005: break; ! 1006: ! 1007: /* BSD-style job control ioctls */ ! 1008: case HPUXTIOCLBIS: ! 1009: case HPUXTIOCLBIC: ! 1010: case HPUXTIOCLSET: ! 1011: *(int *)data &= HPUXLTOSTOP; ! 1012: if (*(int *)data & HPUXLTOSTOP) ! 1013: *(int *)data = LTOSTOP; ! 1014: /* fall into */ ! 1015: case HPUXTIOCLGET: ! 1016: case HPUXTIOCSLTC: ! 1017: case HPUXTIOCGLTC: ! 1018: case HPUXTIOCSPGRP: ! 1019: case HPUXTIOCGPGRP: ! 1020: error = (*fp->f_ops->fo_ioctl) ! 1021: (fp, hpuxtobsdioctl(com), data, p); ! 1022: if (error == 0 && com == HPUXTIOCLGET) { ! 1023: *(int *)data &= LTOSTOP; ! 1024: if (*(int *)data & LTOSTOP) ! 1025: *(int *)data = HPUXLTOSTOP; ! 1026: } ! 1027: break; ! 1028: ! 1029: /* SYS 5 termio */ ! 1030: case HPUXTCGETA: ! 1031: case HPUXTCSETA: ! 1032: case HPUXTCSETAW: ! 1033: case HPUXTCSETAF: ! 1034: error = hpuxtermio(fp, com, data, p); ! 1035: break; ! 1036: ! 1037: default: ! 1038: error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); ! 1039: break; ! 1040: } ! 1041: /* ! 1042: * Copy any data to user, size was ! 1043: * already set and checked above. ! 1044: */ ! 1045: if (error == 0 && (com&IOC_OUT) && size) ! 1046: error = copyout(data, uap->cmarg, (u_int)size); ! 1047: if (memp) ! 1048: free(memp, M_IOCTLOPS); ! 1049: return (error); ! 1050: } ! 1051: ! 1052: /* ! 1053: * Man page lies, behaviour here is based on observed behaviour. ! 1054: */ ! 1055: hpuxgetcontext(p, uap, retval) ! 1056: struct proc *p; ! 1057: struct args { ! 1058: char *buf; ! 1059: int len; ! 1060: } *uap; ! 1061: int *retval; ! 1062: { ! 1063: int error = 0; ! 1064: register int len; ! 1065: ! 1066: len = MIN(uap->len, sizeof(hpuxcontext)); ! 1067: if (len) ! 1068: error = copyout(hpuxcontext, uap->buf, (u_int)len); ! 1069: if (error == 0) ! 1070: *retval = sizeof(hpuxcontext); ! 1071: return (error); ! 1072: } ! 1073: ! 1074: /* ! 1075: * This is the equivalent of BSD getpgrp but with more restrictions. ! 1076: * Note we do not check the real uid or "saved" uid. ! 1077: */ ! 1078: hpuxgetpgrp2(cp, uap, retval) ! 1079: struct proc *cp; ! 1080: register struct args { ! 1081: int pid; ! 1082: } *uap; ! 1083: int *retval; ! 1084: { ! 1085: register struct proc *p; ! 1086: ! 1087: if (uap->pid == 0) ! 1088: uap->pid = cp->p_pid; ! 1089: p = pfind(uap->pid); ! 1090: if (p == 0) ! 1091: return (ESRCH); ! 1092: if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && ! 1093: !inferior(p)) ! 1094: return (EPERM); ! 1095: *retval = p->p_pgid; ! 1096: return (0); ! 1097: } ! 1098: ! 1099: /* ! 1100: * This is the equivalent of BSD setpgrp but with more restrictions. ! 1101: * Note we do not check the real uid or "saved" uid or pgrp. ! 1102: */ ! 1103: hpuxsetpgrp2(p, uap, retval) ! 1104: struct proc *p; ! 1105: struct args { ! 1106: int pid; ! 1107: int pgrp; ! 1108: } *uap; ! 1109: int *retval; ! 1110: { ! 1111: /* empirically determined */ ! 1112: if (uap->pgrp < 0 || uap->pgrp >= 30000) ! 1113: return (EINVAL); ! 1114: return (setpgid(p, uap, retval)); ! 1115: } ! 1116: ! 1117: /* ! 1118: * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. ! 1119: */ ! 1120: hpuxsetresuid(p, uap, retval) ! 1121: struct proc *p; ! 1122: struct args { ! 1123: int ruid; ! 1124: int euid; ! 1125: int suid; ! 1126: } *uap; ! 1127: int *retval; ! 1128: { ! 1129: return (osetreuid(p, uap, retval)); ! 1130: } ! 1131: ! 1132: hpuxsetresgid(p, uap, retval) ! 1133: struct proc *p; ! 1134: struct args { ! 1135: int rgid; ! 1136: int egid; ! 1137: int sgid; ! 1138: } *uap; ! 1139: int *retval; ! 1140: { ! 1141: return (osetregid(p, uap, retval)); ! 1142: } ! 1143: ! 1144: /* ! 1145: * XXX: simple recognition hack to see if we can make grmd work. ! 1146: */ ! 1147: hpuxlockf(p, uap, retval) ! 1148: struct proc *p; ! 1149: struct args { ! 1150: int fd; ! 1151: int func; ! 1152: long size; ! 1153: } *uap; ! 1154: int *retval; ! 1155: { ! 1156: #ifdef DEBUG ! 1157: log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", ! 1158: p->p_pid, uap->fd, uap->func, uap->size); ! 1159: #endif ! 1160: return (0); ! 1161: } ! 1162: ! 1163: hpuxgetaccess(p, uap, retval) ! 1164: register struct proc *p; ! 1165: register struct args { ! 1166: char *path; ! 1167: int uid; ! 1168: int ngroups; ! 1169: int *gidset; ! 1170: void *label; ! 1171: void *privs; ! 1172: } *uap; ! 1173: int *retval; ! 1174: { ! 1175: struct nameidata *ndp; ! 1176: int lgroups[NGROUPS]; ! 1177: int error = 0; ! 1178: register struct ucred *cred; ! 1179: register struct vnode *vp; ! 1180: ! 1181: /* ! 1182: * Build an appropriate credential structure ! 1183: */ ! 1184: cred = crdup(p->p_ucred); ! 1185: switch (uap->uid) { ! 1186: case 65502: /* UID_EUID */ ! 1187: break; ! 1188: case 65503: /* UID_RUID */ ! 1189: cred->cr_uid = p->p_cred->p_ruid; ! 1190: break; ! 1191: case 65504: /* UID_SUID */ ! 1192: error = EINVAL; ! 1193: break; ! 1194: default: ! 1195: if (uap->uid > 65504) ! 1196: error = EINVAL; ! 1197: cred->cr_uid = uap->uid; ! 1198: break; ! 1199: } ! 1200: switch (uap->ngroups) { ! 1201: case -1: /* NGROUPS_EGID */ ! 1202: cred->cr_ngroups = 1; ! 1203: break; ! 1204: case -5: /* NGROUPS_EGID_SUPP */ ! 1205: break; ! 1206: case -2: /* NGROUPS_RGID */ ! 1207: cred->cr_ngroups = 1; ! 1208: cred->cr_gid = p->p_cred->p_rgid; ! 1209: break; ! 1210: case -6: /* NGROUPS_RGID_SUPP */ ! 1211: cred->cr_gid = p->p_cred->p_rgid; ! 1212: break; ! 1213: case -3: /* NGROUPS_SGID */ ! 1214: case -7: /* NGROUPS_SGID_SUPP */ ! 1215: error = EINVAL; ! 1216: break; ! 1217: case -4: /* NGROUPS_SUPP */ ! 1218: if (cred->cr_ngroups > 1) ! 1219: cred->cr_gid = cred->cr_groups[1]; ! 1220: else ! 1221: error = EINVAL; ! 1222: break; ! 1223: default: ! 1224: if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) ! 1225: error = copyin((caddr_t)uap->gidset, ! 1226: (caddr_t)&lgroups[0], ! 1227: uap->ngroups * sizeof(lgroups[0])); ! 1228: else ! 1229: error = EINVAL; ! 1230: if (error == 0) { ! 1231: int gid; ! 1232: ! 1233: for (gid = 0; gid < uap->ngroups; gid++) ! 1234: cred->cr_groups[gid] = lgroups[gid]; ! 1235: cred->cr_ngroups = uap->ngroups; ! 1236: } ! 1237: break; ! 1238: } ! 1239: /* ! 1240: * Lookup file using caller's effective IDs. ! 1241: */ ! 1242: if (error == 0) { ! 1243: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1244: ndp->ni_segflg = UIO_USERSPACE; ! 1245: ndp->ni_dirp = uap->path; ! 1246: error = namei(ndp, p); ! 1247: } ! 1248: if (error) { ! 1249: crfree(cred); ! 1250: return (error); ! 1251: } ! 1252: /* ! 1253: * Use the constructed credentials for access checks. ! 1254: */ ! 1255: vp = ndp->ni_vp; ! 1256: *retval = 0; ! 1257: if (VOP_ACCESS(vp, VREAD, cred, p) == 0) ! 1258: *retval |= R_OK; ! 1259: if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) ! 1260: *retval |= W_OK; ! 1261: /* XXX we return X_OK for root on VREG even if not */ ! 1262: if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) ! 1263: *retval |= X_OK; ! 1264: vput(vp); ! 1265: crfree(cred); ! 1266: return (error); ! 1267: } ! 1268: ! 1269: /* ! 1270: * Brutal hack! Map HPUX u-area offsets into BSD u offsets. ! 1271: * No apologies offered, if you don't like it, rewrite it! ! 1272: */ ! 1273: ! 1274: extern char kstack[]; ! 1275: #define UOFF(f) ((int)&((struct user *)0)->f) ! 1276: #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) ! 1277: ! 1278: /* simplified FP structure */ ! 1279: struct bsdfp { ! 1280: int save[54]; ! 1281: int reg[24]; ! 1282: int ctrl[3]; ! 1283: }; ! 1284: ! 1285: hpuxtobsduoff(off) ! 1286: int *off; ! 1287: { ! 1288: register int *ar0 = curproc->p_regs; ! 1289: struct hpuxfp *hp; ! 1290: struct bsdfp *bp; ! 1291: register u_int raddr; ! 1292: ! 1293: /* u_ar0 field; procxmt puts in U_ar0 */ ! 1294: if ((int)off == HPUOFF(hpuxu_ar0)) ! 1295: return(UOFF(U_ar0)); ! 1296: ! 1297: #ifdef FPCOPROC ! 1298: /* 68881 registers from PCB */ ! 1299: hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); ! 1300: bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); ! 1301: if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) ! 1302: return((int)&bp->ctrl[off - hp->hpfp_ctrl]); ! 1303: if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) ! 1304: return((int)&bp->reg[off - hp->hpfp_reg]); ! 1305: #endif ! 1306: ! 1307: /* ! 1308: * Everything else we recognize comes from the kernel stack, ! 1309: * so we convert off to an absolute address (if not already) ! 1310: * for simplicity. ! 1311: */ ! 1312: if (off < (int *)ctob(UPAGES)) ! 1313: off = (int *)((u_int)off + (u_int)kstack); ! 1314: ! 1315: /* ! 1316: * 68020 registers. ! 1317: * We know that the HPUX registers are in the same order as ours. ! 1318: * The only difference is that their PS is 2 bytes instead of a ! 1319: * padded 4 like ours throwing the alignment off. ! 1320: */ ! 1321: if (off >= ar0 && off < &ar0[18]) { ! 1322: /* ! 1323: * PS: return low word and high word of PC as HP-UX would ! 1324: * (e.g. &u.u_ar0[16.5]). ! 1325: */ ! 1326: if (off == &ar0[PS]) ! 1327: raddr = (u_int) &((short *)ar0)[PS*2+1]; ! 1328: /* ! 1329: * PC: off will be &u.u_ar0[16.5] ! 1330: */ ! 1331: else if (off == (int *)&(((short *)ar0)[PS*2+1])) ! 1332: raddr = (u_int) &ar0[PC]; ! 1333: /* ! 1334: * D0-D7, A0-A7: easy ! 1335: */ ! 1336: else ! 1337: raddr = (u_int) &ar0[(int)(off - ar0)]; ! 1338: return((int)(raddr - (u_int)kstack)); ! 1339: } ! 1340: ! 1341: /* everything else */ ! 1342: return(-1); ! 1343: } ! 1344: ! 1345: /* ! 1346: * Kludge up a uarea dump so that HPUX debuggers can find out ! 1347: * what they need. IMPORTANT NOTE: we do not EVEN attempt to ! 1348: * convert the entire user struct. ! 1349: */ ! 1350: hpuxdumpu(vp, cred) ! 1351: struct vnode *vp; ! 1352: struct ucred *cred; ! 1353: { ! 1354: struct proc *p = curproc; ! 1355: int error; ! 1356: struct hpuxuser *faku; ! 1357: struct bsdfp *bp; ! 1358: short *foop; ! 1359: ! 1360: faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); ! 1361: /* ! 1362: * Make sure there is no mistake about this ! 1363: * being a real user structure. ! 1364: */ ! 1365: bzero((caddr_t)faku, ctob(1)); ! 1366: /* ! 1367: * Fill in the process sizes. ! 1368: */ ! 1369: faku->hpuxu_tsize = p->p_vmspace->vm_tsize; ! 1370: faku->hpuxu_dsize = p->p_vmspace->vm_dsize; ! 1371: faku->hpuxu_ssize = p->p_vmspace->vm_ssize; ! 1372: /* ! 1373: * Fill in the exec header for CDB. ! 1374: * This was saved back in exec(). As far as I can tell CDB ! 1375: * only uses this information to verify that a particular ! 1376: * core file goes with a particular binary. ! 1377: */ ! 1378: bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, ! 1379: (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); ! 1380: /* ! 1381: * Adjust user's saved registers (on kernel stack) to reflect ! 1382: * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 ! 1383: * so we have to move it up. ! 1384: */ ! 1385: faku->hpuxu_ar0 = p->p_regs; ! 1386: foop = (short *) p->p_regs; ! 1387: foop[32] = foop[33]; ! 1388: foop[33] = foop[34]; ! 1389: foop[34] = foop[35]; ! 1390: #ifdef FPCOPROC ! 1391: /* ! 1392: * Copy 68881 registers from our PCB format to HPUX format ! 1393: */ ! 1394: bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; ! 1395: bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, ! 1396: sizeof(bp->save)); ! 1397: bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, ! 1398: sizeof(bp->ctrl)); ! 1399: bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, ! 1400: sizeof(bp->reg)); ! 1401: #endif ! 1402: /* ! 1403: * Slay the dragon ! 1404: */ ! 1405: faku->hpuxu_dragon = -1; ! 1406: /* ! 1407: * Dump this artfully constructed page in place of the ! 1408: * user struct page. ! 1409: */ ! 1410: error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, ! 1411: UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, ! 1412: (int *)NULL, p); ! 1413: /* ! 1414: * Dump the remaining UPAGES-1 pages normally ! 1415: */ ! 1416: if (!error) ! 1417: error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), ! 1418: ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, ! 1419: IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); ! 1420: free((caddr_t)faku, M_TEMP); ! 1421: return(error); ! 1422: } ! 1423: ! 1424: /* ! 1425: * The remaining routines are essentially the same as those in kern_xxx.c ! 1426: * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here ! 1427: * to avoid HPUXCOMPAT dependencies in those files and to make sure that ! 1428: * HP-UX compatibility still works even when COMPAT is not defined. ! 1429: */ ! 1430: /* #ifdef COMPAT */ ! 1431: ! 1432: #define HPUX_HZ 50 ! 1433: ! 1434: #include "sys/times.h" ! 1435: ! 1436: /* from old timeb.h */ ! 1437: struct hpuxtimeb { ! 1438: time_t time; ! 1439: u_short millitm; ! 1440: short timezone; ! 1441: short dstflag; ! 1442: }; ! 1443: ! 1444: /* ye ole stat structure */ ! 1445: struct ohpuxstat { ! 1446: dev_t ohst_dev; ! 1447: u_short ohst_ino; ! 1448: u_short ohst_mode; ! 1449: short ohst_nlink; ! 1450: short ohst_uid; ! 1451: short ohst_gid; ! 1452: dev_t ohst_rdev; ! 1453: int ohst_size; ! 1454: int ohst_atime; ! 1455: int ohst_mtime; ! 1456: int ohst_ctime; ! 1457: }; ! 1458: ! 1459: /* ! 1460: * SYS V style setpgrp() ! 1461: */ ! 1462: ohpuxsetpgrp(p, uap, retval) ! 1463: register struct proc *p; ! 1464: int *uap, *retval; ! 1465: { ! 1466: if (p->p_pid != p->p_pgid) ! 1467: enterpgrp(p, p->p_pid, 0); ! 1468: *retval = p->p_pgid; ! 1469: return (0); ! 1470: } ! 1471: ! 1472: ohpuxtime(p, uap, retval) ! 1473: struct proc *p; ! 1474: register struct args { ! 1475: long *tp; ! 1476: } *uap; ! 1477: time_t *retval; ! 1478: { ! 1479: int error = 0; ! 1480: ! 1481: if (uap->tp) ! 1482: error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, ! 1483: sizeof (long)); ! 1484: *retval = time.tv_sec; ! 1485: return (error); ! 1486: } ! 1487: ! 1488: ohpuxstime(p, uap, retval) ! 1489: struct proc *p; ! 1490: register struct args { ! 1491: int time; ! 1492: } *uap; ! 1493: int *retval; ! 1494: { ! 1495: struct timeval tv; ! 1496: int s, error; ! 1497: ! 1498: tv.tv_sec = uap->time; ! 1499: tv.tv_usec = 0; ! 1500: if (error = suser(p->p_ucred, &p->p_acflag)) ! 1501: return (error); ! 1502: ! 1503: /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ ! 1504: boottime.tv_sec += tv.tv_sec - time.tv_sec; ! 1505: s = splhigh(); time = tv; splx(s); ! 1506: resettodr(); ! 1507: return (0); ! 1508: } ! 1509: ! 1510: ohpuxftime(p, uap, retval) ! 1511: struct proc *p; ! 1512: register struct args { ! 1513: struct hpuxtimeb *tp; ! 1514: } *uap; ! 1515: int *retval; ! 1516: { ! 1517: struct hpuxtimeb tb; ! 1518: int s; ! 1519: ! 1520: s = splhigh(); ! 1521: tb.time = time.tv_sec; ! 1522: tb.millitm = time.tv_usec / 1000; ! 1523: splx(s); ! 1524: tb.timezone = tz.tz_minuteswest; ! 1525: tb.dstflag = tz.tz_dsttime; ! 1526: return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); ! 1527: } ! 1528: ! 1529: ohpuxalarm(p, uap, retval) ! 1530: register struct proc *p; ! 1531: register struct args { ! 1532: int deltat; ! 1533: } *uap; ! 1534: int *retval; ! 1535: { ! 1536: int s = splhigh(); ! 1537: ! 1538: untimeout(realitexpire, (caddr_t)p); ! 1539: timerclear(&p->p_realtimer.it_interval); ! 1540: *retval = 0; ! 1541: if (timerisset(&p->p_realtimer.it_value) && ! 1542: timercmp(&p->p_realtimer.it_value, &time, >)) ! 1543: *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; ! 1544: if (uap->deltat == 0) { ! 1545: timerclear(&p->p_realtimer.it_value); ! 1546: splx(s); ! 1547: return (0); ! 1548: } ! 1549: p->p_realtimer.it_value = time; ! 1550: p->p_realtimer.it_value.tv_sec += uap->deltat; ! 1551: timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); ! 1552: splx(s); ! 1553: return (0); ! 1554: } ! 1555: ! 1556: ohpuxnice(p, uap, retval) ! 1557: register struct proc *p; ! 1558: register struct args { ! 1559: int niceness; ! 1560: } *uap; ! 1561: int *retval; ! 1562: { ! 1563: int error; ! 1564: ! 1565: error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); ! 1566: if (error == 0) ! 1567: *retval = p->p_nice - NZERO; ! 1568: return (error); ! 1569: } ! 1570: ! 1571: ohpuxtimes(p, uap, retval) ! 1572: struct proc *p; ! 1573: register struct args { ! 1574: struct tms *tmsb; ! 1575: } *uap; ! 1576: time_t *retval; ! 1577: { ! 1578: struct tms atms; ! 1579: int error; ! 1580: ! 1581: atms.tms_utime = hpuxscale(&p->p_utime); ! 1582: atms.tms_stime = hpuxscale(&p->p_stime); ! 1583: atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); ! 1584: atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); ! 1585: error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); ! 1586: if (error == 0) ! 1587: *retval = hpuxscale(&time) - hpuxscale(&boottime); ! 1588: return (error); ! 1589: } ! 1590: ! 1591: /* ! 1592: * Doesn't exactly do what the documentation says. ! 1593: * What we really do is return 1/HPUX_HZ-th of a second since that ! 1594: * is what HP-UX returns. ! 1595: */ ! 1596: hpuxscale(tvp) ! 1597: register struct timeval *tvp; ! 1598: { ! 1599: return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); ! 1600: } ! 1601: ! 1602: /* ! 1603: * Set IUPD and IACC times on file. ! 1604: * Can't set ICHG. ! 1605: */ ! 1606: ohpuxutime(p, uap, retval) ! 1607: struct proc *p; ! 1608: register struct a { ! 1609: char *fname; ! 1610: time_t *tptr; ! 1611: } *uap; ! 1612: int *retval; ! 1613: { ! 1614: register struct vnode *vp; ! 1615: register struct nameidata *ndp; ! 1616: struct vattr vattr; ! 1617: time_t tv[2]; ! 1618: int error; ! 1619: struct nameidata nd; ! 1620: ! 1621: ndp = &nd; ! 1622: if (uap->tptr) { ! 1623: error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); ! 1624: if (error) ! 1625: return (error); ! 1626: } else ! 1627: tv[0] = tv[1] = time.tv_sec; ! 1628: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; ! 1629: ndp->ni_segflg = UIO_USERSPACE; ! 1630: ndp->ni_dirp = uap->fname; ! 1631: vattr_null(&vattr); ! 1632: vattr.va_atime.tv_sec = tv[0]; ! 1633: vattr.va_atime.tv_usec = 0; ! 1634: vattr.va_mtime.tv_sec = tv[1]; ! 1635: vattr.va_mtime.tv_usec = 0; ! 1636: if (error = namei(ndp, p)) ! 1637: return (error); ! 1638: vp = ndp->ni_vp; ! 1639: if (vp->v_mount->mnt_flag & MNT_RDONLY) ! 1640: error = EROFS; ! 1641: else ! 1642: error = VOP_SETATTR(vp, &vattr, ndp->ni_cred, p); ! 1643: vput(vp); ! 1644: return (error); ! 1645: } ! 1646: ! 1647: ohpuxpause(p, uap, retval) ! 1648: struct proc *p; ! 1649: int *uap, *retval; ! 1650: { ! 1651: (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); ! 1652: /* always return EINTR rather than ERESTART... */ ! 1653: return (EINTR); ! 1654: } ! 1655: ! 1656: /* ! 1657: * The old fstat system call. ! 1658: */ ! 1659: ohpuxfstat(p, uap, retval) ! 1660: struct proc *p; ! 1661: register struct args { ! 1662: int fd; ! 1663: struct ohpuxstat *sb; ! 1664: } *uap; ! 1665: int *retval; ! 1666: { ! 1667: register struct filedesc *fdp = p->p_fd; ! 1668: struct file *fp; ! 1669: ! 1670: if (((unsigned)uap->fd) >= fdp->fd_nfiles || ! 1671: (fp = fdp->fd_ofiles[uap->fd]) == NULL) ! 1672: return (EBADF); ! 1673: if (fp->f_type != DTYPE_VNODE) ! 1674: return (EINVAL); ! 1675: return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); ! 1676: } ! 1677: ! 1678: /* ! 1679: * Old stat system call. This version follows links. ! 1680: */ ! 1681: ohpuxstat(p, uap, retval) ! 1682: struct proc *p; ! 1683: register struct args { ! 1684: char *fname; ! 1685: struct ohpuxstat *sb; ! 1686: } *uap; ! 1687: int *retval; ! 1688: { ! 1689: register struct nameidata *ndp; ! 1690: int error; ! 1691: struct nameidata nd; ! 1692: ! 1693: ndp = &nd; ! 1694: ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; ! 1695: ndp->ni_segflg = UIO_USERSPACE; ! 1696: ndp->ni_dirp = uap->fname; ! 1697: if (error = namei(ndp, p)) ! 1698: return (error); ! 1699: error = ohpuxstat1(ndp->ni_vp, uap->sb); ! 1700: vput(ndp->ni_vp); ! 1701: return (error); ! 1702: } ! 1703: ! 1704: int ! 1705: ohpuxstat1(vp, ub) ! 1706: register struct vnode *vp; ! 1707: struct ohpuxstat *ub; ! 1708: { ! 1709: struct ohpuxstat ds; ! 1710: struct vattr vattr; ! 1711: register int error; ! 1712: ! 1713: error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); ! 1714: if (error) ! 1715: return(error); ! 1716: /* ! 1717: * Copy from inode table ! 1718: */ ! 1719: ds.ohst_dev = vattr.va_fsid; ! 1720: ds.ohst_ino = (short)vattr.va_fileid; ! 1721: ds.ohst_mode = (u_short)vattr.va_mode; ! 1722: ds.ohst_nlink = vattr.va_nlink; ! 1723: ds.ohst_uid = (short)vattr.va_uid; ! 1724: ds.ohst_gid = (short)vattr.va_gid; ! 1725: ds.ohst_rdev = (dev_t)vattr.va_rdev; ! 1726: ds.ohst_size = (int)vattr.va_size; ! 1727: ds.ohst_atime = (int)vattr.va_atime.tv_sec; ! 1728: ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; ! 1729: ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; ! 1730: return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); ! 1731: } ! 1732: /* #endif */ ! 1733: ! 1734: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.