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