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.16 (Berkeley) 05/30/91 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_regs[PS] = PSL_ALLCC; 153 p->p_regs[R0] = uap->options; 154 p->p_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 off_t *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 register struct nameidata *ndp; 815 int error; 816 struct stat sb; 817 struct nameidata nd; 818 819 ndp = &nd; 820 ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 821 ndp->ni_segflg = UIO_USERSPACE; 822 ndp->ni_dirp = fname; 823 if (error = namei(ndp, curproc)) 824 return (error); 825 error = vn_stat(ndp->ni_vp, &sb); 826 vput(ndp->ni_vp); 827 if (error == 0) 828 error = bsdtohpuxstat(&sb, hsb); 829 return (error); 830 } 831 832 #include "grf.h" 833 834 bsdtohpuxstat(sb, hsb) 835 struct stat *sb; 836 struct hpuxstat *hsb; 837 { 838 struct hpuxstat ds; 839 840 bzero((caddr_t)&ds, sizeof(ds)); 841 ds.hst_dev = sb->st_dev; 842 ds.hst_ino = (u_long)sb->st_ino; 843 ds.hst_mode = sb->st_mode; 844 ds.hst_nlink = sb->st_nlink; 845 ds.hst_uid = (u_short)sb->st_uid; 846 ds.hst_gid = (u_short)sb->st_gid; 847 #if NGRF > 0 848 /* XXX: I don't want to talk about it... */ 849 if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 850 ds.hst_rdev = grfdevno(sb->st_rdev); 851 else 852 #endif 853 ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 854 ds.hst_size = sb->st_size; 855 ds.hst_atime = sb->st_atime; 856 ds.hst_mtime = sb->st_mtime; 857 ds.hst_ctime = sb->st_ctime; 858 ds.hst_blksize = sb->st_blksize; 859 ds.hst_blocks = sb->st_blocks; 860 return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 861 } 862 863 hpuxtobsdioctl(com) 864 int com; 865 { 866 switch (com) { 867 case HPUXTIOCSLTC: 868 com = TIOCSLTC; break; 869 case HPUXTIOCGLTC: 870 com = TIOCGLTC; break; 871 case HPUXTIOCSPGRP: 872 com = TIOCSPGRP; break; 873 case HPUXTIOCGPGRP: 874 com = TIOCGPGRP; break; 875 case HPUXTIOCLBIS: 876 com = TIOCLBIS; break; 877 case HPUXTIOCLBIC: 878 com = TIOCLBIC; break; 879 case HPUXTIOCLSET: 880 com = TIOCLSET; break; 881 case HPUXTIOCLGET: 882 com = TIOCLGET; break; 883 } 884 return(com); 885 } 886 887 /* 888 * HPUX ioctl system call. The differences here are: 889 * IOC_IN also means IOC_VOID if the size portion is zero. 890 * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 891 * the sgttyb struct is 2 bytes longer 892 */ 893 hpuxioctl(p, uap, retval) 894 struct proc *p; 895 register struct args { 896 int fdes; 897 int cmd; 898 caddr_t cmarg; 899 } *uap; 900 int *retval; 901 { 902 register struct filedesc *fdp = p->p_fd; 903 register struct file *fp; 904 register int com, error; 905 register u_int size; 906 caddr_t memp = 0; 907 #define STK_PARAMS 128 908 char stkbuf[STK_PARAMS]; 909 caddr_t data = stkbuf; 910 911 com = uap->cmd; 912 913 /* XXX */ 914 if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 915 return (getsettty(p, uap->fdes, com, uap->cmarg)); 916 917 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 918 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 919 return (EBADF); 920 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 921 return (EBADF); 922 923 /* 924 * Interpret high order word to find 925 * amount of data to be copied to/from the 926 * user's address space. 927 */ 928 size = IOCPARM_LEN(com); 929 if (size > IOCPARM_MAX) 930 return (ENOTTY); 931 if (size > sizeof (stkbuf)) { 932 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 933 data = memp; 934 } 935 if (com&IOC_IN) { 936 if (size) { 937 error = copyin(uap->cmarg, data, (u_int)size); 938 if (error) { 939 if (memp) 940 free(memp, M_IOCTLOPS); 941 return (error); 942 } 943 } else 944 *(caddr_t *)data = uap->cmarg; 945 } else if ((com&IOC_OUT) && size) 946 /* 947 * Zero the buffer so the user always 948 * gets back something deterministic. 949 */ 950 bzero(data, size); 951 else if (com&IOC_VOID) 952 *(caddr_t *)data = uap->cmarg; 953 954 switch (com) { 955 956 case HPUXFIOSNBIO: 957 { 958 char *ofp = &fdp->fd_ofileflags[uap->fdes]; 959 int tmp; 960 961 if (*(int *)data) 962 *ofp |= UF_FIONBIO_ON; 963 else 964 *ofp &= ~UF_FIONBIO_ON; 965 /* 966 * Only set/clear if FNONBLOCK not in effect 967 */ 968 if ((*ofp & UF_FNDELAY_ON) == 0) { 969 tmp = fp->f_flag & FNONBLOCK; 970 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 971 (caddr_t)&tmp, p); 972 } 973 break; 974 } 975 976 case HPUXTIOCCONS: 977 *(int *)data = 1; 978 error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 979 break; 980 981 /* BSD-style job control ioctls */ 982 case HPUXTIOCLBIS: 983 case HPUXTIOCLBIC: 984 case HPUXTIOCLSET: 985 *(int *)data &= HPUXLTOSTOP; 986 if (*(int *)data & HPUXLTOSTOP) 987 *(int *)data = LTOSTOP; 988 /* fall into */ 989 case HPUXTIOCLGET: 990 case HPUXTIOCSLTC: 991 case HPUXTIOCGLTC: 992 case HPUXTIOCSPGRP: 993 case HPUXTIOCGPGRP: 994 error = (*fp->f_ops->fo_ioctl) 995 (fp, hpuxtobsdioctl(com), data, p); 996 if (error == 0 && com == HPUXTIOCLGET) { 997 *(int *)data &= LTOSTOP; 998 if (*(int *)data & LTOSTOP) 999 *(int *)data = HPUXLTOSTOP; 1000 } 1001 break; 1002 1003 /* SYS 5 termio */ 1004 case HPUXTCGETA: 1005 case HPUXTCSETA: 1006 case HPUXTCSETAW: 1007 case HPUXTCSETAF: 1008 error = hpuxtermio(fp, com, data, p); 1009 break; 1010 1011 default: 1012 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 1013 break; 1014 } 1015 /* 1016 * Copy any data to user, size was 1017 * already set and checked above. 1018 */ 1019 if (error == 0 && (com&IOC_OUT) && size) 1020 error = copyout(data, uap->cmarg, (u_int)size); 1021 if (memp) 1022 free(memp, M_IOCTLOPS); 1023 return (error); 1024 } 1025 1026 /* 1027 * Man page lies, behaviour here is based on observed behaviour. 1028 */ 1029 hpuxgetcontext(p, uap, retval) 1030 struct proc *p; 1031 struct args { 1032 char *buf; 1033 int len; 1034 } *uap; 1035 int *retval; 1036 { 1037 int error = 0; 1038 register int len; 1039 1040 len = MIN(uap->len, sizeof(hpuxcontext)); 1041 if (len) 1042 error = copyout(hpuxcontext, uap->buf, (u_int)len); 1043 if (error == 0) 1044 *retval = sizeof(hpuxcontext); 1045 return (error); 1046 } 1047 1048 /* 1049 * This is the equivalent of BSD getpgrp but with more restrictions. 1050 * Note we do not check the real uid or "saved" uid. 1051 */ 1052 hpuxgetpgrp2(cp, uap, retval) 1053 struct proc *cp; 1054 register struct args { 1055 int pid; 1056 } *uap; 1057 int *retval; 1058 { 1059 register struct proc *p; 1060 1061 if (uap->pid == 0) 1062 uap->pid = cp->p_pid; 1063 p = pfind(uap->pid); 1064 if (p == 0) 1065 return (ESRCH); 1066 if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1067 !inferior(p)) 1068 return (EPERM); 1069 *retval = p->p_pgid; 1070 return (0); 1071 } 1072 1073 /* 1074 * This is the equivalent of BSD setpgrp but with more restrictions. 1075 * Note we do not check the real uid or "saved" uid or pgrp. 1076 */ 1077 hpuxsetpgrp2(p, uap, retval) 1078 struct proc *p; 1079 struct args { 1080 int pid; 1081 int pgrp; 1082 } *uap; 1083 int *retval; 1084 { 1085 /* empirically determined */ 1086 if (uap->pgrp < 0 || uap->pgrp >= 30000) 1087 return (EINVAL); 1088 return (setpgid(p, uap, retval)); 1089 } 1090 1091 /* 1092 * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 1093 */ 1094 hpuxsetresuid(p, uap, retval) 1095 struct proc *p; 1096 struct args { 1097 int ruid; 1098 int euid; 1099 int suid; 1100 } *uap; 1101 int *retval; 1102 { 1103 return (osetreuid(p, uap, retval)); 1104 } 1105 1106 hpuxsetresgid(p, uap, retval) 1107 struct proc *p; 1108 struct args { 1109 int rgid; 1110 int egid; 1111 int sgid; 1112 } *uap; 1113 int *retval; 1114 { 1115 return (osetregid(p, uap, retval)); 1116 } 1117 1118 /* 1119 * XXX: simple recognition hack to see if we can make grmd work. 1120 */ 1121 hpuxlockf(p, uap, retval) 1122 struct proc *p; 1123 struct args { 1124 int fd; 1125 int func; 1126 long size; 1127 } *uap; 1128 int *retval; 1129 { 1130 #ifdef DEBUG 1131 log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 1132 p->p_pid, uap->fd, uap->func, uap->size); 1133 #endif 1134 return (0); 1135 } 1136 1137 hpuxgetaccess(p, uap, retval) 1138 register struct proc *p; 1139 register struct args { 1140 char *path; 1141 int uid; 1142 int ngroups; 1143 int *gidset; 1144 void *label; 1145 void *privs; 1146 } *uap; 1147 int *retval; 1148 { 1149 struct nameidata *ndp; 1150 int lgroups[NGROUPS]; 1151 int error = 0; 1152 register struct ucred *cred; 1153 register struct vnode *vp; 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 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1218 ndp->ni_segflg = UIO_USERSPACE; 1219 ndp->ni_dirp = uap->path; 1220 error = namei(ndp, p); 1221 } 1222 if (error) { 1223 crfree(cred); 1224 return (error); 1225 } 1226 /* 1227 * Use the constructed credentials for access checks. 1228 */ 1229 vp = ndp->ni_vp; 1230 *retval = 0; 1231 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1232 *retval |= R_OK; 1233 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1234 *retval |= W_OK; 1235 /* XXX we return X_OK for root on VREG even if not */ 1236 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1237 *retval |= X_OK; 1238 vput(vp); 1239 crfree(cred); 1240 return (error); 1241 } 1242 1243 /* 1244 * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 1245 * No apologies offered, if you don't like it, rewrite it! 1246 */ 1247 1248 extern char kstack[]; 1249 #define UOFF(f) ((int)&((struct user *)0)->f) 1250 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1251 1252 /* simplified FP structure */ 1253 struct bsdfp { 1254 int save[54]; 1255 int reg[24]; 1256 int ctrl[3]; 1257 }; 1258 1259 hpuxtobsduoff(off) 1260 int *off; 1261 { 1262 register int *ar0 = curproc->p_regs; 1263 struct hpuxfp *hp; 1264 struct bsdfp *bp; 1265 register u_int raddr; 1266 1267 /* u_ar0 field; procxmt puts in U_ar0 */ 1268 if ((int)off == HPUOFF(hpuxu_ar0)) 1269 return(UOFF(U_ar0)); 1270 1271 #ifdef FPCOPROC 1272 /* 68881 registers from PCB */ 1273 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1274 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1275 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1276 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1277 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1278 return((int)&bp->reg[off - hp->hpfp_reg]); 1279 #endif 1280 1281 /* 1282 * Everything else we recognize comes from the kernel stack, 1283 * so we convert off to an absolute address (if not already) 1284 * for simplicity. 1285 */ 1286 if (off < (int *)ctob(UPAGES)) 1287 off = (int *)((u_int)off + (u_int)kstack); 1288 1289 /* 1290 * 68020 registers. 1291 * We know that the HPUX registers are in the same order as ours. 1292 * The only difference is that their PS is 2 bytes instead of a 1293 * padded 4 like ours throwing the alignment off. 1294 */ 1295 if (off >= ar0 && off < &ar0[18]) { 1296 /* 1297 * PS: return low word and high word of PC as HP-UX would 1298 * (e.g. &u.u_ar0[16.5]). 1299 */ 1300 if (off == &ar0[PS]) 1301 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1302 /* 1303 * PC: off will be &u.u_ar0[16.5] 1304 */ 1305 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1306 raddr = (u_int) &ar0[PC]; 1307 /* 1308 * D0-D7, A0-A7: easy 1309 */ 1310 else 1311 raddr = (u_int) &ar0[(int)(off - ar0)]; 1312 return((int)(raddr - (u_int)kstack)); 1313 } 1314 1315 /* everything else */ 1316 return(-1); 1317 } 1318 1319 /* 1320 * Kludge up a uarea dump so that HPUX debuggers can find out 1321 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1322 * convert the entire user struct. 1323 */ 1324 hpuxdumpu(vp, cred) 1325 struct vnode *vp; 1326 struct ucred *cred; 1327 { 1328 struct proc *p = curproc; 1329 int error; 1330 struct hpuxuser *faku; 1331 struct bsdfp *bp; 1332 short *foop; 1333 1334 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1335 /* 1336 * Make sure there is no mistake about this 1337 * being a real user structure. 1338 */ 1339 bzero((caddr_t)faku, ctob(1)); 1340 /* 1341 * Fill in the process sizes. 1342 */ 1343 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1344 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1345 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1346 /* 1347 * Fill in the exec header for CDB. 1348 * This was saved back in exec(). As far as I can tell CDB 1349 * only uses this information to verify that a particular 1350 * core file goes with a particular binary. 1351 */ 1352 bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 1353 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1354 /* 1355 * Adjust user's saved registers (on kernel stack) to reflect 1356 * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 1357 * so we have to move it up. 1358 */ 1359 faku->hpuxu_ar0 = p->p_regs; 1360 foop = (short *) p->p_regs; 1361 foop[32] = foop[33]; 1362 foop[33] = foop[34]; 1363 foop[34] = foop[35]; 1364 #ifdef FPCOPROC 1365 /* 1366 * Copy 68881 registers from our PCB format to HPUX format 1367 */ 1368 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1369 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1370 sizeof(bp->save)); 1371 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1372 sizeof(bp->ctrl)); 1373 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1374 sizeof(bp->reg)); 1375 #endif 1376 /* 1377 * Slay the dragon 1378 */ 1379 faku->hpuxu_dragon = -1; 1380 /* 1381 * Dump this artfully constructed page in place of the 1382 * user struct page. 1383 */ 1384 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1385 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1386 (int *)NULL, p); 1387 /* 1388 * Dump the remaining UPAGES-1 pages normally 1389 */ 1390 if (!error) 1391 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1392 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1393 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1394 free((caddr_t)faku, M_TEMP); 1395 return(error); 1396 } 1397 1398 /* 1399 * The remaining routines are essentially the same as those in kern_xxx.c 1400 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1401 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1402 * HP-UX compatibility still works even when COMPAT is not defined. 1403 */ 1404 /* #ifdef COMPAT */ 1405 1406 #define HPUX_HZ 50 1407 1408 #include "sys/times.h" 1409 1410 /* from old timeb.h */ 1411 struct hpuxtimeb { 1412 time_t time; 1413 u_short millitm; 1414 short timezone; 1415 short dstflag; 1416 }; 1417 1418 /* ye ole stat structure */ 1419 struct ohpuxstat { 1420 dev_t ohst_dev; 1421 u_short ohst_ino; 1422 u_short ohst_mode; 1423 short ohst_nlink; 1424 short ohst_uid; 1425 short ohst_gid; 1426 dev_t ohst_rdev; 1427 int ohst_size; 1428 int ohst_atime; 1429 int ohst_mtime; 1430 int ohst_ctime; 1431 }; 1432 1433 /* 1434 * SYS V style setpgrp() 1435 */ 1436 ohpuxsetpgrp(p, uap, retval) 1437 register struct proc *p; 1438 int *uap, *retval; 1439 { 1440 if (p->p_pid != p->p_pgid) 1441 enterpgrp(p, p->p_pid, 0); 1442 *retval = p->p_pgid; 1443 return (0); 1444 } 1445 1446 ohpuxtime(p, uap, retval) 1447 struct proc *p; 1448 register struct args { 1449 long *tp; 1450 } *uap; 1451 time_t *retval; 1452 { 1453 int error = 0; 1454 1455 if (uap->tp) 1456 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1457 sizeof (long)); 1458 *retval = time.tv_sec; 1459 return (error); 1460 } 1461 1462 ohpuxstime(p, uap, retval) 1463 struct proc *p; 1464 register struct args { 1465 int time; 1466 } *uap; 1467 int *retval; 1468 { 1469 struct timeval tv; 1470 int s, error; 1471 1472 tv.tv_sec = uap->time; 1473 tv.tv_usec = 0; 1474 if (error = suser(p->p_ucred, &p->p_acflag)) 1475 return (error); 1476 1477 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1478 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1479 s = splhigh(); time = tv; splx(s); 1480 resettodr(); 1481 return (0); 1482 } 1483 1484 ohpuxftime(p, uap, retval) 1485 struct proc *p; 1486 register struct args { 1487 struct hpuxtimeb *tp; 1488 } *uap; 1489 int *retval; 1490 { 1491 struct hpuxtimeb tb; 1492 int s; 1493 1494 s = splhigh(); 1495 tb.time = time.tv_sec; 1496 tb.millitm = time.tv_usec / 1000; 1497 splx(s); 1498 tb.timezone = tz.tz_minuteswest; 1499 tb.dstflag = tz.tz_dsttime; 1500 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1501 } 1502 1503 ohpuxalarm(p, uap, retval) 1504 register struct proc *p; 1505 register struct args { 1506 int deltat; 1507 } *uap; 1508 int *retval; 1509 { 1510 int s = splhigh(); 1511 1512 untimeout(realitexpire, (caddr_t)p); 1513 timerclear(&p->p_realtimer.it_interval); 1514 *retval = 0; 1515 if (timerisset(&p->p_realtimer.it_value) && 1516 timercmp(&p->p_realtimer.it_value, &time, >)) 1517 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1518 if (uap->deltat == 0) { 1519 timerclear(&p->p_realtimer.it_value); 1520 splx(s); 1521 return (0); 1522 } 1523 p->p_realtimer.it_value = time; 1524 p->p_realtimer.it_value.tv_sec += uap->deltat; 1525 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1526 splx(s); 1527 return (0); 1528 } 1529 1530 ohpuxnice(p, uap, retval) 1531 register struct proc *p; 1532 register struct args { 1533 int niceness; 1534 } *uap; 1535 int *retval; 1536 { 1537 int error; 1538 1539 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1540 if (error == 0) 1541 *retval = p->p_nice - NZERO; 1542 return (error); 1543 } 1544 1545 ohpuxtimes(p, uap, retval) 1546 struct proc *p; 1547 register struct args { 1548 struct tms *tmsb; 1549 } *uap; 1550 time_t *retval; 1551 { 1552 struct tms atms; 1553 int error; 1554 1555 atms.tms_utime = hpuxscale(&p->p_utime); 1556 atms.tms_stime = hpuxscale(&p->p_stime); 1557 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1558 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 1559 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1560 if (error == 0) 1561 *retval = hpuxscale(&time) - hpuxscale(&boottime); 1562 return (error); 1563 } 1564 1565 /* 1566 * Doesn't exactly do what the documentation says. 1567 * What we really do is return 1/HPUX_HZ-th of a second since that 1568 * is what HP-UX returns. 1569 */ 1570 hpuxscale(tvp) 1571 register struct timeval *tvp; 1572 { 1573 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 1574 } 1575 1576 /* 1577 * Set IUPD and IACC times on file. 1578 * Can't set ICHG. 1579 */ 1580 ohpuxutime(p, uap, retval) 1581 struct proc *p; 1582 register struct a { 1583 char *fname; 1584 time_t *tptr; 1585 } *uap; 1586 int *retval; 1587 { 1588 register struct vnode *vp; 1589 register struct nameidata *ndp; 1590 struct vattr vattr; 1591 time_t tv[2]; 1592 int error; 1593 struct nameidata nd; 1594 1595 ndp = &nd; 1596 if (uap->tptr) { 1597 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1598 if (error) 1599 return (error); 1600 } else 1601 tv[0] = tv[1] = time.tv_sec; 1602 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1603 ndp->ni_segflg = UIO_USERSPACE; 1604 ndp->ni_dirp = uap->fname; 1605 vattr_null(&vattr); 1606 vattr.va_atime.tv_sec = tv[0]; 1607 vattr.va_atime.tv_usec = 0; 1608 vattr.va_mtime.tv_sec = tv[1]; 1609 vattr.va_mtime.tv_usec = 0; 1610 if (error = namei(ndp, p)) 1611 return (error); 1612 vp = ndp->ni_vp; 1613 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1614 error = EROFS; 1615 else 1616 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred, p); 1617 vput(vp); 1618 return (error); 1619 } 1620 1621 ohpuxpause(p, uap, retval) 1622 struct proc *p; 1623 int *uap, *retval; 1624 { 1625 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 1626 /* always return EINTR rather than ERESTART... */ 1627 return (EINTR); 1628 } 1629 1630 /* 1631 * The old fstat system call. 1632 */ 1633 ohpuxfstat(p, uap, retval) 1634 struct proc *p; 1635 register struct args { 1636 int fd; 1637 struct ohpuxstat *sb; 1638 } *uap; 1639 int *retval; 1640 { 1641 register struct filedesc *fdp = p->p_fd; 1642 struct file *fp; 1643 1644 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1645 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1646 return (EBADF); 1647 if (fp->f_type != DTYPE_VNODE) 1648 return (EINVAL); 1649 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 1650 } 1651 1652 /* 1653 * Old stat system call. This version follows links. 1654 */ 1655 ohpuxstat(p, uap, retval) 1656 struct proc *p; 1657 register struct args { 1658 char *fname; 1659 struct ohpuxstat *sb; 1660 } *uap; 1661 int *retval; 1662 { 1663 register struct nameidata *ndp; 1664 int error; 1665 struct nameidata nd; 1666 1667 ndp = &nd; 1668 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 1669 ndp->ni_segflg = UIO_USERSPACE; 1670 ndp->ni_dirp = uap->fname; 1671 if (error = namei(ndp, p)) 1672 return (error); 1673 error = ohpuxstat1(ndp->ni_vp, uap->sb); 1674 vput(ndp->ni_vp); 1675 return (error); 1676 } 1677 1678 int 1679 ohpuxstat1(vp, ub) 1680 register struct vnode *vp; 1681 struct ohpuxstat *ub; 1682 { 1683 struct ohpuxstat ds; 1684 struct vattr vattr; 1685 register int error; 1686 1687 error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 1688 if (error) 1689 return(error); 1690 /* 1691 * Copy from inode table 1692 */ 1693 ds.ohst_dev = vattr.va_fsid; 1694 ds.ohst_ino = (short)vattr.va_fileid; 1695 ds.ohst_mode = (u_short)vattr.va_mode; 1696 ds.ohst_nlink = vattr.va_nlink; 1697 ds.ohst_uid = (short)vattr.va_uid; 1698 ds.ohst_gid = (short)vattr.va_gid; 1699 ds.ohst_rdev = (dev_t)vattr.va_rdev; 1700 ds.ohst_size = (int)vattr.va_size; 1701 ds.ohst_atime = (int)vattr.va_atime.tv_sec; 1702 ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 1703 ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 1704 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1705 } 1706 /* #endif */ 1707 1708 #endif 1709