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.30 (Berkeley) 07/15/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, p)); 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, p)); 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, p); 607 break; 608 609 case DTYPE_SOCKET: 610 error = soo_stat((struct socket *)fp->f_data, &sb, p); 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, p) 908 char *fname; 909 struct hpuxstat *hsb; 910 int follow; 911 struct proc *p; 912 { 913 int error; 914 struct stat sb; 915 struct nameidata nd; 916 917 NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 918 if (error = namei(&nd)) 919 return (error); 920 error = vn_stat(nd.ni_vp, &sb, p); 921 vput(nd.ni_vp); 922 if (error == 0) 923 error = bsdtohpuxstat(&sb, hsb); 924 return (error); 925 } 926 927 #include "grf.h" 928 #if NGRF > 0 929 #ifdef __STDC__ 930 extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 931 #else 932 extern int grfopen(); 933 #endif 934 #endif 935 936 #define NHIL 1 /* XXX */ 937 #if NHIL > 0 938 #ifdef __STDC__ 939 extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 940 #else 941 extern int hilopen(); 942 #endif 943 #endif 944 945 #include "conf.h" 946 947 bsdtohpuxstat(sb, hsb) 948 struct stat *sb; 949 struct hpuxstat *hsb; 950 { 951 struct hpuxstat ds; 952 953 bzero((caddr_t)&ds, sizeof(ds)); 954 ds.hst_dev = (u_short)sb->st_dev; 955 ds.hst_ino = (u_long)sb->st_ino; 956 ds.hst_mode = sb->st_mode; 957 ds.hst_nlink = sb->st_nlink; 958 ds.hst_uid = (u_short)sb->st_uid; 959 ds.hst_gid = (u_short)sb->st_gid; 960 /* XXX: I don't want to talk about it... */ 961 if ((sb->st_mode & S_IFMT) == S_IFCHR) { 962 #if NGRF > 0 963 if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 964 ds.hst_rdev = grfdevno(sb->st_rdev); 965 #endif 966 #if NHIL > 0 967 if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 968 ds.hst_rdev = hildevno(sb->st_rdev); 969 #endif 970 ; 971 } else 972 ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 973 if (sb->st_size < (quad_t)1 << 32) 974 ds.hst_size = (long)sb->st_size; 975 else 976 ds.hst_size = -2; 977 ds.hst_atime = sb->st_atime; 978 ds.hst_mtime = sb->st_mtime; 979 ds.hst_ctime = sb->st_ctime; 980 ds.hst_blksize = sb->st_blksize; 981 ds.hst_blocks = sb->st_blocks; 982 return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 983 } 984 985 hpuxtobsdioctl(com) 986 int com; 987 { 988 switch (com) { 989 case HPUXTIOCSLTC: 990 com = TIOCSLTC; break; 991 case HPUXTIOCGLTC: 992 com = TIOCGLTC; break; 993 case HPUXTIOCSPGRP: 994 com = TIOCSPGRP; break; 995 case HPUXTIOCGPGRP: 996 com = TIOCGPGRP; break; 997 case HPUXTIOCLBIS: 998 com = TIOCLBIS; break; 999 case HPUXTIOCLBIC: 1000 com = TIOCLBIC; break; 1001 case HPUXTIOCLSET: 1002 com = TIOCLSET; break; 1003 case HPUXTIOCLGET: 1004 com = TIOCLGET; break; 1005 } 1006 return(com); 1007 } 1008 1009 /* 1010 * HP-UX ioctl system call. The differences here are: 1011 * IOC_IN also means IOC_VOID if the size portion is zero. 1012 * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 1013 * the sgttyb struct is 2 bytes longer 1014 */ 1015 struct hpuxioctl_args { 1016 int fdes; 1017 int cmd; 1018 caddr_t cmarg; 1019 }; 1020 hpuxioctl(p, uap, retval) 1021 struct proc *p; 1022 register struct hpuxioctl_args *uap; 1023 int *retval; 1024 { 1025 register struct filedesc *fdp = p->p_fd; 1026 register struct file *fp; 1027 register int com, error; 1028 register u_int size; 1029 caddr_t memp = 0; 1030 #define STK_PARAMS 128 1031 char stkbuf[STK_PARAMS]; 1032 caddr_t data = stkbuf; 1033 1034 com = uap->cmd; 1035 1036 /* XXX */ 1037 if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 1038 return (getsettty(p, uap->fdes, com, uap->cmarg)); 1039 1040 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 1041 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 1042 return (EBADF); 1043 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 1044 return (EBADF); 1045 1046 /* 1047 * Interpret high order word to find 1048 * amount of data to be copied to/from the 1049 * user's address space. 1050 */ 1051 size = IOCPARM_LEN(com); 1052 if (size > IOCPARM_MAX) 1053 return (ENOTTY); 1054 if (size > sizeof (stkbuf)) { 1055 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 1056 data = memp; 1057 } 1058 if (com&IOC_IN) { 1059 if (size) { 1060 error = copyin(uap->cmarg, data, (u_int)size); 1061 if (error) { 1062 if (memp) 1063 free(memp, M_IOCTLOPS); 1064 return (error); 1065 } 1066 } else 1067 *(caddr_t *)data = uap->cmarg; 1068 } else if ((com&IOC_OUT) && size) 1069 /* 1070 * Zero the buffer so the user always 1071 * gets back something deterministic. 1072 */ 1073 bzero(data, size); 1074 else if (com&IOC_VOID) 1075 *(caddr_t *)data = uap->cmarg; 1076 1077 switch (com) { 1078 1079 case HPUXFIOSNBIO: 1080 { 1081 char *ofp = &fdp->fd_ofileflags[uap->fdes]; 1082 int tmp; 1083 1084 if (*(int *)data) 1085 *ofp |= UF_FIONBIO_ON; 1086 else 1087 *ofp &= ~UF_FIONBIO_ON; 1088 /* 1089 * Only set/clear if FNONBLOCK not in effect 1090 */ 1091 if ((*ofp & UF_FNDELAY_ON) == 0) { 1092 tmp = fp->f_flag & FNONBLOCK; 1093 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 1094 (caddr_t)&tmp, p); 1095 } 1096 break; 1097 } 1098 1099 case HPUXTIOCCONS: 1100 *(int *)data = 1; 1101 error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 1102 break; 1103 1104 /* BSD-style job control ioctls */ 1105 case HPUXTIOCLBIS: 1106 case HPUXTIOCLBIC: 1107 case HPUXTIOCLSET: 1108 *(int *)data &= HPUXLTOSTOP; 1109 if (*(int *)data & HPUXLTOSTOP) 1110 *(int *)data = LTOSTOP; 1111 /* fall into */ 1112 case HPUXTIOCLGET: 1113 case HPUXTIOCSLTC: 1114 case HPUXTIOCGLTC: 1115 case HPUXTIOCSPGRP: 1116 case HPUXTIOCGPGRP: 1117 error = (*fp->f_ops->fo_ioctl) 1118 (fp, hpuxtobsdioctl(com), data, p); 1119 if (error == 0 && com == HPUXTIOCLGET) { 1120 *(int *)data &= LTOSTOP; 1121 if (*(int *)data & LTOSTOP) 1122 *(int *)data = HPUXLTOSTOP; 1123 } 1124 break; 1125 1126 /* SYS 5 termio */ 1127 case HPUXTCGETA: 1128 case HPUXTCSETA: 1129 case HPUXTCSETAW: 1130 case HPUXTCSETAF: 1131 error = hpuxtermio(fp, com, data, p); 1132 break; 1133 1134 default: 1135 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 1136 break; 1137 } 1138 /* 1139 * Copy any data to user, size was 1140 * already set and checked above. 1141 */ 1142 if (error == 0 && (com&IOC_OUT) && size) 1143 error = copyout(data, uap->cmarg, (u_int)size); 1144 if (memp) 1145 free(memp, M_IOCTLOPS); 1146 return (error); 1147 } 1148 1149 /* 1150 * Man page lies, behaviour here is based on observed behaviour. 1151 */ 1152 struct hpuxgetcontext_args { 1153 char *buf; 1154 int len; 1155 }; 1156 hpuxgetcontext(p, uap, retval) 1157 struct proc *p; 1158 struct hpuxgetcontext_args *uap; 1159 int *retval; 1160 { 1161 int error = 0; 1162 register int len; 1163 1164 #if defined(HP380) 1165 if (machineid == HP_380) { 1166 len = min(uap->len, sizeof(hpux040context)); 1167 if (len) 1168 error = copyout(hpux040context, uap->buf, len); 1169 if (error == 0) 1170 *retval = sizeof(hpux040context); 1171 return (error); 1172 } 1173 #endif 1174 len = min(uap->len, sizeof(hpuxcontext)); 1175 if (len) 1176 error = copyout(hpuxcontext, uap->buf, (u_int)len); 1177 if (error == 0) 1178 *retval = sizeof(hpuxcontext); 1179 return (error); 1180 } 1181 1182 /* 1183 * This is the equivalent of BSD getpgrp but with more restrictions. 1184 * Note we do not check the real uid or "saved" uid. 1185 */ 1186 struct hpuxgetpgrp2_args { 1187 int pid; 1188 }; 1189 hpuxgetpgrp2(cp, uap, retval) 1190 struct proc *cp; 1191 register struct hpuxgetpgrp2_args *uap; 1192 int *retval; 1193 { 1194 register struct proc *p; 1195 1196 if (uap->pid == 0) 1197 uap->pid = cp->p_pid; 1198 p = pfind(uap->pid); 1199 if (p == 0) 1200 return (ESRCH); 1201 if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1202 !inferior(p)) 1203 return (EPERM); 1204 *retval = p->p_pgid; 1205 return (0); 1206 } 1207 1208 /* 1209 * This is the equivalent of BSD setpgrp but with more restrictions. 1210 * Note we do not check the real uid or "saved" uid or pgrp. 1211 */ 1212 struct hpuxsetpgrp2_args { 1213 int pid; 1214 int pgrp; 1215 }; 1216 hpuxsetpgrp2(p, uap, retval) 1217 struct proc *p; 1218 struct hpuxsetpgrp2_args *uap; 1219 int *retval; 1220 { 1221 /* empirically determined */ 1222 if (uap->pgrp < 0 || uap->pgrp >= 30000) 1223 return (EINVAL); 1224 return (setpgid(p, uap, retval)); 1225 } 1226 1227 /* 1228 * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 1229 */ 1230 struct hpuxsetresuid_args { 1231 int ruid; 1232 int euid; 1233 int suid; 1234 }; 1235 hpuxsetresuid(p, uap, retval) 1236 struct proc *p; 1237 struct hpuxsetresuid_args *uap; 1238 int *retval; 1239 { 1240 return (osetreuid(p, uap, retval)); 1241 } 1242 1243 struct hpuxsetresgid_args { 1244 int rgid; 1245 int egid; 1246 int sgid; 1247 }; 1248 hpuxsetresgid(p, uap, retval) 1249 struct proc *p; 1250 struct hpuxsetresgid_args *uap; 1251 int *retval; 1252 { 1253 return (osetregid(p, uap, retval)); 1254 } 1255 1256 /* 1257 * XXX: simple recognition hack to see if we can make grmd work. 1258 */ 1259 struct hpuxlockf_args { 1260 int fd; 1261 int func; 1262 long size; 1263 }; 1264 hpuxlockf(p, uap, retval) 1265 struct proc *p; 1266 struct hpuxlockf_args *uap; 1267 int *retval; 1268 { 1269 #ifdef DEBUG 1270 log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 1271 p->p_pid, uap->fd, uap->func, uap->size); 1272 #endif 1273 return (0); 1274 } 1275 1276 struct hpuxgetaccess_args { 1277 char *path; 1278 int uid; 1279 int ngroups; 1280 int *gidset; 1281 void *label; 1282 void *privs; 1283 }; 1284 hpuxgetaccess(p, uap, retval) 1285 register struct proc *p; 1286 register struct hpuxgetaccess_args *uap; 1287 int *retval; 1288 { 1289 int lgroups[NGROUPS]; 1290 int error = 0; 1291 register struct ucred *cred; 1292 register struct vnode *vp; 1293 struct nameidata nd; 1294 1295 /* 1296 * Build an appropriate credential structure 1297 */ 1298 cred = crdup(p->p_ucred); 1299 switch (uap->uid) { 1300 case 65502: /* UID_EUID */ 1301 break; 1302 case 65503: /* UID_RUID */ 1303 cred->cr_uid = p->p_cred->p_ruid; 1304 break; 1305 case 65504: /* UID_SUID */ 1306 error = EINVAL; 1307 break; 1308 default: 1309 if (uap->uid > 65504) 1310 error = EINVAL; 1311 cred->cr_uid = uap->uid; 1312 break; 1313 } 1314 switch (uap->ngroups) { 1315 case -1: /* NGROUPS_EGID */ 1316 cred->cr_ngroups = 1; 1317 break; 1318 case -5: /* NGROUPS_EGID_SUPP */ 1319 break; 1320 case -2: /* NGROUPS_RGID */ 1321 cred->cr_ngroups = 1; 1322 cred->cr_gid = p->p_cred->p_rgid; 1323 break; 1324 case -6: /* NGROUPS_RGID_SUPP */ 1325 cred->cr_gid = p->p_cred->p_rgid; 1326 break; 1327 case -3: /* NGROUPS_SGID */ 1328 case -7: /* NGROUPS_SGID_SUPP */ 1329 error = EINVAL; 1330 break; 1331 case -4: /* NGROUPS_SUPP */ 1332 if (cred->cr_ngroups > 1) 1333 cred->cr_gid = cred->cr_groups[1]; 1334 else 1335 error = EINVAL; 1336 break; 1337 default: 1338 if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1339 error = copyin((caddr_t)uap->gidset, 1340 (caddr_t)&lgroups[0], 1341 uap->ngroups * sizeof(lgroups[0])); 1342 else 1343 error = EINVAL; 1344 if (error == 0) { 1345 int gid; 1346 1347 for (gid = 0; gid < uap->ngroups; gid++) 1348 cred->cr_groups[gid] = lgroups[gid]; 1349 cred->cr_ngroups = uap->ngroups; 1350 } 1351 break; 1352 } 1353 /* 1354 * Lookup file using caller's effective IDs. 1355 */ 1356 if (error == 0) { 1357 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1358 uap->path, p); 1359 error = namei(&nd); 1360 } 1361 if (error) { 1362 crfree(cred); 1363 return (error); 1364 } 1365 /* 1366 * Use the constructed credentials for access checks. 1367 */ 1368 vp = nd.ni_vp; 1369 *retval = 0; 1370 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1371 *retval |= R_OK; 1372 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1373 *retval |= W_OK; 1374 /* XXX we return X_OK for root on VREG even if not */ 1375 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1376 *retval |= X_OK; 1377 vput(vp); 1378 crfree(cred); 1379 return (error); 1380 } 1381 1382 /* 1383 * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 1384 * No apologies offered, if you don't like it, rewrite it! 1385 */ 1386 1387 extern char kstack[]; 1388 #define UOFF(f) ((int)&((struct user *)0)->f) 1389 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1390 1391 /* simplified FP structure */ 1392 struct bsdfp { 1393 int save[54]; 1394 int reg[24]; 1395 int ctrl[3]; 1396 }; 1397 1398 hpuxtobsduoff(off) 1399 int *off; 1400 { 1401 register int *ar0 = curproc->p_md.md_regs; 1402 struct hpuxfp *hp; 1403 struct bsdfp *bp; 1404 register u_int raddr; 1405 1406 /* u_ar0 field; procxmt puts in U_ar0 */ 1407 if ((int)off == HPUOFF(hpuxu_ar0)) 1408 return(UOFF(U_ar0)); 1409 1410 #ifdef FPCOPROC 1411 /* 68881 registers from PCB */ 1412 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1413 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1414 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1415 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1416 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1417 return((int)&bp->reg[off - hp->hpfp_reg]); 1418 #endif 1419 1420 /* 1421 * Everything else we recognize comes from the kernel stack, 1422 * so we convert off to an absolute address (if not already) 1423 * for simplicity. 1424 */ 1425 if (off < (int *)ctob(UPAGES)) 1426 off = (int *)((u_int)off + (u_int)kstack); 1427 1428 /* 1429 * 68020 registers. 1430 * We know that the HP-UX registers are in the same order as ours. 1431 * The only difference is that their PS is 2 bytes instead of a 1432 * padded 4 like ours throwing the alignment off. 1433 */ 1434 if (off >= ar0 && off < &ar0[18]) { 1435 /* 1436 * PS: return low word and high word of PC as HP-UX would 1437 * (e.g. &u.u_ar0[16.5]). 1438 */ 1439 if (off == &ar0[PS]) 1440 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1441 /* 1442 * PC: off will be &u.u_ar0[16.5] 1443 */ 1444 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1445 raddr = (u_int) &ar0[PC]; 1446 /* 1447 * D0-D7, A0-A7: easy 1448 */ 1449 else 1450 raddr = (u_int) &ar0[(int)(off - ar0)]; 1451 return((int)(raddr - (u_int)kstack)); 1452 } 1453 1454 /* everything else */ 1455 return(-1); 1456 } 1457 1458 /* 1459 * Kludge up a uarea dump so that HP-UX debuggers can find out 1460 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1461 * convert the entire user struct. 1462 */ 1463 hpuxdumpu(vp, cred) 1464 struct vnode *vp; 1465 struct ucred *cred; 1466 { 1467 struct proc *p = curproc; 1468 int error; 1469 struct hpuxuser *faku; 1470 struct bsdfp *bp; 1471 short *foop; 1472 1473 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1474 /* 1475 * Make sure there is no mistake about this 1476 * being a real user structure. 1477 */ 1478 bzero((caddr_t)faku, ctob(1)); 1479 /* 1480 * Fill in the process sizes. 1481 */ 1482 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1483 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1484 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1485 /* 1486 * Fill in the exec header for CDB. 1487 * This was saved back in exec(). As far as I can tell CDB 1488 * only uses this information to verify that a particular 1489 * core file goes with a particular binary. 1490 */ 1491 bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 1492 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1493 /* 1494 * Adjust user's saved registers (on kernel stack) to reflect 1495 * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 1496 * so we have to move it up. 1497 */ 1498 faku->hpuxu_ar0 = p->p_md.md_regs; 1499 foop = (short *) p->p_md.md_regs; 1500 foop[32] = foop[33]; 1501 foop[33] = foop[34]; 1502 foop[34] = foop[35]; 1503 #ifdef FPCOPROC 1504 /* 1505 * Copy 68881 registers from our PCB format to HP-UX format 1506 */ 1507 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1508 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1509 sizeof(bp->save)); 1510 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1511 sizeof(bp->ctrl)); 1512 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1513 sizeof(bp->reg)); 1514 #endif 1515 /* 1516 * Slay the dragon 1517 */ 1518 faku->hpuxu_dragon = -1; 1519 /* 1520 * Dump this artfully constructed page in place of the 1521 * user struct page. 1522 */ 1523 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1524 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1525 (int *)NULL, p); 1526 /* 1527 * Dump the remaining UPAGES-1 pages normally 1528 */ 1529 if (!error) 1530 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1531 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1532 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1533 free((caddr_t)faku, M_TEMP); 1534 return(error); 1535 } 1536 1537 /* 1538 * The remaining routines are essentially the same as those in kern_xxx.c 1539 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1540 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1541 * HP-UX compatibility still works even when COMPAT is not defined. 1542 */ 1543 #define HPUX_HZ 50 1544 1545 #include "sys/times.h" 1546 1547 /* from old timeb.h */ 1548 struct hpuxtimeb { 1549 time_t time; 1550 u_short millitm; 1551 short timezone; 1552 short dstflag; 1553 }; 1554 1555 /* ye ole stat structure */ 1556 struct ohpuxstat { 1557 u_short ohst_dev; 1558 u_short ohst_ino; 1559 u_short ohst_mode; 1560 short ohst_nlink; 1561 short ohst_uid; 1562 short ohst_gid; 1563 u_short ohst_rdev; 1564 int ohst_size; 1565 int ohst_atime; 1566 int ohst_mtime; 1567 int ohst_ctime; 1568 }; 1569 1570 /* 1571 * SYS V style setpgrp() 1572 */ 1573 ohpuxsetpgrp(p, uap, retval) 1574 register struct proc *p; 1575 int *uap, *retval; 1576 { 1577 if (p->p_pid != p->p_pgid) 1578 enterpgrp(p, p->p_pid, 0); 1579 *retval = p->p_pgid; 1580 return (0); 1581 } 1582 1583 struct ohpuxtime_args { 1584 long *tp; 1585 }; 1586 ohpuxtime(p, uap, retval) 1587 struct proc *p; 1588 register struct ohpuxtime_args *uap; 1589 int *retval; 1590 { 1591 int error = 0; 1592 1593 if (uap->tp) 1594 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1595 sizeof (long)); 1596 *(time_t *)retval = time.tv_sec; 1597 return (error); 1598 } 1599 1600 struct ohpuxstime_args { 1601 int time; 1602 }; 1603 ohpuxstime(p, uap, retval) 1604 struct proc *p; 1605 register struct ohpuxstime_args *uap; 1606 int *retval; 1607 { 1608 struct timeval tv; 1609 int s, error; 1610 1611 tv.tv_sec = uap->time; 1612 tv.tv_usec = 0; 1613 if (error = suser(p->p_ucred, &p->p_acflag)) 1614 return (error); 1615 1616 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1617 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1618 s = splhigh(); time = tv; splx(s); 1619 resettodr(); 1620 return (0); 1621 } 1622 1623 struct ohpuxftime_args { 1624 struct hpuxtimeb *tp; 1625 }; 1626 ohpuxftime(p, uap, retval) 1627 struct proc *p; 1628 register struct ohpuxftime_args *uap; 1629 int *retval; 1630 { 1631 struct hpuxtimeb tb; 1632 int s; 1633 1634 s = splhigh(); 1635 tb.time = time.tv_sec; 1636 tb.millitm = time.tv_usec / 1000; 1637 splx(s); 1638 tb.timezone = tz.tz_minuteswest; 1639 tb.dstflag = tz.tz_dsttime; 1640 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1641 } 1642 1643 struct ohpuxalarm_args { 1644 int deltat; 1645 }; 1646 ohpuxalarm(p, uap, retval) 1647 register struct proc *p; 1648 register struct ohpuxalarm_args *uap; 1649 int *retval; 1650 { 1651 int s = splhigh(); 1652 1653 untimeout(realitexpire, (caddr_t)p); 1654 timerclear(&p->p_realtimer.it_interval); 1655 *retval = 0; 1656 if (timerisset(&p->p_realtimer.it_value) && 1657 timercmp(&p->p_realtimer.it_value, &time, >)) 1658 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1659 if (uap->deltat == 0) { 1660 timerclear(&p->p_realtimer.it_value); 1661 splx(s); 1662 return (0); 1663 } 1664 p->p_realtimer.it_value = time; 1665 p->p_realtimer.it_value.tv_sec += uap->deltat; 1666 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1667 splx(s); 1668 return (0); 1669 } 1670 1671 struct ohpuxnice_args { 1672 int niceness; 1673 }; 1674 ohpuxnice(p, uap, retval) 1675 register struct proc *p; 1676 register struct ohpuxnice_args *uap; 1677 int *retval; 1678 { 1679 int error; 1680 1681 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1682 if (error == 0) 1683 *retval = p->p_nice - NZERO; 1684 return (error); 1685 } 1686 1687 struct ohpuxtimes_args { 1688 struct tms *tmsb; 1689 }; 1690 ohpuxtimes(p, uap, retval) 1691 struct proc *p; 1692 register struct ohpuxtimes_args *uap; 1693 int *retval; 1694 { 1695 struct timeval ru, rs; 1696 struct tms atms; 1697 int error; 1698 1699 calcru(p, &ru, &rs, NULL); 1700 atms.tms_utime = hpuxscale(&ru); 1701 atms.tms_stime = hpuxscale(&rs); 1702 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1703 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 1704 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1705 if (error == 0) 1706 *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 1707 return (error); 1708 } 1709 1710 /* 1711 * Doesn't exactly do what the documentation says. 1712 * What we really do is return 1/HPUX_HZ-th of a second since that 1713 * is what HP-UX returns. 1714 */ 1715 hpuxscale(tvp) 1716 register struct timeval *tvp; 1717 { 1718 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 1719 } 1720 1721 /* 1722 * Set IUPD and IACC times on file. 1723 * Can't set ICHG. 1724 */ 1725 struct ohpuxutime_args { 1726 char *fname; 1727 time_t *tptr; 1728 }; 1729 ohpuxutime(p, uap, retval) 1730 struct proc *p; 1731 register struct ohpuxutime_args *uap; 1732 int *retval; 1733 { 1734 register struct vnode *vp; 1735 struct vattr vattr; 1736 time_t tv[2]; 1737 int error; 1738 struct nameidata nd; 1739 1740 if (uap->tptr) { 1741 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1742 if (error) 1743 return (error); 1744 } else 1745 tv[0] = tv[1] = time.tv_sec; 1746 vattr_null(&vattr); 1747 vattr.va_atime.ts_sec = tv[0]; 1748 vattr.va_atime.ts_nsec = 0; 1749 vattr.va_mtime.ts_sec = tv[1]; 1750 vattr.va_mtime.ts_nsec = 0; 1751 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1752 if (error = namei(&nd)) 1753 return (error); 1754 vp = nd.ni_vp; 1755 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1756 error = EROFS; 1757 else 1758 error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 1759 vput(vp); 1760 return (error); 1761 } 1762 1763 ohpuxpause(p, uap, retval) 1764 struct proc *p; 1765 int *uap, *retval; 1766 { 1767 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 1768 /* always return EINTR rather than ERESTART... */ 1769 return (EINTR); 1770 } 1771 1772 /* 1773 * The old fstat system call. 1774 */ 1775 struct ohpuxfstat_args { 1776 int fd; 1777 struct ohpuxstat *sb; 1778 }; 1779 ohpuxfstat(p, uap, retval) 1780 struct proc *p; 1781 register struct ohpuxfstat_args *uap; 1782 int *retval; 1783 { 1784 register struct filedesc *fdp = p->p_fd; 1785 struct file *fp; 1786 1787 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1788 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1789 return (EBADF); 1790 if (fp->f_type != DTYPE_VNODE) 1791 return (EINVAL); 1792 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 1793 } 1794 1795 /* 1796 * Old stat system call. This version follows links. 1797 */ 1798 struct ohpuxstat_args { 1799 char *fname; 1800 struct ohpuxstat *sb; 1801 }; 1802 ohpuxstat(p, uap, retval) 1803 struct proc *p; 1804 register struct ohpuxstat_args *uap; 1805 int *retval; 1806 { 1807 int error; 1808 struct nameidata nd; 1809 1810 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1811 if (error = namei(&nd)) 1812 return (error); 1813 error = ohpuxstat1(nd.ni_vp, uap->sb, p); 1814 vput(nd.ni_vp); 1815 return (error); 1816 } 1817 1818 int 1819 ohpuxstat1(vp, ub, p) 1820 register struct vnode *vp; 1821 struct ohpuxstat *ub; 1822 struct proc *p; 1823 { 1824 struct ohpuxstat ds; 1825 struct vattr vattr; 1826 register int error; 1827 1828 error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 1829 if (error) 1830 return(error); 1831 /* 1832 * Copy from inode table 1833 */ 1834 ds.ohst_dev = vattr.va_fsid; 1835 ds.ohst_ino = (short)vattr.va_fileid; 1836 ds.ohst_mode = (u_short)vattr.va_mode; 1837 ds.ohst_nlink = vattr.va_nlink; 1838 ds.ohst_uid = (short)vattr.va_uid; 1839 ds.ohst_gid = (short)vattr.va_gid; 1840 ds.ohst_rdev = (u_short)vattr.va_rdev; 1841 ds.ohst_size = (int)vattr.va_size; 1842 ds.ohst_atime = (int)vattr.va_atime.ts_sec; 1843 ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 1844 ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 1845 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1846 } 1847 #endif 1848