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