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.20 (Berkeley) 05/14/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 USES_VOP_ACCESS; 1149 int lgroups[NGROUPS]; 1150 int error = 0; 1151 register struct ucred *cred; 1152 register struct vnode *vp; 1153 struct nameidata nd; 1154 1155 /* 1156 * Build an appropriate credential structure 1157 */ 1158 cred = crdup(p->p_ucred); 1159 switch (uap->uid) { 1160 case 65502: /* UID_EUID */ 1161 break; 1162 case 65503: /* UID_RUID */ 1163 cred->cr_uid = p->p_cred->p_ruid; 1164 break; 1165 case 65504: /* UID_SUID */ 1166 error = EINVAL; 1167 break; 1168 default: 1169 if (uap->uid > 65504) 1170 error = EINVAL; 1171 cred->cr_uid = uap->uid; 1172 break; 1173 } 1174 switch (uap->ngroups) { 1175 case -1: /* NGROUPS_EGID */ 1176 cred->cr_ngroups = 1; 1177 break; 1178 case -5: /* NGROUPS_EGID_SUPP */ 1179 break; 1180 case -2: /* NGROUPS_RGID */ 1181 cred->cr_ngroups = 1; 1182 cred->cr_gid = p->p_cred->p_rgid; 1183 break; 1184 case -6: /* NGROUPS_RGID_SUPP */ 1185 cred->cr_gid = p->p_cred->p_rgid; 1186 break; 1187 case -3: /* NGROUPS_SGID */ 1188 case -7: /* NGROUPS_SGID_SUPP */ 1189 error = EINVAL; 1190 break; 1191 case -4: /* NGROUPS_SUPP */ 1192 if (cred->cr_ngroups > 1) 1193 cred->cr_gid = cred->cr_groups[1]; 1194 else 1195 error = EINVAL; 1196 break; 1197 default: 1198 if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1199 error = copyin((caddr_t)uap->gidset, 1200 (caddr_t)&lgroups[0], 1201 uap->ngroups * sizeof(lgroups[0])); 1202 else 1203 error = EINVAL; 1204 if (error == 0) { 1205 int gid; 1206 1207 for (gid = 0; gid < uap->ngroups; gid++) 1208 cred->cr_groups[gid] = lgroups[gid]; 1209 cred->cr_ngroups = uap->ngroups; 1210 } 1211 break; 1212 } 1213 /* 1214 * Lookup file using caller's effective IDs. 1215 */ 1216 if (error == 0) { 1217 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1218 uap->path, p); 1219 error = namei(&nd); 1220 } 1221 if (error) { 1222 crfree(cred); 1223 return (error); 1224 } 1225 /* 1226 * Use the constructed credentials for access checks. 1227 */ 1228 vp = nd.ni_vp; 1229 *retval = 0; 1230 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1231 *retval |= R_OK; 1232 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1233 *retval |= W_OK; 1234 /* XXX we return X_OK for root on VREG even if not */ 1235 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1236 *retval |= X_OK; 1237 vput(vp); 1238 crfree(cred); 1239 return (error); 1240 } 1241 1242 /* 1243 * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 1244 * No apologies offered, if you don't like it, rewrite it! 1245 */ 1246 1247 extern char kstack[]; 1248 #define UOFF(f) ((int)&((struct user *)0)->f) 1249 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1250 1251 /* simplified FP structure */ 1252 struct bsdfp { 1253 int save[54]; 1254 int reg[24]; 1255 int ctrl[3]; 1256 }; 1257 1258 hpuxtobsduoff(off) 1259 int *off; 1260 { 1261 register int *ar0 = curproc->p_md.md_regs; 1262 struct hpuxfp *hp; 1263 struct bsdfp *bp; 1264 register u_int raddr; 1265 1266 /* u_ar0 field; procxmt puts in U_ar0 */ 1267 if ((int)off == HPUOFF(hpuxu_ar0)) 1268 return(UOFF(U_ar0)); 1269 1270 #ifdef FPCOPROC 1271 /* 68881 registers from PCB */ 1272 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1273 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1274 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1275 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1276 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1277 return((int)&bp->reg[off - hp->hpfp_reg]); 1278 #endif 1279 1280 /* 1281 * Everything else we recognize comes from the kernel stack, 1282 * so we convert off to an absolute address (if not already) 1283 * for simplicity. 1284 */ 1285 if (off < (int *)ctob(UPAGES)) 1286 off = (int *)((u_int)off + (u_int)kstack); 1287 1288 /* 1289 * 68020 registers. 1290 * We know that the HPUX registers are in the same order as ours. 1291 * The only difference is that their PS is 2 bytes instead of a 1292 * padded 4 like ours throwing the alignment off. 1293 */ 1294 if (off >= ar0 && off < &ar0[18]) { 1295 /* 1296 * PS: return low word and high word of PC as HP-UX would 1297 * (e.g. &u.u_ar0[16.5]). 1298 */ 1299 if (off == &ar0[PS]) 1300 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1301 /* 1302 * PC: off will be &u.u_ar0[16.5] 1303 */ 1304 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1305 raddr = (u_int) &ar0[PC]; 1306 /* 1307 * D0-D7, A0-A7: easy 1308 */ 1309 else 1310 raddr = (u_int) &ar0[(int)(off - ar0)]; 1311 return((int)(raddr - (u_int)kstack)); 1312 } 1313 1314 /* everything else */ 1315 return(-1); 1316 } 1317 1318 /* 1319 * Kludge up a uarea dump so that HPUX debuggers can find out 1320 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1321 * convert the entire user struct. 1322 */ 1323 hpuxdumpu(vp, cred) 1324 struct vnode *vp; 1325 struct ucred *cred; 1326 { 1327 struct proc *p = curproc; 1328 int error; 1329 struct hpuxuser *faku; 1330 struct bsdfp *bp; 1331 short *foop; 1332 1333 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1334 /* 1335 * Make sure there is no mistake about this 1336 * being a real user structure. 1337 */ 1338 bzero((caddr_t)faku, ctob(1)); 1339 /* 1340 * Fill in the process sizes. 1341 */ 1342 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1343 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1344 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1345 /* 1346 * Fill in the exec header for CDB. 1347 * This was saved back in exec(). As far as I can tell CDB 1348 * only uses this information to verify that a particular 1349 * core file goes with a particular binary. 1350 */ 1351 bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 1352 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1353 /* 1354 * Adjust user's saved registers (on kernel stack) to reflect 1355 * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 1356 * so we have to move it up. 1357 */ 1358 faku->hpuxu_ar0 = p->p_md.md_regs; 1359 foop = (short *) p->p_md.md_regs; 1360 foop[32] = foop[33]; 1361 foop[33] = foop[34]; 1362 foop[34] = foop[35]; 1363 #ifdef FPCOPROC 1364 /* 1365 * Copy 68881 registers from our PCB format to HPUX format 1366 */ 1367 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1368 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1369 sizeof(bp->save)); 1370 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1371 sizeof(bp->ctrl)); 1372 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1373 sizeof(bp->reg)); 1374 #endif 1375 /* 1376 * Slay the dragon 1377 */ 1378 faku->hpuxu_dragon = -1; 1379 /* 1380 * Dump this artfully constructed page in place of the 1381 * user struct page. 1382 */ 1383 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1384 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1385 (int *)NULL, p); 1386 /* 1387 * Dump the remaining UPAGES-1 pages normally 1388 */ 1389 if (!error) 1390 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1391 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1392 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1393 free((caddr_t)faku, M_TEMP); 1394 return(error); 1395 } 1396 1397 /* 1398 * The remaining routines are essentially the same as those in kern_xxx.c 1399 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1400 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1401 * HP-UX compatibility still works even when COMPAT is not defined. 1402 */ 1403 /* #ifdef COMPAT */ 1404 1405 #define HPUX_HZ 50 1406 1407 #include "sys/times.h" 1408 1409 /* from old timeb.h */ 1410 struct hpuxtimeb { 1411 time_t time; 1412 u_short millitm; 1413 short timezone; 1414 short dstflag; 1415 }; 1416 1417 /* ye ole stat structure */ 1418 struct ohpuxstat { 1419 u_short ohst_dev; 1420 u_short ohst_ino; 1421 u_short ohst_mode; 1422 short ohst_nlink; 1423 short ohst_uid; 1424 short ohst_gid; 1425 u_short ohst_rdev; 1426 int ohst_size; 1427 int ohst_atime; 1428 int ohst_mtime; 1429 int ohst_ctime; 1430 }; 1431 1432 /* 1433 * SYS V style setpgrp() 1434 */ 1435 ohpuxsetpgrp(p, uap, retval) 1436 register struct proc *p; 1437 int *uap, *retval; 1438 { 1439 if (p->p_pid != p->p_pgid) 1440 enterpgrp(p, p->p_pid, 0); 1441 *retval = p->p_pgid; 1442 return (0); 1443 } 1444 1445 ohpuxtime(p, uap, retval) 1446 struct proc *p; 1447 register struct args { 1448 long *tp; 1449 } *uap; 1450 time_t *retval; 1451 { 1452 int error = 0; 1453 1454 if (uap->tp) 1455 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1456 sizeof (long)); 1457 *retval = time.tv_sec; 1458 return (error); 1459 } 1460 1461 ohpuxstime(p, uap, retval) 1462 struct proc *p; 1463 register struct args { 1464 int time; 1465 } *uap; 1466 int *retval; 1467 { 1468 struct timeval tv; 1469 int s, error; 1470 1471 tv.tv_sec = uap->time; 1472 tv.tv_usec = 0; 1473 if (error = suser(p->p_ucred, &p->p_acflag)) 1474 return (error); 1475 1476 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1477 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1478 s = splhigh(); time = tv; splx(s); 1479 resettodr(); 1480 return (0); 1481 } 1482 1483 ohpuxftime(p, uap, retval) 1484 struct proc *p; 1485 register struct args { 1486 struct hpuxtimeb *tp; 1487 } *uap; 1488 int *retval; 1489 { 1490 struct hpuxtimeb tb; 1491 int s; 1492 1493 s = splhigh(); 1494 tb.time = time.tv_sec; 1495 tb.millitm = time.tv_usec / 1000; 1496 splx(s); 1497 tb.timezone = tz.tz_minuteswest; 1498 tb.dstflag = tz.tz_dsttime; 1499 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1500 } 1501 1502 ohpuxalarm(p, uap, retval) 1503 register struct proc *p; 1504 register struct args { 1505 int deltat; 1506 } *uap; 1507 int *retval; 1508 { 1509 int s = splhigh(); 1510 1511 untimeout(realitexpire, (caddr_t)p); 1512 timerclear(&p->p_realtimer.it_interval); 1513 *retval = 0; 1514 if (timerisset(&p->p_realtimer.it_value) && 1515 timercmp(&p->p_realtimer.it_value, &time, >)) 1516 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1517 if (uap->deltat == 0) { 1518 timerclear(&p->p_realtimer.it_value); 1519 splx(s); 1520 return (0); 1521 } 1522 p->p_realtimer.it_value = time; 1523 p->p_realtimer.it_value.tv_sec += uap->deltat; 1524 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1525 splx(s); 1526 return (0); 1527 } 1528 1529 ohpuxnice(p, uap, retval) 1530 register struct proc *p; 1531 register struct args { 1532 int niceness; 1533 } *uap; 1534 int *retval; 1535 { 1536 int error; 1537 1538 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1539 if (error == 0) 1540 *retval = p->p_nice - NZERO; 1541 return (error); 1542 } 1543 1544 ohpuxtimes(p, uap, retval) 1545 struct proc *p; 1546 register struct args { 1547 struct tms *tmsb; 1548 } *uap; 1549 time_t *retval; 1550 { 1551 struct tms atms; 1552 int error; 1553 1554 atms.tms_utime = hpuxscale(&p->p_utime); 1555 atms.tms_stime = hpuxscale(&p->p_stime); 1556 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1557 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 1558 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1559 if (error == 0) 1560 *retval = hpuxscale(&time) - hpuxscale(&boottime); 1561 return (error); 1562 } 1563 1564 /* 1565 * Doesn't exactly do what the documentation says. 1566 * What we really do is return 1/HPUX_HZ-th of a second since that 1567 * is what HP-UX returns. 1568 */ 1569 hpuxscale(tvp) 1570 register struct timeval *tvp; 1571 { 1572 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 1573 } 1574 1575 /* 1576 * Set IUPD and IACC times on file. 1577 * Can't set ICHG. 1578 */ 1579 ohpuxutime(p, uap, retval) 1580 struct proc *p; 1581 register struct a { 1582 char *fname; 1583 time_t *tptr; 1584 } *uap; 1585 int *retval; 1586 { 1587 USES_VOP_SETATTR; 1588 register struct vnode *vp; 1589 struct vattr vattr; 1590 time_t tv[2]; 1591 int error; 1592 struct nameidata nd; 1593 1594 if (uap->tptr) { 1595 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1596 if (error) 1597 return (error); 1598 } else 1599 tv[0] = tv[1] = time.tv_sec; 1600 vattr_null(&vattr); 1601 vattr.va_atime.tv_sec = tv[0]; 1602 vattr.va_atime.tv_usec = 0; 1603 vattr.va_mtime.tv_sec = tv[1]; 1604 vattr.va_mtime.tv_usec = 0; 1605 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1606 if (error = namei(&nd)) 1607 return (error); 1608 vp = nd.ni_vp; 1609 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1610 error = EROFS; 1611 else 1612 error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 1613 vput(vp); 1614 return (error); 1615 } 1616 1617 ohpuxpause(p, uap, retval) 1618 struct proc *p; 1619 int *uap, *retval; 1620 { 1621 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 1622 /* always return EINTR rather than ERESTART... */ 1623 return (EINTR); 1624 } 1625 1626 /* 1627 * The old fstat system call. 1628 */ 1629 ohpuxfstat(p, uap, retval) 1630 struct proc *p; 1631 register struct args { 1632 int fd; 1633 struct ohpuxstat *sb; 1634 } *uap; 1635 int *retval; 1636 { 1637 register struct filedesc *fdp = p->p_fd; 1638 struct file *fp; 1639 1640 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1641 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1642 return (EBADF); 1643 if (fp->f_type != DTYPE_VNODE) 1644 return (EINVAL); 1645 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 1646 } 1647 1648 /* 1649 * Old stat system call. This version follows links. 1650 */ 1651 ohpuxstat(p, uap, retval) 1652 struct proc *p; 1653 register struct args { 1654 char *fname; 1655 struct ohpuxstat *sb; 1656 } *uap; 1657 int *retval; 1658 { 1659 int error; 1660 struct nameidata nd; 1661 1662 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1663 if (error = namei(&nd)) 1664 return (error); 1665 error = ohpuxstat1(nd.ni_vp, uap->sb); 1666 vput(nd.ni_vp); 1667 return (error); 1668 } 1669 1670 int 1671 ohpuxstat1(vp, ub) 1672 register struct vnode *vp; 1673 struct ohpuxstat *ub; 1674 { 1675 USES_VOP_GETATTR; 1676 struct ohpuxstat ds; 1677 struct vattr vattr; 1678 register int error; 1679 1680 error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 1681 if (error) 1682 return(error); 1683 /* 1684 * Copy from inode table 1685 */ 1686 ds.ohst_dev = vattr.va_fsid; 1687 ds.ohst_ino = (short)vattr.va_fileid; 1688 ds.ohst_mode = (u_short)vattr.va_mode; 1689 ds.ohst_nlink = vattr.va_nlink; 1690 ds.ohst_uid = (short)vattr.va_uid; 1691 ds.ohst_gid = (short)vattr.va_gid; 1692 ds.ohst_rdev = (u_short)vattr.va_rdev; 1693 ds.ohst_size = (int)vattr.va_size; 1694 ds.ohst_atime = (int)vattr.va_atime.tv_sec; 1695 ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 1696 ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 1697 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1698 } 1699 /* #endif */ 1700 1701 #endif 1702