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.29 (Berkeley) 07/13/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 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 hpuxsetresuid(p, uap, retval) 1235 struct proc *p; 1236 struct hpuxsetresuid_args *uap; 1237 int *retval; 1238 { 1239 return (osetreuid(p, uap, retval)); 1240 } 1241 1242 struct hpuxsetresgid_args { 1243 int rgid; 1244 int egid; 1245 int sgid; 1246 }; 1247 hpuxsetresgid(p, uap, retval) 1248 struct proc *p; 1249 struct hpuxsetresgid_args *uap; 1250 int *retval; 1251 { 1252 return (osetregid(p, uap, retval)); 1253 } 1254 1255 /* 1256 * XXX: simple recognition hack to see if we can make grmd work. 1257 */ 1258 struct hpuxlockf_args { 1259 int fd; 1260 int func; 1261 long size; 1262 }; 1263 hpuxlockf(p, uap, retval) 1264 struct proc *p; 1265 struct hpuxlockf_args *uap; 1266 int *retval; 1267 { 1268 #ifdef DEBUG 1269 log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 1270 p->p_pid, uap->fd, uap->func, uap->size); 1271 #endif 1272 return (0); 1273 } 1274 1275 struct hpuxgetaccess_args { 1276 char *path; 1277 int uid; 1278 int ngroups; 1279 int *gidset; 1280 void *label; 1281 void *privs; 1282 }; 1283 hpuxgetaccess(p, uap, retval) 1284 register struct proc *p; 1285 register struct hpuxgetaccess_args *uap; 1286 int *retval; 1287 { 1288 int lgroups[NGROUPS]; 1289 int error = 0; 1290 register struct ucred *cred; 1291 register struct vnode *vp; 1292 struct nameidata nd; 1293 1294 /* 1295 * Build an appropriate credential structure 1296 */ 1297 cred = crdup(p->p_ucred); 1298 switch (uap->uid) { 1299 case 65502: /* UID_EUID */ 1300 break; 1301 case 65503: /* UID_RUID */ 1302 cred->cr_uid = p->p_cred->p_ruid; 1303 break; 1304 case 65504: /* UID_SUID */ 1305 error = EINVAL; 1306 break; 1307 default: 1308 if (uap->uid > 65504) 1309 error = EINVAL; 1310 cred->cr_uid = uap->uid; 1311 break; 1312 } 1313 switch (uap->ngroups) { 1314 case -1: /* NGROUPS_EGID */ 1315 cred->cr_ngroups = 1; 1316 break; 1317 case -5: /* NGROUPS_EGID_SUPP */ 1318 break; 1319 case -2: /* NGROUPS_RGID */ 1320 cred->cr_ngroups = 1; 1321 cred->cr_gid = p->p_cred->p_rgid; 1322 break; 1323 case -6: /* NGROUPS_RGID_SUPP */ 1324 cred->cr_gid = p->p_cred->p_rgid; 1325 break; 1326 case -3: /* NGROUPS_SGID */ 1327 case -7: /* NGROUPS_SGID_SUPP */ 1328 error = EINVAL; 1329 break; 1330 case -4: /* NGROUPS_SUPP */ 1331 if (cred->cr_ngroups > 1) 1332 cred->cr_gid = cred->cr_groups[1]; 1333 else 1334 error = EINVAL; 1335 break; 1336 default: 1337 if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1338 error = copyin((caddr_t)uap->gidset, 1339 (caddr_t)&lgroups[0], 1340 uap->ngroups * sizeof(lgroups[0])); 1341 else 1342 error = EINVAL; 1343 if (error == 0) { 1344 int gid; 1345 1346 for (gid = 0; gid < uap->ngroups; gid++) 1347 cred->cr_groups[gid] = lgroups[gid]; 1348 cred->cr_ngroups = uap->ngroups; 1349 } 1350 break; 1351 } 1352 /* 1353 * Lookup file using caller's effective IDs. 1354 */ 1355 if (error == 0) { 1356 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1357 uap->path, p); 1358 error = namei(&nd); 1359 } 1360 if (error) { 1361 crfree(cred); 1362 return (error); 1363 } 1364 /* 1365 * Use the constructed credentials for access checks. 1366 */ 1367 vp = nd.ni_vp; 1368 *retval = 0; 1369 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1370 *retval |= R_OK; 1371 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1372 *retval |= W_OK; 1373 /* XXX we return X_OK for root on VREG even if not */ 1374 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1375 *retval |= X_OK; 1376 vput(vp); 1377 crfree(cred); 1378 return (error); 1379 } 1380 1381 /* 1382 * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 1383 * No apologies offered, if you don't like it, rewrite it! 1384 */ 1385 1386 extern char kstack[]; 1387 #define UOFF(f) ((int)&((struct user *)0)->f) 1388 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1389 1390 /* simplified FP structure */ 1391 struct bsdfp { 1392 int save[54]; 1393 int reg[24]; 1394 int ctrl[3]; 1395 }; 1396 1397 hpuxtobsduoff(off) 1398 int *off; 1399 { 1400 register int *ar0 = curproc->p_md.md_regs; 1401 struct hpuxfp *hp; 1402 struct bsdfp *bp; 1403 register u_int raddr; 1404 1405 /* u_ar0 field; procxmt puts in U_ar0 */ 1406 if ((int)off == HPUOFF(hpuxu_ar0)) 1407 return(UOFF(U_ar0)); 1408 1409 #ifdef FPCOPROC 1410 /* 68881 registers from PCB */ 1411 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1412 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1413 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1414 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1415 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1416 return((int)&bp->reg[off - hp->hpfp_reg]); 1417 #endif 1418 1419 /* 1420 * Everything else we recognize comes from the kernel stack, 1421 * so we convert off to an absolute address (if not already) 1422 * for simplicity. 1423 */ 1424 if (off < (int *)ctob(UPAGES)) 1425 off = (int *)((u_int)off + (u_int)kstack); 1426 1427 /* 1428 * 68020 registers. 1429 * We know that the HP-UX registers are in the same order as ours. 1430 * The only difference is that their PS is 2 bytes instead of a 1431 * padded 4 like ours throwing the alignment off. 1432 */ 1433 if (off >= ar0 && off < &ar0[18]) { 1434 /* 1435 * PS: return low word and high word of PC as HP-UX would 1436 * (e.g. &u.u_ar0[16.5]). 1437 */ 1438 if (off == &ar0[PS]) 1439 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1440 /* 1441 * PC: off will be &u.u_ar0[16.5] 1442 */ 1443 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1444 raddr = (u_int) &ar0[PC]; 1445 /* 1446 * D0-D7, A0-A7: easy 1447 */ 1448 else 1449 raddr = (u_int) &ar0[(int)(off - ar0)]; 1450 return((int)(raddr - (u_int)kstack)); 1451 } 1452 1453 /* everything else */ 1454 return(-1); 1455 } 1456 1457 /* 1458 * Kludge up a uarea dump so that HP-UX debuggers can find out 1459 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1460 * convert the entire user struct. 1461 */ 1462 hpuxdumpu(vp, cred) 1463 struct vnode *vp; 1464 struct ucred *cred; 1465 { 1466 struct proc *p = curproc; 1467 int error; 1468 struct hpuxuser *faku; 1469 struct bsdfp *bp; 1470 short *foop; 1471 1472 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1473 /* 1474 * Make sure there is no mistake about this 1475 * being a real user structure. 1476 */ 1477 bzero((caddr_t)faku, ctob(1)); 1478 /* 1479 * Fill in the process sizes. 1480 */ 1481 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1482 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1483 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1484 /* 1485 * Fill in the exec header for CDB. 1486 * This was saved back in exec(). As far as I can tell CDB 1487 * only uses this information to verify that a particular 1488 * core file goes with a particular binary. 1489 */ 1490 bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 1491 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1492 /* 1493 * Adjust user's saved registers (on kernel stack) to reflect 1494 * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 1495 * so we have to move it up. 1496 */ 1497 faku->hpuxu_ar0 = p->p_md.md_regs; 1498 foop = (short *) p->p_md.md_regs; 1499 foop[32] = foop[33]; 1500 foop[33] = foop[34]; 1501 foop[34] = foop[35]; 1502 #ifdef FPCOPROC 1503 /* 1504 * Copy 68881 registers from our PCB format to HP-UX format 1505 */ 1506 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1507 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1508 sizeof(bp->save)); 1509 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1510 sizeof(bp->ctrl)); 1511 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1512 sizeof(bp->reg)); 1513 #endif 1514 /* 1515 * Slay the dragon 1516 */ 1517 faku->hpuxu_dragon = -1; 1518 /* 1519 * Dump this artfully constructed page in place of the 1520 * user struct page. 1521 */ 1522 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1523 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1524 (int *)NULL, p); 1525 /* 1526 * Dump the remaining UPAGES-1 pages normally 1527 */ 1528 if (!error) 1529 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1530 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1531 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1532 free((caddr_t)faku, M_TEMP); 1533 return(error); 1534 } 1535 1536 /* 1537 * The remaining routines are essentially the same as those in kern_xxx.c 1538 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1539 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1540 * HP-UX compatibility still works even when COMPAT is not defined. 1541 */ 1542 #define HPUX_HZ 50 1543 1544 #include "sys/times.h" 1545 1546 /* from old timeb.h */ 1547 struct hpuxtimeb { 1548 time_t time; 1549 u_short millitm; 1550 short timezone; 1551 short dstflag; 1552 }; 1553 1554 /* ye ole stat structure */ 1555 struct ohpuxstat { 1556 u_short ohst_dev; 1557 u_short ohst_ino; 1558 u_short ohst_mode; 1559 short ohst_nlink; 1560 short ohst_uid; 1561 short ohst_gid; 1562 u_short ohst_rdev; 1563 int ohst_size; 1564 int ohst_atime; 1565 int ohst_mtime; 1566 int ohst_ctime; 1567 }; 1568 1569 /* 1570 * SYS V style setpgrp() 1571 */ 1572 ohpuxsetpgrp(p, uap, retval) 1573 register struct proc *p; 1574 int *uap, *retval; 1575 { 1576 if (p->p_pid != p->p_pgid) 1577 enterpgrp(p, p->p_pid, 0); 1578 *retval = p->p_pgid; 1579 return (0); 1580 } 1581 1582 struct ohpuxtime_args { 1583 long *tp; 1584 }; 1585 ohpuxtime(p, uap, retval) 1586 struct proc *p; 1587 register struct ohpuxtime_args *uap; 1588 int *retval; 1589 { 1590 int error = 0; 1591 1592 if (uap->tp) 1593 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1594 sizeof (long)); 1595 *(time_t *)retval = time.tv_sec; 1596 return (error); 1597 } 1598 1599 struct ohpuxstime_args { 1600 int time; 1601 }; 1602 ohpuxstime(p, uap, retval) 1603 struct proc *p; 1604 register struct ohpuxstime_args *uap; 1605 int *retval; 1606 { 1607 struct timeval tv; 1608 int s, error; 1609 1610 tv.tv_sec = uap->time; 1611 tv.tv_usec = 0; 1612 if (error = suser(p->p_ucred, &p->p_acflag)) 1613 return (error); 1614 1615 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1616 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1617 s = splhigh(); time = tv; splx(s); 1618 resettodr(); 1619 return (0); 1620 } 1621 1622 struct ohpuxftime_args { 1623 struct hpuxtimeb *tp; 1624 }; 1625 ohpuxftime(p, uap, retval) 1626 struct proc *p; 1627 register struct ohpuxftime_args *uap; 1628 int *retval; 1629 { 1630 struct hpuxtimeb tb; 1631 int s; 1632 1633 s = splhigh(); 1634 tb.time = time.tv_sec; 1635 tb.millitm = time.tv_usec / 1000; 1636 splx(s); 1637 tb.timezone = tz.tz_minuteswest; 1638 tb.dstflag = tz.tz_dsttime; 1639 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1640 } 1641 1642 struct ohpuxalarm_args { 1643 int deltat; 1644 }; 1645 ohpuxalarm(p, uap, retval) 1646 register struct proc *p; 1647 register struct ohpuxalarm_args *uap; 1648 int *retval; 1649 { 1650 int s = splhigh(); 1651 1652 untimeout(realitexpire, (caddr_t)p); 1653 timerclear(&p->p_realtimer.it_interval); 1654 *retval = 0; 1655 if (timerisset(&p->p_realtimer.it_value) && 1656 timercmp(&p->p_realtimer.it_value, &time, >)) 1657 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1658 if (uap->deltat == 0) { 1659 timerclear(&p->p_realtimer.it_value); 1660 splx(s); 1661 return (0); 1662 } 1663 p->p_realtimer.it_value = time; 1664 p->p_realtimer.it_value.tv_sec += uap->deltat; 1665 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1666 splx(s); 1667 return (0); 1668 } 1669 1670 struct ohpuxnice_args { 1671 int niceness; 1672 }; 1673 ohpuxnice(p, uap, retval) 1674 register struct proc *p; 1675 register struct ohpuxnice_args *uap; 1676 int *retval; 1677 { 1678 int error; 1679 1680 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1681 if (error == 0) 1682 *retval = p->p_nice - NZERO; 1683 return (error); 1684 } 1685 1686 struct ohpuxtimes_args { 1687 struct tms *tmsb; 1688 }; 1689 ohpuxtimes(p, uap, retval) 1690 struct proc *p; 1691 register struct ohpuxtimes_args *uap; 1692 int *retval; 1693 { 1694 struct timeval ru, rs; 1695 struct tms atms; 1696 int error; 1697 1698 calcru(p, &ru, &rs, NULL); 1699 atms.tms_utime = hpuxscale(&ru); 1700 atms.tms_stime = hpuxscale(&rs); 1701 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1702 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 1703 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1704 if (error == 0) 1705 *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 1706 return (error); 1707 } 1708 1709 /* 1710 * Doesn't exactly do what the documentation says. 1711 * What we really do is return 1/HPUX_HZ-th of a second since that 1712 * is what HP-UX returns. 1713 */ 1714 hpuxscale(tvp) 1715 register struct timeval *tvp; 1716 { 1717 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 1718 } 1719 1720 /* 1721 * Set IUPD and IACC times on file. 1722 * Can't set ICHG. 1723 */ 1724 struct ohpuxutime_args { 1725 char *fname; 1726 time_t *tptr; 1727 }; 1728 ohpuxutime(p, uap, retval) 1729 struct proc *p; 1730 register struct ohpuxutime_args *uap; 1731 int *retval; 1732 { 1733 register struct vnode *vp; 1734 struct vattr vattr; 1735 time_t tv[2]; 1736 int error; 1737 struct nameidata nd; 1738 1739 if (uap->tptr) { 1740 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1741 if (error) 1742 return (error); 1743 } else 1744 tv[0] = tv[1] = time.tv_sec; 1745 vattr_null(&vattr); 1746 vattr.va_atime.ts_sec = tv[0]; 1747 vattr.va_atime.ts_nsec = 0; 1748 vattr.va_mtime.ts_sec = tv[1]; 1749 vattr.va_mtime.ts_nsec = 0; 1750 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1751 if (error = namei(&nd)) 1752 return (error); 1753 vp = nd.ni_vp; 1754 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1755 error = EROFS; 1756 else 1757 error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 1758 vput(vp); 1759 return (error); 1760 } 1761 1762 ohpuxpause(p, uap, retval) 1763 struct proc *p; 1764 int *uap, *retval; 1765 { 1766 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 1767 /* always return EINTR rather than ERESTART... */ 1768 return (EINTR); 1769 } 1770 1771 /* 1772 * The old fstat system call. 1773 */ 1774 struct ohpuxfstat_args { 1775 int fd; 1776 struct ohpuxstat *sb; 1777 }; 1778 ohpuxfstat(p, uap, retval) 1779 struct proc *p; 1780 register struct ohpuxfstat_args *uap; 1781 int *retval; 1782 { 1783 register struct filedesc *fdp = p->p_fd; 1784 struct file *fp; 1785 1786 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1787 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 1788 return (EBADF); 1789 if (fp->f_type != DTYPE_VNODE) 1790 return (EINVAL); 1791 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 1792 } 1793 1794 /* 1795 * Old stat system call. This version follows links. 1796 */ 1797 struct ohpuxstat_args { 1798 char *fname; 1799 struct ohpuxstat *sb; 1800 }; 1801 ohpuxstat(p, uap, retval) 1802 struct proc *p; 1803 register struct ohpuxstat_args *uap; 1804 int *retval; 1805 { 1806 int error; 1807 struct nameidata nd; 1808 1809 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1810 if (error = namei(&nd)) 1811 return (error); 1812 error = ohpuxstat1(nd.ni_vp, uap->sb); 1813 vput(nd.ni_vp); 1814 return (error); 1815 } 1816 1817 int 1818 ohpuxstat1(vp, ub) 1819 register struct vnode *vp; 1820 struct ohpuxstat *ub; 1821 { 1822 struct ohpuxstat ds; 1823 struct vattr vattr; 1824 register int error; 1825 1826 error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 1827 if (error) 1828 return(error); 1829 /* 1830 * Copy from inode table 1831 */ 1832 ds.ohst_dev = vattr.va_fsid; 1833 ds.ohst_ino = (short)vattr.va_fileid; 1834 ds.ohst_mode = (u_short)vattr.va_mode; 1835 ds.ohst_nlink = vattr.va_nlink; 1836 ds.ohst_uid = (short)vattr.va_uid; 1837 ds.ohst_gid = (short)vattr.va_gid; 1838 ds.ohst_rdev = (u_short)vattr.va_rdev; 1839 ds.ohst_size = (int)vattr.va_size; 1840 ds.ohst_atime = (int)vattr.va_atime.ts_sec; 1841 ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 1842 ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 1843 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1844 } 1845 #endif 1846