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