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