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