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