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.43 92/04/23$ 13 * 14 * @(#)hpux_compat.c 7.26 (Berkeley) 07/09/92 15 */ 16 17 /* 18 * Various HP-UX 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("HP-UX %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 * HP-UX 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 HP-UX. 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. HP-UX 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 /* includes 425 */ 476 case HP_380: 477 protoutsname.machine[6] = '8'; 478 break; 479 } 480 /* copy hostname (sans domain) to nodename */ 481 for (i = 0; i < 8 && hostname[i] != '.'; i++) 482 protoutsname.nodename[i] = hostname[i]; 483 protoutsname.nodename[i] = '\0'; 484 error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 485 sizeof(struct hpuxutsname)); 486 break; 487 488 /* gethostname */ 489 case 5: 490 /* uap->dev is length */ 491 if (uap->dev > hostnamelen + 1) 492 uap->dev = hostnamelen + 1; 493 error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 494 uap->dev); 495 break; 496 497 case 1: /* ?? */ 498 case 2: /* ustat */ 499 case 3: /* ?? */ 500 case 4: /* sethostname */ 501 default: 502 error = EINVAL; 503 break; 504 } 505 return (error); 506 } 507 508 hpuxsysconf(p, uap, retval) 509 struct proc *p; 510 struct args { 511 int name; 512 } *uap; 513 int *retval; 514 { 515 switch (uap->name) { 516 517 /* open files */ 518 case HPUX_SYSCONF_OPENMAX: 519 *retval = NOFILE; 520 break; 521 522 /* architecture */ 523 case HPUX_SYSCONF_CPUTYPE: 524 switch (machineid) { 525 case HP_320: 526 case HP_330: 527 case HP_350: 528 *retval = HPUX_SYSCONF_CPUM020; 529 break; 530 case HP_340: 531 case HP_360: 532 case HP_370: 533 case HP_375: 534 *retval = HPUX_SYSCONF_CPUM030; 535 break; 536 case HP_380: 537 *retval = HPUX_SYSCONF_CPUM040; 538 break; 539 } 540 break; 541 default: 542 uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 543 return (EINVAL); 544 } 545 return (0); 546 } 547 548 hpuxstat(p, uap, retval) 549 struct proc *p; 550 struct args { 551 char *fname; 552 struct hpuxstat *hsb; 553 } *uap; 554 int *retval; 555 { 556 return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 557 } 558 559 hpuxlstat(p, uap, retval) 560 struct proc *p; 561 struct args { 562 char *fname; 563 struct hpuxstat *hsb; 564 } *uap; 565 int *retval; 566 { 567 return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 568 } 569 570 hpuxfstat(p, uap, retval) 571 struct proc *p; 572 register struct args { 573 int fdes; 574 struct hpuxstat *hsb; 575 } *uap; 576 int *retval; 577 { 578 register struct filedesc *fdp = p->p_fd; 579 register struct file *fp; 580 struct stat sb; 581 int error; 582 583 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 584 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 585 return (EBADF); 586 587 switch (fp->f_type) { 588 589 case DTYPE_VNODE: 590 error = vn_stat((struct vnode *)fp->f_data, &sb); 591 break; 592 593 case DTYPE_SOCKET: 594 error = soo_stat((struct socket *)fp->f_data, &sb); 595 break; 596 597 default: 598 panic("fstat"); 599 /*NOTREACHED*/ 600 } 601 /* is this right for sockets?? */ 602 if (error == 0) 603 error = bsdtohpuxstat(&sb, uap->hsb); 604 return (error); 605 } 606 607 hpuxulimit(p, uap, retval) 608 struct proc *p; 609 register struct args { 610 int cmd; 611 long newlimit; 612 } *uap; 613 long *retval; 614 { 615 struct rlimit *limp; 616 int error = 0; 617 618 limp = &p->p_rlimit[RLIMIT_FSIZE]; 619 switch (uap->cmd) { 620 case 2: 621 uap->newlimit *= 512; 622 if (uap->newlimit > limp->rlim_max && 623 (error = suser(p->p_ucred, &p->p_acflag))) 624 break; 625 limp->rlim_cur = limp->rlim_max = uap->newlimit; 626 /* else fall into... */ 627 628 case 1: 629 *retval = limp->rlim_max / 512; 630 break; 631 632 case 3: 633 limp = &p->p_rlimit[RLIMIT_DATA]; 634 *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 635 break; 636 637 default: 638 error = EINVAL; 639 break; 640 } 641 return (error); 642 } 643 644 /* 645 * Map "real time" priorities 0 (high) thru 127 (low) into nice 646 * values -16 (high) thru -1 (low). 647 */ 648 hpuxrtprio(cp, uap, retval) 649 struct proc *cp; 650 register struct args { 651 int pid; 652 int prio; 653 } *uap; 654 int *retval; 655 { 656 struct proc *p; 657 int nice, error; 658 659 if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 660 uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 661 return (EINVAL); 662 if (uap->pid == 0) 663 p = cp; 664 else if ((p = pfind(uap->pid)) == 0) 665 return (ESRCH); 666 nice = p->p_nice; 667 if (nice < NZERO) 668 *retval = (nice + 16) << 3; 669 else 670 *retval = RTPRIO_RTOFF; 671 switch (uap->prio) { 672 673 case RTPRIO_NOCHG: 674 return (0); 675 676 case RTPRIO_RTOFF: 677 if (nice >= NZERO) 678 return (0); 679 nice = NZERO; 680 break; 681 682 default: 683 nice = (uap->prio >> 3) - 16; 684 break; 685 } 686 error = donice(cp, p, nice); 687 if (error == EACCES) 688 error = EPERM; 689 return (error); 690 } 691 692 hpuxadvise(p, uap, retval) 693 struct proc *p; 694 struct args { 695 int arg; 696 } *uap; 697 int *retval; 698 { 699 int error = 0; 700 701 switch (uap->arg) { 702 case 0: 703 p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; 704 break; 705 case 1: 706 ICIA(); 707 break; 708 case 2: 709 DCIA(); 710 break; 711 default: 712 error = EINVAL; 713 break; 714 } 715 return (error); 716 } 717 718 hpuxptrace(p, uap, retval) 719 struct proc *p; 720 struct args { 721 int req; 722 int pid; 723 int *addr; 724 int data; 725 } *uap; 726 int *retval; 727 { 728 int error; 729 730 if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 731 if (uap->data) { 732 uap->data = hpuxtobsdsig(uap->data); 733 if (uap->data == 0) 734 uap->data = NSIG; 735 } 736 } 737 error = ptrace(p, uap, retval); 738 return (error); 739 } 740 741 hpuxgetdomainname(p, uap, retval) 742 struct proc *p; 743 register struct args { 744 char *domainname; 745 u_int len; 746 } *uap; 747 int *retval; 748 { 749 if (uap->len > domainnamelen + 1) 750 uap->len = domainnamelen + 1; 751 return (copyout(domainname, uap->domainname, uap->len)); 752 } 753 754 hpuxsetdomainname(p, uap, retval) 755 struct proc *p; 756 register struct args { 757 char *domainname; 758 u_int len; 759 } *uap; 760 int *retval; 761 { 762 int error; 763 764 if (error = suser(p->p_ucred, &p->p_acflag)) 765 return (error); 766 if (uap->len > sizeof (domainname) - 1) 767 return (EINVAL); 768 domainnamelen = uap->len; 769 error = copyin(uap->domainname, domainname, uap->len); 770 domainname[domainnamelen] = 0; 771 return (error); 772 } 773 774 #ifdef SYSVSHM 775 #include "shm.h" 776 777 hpuxshmat(p, uap, retval) 778 struct proc *p; 779 int *uap, *retval; 780 { 781 return (shmat(p, uap, retval)); 782 } 783 784 hpuxshmdt(p, uap, retval) 785 struct proc *p; 786 int *uap, *retval; 787 { 788 return (shmdt(p, uap, retval)); 789 } 790 791 hpuxshmget(p, uap, retval) 792 struct proc *p; 793 int *uap, *retval; 794 { 795 return (shmget(p, uap, retval)); 796 } 797 798 /* 799 * Handle HP-UX specific commands. 800 */ 801 hpuxshmctl(p, uap, retval) 802 struct proc *p; 803 struct args { 804 int shmid; 805 int cmd; 806 caddr_t buf; 807 } *uap; 808 int *retval; 809 { 810 register struct shmid_ds *shp; 811 register struct ucred *cred = p->p_ucred; 812 int error; 813 814 if (error = shmvalid(uap->shmid)) 815 return (error); 816 shp = &shmsegs[uap->shmid % SHMMMNI]; 817 if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 818 /* don't really do anything, but make them think we did */ 819 if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 820 cred->cr_uid != shp->shm_perm.cuid) 821 return (EPERM); 822 return (0); 823 } 824 return (shmctl(p, uap, retval)); 825 } 826 #endif 827 828 /* 829 * Fake semaphore routines, just don't return an error. 830 * Should be adequate for starbase to run. 831 */ 832 hpuxsemctl(p, uap, retval) 833 struct proc *p; 834 struct args { 835 int semid; 836 u_int semnum; 837 int cmd; 838 int arg; 839 } *uap; 840 int *retval; 841 { 842 /* XXX: should do something here */ 843 return (0); 844 } 845 846 hpuxsemget(p, uap, retval) 847 struct proc *p; 848 struct args { 849 key_t key; 850 int nsems; 851 int semflg; 852 } *uap; 853 int *retval; 854 { 855 /* XXX: should do something here */ 856 return (0); 857 } 858 859 hpuxsemop(p, uap, retval) 860 struct proc *p; 861 struct args { 862 int semid; 863 struct sembuf *sops; 864 u_int nsops; 865 } *uap; 866 int *retval; 867 { 868 /* XXX: should do something here */ 869 return (0); 870 } 871 872 /* convert from BSD to HP-UX errno */ 873 bsdtohpuxerrno(err) 874 int err; 875 { 876 if (err < 0 || err >= NERR) 877 return(BERR); 878 return((int)bsdtohpuxerrnomap[err]); 879 } 880 881 hpuxstat1(fname, hsb, follow) 882 char *fname; 883 struct hpuxstat *hsb; 884 int follow; 885 { 886 int error; 887 struct stat sb; 888 struct nameidata nd; 889 890 NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, curproc); 891 if (error = namei(&nd)) 892 return (error); 893 error = vn_stat(nd.ni_vp, &sb); 894 vput(nd.ni_vp); 895 if (error == 0) 896 error = bsdtohpuxstat(&sb, hsb); 897 return (error); 898 } 899 900 #include "grf.h" 901 #if NGRF > 0 902 #ifdef __STDC__ 903 extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 904 #else 905 extern int grfopen(); 906 #endif 907 #endif 908 909 #define NHIL 1 /* XXX */ 910 #if NHIL > 0 911 #ifdef __STDC__ 912 extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 913 #else 914 extern int hilopen(); 915 #endif 916 #endif 917 918 #include "conf.h" 919 920 bsdtohpuxstat(sb, hsb) 921 struct stat *sb; 922 struct hpuxstat *hsb; 923 { 924 struct hpuxstat ds; 925 926 bzero((caddr_t)&ds, sizeof(ds)); 927 ds.hst_dev = (u_short)sb->st_dev; 928 ds.hst_ino = (u_long)sb->st_ino; 929 ds.hst_mode = sb->st_mode; 930 ds.hst_nlink = sb->st_nlink; 931 ds.hst_uid = (u_short)sb->st_uid; 932 ds.hst_gid = (u_short)sb->st_gid; 933 /* XXX: I don't want to talk about it... */ 934 if ((sb->st_mode & S_IFMT) == S_IFCHR) { 935 #if NGRF > 0 936 if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 937 ds.hst_rdev = grfdevno(sb->st_rdev); 938 #endif 939 #if NHIL > 0 940 if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 941 ds.hst_rdev = hildevno(sb->st_rdev); 942 #endif 943 ; 944 } else 945 ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 946 if (sb->st_size < (quad_t)1 << 32) 947 ds.hst_size = (long)sb->st_size; 948 else 949 ds.hst_size = -2; 950 ds.hst_atime = sb->st_atime; 951 ds.hst_mtime = sb->st_mtime; 952 ds.hst_ctime = sb->st_ctime; 953 ds.hst_blksize = sb->st_blksize; 954 ds.hst_blocks = sb->st_blocks; 955 return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 956 } 957 958 hpuxtobsdioctl(com) 959 int com; 960 { 961 switch (com) { 962 case HPUXTIOCSLTC: 963 com = TIOCSLTC; break; 964 case HPUXTIOCGLTC: 965 com = TIOCGLTC; break; 966 case HPUXTIOCSPGRP: 967 com = TIOCSPGRP; break; 968 case HPUXTIOCGPGRP: 969 com = TIOCGPGRP; break; 970 case HPUXTIOCLBIS: 971 com = TIOCLBIS; break; 972 case HPUXTIOCLBIC: 973 com = TIOCLBIC; break; 974 case HPUXTIOCLSET: 975 com = TIOCLSET; break; 976 case HPUXTIOCLGET: 977 com = TIOCLGET; break; 978 } 979 return(com); 980 } 981 982 /* 983 * HP-UX ioctl system call. The differences here are: 984 * IOC_IN also means IOC_VOID if the size portion is zero. 985 * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 986 * the sgttyb struct is 2 bytes longer 987 */ 988 hpuxioctl(p, uap, retval) 989 struct proc *p; 990 register struct args { 991 int fdes; 992 int cmd; 993 caddr_t cmarg; 994 } *uap; 995 int *retval; 996 { 997 register struct filedesc *fdp = p->p_fd; 998 register struct file *fp; 999 register int com, error; 1000 register u_int size; 1001 caddr_t memp = 0; 1002 #define STK_PARAMS 128 1003 char stkbuf[STK_PARAMS]; 1004 caddr_t data = stkbuf; 1005 1006 com = uap->cmd; 1007 1008 /* XXX */ 1009 if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 1010 return (getsettty(p, uap->fdes, com, uap->cmarg)); 1011 1012 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 1013 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 1014 return (EBADF); 1015 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 1016 return (EBADF); 1017 1018 /* 1019 * Interpret high order word to find 1020 * amount of data to be copied to/from the 1021 * user's address space. 1022 */ 1023 size = IOCPARM_LEN(com); 1024 if (size > IOCPARM_MAX) 1025 return (ENOTTY); 1026 if (size > sizeof (stkbuf)) { 1027 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 1028 data = memp; 1029 } 1030 if (com&IOC_IN) { 1031 if (size) { 1032 error = copyin(uap->cmarg, data, (u_int)size); 1033 if (error) { 1034 if (memp) 1035 free(memp, M_IOCTLOPS); 1036 return (error); 1037 } 1038 } else 1039 *(caddr_t *)data = uap->cmarg; 1040 } else if ((com&IOC_OUT) && size) 1041 /* 1042 * Zero the buffer so the user always 1043 * gets back something deterministic. 1044 */ 1045 bzero(data, size); 1046 else if (com&IOC_VOID) 1047 *(caddr_t *)data = uap->cmarg; 1048 1049 switch (com) { 1050 1051 case HPUXFIOSNBIO: 1052 { 1053 char *ofp = &fdp->fd_ofileflags[uap->fdes]; 1054 int tmp; 1055 1056 if (*(int *)data) 1057 *ofp |= UF_FIONBIO_ON; 1058 else 1059 *ofp &= ~UF_FIONBIO_ON; 1060 /* 1061 * Only set/clear if FNONBLOCK not in effect 1062 */ 1063 if ((*ofp & UF_FNDELAY_ON) == 0) { 1064 tmp = fp->f_flag & FNONBLOCK; 1065 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 1066 (caddr_t)&tmp, p); 1067 } 1068 break; 1069 } 1070 1071 case HPUXTIOCCONS: 1072 *(int *)data = 1; 1073 error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 1074 break; 1075 1076 /* BSD-style job control ioctls */ 1077 case HPUXTIOCLBIS: 1078 case HPUXTIOCLBIC: 1079 case HPUXTIOCLSET: 1080 *(int *)data &= HPUXLTOSTOP; 1081 if (*(int *)data & HPUXLTOSTOP) 1082 *(int *)data = LTOSTOP; 1083 /* fall into */ 1084 case HPUXTIOCLGET: 1085 case HPUXTIOCSLTC: 1086 case HPUXTIOCGLTC: 1087 case HPUXTIOCSPGRP: 1088 case HPUXTIOCGPGRP: 1089 error = (*fp->f_ops->fo_ioctl) 1090 (fp, hpuxtobsdioctl(com), data, p); 1091 if (error == 0 && com == HPUXTIOCLGET) { 1092 *(int *)data &= LTOSTOP; 1093 if (*(int *)data & LTOSTOP) 1094 *(int *)data = HPUXLTOSTOP; 1095 } 1096 break; 1097 1098 /* SYS 5 termio */ 1099 case HPUXTCGETA: 1100 case HPUXTCSETA: 1101 case HPUXTCSETAW: 1102 case HPUXTCSETAF: 1103 error = hpuxtermio(fp, com, data, p); 1104 break; 1105 1106 default: 1107 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 1108 break; 1109 } 1110 /* 1111 * Copy any data to user, size was 1112 * already set and checked above. 1113 */ 1114 if (error == 0 && (com&IOC_OUT) && size) 1115 error = copyout(data, uap->cmarg, (u_int)size); 1116 if (memp) 1117 free(memp, M_IOCTLOPS); 1118 return (error); 1119 } 1120 1121 /* 1122 * Man page lies, behaviour here is based on observed behaviour. 1123 */ 1124 hpuxgetcontext(p, uap, retval) 1125 struct proc *p; 1126 struct args { 1127 char *buf; 1128 int len; 1129 } *uap; 1130 int *retval; 1131 { 1132 int error = 0; 1133 register int len; 1134 1135 #if defined(HP380) 1136 if (machineid == HP_380) { 1137 len = MIN(uap->len, sizeof(hpux040context)); 1138 if (len) 1139 error = copyout(hpux040context, uap->buf, len); 1140 if (error == 0) 1141 *retval = sizeof(hpux040context); 1142 return (error); 1143 } 1144 #endif 1145 len = MIN(uap->len, sizeof(hpuxcontext)); 1146 if (len) 1147 error = copyout(hpuxcontext, uap->buf, (u_int)len); 1148 if (error == 0) 1149 *retval = sizeof(hpuxcontext); 1150 return (error); 1151 } 1152 1153 /* 1154 * This is the equivalent of BSD getpgrp but with more restrictions. 1155 * Note we do not check the real uid or "saved" uid. 1156 */ 1157 hpuxgetpgrp2(cp, uap, retval) 1158 struct proc *cp; 1159 register struct args { 1160 int pid; 1161 } *uap; 1162 int *retval; 1163 { 1164 register struct proc *p; 1165 1166 if (uap->pid == 0) 1167 uap->pid = cp->p_pid; 1168 p = pfind(uap->pid); 1169 if (p == 0) 1170 return (ESRCH); 1171 if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1172 !inferior(p)) 1173 return (EPERM); 1174 *retval = p->p_pgid; 1175 return (0); 1176 } 1177 1178 /* 1179 * This is the equivalent of BSD setpgrp but with more restrictions. 1180 * Note we do not check the real uid or "saved" uid or pgrp. 1181 */ 1182 hpuxsetpgrp2(p, uap, retval) 1183 struct proc *p; 1184 struct args { 1185 int pid; 1186 int pgrp; 1187 } *uap; 1188 int *retval; 1189 { 1190 /* empirically determined */ 1191 if (uap->pgrp < 0 || uap->pgrp >= 30000) 1192 return (EINVAL); 1193 return (setpgid(p, uap, retval)); 1194 } 1195 1196 /* 1197 * XXX Same as old BSD setre[ug]id right now. Need to consider saved ids. 1198 */ 1199 /* ARGSUSED */ 1200 hpuxsetresuid(p, uap, retval) 1201 register struct proc *p; 1202 struct args { 1203 int ruid; 1204 int euid; 1205 int suid; 1206 } *uap; 1207 int *retval; 1208 { 1209 register struct pcred *pc = p->p_cred; 1210 register uid_t ruid, euid; 1211 int error; 1212 1213 if (uap->ruid == -1) 1214 ruid = pc->p_ruid; 1215 else 1216 ruid = uap->ruid; 1217 /* 1218 * Allow setting real uid to previous effective, for swapping real and 1219 * effective. This should be: 1220 * 1221 * if (ruid != pc->p_ruid && 1222 * (error = suser(pc->pc_ucred, &p->p_acflag))) 1223 */ 1224 if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ && 1225 (error = suser(pc->pc_ucred, &p->p_acflag))) 1226 return (error); 1227 if (uap->euid == -1) 1228 euid = pc->pc_ucred->cr_uid; 1229 else 1230 euid = uap->euid; 1231 if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && 1232 euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag))) 1233 return (error); 1234 /* 1235 * Everything's okay, do it. Copy credentials so other references do 1236 * not see our changes. 1237 */ 1238 pc->pc_ucred = crcopy(pc->pc_ucred); 1239 pc->pc_ucred->cr_uid = euid; 1240 pc->p_ruid = ruid; 1241 p->p_flag |= SUGID; 1242 return (0); 1243 } 1244 1245 /* ARGSUSED */ 1246 hpuxsetresgid(p, uap, retval) 1247 register struct proc *p; 1248 struct args { 1249 int rgid; 1250 int egid; 1251 int sgid; 1252 } *uap; 1253 int *retval; 1254 { 1255 register struct pcred *pc = p->p_cred; 1256 register gid_t rgid, egid; 1257 int error; 1258 1259 if (uap->rgid == -1) 1260 rgid = pc->p_rgid; 1261 else 1262 rgid = uap->rgid; 1263 /* 1264 * Allow setting real gid to previous effective, for swapping real and 1265 * effective. This didn't really work correctly in 4.[23], but is 1266 * preserved so old stuff doesn't fail. This should be: 1267 * 1268 * if (rgid != pc->p_rgid && 1269 * (error = suser(pc->pc_ucred, &p->p_acflag))) 1270 */ 1271 if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ && 1272 (error = suser(pc->pc_ucred, &p->p_acflag))) 1273 return (error); 1274 if (uap->egid == -1) 1275 egid = pc->pc_ucred->cr_groups[0]; 1276 else 1277 egid = uap->egid; 1278 if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && 1279 egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag))) 1280 return (error); 1281 pc->pc_ucred = crcopy(pc->pc_ucred); 1282 pc->pc_ucred->cr_groups[0] = egid; 1283 pc->p_rgid = rgid; 1284 p->p_flag |= SUGID; 1285 return (0); 1286 } 1287 1288 /* 1289 * XXX: simple recognition hack to see if we can make grmd work. 1290 */ 1291 hpuxlockf(p, uap, retval) 1292 struct proc *p; 1293 struct args { 1294 int fd; 1295 int func; 1296 long size; 1297 } *uap; 1298 int *retval; 1299 { 1300 #ifdef DEBUG 1301 log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 1302 p->p_pid, uap->fd, uap->func, uap->size); 1303 #endif 1304 return (0); 1305 } 1306 1307 hpuxgetaccess(p, uap, retval) 1308 register struct proc *p; 1309 register struct args { 1310 char *path; 1311 int uid; 1312 int ngroups; 1313 int *gidset; 1314 void *label; 1315 void *privs; 1316 } *uap; 1317 int *retval; 1318 { 1319 int lgroups[NGROUPS]; 1320 int error = 0; 1321 register struct ucred *cred; 1322 register struct vnode *vp; 1323 struct nameidata nd; 1324 1325 /* 1326 * Build an appropriate credential structure 1327 */ 1328 cred = crdup(p->p_ucred); 1329 switch (uap->uid) { 1330 case 65502: /* UID_EUID */ 1331 break; 1332 case 65503: /* UID_RUID */ 1333 cred->cr_uid = p->p_cred->p_ruid; 1334 break; 1335 case 65504: /* UID_SUID */ 1336 error = EINVAL; 1337 break; 1338 default: 1339 if (uap->uid > 65504) 1340 error = EINVAL; 1341 cred->cr_uid = uap->uid; 1342 break; 1343 } 1344 switch (uap->ngroups) { 1345 case -1: /* NGROUPS_EGID */ 1346 cred->cr_ngroups = 1; 1347 break; 1348 case -5: /* NGROUPS_EGID_SUPP */ 1349 break; 1350 case -2: /* NGROUPS_RGID */ 1351 cred->cr_ngroups = 1; 1352 cred->cr_gid = p->p_cred->p_rgid; 1353 break; 1354 case -6: /* NGROUPS_RGID_SUPP */ 1355 cred->cr_gid = p->p_cred->p_rgid; 1356 break; 1357 case -3: /* NGROUPS_SGID */ 1358 case -7: /* NGROUPS_SGID_SUPP */ 1359 error = EINVAL; 1360 break; 1361 case -4: /* NGROUPS_SUPP */ 1362 if (cred->cr_ngroups > 1) 1363 cred->cr_gid = cred->cr_groups[1]; 1364 else 1365 error = EINVAL; 1366 break; 1367 default: 1368 if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1369 error = copyin((caddr_t)uap->gidset, 1370 (caddr_t)&lgroups[0], 1371 uap->ngroups * sizeof(lgroups[0])); 1372 else 1373 error = EINVAL; 1374 if (error == 0) { 1375 int gid; 1376 1377 for (gid = 0; gid < uap->ngroups; gid++) 1378 cred->cr_groups[gid] = lgroups[gid]; 1379 cred->cr_ngroups = uap->ngroups; 1380 } 1381 break; 1382 } 1383 /* 1384 * Lookup file using caller's effective IDs. 1385 */ 1386 if (error == 0) { 1387 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1388 uap->path, p); 1389 error = namei(&nd); 1390 } 1391 if (error) { 1392 crfree(cred); 1393 return (error); 1394 } 1395 /* 1396 * Use the constructed credentials for access checks. 1397 */ 1398 vp = nd.ni_vp; 1399 *retval = 0; 1400 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1401 *retval |= R_OK; 1402 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1403 *retval |= W_OK; 1404 /* XXX we return X_OK for root on VREG even if not */ 1405 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1406 *retval |= X_OK; 1407 vput(vp); 1408 crfree(cred); 1409 return (error); 1410 } 1411 1412 /* 1413 * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 1414 * No apologies offered, if you don't like it, rewrite it! 1415 */ 1416 1417 extern char kstack[]; 1418 #define UOFF(f) ((int)&((struct user *)0)->f) 1419 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1420 1421 /* simplified FP structure */ 1422 struct bsdfp { 1423 int save[54]; 1424 int reg[24]; 1425 int ctrl[3]; 1426 }; 1427 1428 hpuxtobsduoff(off) 1429 int *off; 1430 { 1431 register int *ar0 = curproc->p_md.md_regs; 1432 struct hpuxfp *hp; 1433 struct bsdfp *bp; 1434 register u_int raddr; 1435 1436 /* u_ar0 field; procxmt puts in U_ar0 */ 1437 if ((int)off == HPUOFF(hpuxu_ar0)) 1438 return(UOFF(U_ar0)); 1439 1440 #ifdef FPCOPROC 1441 /* 68881 registers from PCB */ 1442 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1443 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1444 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1445 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1446 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1447 return((int)&bp->reg[off - hp->hpfp_reg]); 1448 #endif 1449 1450 /* 1451 * Everything else we recognize comes from the kernel stack, 1452 * so we convert off to an absolute address (if not already) 1453 * for simplicity. 1454 */ 1455 if (off < (int *)ctob(UPAGES)) 1456 off = (int *)((u_int)off + (u_int)kstack); 1457 1458 /* 1459 * 68020 registers. 1460 * We know that the HP-UX registers are in the same order as ours. 1461 * The only difference is that their PS is 2 bytes instead of a 1462 * padded 4 like ours throwing the alignment off. 1463 */ 1464 if (off >= ar0 && off < &ar0[18]) { 1465 /* 1466 * PS: return low word and high word of PC as HP-UX would 1467 * (e.g. &u.u_ar0[16.5]). 1468 */ 1469 if (off == &ar0[PS]) 1470 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1471 /* 1472 * PC: off will be &u.u_ar0[16.5] 1473 */ 1474 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1475 raddr = (u_int) &ar0[PC]; 1476 /* 1477 * D0-D7, A0-A7: easy 1478 */ 1479 else 1480 raddr = (u_int) &ar0[(int)(off - ar0)]; 1481 return((int)(raddr - (u_int)kstack)); 1482 } 1483 1484 /* everything else */ 1485 return(-1); 1486 } 1487 1488 /* 1489 * Kludge up a uarea dump so that HP-UX debuggers can find out 1490 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1491 * convert the entire user struct. 1492 */ 1493 hpuxdumpu(vp, cred) 1494 struct vnode *vp; 1495 struct ucred *cred; 1496 { 1497 struct proc *p = curproc; 1498 int error; 1499 struct hpuxuser *faku; 1500 struct bsdfp *bp; 1501 short *foop; 1502 1503 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1504 /* 1505 * Make sure there is no mistake about this 1506 * being a real user structure. 1507 */ 1508 bzero((caddr_t)faku, ctob(1)); 1509 /* 1510 * Fill in the process sizes. 1511 */ 1512 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1513 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1514 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1515 /* 1516 * Fill in the exec header for CDB. 1517 * This was saved back in exec(). As far as I can tell CDB 1518 * only uses this information to verify that a particular 1519 * core file goes with a particular binary. 1520 */ 1521 bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 1522 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1523 /* 1524 * Adjust user's saved registers (on kernel stack) to reflect 1525 * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 1526 * so we have to move it up. 1527 */ 1528 faku->hpuxu_ar0 = p->p_md.md_regs; 1529 foop = (short *) p->p_md.md_regs; 1530 foop[32] = foop[33]; 1531 foop[33] = foop[34]; 1532 foop[34] = foop[35]; 1533 #ifdef FPCOPROC 1534 /* 1535 * Copy 68881 registers from our PCB format to HP-UX format 1536 */ 1537 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1538 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1539 sizeof(bp->save)); 1540 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1541 sizeof(bp->ctrl)); 1542 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1543 sizeof(bp->reg)); 1544 #endif 1545 /* 1546 * Slay the dragon 1547 */ 1548 faku->hpuxu_dragon = -1; 1549 /* 1550 * Dump this artfully constructed page in place of the 1551 * user struct page. 1552 */ 1553 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1554 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1555 (int *)NULL, p); 1556 /* 1557 * Dump the remaining UPAGES-1 pages normally 1558 */ 1559 if (!error) 1560 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1561 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1562 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1563 free((caddr_t)faku, M_TEMP); 1564 return(error); 1565 } 1566 1567 /* 1568 * The remaining routines are essentially the same as those in kern_xxx.c 1569 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1570 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1571 * HP-UX compatibility still works even when COMPAT is not defined. 1572 */ 1573 #define HPUX_HZ 50 1574 1575 #include "sys/times.h" 1576 1577 /* from old timeb.h */ 1578 struct hpuxtimeb { 1579 time_t time; 1580 u_short millitm; 1581 short timezone; 1582 short dstflag; 1583 }; 1584 1585 /* ye ole stat structure */ 1586 struct ohpuxstat { 1587 u_short ohst_dev; 1588 u_short ohst_ino; 1589 u_short ohst_mode; 1590 short ohst_nlink; 1591 short ohst_uid; 1592 short ohst_gid; 1593 u_short ohst_rdev; 1594 int ohst_size; 1595 int ohst_atime; 1596 int ohst_mtime; 1597 int ohst_ctime; 1598 }; 1599 1600 /* 1601 * SYS V style setpgrp() 1602 */ 1603 ohpuxsetpgrp(p, uap, retval) 1604 register struct proc *p; 1605 int *uap, *retval; 1606 { 1607 if (p->p_pid != p->p_pgid) 1608 enterpgrp(p, p->p_pid, 0); 1609 *retval = p->p_pgid; 1610 return (0); 1611 } 1612 1613 ohpuxtime(p, uap, retval) 1614 struct proc *p; 1615 register struct args { 1616 long *tp; 1617 } *uap; 1618 time_t *retval; 1619 { 1620 int error = 0; 1621 1622 if (uap->tp) 1623 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1624 sizeof (long)); 1625 *retval = time.tv_sec; 1626 return (error); 1627 } 1628 1629 ohpuxstime(p, uap, retval) 1630 struct proc *p; 1631 register struct args { 1632 int time; 1633 } *uap; 1634 int *retval; 1635 { 1636 struct timeval tv; 1637 int s, error; 1638 1639 tv.tv_sec = uap->time; 1640 tv.tv_usec = 0; 1641 if (error = suser(p->p_ucred, &p->p_acflag)) 1642 return (error); 1643 1644 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1645 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1646 s = splhigh(); time = tv; splx(s); 1647 resettodr(); 1648 return (0); 1649 } 1650 1651 ohpuxftime(p, uap, retval) 1652 struct proc *p; 1653 register struct args { 1654 struct hpuxtimeb *tp; 1655 } *uap; 1656 int *retval; 1657 { 1658 struct hpuxtimeb tb; 1659 int s; 1660 1661 s = splhigh(); 1662 tb.time = time.tv_sec; 1663 tb.millitm = time.tv_usec / 1000; 1664 splx(s); 1665 tb.timezone = tz.tz_minuteswest; 1666 tb.dstflag = tz.tz_dsttime; 1667 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1668 } 1669 1670 ohpuxalarm(p, uap, retval) 1671 register struct proc *p; 1672 register struct args { 1673 int deltat; 1674 } *uap; 1675 int *retval; 1676 { 1677 int s = splhigh(); 1678 1679 untimeout(realitexpire, (caddr_t)p); 1680 timerclear(&p->p_realtimer.it_interval); 1681 *retval = 0; 1682 if (timerisset(&p->p_realtimer.it_value) && 1683 timercmp(&p->p_realtimer.it_value, &time, >)) 1684 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1685 if (uap->deltat == 0) { 1686 timerclear(&p->p_realtimer.it_value); 1687 splx(s); 1688 return (0); 1689 } 1690 p->p_realtimer.it_value = time; 1691 p->p_realtimer.it_value.tv_sec += uap->deltat; 1692 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1693 splx(s); 1694 return (0); 1695 } 1696 1697 ohpuxnice(p, uap, retval) 1698 register struct proc *p; 1699 register struct args { 1700 int niceness; 1701 } *uap; 1702 int *retval; 1703 { 1704 int error; 1705 1706 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1707 if (error == 0) 1708 *retval = p->p_nice - NZERO; 1709 return (error); 1710 } 1711 1712 ohpuxtimes(p, uap, retval) 1713 struct proc *p; 1714 register struct args { 1715 struct tms *tmsb; 1716 } *uap; 1717 time_t *retval; 1718 { 1719 struct timeval ru, rs; 1720 struct tms atms; 1721 int error; 1722 1723 calcru(p, &ru, &rs, NULL); 1724 atms.tms_utime = hpuxscale(&ru); 1725 atms.tms_stime = hpuxscale(&rs); 1726 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1727 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 1728 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1729 if (error == 0) 1730 *retval = hpuxscale(&time) - hpuxscale(&boottime); 1731 return (error); 1732 } 1733 1734 /* 1735 * Doesn't exactly do what the documentation says. 1736 * What we really do is return 1/HPUX_HZ-th of a second since that 1737 * is what HP-UX returns. 1738 */ 1739 hpuxscale(tvp) 1740 register struct timeval *tvp; 1741 { 1742 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 1743 } 1744 1745 /* 1746 * Set IUPD and IACC times on file. 1747 * Can't set ICHG. 1748 */ 1749 ohpuxutime(p, uap, retval) 1750 struct proc *p; 1751 register struct a { 1752 char *fname; 1753 time_t *tptr; 1754 } *uap; 1755 int *retval; 1756 { 1757 register struct vnode *vp; 1758 struct vattr vattr; 1759 time_t tv[2]; 1760 int error; 1761 struct nameidata nd; 1762 1763 if (uap->tptr) { 1764 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1765 if (error) 1766 return (error); 1767 } else 1768 tv[0] = tv[1] = time.tv_sec; 1769 vattr_null(&vattr); 1770 vattr.va_atime.ts_sec = tv[0]; 1771 vattr.va_atime.ts_nsec = 0; 1772 vattr.va_mtime.ts_sec = tv[1]; 1773 vattr.va_mtime.ts_nsec = 0; 1774 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1775 if (error = namei(&nd)) 1776 return (error); 1777 vp = nd.ni_vp; 1778 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1779 error = EROFS; 1780 else 1781 error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 1782 vput(vp); 1783 return (error); 1784 } 1785 1786 ohpuxpause(p, uap, retval) 1787 struct proc *p; 1788 int *uap, *retval; 1789 { 1790 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 1791 /* always return EINTR rather than ERESTART... */ 1792 return (EINTR); 1793 } 1794 1795 /* 1796 * The old fstat system call. 1797 */ 1798 ohpuxfstat(p, uap, retval) 1799 struct proc *p; 1800 register struct args { 1801 int fd; 1802 struct ohpuxstat *sb; 1803 } *uap; 1804 int *retval; 1805 { 1806 register struct filedesc *fdp = p->p_fd; 1807 struct file *fp; 1808 1809 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1810 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1811 return (EBADF); 1812 if (fp->f_type != DTYPE_VNODE) 1813 return (EINVAL); 1814 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 1815 } 1816 1817 /* 1818 * Old stat system call. This version follows links. 1819 */ 1820 ohpuxstat(p, uap, retval) 1821 struct proc *p; 1822 register struct args { 1823 char *fname; 1824 struct ohpuxstat *sb; 1825 } *uap; 1826 int *retval; 1827 { 1828 int error; 1829 struct nameidata nd; 1830 1831 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1832 if (error = namei(&nd)) 1833 return (error); 1834 error = ohpuxstat1(nd.ni_vp, uap->sb); 1835 vput(nd.ni_vp); 1836 return (error); 1837 } 1838 1839 int 1840 ohpuxstat1(vp, ub) 1841 register struct vnode *vp; 1842 struct ohpuxstat *ub; 1843 { 1844 struct ohpuxstat ds; 1845 struct vattr vattr; 1846 register int error; 1847 1848 error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 1849 if (error) 1850 return(error); 1851 /* 1852 * Copy from inode table 1853 */ 1854 ds.ohst_dev = vattr.va_fsid; 1855 ds.ohst_ino = (short)vattr.va_fileid; 1856 ds.ohst_mode = (u_short)vattr.va_mode; 1857 ds.ohst_nlink = vattr.va_nlink; 1858 ds.ohst_uid = (short)vattr.va_uid; 1859 ds.ohst_gid = (short)vattr.va_gid; 1860 ds.ohst_rdev = (u_short)vattr.va_rdev; 1861 ds.ohst_size = (int)vattr.va_size; 1862 ds.ohst_atime = (int)vattr.va_atime.ts_sec; 1863 ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 1864 ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 1865 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1866 } 1867 #endif 1868