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