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