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