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