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.2 (Berkeley) 09/09/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 /* open files */ 639 case HPUX_SYSCONF_OPENMAX: 640 *retval = NOFILE; 641 break; 642 643 /* architecture */ 644 case HPUX_SYSCONF_CPUTYPE: 645 switch (machineid) { 646 case HP_320: 647 case HP_330: 648 case HP_350: 649 *retval = HPUX_SYSCONF_CPUM020; 650 break; 651 case HP_340: 652 case HP_360: 653 case HP_370: 654 case HP_375: 655 *retval = HPUX_SYSCONF_CPUM030; 656 break; 657 case HP_380: 658 case HP_433: 659 *retval = HPUX_SYSCONF_CPUM040; 660 break; 661 } 662 break; 663 default: 664 uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 665 return (EINVAL); 666 } 667 return (0); 668 } 669 670 struct hpuxstat_args { 671 char *fname; 672 struct hpuxstat *hsb; 673 }; 674 hpuxstat(p, uap, retval) 675 struct proc *p; 676 struct hpuxstat_args *uap; 677 int *retval; 678 { 679 return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 680 } 681 682 struct hpuxlstat_args { 683 char *fname; 684 struct hpuxstat *hsb; 685 }; 686 hpuxlstat(p, uap, retval) 687 struct proc *p; 688 struct hpuxlstat_args *uap; 689 int *retval; 690 { 691 return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 692 } 693 694 struct hpuxfstat_args { 695 int fdes; 696 struct hpuxstat *hsb; 697 }; 698 hpuxfstat(p, uap, retval) 699 struct proc *p; 700 register struct hpuxfstat_args *uap; 701 int *retval; 702 { 703 register struct filedesc *fdp = p->p_fd; 704 register struct file *fp; 705 struct stat sb; 706 int error; 707 708 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 709 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 710 return (EBADF); 711 712 switch (fp->f_type) { 713 714 case DTYPE_VNODE: 715 error = vn_stat((struct vnode *)fp->f_data, &sb, p); 716 break; 717 718 case DTYPE_SOCKET: 719 error = soo_stat((struct socket *)fp->f_data, &sb, p); 720 break; 721 722 default: 723 panic("fstat"); 724 /*NOTREACHED*/ 725 } 726 /* is this right for sockets?? */ 727 if (error == 0) 728 error = bsdtohpuxstat(&sb, uap->hsb); 729 return (error); 730 } 731 732 struct hpuxulimit_args { 733 int cmd; 734 long newlimit; 735 }; 736 hpuxulimit(p, uap, retval) 737 struct proc *p; 738 register struct hpuxulimit_args *uap; 739 long *retval; 740 { 741 struct rlimit *limp; 742 int error = 0; 743 744 limp = &p->p_rlimit[RLIMIT_FSIZE]; 745 switch (uap->cmd) { 746 case 2: 747 uap->newlimit *= 512; 748 if (uap->newlimit > limp->rlim_max && 749 (error = suser(p->p_ucred, &p->p_acflag))) 750 break; 751 limp->rlim_cur = limp->rlim_max = uap->newlimit; 752 /* else fall into... */ 753 754 case 1: 755 *retval = limp->rlim_max / 512; 756 break; 757 758 case 3: 759 limp = &p->p_rlimit[RLIMIT_DATA]; 760 *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 761 break; 762 763 default: 764 error = EINVAL; 765 break; 766 } 767 return (error); 768 } 769 770 /* 771 * Map "real time" priorities 0 (high) thru 127 (low) into nice 772 * values -16 (high) thru -1 (low). 773 */ 774 struct hpuxrtprio_args { 775 int pid; 776 int prio; 777 }; 778 hpuxrtprio(cp, uap, retval) 779 struct proc *cp; 780 register struct hpuxrtprio_args *uap; 781 int *retval; 782 { 783 struct proc *p; 784 int nice, error; 785 786 if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 787 uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 788 return (EINVAL); 789 if (uap->pid == 0) 790 p = cp; 791 else if ((p = pfind(uap->pid)) == 0) 792 return (ESRCH); 793 nice = p->p_nice; 794 if (nice < NZERO) 795 *retval = (nice + 16) << 3; 796 else 797 *retval = RTPRIO_RTOFF; 798 switch (uap->prio) { 799 800 case RTPRIO_NOCHG: 801 return (0); 802 803 case RTPRIO_RTOFF: 804 if (nice >= NZERO) 805 return (0); 806 nice = NZERO; 807 break; 808 809 default: 810 nice = (uap->prio >> 3) - 16; 811 break; 812 } 813 error = donice(cp, p, nice); 814 if (error == EACCES) 815 error = EPERM; 816 return (error); 817 } 818 819 struct hpuxadvise_args { 820 int arg; 821 }; 822 hpuxadvise(p, uap, retval) 823 struct proc *p; 824 struct hpuxadvise_args *uap; 825 int *retval; 826 { 827 int error = 0; 828 829 switch (uap->arg) { 830 case 0: 831 p->p_md.md_flags |= MDP_HPUXMMAP; 832 break; 833 case 1: 834 ICIA(); 835 break; 836 case 2: 837 DCIA(); 838 break; 839 default: 840 error = EINVAL; 841 break; 842 } 843 return (error); 844 } 845 846 struct hpuxptrace_args { 847 int req; 848 int pid; 849 int *addr; 850 int data; 851 }; 852 hpuxptrace(p, uap, retval) 853 struct proc *p; 854 struct hpuxptrace_args *uap; 855 int *retval; 856 { 857 int error, isps = 0; 858 struct proc *cp; 859 860 switch (uap->req) { 861 /* map signal */ 862 case PT_STEP: 863 case PT_CONTINUE: 864 if (uap->data) { 865 uap->data = hpuxtobsdsig(uap->data); 866 if (uap->data == 0) 867 uap->data = NSIG; 868 } 869 break; 870 /* map u-area offset */ 871 case PT_READ_U: 872 case PT_WRITE_U: 873 /* 874 * Big, cheezy hack: hpuxtobsduoff is really intended 875 * to be called in the child context (procxmt) but we 876 * do it here in the parent context to avoid hacks in 877 * the MI sys_process.c file. This works only because 878 * we can access the child's md_regs pointer and it 879 * has the correct value (the child has already trapped 880 * into the kernel). 881 */ 882 if ((cp = pfind(uap->pid)) == 0) 883 return (ESRCH); 884 uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 885 886 /* 887 * Since HP-UX PS is only 16-bits in ar0, requests 888 * to write PS actually contain the PS in the high word 889 * and the high half of the PC (the following register) 890 * in the low word. Move the PS value to where BSD 891 * expects it. 892 */ 893 if (isps && uap->req == PT_WRITE_U) 894 uap->data >>= 16; 895 break; 896 } 897 error = ptrace(p, uap, retval); 898 /* 899 * Align PS as HP-UX expects it (see WRITE_U comment above). 900 * Note that we do not return the high part of PC like HP-UX 901 * would, but the HP-UX debuggers don't require it. 902 */ 903 if (isps && error == 0 && uap->req == PT_READ_U) 904 *retval <<= 16; 905 return (error); 906 } 907 908 struct hpuxgetdomainname_args { 909 char *domainname; 910 u_int len; 911 }; 912 hpuxgetdomainname(p, uap, retval) 913 struct proc *p; 914 register struct hpuxgetdomainname_args *uap; 915 int *retval; 916 { 917 if (uap->len > domainnamelen + 1) 918 uap->len = domainnamelen + 1; 919 return (copyout(domainname, uap->domainname, uap->len)); 920 } 921 922 struct hpuxsetdomainname_args { 923 char *domainname; 924 u_int len; 925 }; 926 hpuxsetdomainname(p, uap, retval) 927 struct proc *p; 928 register struct hpuxsetdomainname_args *uap; 929 int *retval; 930 { 931 int error; 932 933 if (error = suser(p->p_ucred, &p->p_acflag)) 934 return (error); 935 if (uap->len > sizeof (domainname) - 1) 936 return (EINVAL); 937 domainnamelen = uap->len; 938 error = copyin(uap->domainname, domainname, uap->len); 939 domainname[domainnamelen] = 0; 940 return (error); 941 } 942 943 #ifdef SYSVSHM 944 #include <sys/shm.h> 945 946 hpuxshmat(p, uap, retval) 947 struct proc *p; 948 int *uap, *retval; 949 { 950 return (shmat(p, uap, retval)); 951 } 952 953 hpuxshmdt(p, uap, retval) 954 struct proc *p; 955 int *uap, *retval; 956 { 957 return (shmdt(p, uap, retval)); 958 } 959 960 hpuxshmget(p, uap, retval) 961 struct proc *p; 962 int *uap, *retval; 963 { 964 return (shmget(p, uap, retval)); 965 } 966 967 hpuxshmctl(p, uap, retval) 968 struct proc *p; 969 int *uap, *retval; 970 { 971 return (hpuxshmctl1(p, uap, retval, 0)); 972 } 973 974 hpuxnshmctl(p, uap, retval) 975 struct proc *p; 976 int *uap, *retval; 977 { 978 return (hpuxshmctl1(p, uap, retval, 1)); 979 } 980 981 /* 982 * Handle HP-UX specific commands. 983 */ 984 struct hpuxshmctl_args { 985 int shmid; 986 int cmd; 987 caddr_t buf; 988 }; 989 hpuxshmctl1(p, uap, retval, isnew) 990 struct proc *p; 991 struct hpuxshmctl_args *uap; 992 int *retval; 993 int isnew; 994 { 995 register struct shmid_ds *shp; 996 register struct ucred *cred = p->p_ucred; 997 struct hpuxshmid_ds sbuf; 998 int error; 999 1000 if (error = shmvalid(uap->shmid)) 1001 return (error); 1002 shp = &shmsegs[uap->shmid % SHMMMNI]; 1003 switch (uap->cmd) { 1004 case SHM_LOCK: 1005 case SHM_UNLOCK: 1006 /* don't really do anything, but make them think we did */ 1007 if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 1008 cred->cr_uid != shp->shm_perm.cuid) 1009 return (EPERM); 1010 return (0); 1011 1012 case IPC_STAT: 1013 if (!isnew) 1014 break; 1015 error = ipcaccess(&shp->shm_perm, IPC_R, cred); 1016 if (error == 0) { 1017 sbuf.shm_perm.uid = shp->shm_perm.uid; 1018 sbuf.shm_perm.gid = shp->shm_perm.gid; 1019 sbuf.shm_perm.cuid = shp->shm_perm.cuid; 1020 sbuf.shm_perm.cgid = shp->shm_perm.cgid; 1021 sbuf.shm_perm.mode = shp->shm_perm.mode; 1022 sbuf.shm_perm.seq = shp->shm_perm.seq; 1023 sbuf.shm_perm.key = shp->shm_perm.key; 1024 sbuf.shm_segsz = shp->shm_segsz; 1025 sbuf.shm_ptbl = shp->shm_handle; /* XXX */ 1026 sbuf.shm_lpid = shp->shm_lpid; 1027 sbuf.shm_cpid = shp->shm_cpid; 1028 sbuf.shm_nattch = shp->shm_nattch; 1029 sbuf.shm_cnattch = shp->shm_nattch; /* XXX */ 1030 sbuf.shm_atime = shp->shm_atime; 1031 sbuf.shm_dtime = shp->shm_dtime; 1032 sbuf.shm_ctime = shp->shm_ctime; 1033 error = copyout((caddr_t)&sbuf, uap->buf, sizeof sbuf); 1034 } 1035 return (error); 1036 1037 case IPC_SET: 1038 if (!isnew) 1039 break; 1040 if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 1041 cred->cr_uid != shp->shm_perm.cuid) { 1042 return (EPERM); 1043 } 1044 error = copyin(uap->buf, (caddr_t)&sbuf, sizeof sbuf); 1045 if (error == 0) { 1046 shp->shm_perm.uid = sbuf.shm_perm.uid; 1047 shp->shm_perm.gid = sbuf.shm_perm.gid; 1048 shp->shm_perm.mode = (shp->shm_perm.mode & ~0777) 1049 | (sbuf.shm_perm.mode & 0777); 1050 shp->shm_ctime = time.tv_sec; 1051 } 1052 return (error); 1053 } 1054 return (shmctl(p, uap, retval)); 1055 } 1056 #endif 1057 1058 /* 1059 * Fake semaphore routines, just don't return an error. 1060 * Should be adequate for starbase to run. 1061 */ 1062 struct hpuxsemctl_args { 1063 int semid; 1064 u_int semnum; 1065 int cmd; 1066 int arg; 1067 }; 1068 hpuxsemctl(p, uap, retval) 1069 struct proc *p; 1070 struct hpuxsemctl_args *uap; 1071 int *retval; 1072 { 1073 /* XXX: should do something here */ 1074 return (0); 1075 } 1076 1077 struct hpuxsemget_args { 1078 key_t key; 1079 int nsems; 1080 int semflg; 1081 }; 1082 hpuxsemget(p, uap, retval) 1083 struct proc *p; 1084 struct hpuxsemget_args *uap; 1085 int *retval; 1086 { 1087 /* XXX: should do something here */ 1088 return (0); 1089 } 1090 1091 struct hpuxsemop_args { 1092 int semid; 1093 struct sembuf *sops; 1094 u_int nsops; 1095 }; 1096 hpuxsemop(p, uap, retval) 1097 struct proc *p; 1098 struct hpuxsemop_args *uap; 1099 int *retval; 1100 { 1101 /* XXX: should do something here */ 1102 return (0); 1103 } 1104 1105 /* 1106 * HP-UX mmap() emulation (mainly for shared library support). 1107 */ 1108 struct hpuxmmap_args { 1109 caddr_t addr; 1110 int len; 1111 int prot; 1112 int flags; 1113 int fd; 1114 long pos; 1115 }; 1116 hpuxmmap(p, uap, retval) 1117 struct proc *p; 1118 struct hpuxmmap_args *uap; 1119 int *retval; 1120 { 1121 struct mmap_args { 1122 caddr_t addr; 1123 int len; 1124 int prot; 1125 int flags; 1126 int fd; 1127 long pad; 1128 off_t pos; 1129 } nargs; 1130 1131 nargs.addr = uap->addr; 1132 nargs.len = uap->len; 1133 nargs.prot = uap->prot; 1134 nargs.flags = uap->flags & 1135 ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 1136 if (uap->flags & HPUXMAP_FIXED) 1137 nargs.flags |= MAP_FIXED; 1138 if (uap->flags & HPUXMAP_ANON) 1139 nargs.flags |= MAP_ANON; 1140 nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 1141 nargs.pos = uap->pos; 1142 return (mmap(p, &nargs, retval)); 1143 } 1144 1145 /* convert from BSD to HP-UX errno */ 1146 bsdtohpuxerrno(err) 1147 int err; 1148 { 1149 if (err < 0 || err >= NERR) 1150 return(BERR); 1151 return((int)bsdtohpuxerrnomap[err]); 1152 } 1153 1154 hpuxstat1(fname, hsb, follow, p) 1155 char *fname; 1156 struct hpuxstat *hsb; 1157 int follow; 1158 struct proc *p; 1159 { 1160 int error; 1161 struct stat sb; 1162 struct nameidata nd; 1163 1164 NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 1165 if (error = namei(&nd)) 1166 return (error); 1167 error = vn_stat(nd.ni_vp, &sb, p); 1168 vput(nd.ni_vp); 1169 if (error == 0) 1170 error = bsdtohpuxstat(&sb, hsb); 1171 return (error); 1172 } 1173 1174 #include "grf.h" 1175 #if NGRF > 0 1176 #ifdef __STDC__ 1177 extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 1178 #else 1179 extern int grfopen(); 1180 #endif 1181 #endif 1182 1183 #define NHIL 1 /* XXX */ 1184 #if NHIL > 0 1185 #ifdef __STDC__ 1186 extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 1187 #else 1188 extern int hilopen(); 1189 #endif 1190 #endif 1191 1192 #include <sys/conf.h> 1193 1194 bsdtohpuxstat(sb, hsb) 1195 struct stat *sb; 1196 struct hpuxstat *hsb; 1197 { 1198 struct hpuxstat ds; 1199 1200 bzero((caddr_t)&ds, sizeof(ds)); 1201 ds.hst_dev = (u_short)sb->st_dev; 1202 ds.hst_ino = (u_long)sb->st_ino; 1203 ds.hst_mode = sb->st_mode; 1204 ds.hst_nlink = sb->st_nlink; 1205 ds.hst_uid = (u_short)sb->st_uid; 1206 ds.hst_gid = (u_short)sb->st_gid; 1207 ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 1208 1209 /* XXX: I don't want to talk about it... */ 1210 if ((sb->st_mode & S_IFMT) == S_IFCHR) { 1211 #if NGRF > 0 1212 if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 1213 ds.hst_rdev = grfdevno(sb->st_rdev); 1214 #endif 1215 #if NHIL > 0 1216 if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 1217 ds.hst_rdev = hildevno(sb->st_rdev); 1218 #endif 1219 ; 1220 } 1221 if (sb->st_size < (quad_t)1 << 32) 1222 ds.hst_size = (long)sb->st_size; 1223 else 1224 ds.hst_size = -2; 1225 ds.hst_atime = sb->st_atime; 1226 ds.hst_mtime = sb->st_mtime; 1227 ds.hst_ctime = sb->st_ctime; 1228 ds.hst_blksize = sb->st_blksize; 1229 ds.hst_blocks = sb->st_blocks; 1230 return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 1231 } 1232 1233 hpuxtobsdioctl(com) 1234 int com; 1235 { 1236 switch (com) { 1237 case HPUXTIOCSLTC: 1238 com = TIOCSLTC; break; 1239 case HPUXTIOCGLTC: 1240 com = TIOCGLTC; break; 1241 case HPUXTIOCSPGRP: 1242 com = TIOCSPGRP; break; 1243 case HPUXTIOCGPGRP: 1244 com = TIOCGPGRP; break; 1245 case HPUXTIOCLBIS: 1246 com = TIOCLBIS; break; 1247 case HPUXTIOCLBIC: 1248 com = TIOCLBIC; break; 1249 case HPUXTIOCLSET: 1250 com = TIOCLSET; break; 1251 case HPUXTIOCLGET: 1252 com = TIOCLGET; break; 1253 case HPUXTIOCGWINSZ: 1254 com = TIOCGWINSZ; break; 1255 case HPUXTIOCSWINSZ: 1256 com = TIOCSWINSZ; break; 1257 } 1258 return(com); 1259 } 1260 1261 /* 1262 * HP-UX ioctl system call. The differences here are: 1263 * IOC_IN also means IOC_VOID if the size portion is zero. 1264 * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 1265 * the sgttyb struct is 2 bytes longer 1266 */ 1267 struct hpuxioctl_args { 1268 int fdes; 1269 int cmd; 1270 caddr_t cmarg; 1271 }; 1272 hpuxioctl(p, uap, retval) 1273 struct proc *p; 1274 register struct hpuxioctl_args *uap; 1275 int *retval; 1276 { 1277 register struct filedesc *fdp = p->p_fd; 1278 register struct file *fp; 1279 register int com, error; 1280 register u_int size; 1281 caddr_t memp = 0; 1282 #define STK_PARAMS 128 1283 char stkbuf[STK_PARAMS]; 1284 caddr_t data = stkbuf; 1285 1286 com = uap->cmd; 1287 1288 /* XXX */ 1289 if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 1290 return (getsettty(p, uap->fdes, com, uap->cmarg)); 1291 1292 if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 1293 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 1294 return (EBADF); 1295 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 1296 return (EBADF); 1297 1298 /* 1299 * Interpret high order word to find 1300 * amount of data to be copied to/from the 1301 * user's address space. 1302 */ 1303 size = IOCPARM_LEN(com); 1304 if (size > IOCPARM_MAX) 1305 return (ENOTTY); 1306 if (size > sizeof (stkbuf)) { 1307 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 1308 data = memp; 1309 } 1310 if (com&IOC_IN) { 1311 if (size) { 1312 error = copyin(uap->cmarg, data, (u_int)size); 1313 if (error) { 1314 if (memp) 1315 free(memp, M_IOCTLOPS); 1316 return (error); 1317 } 1318 } else 1319 *(caddr_t *)data = uap->cmarg; 1320 } else if ((com&IOC_OUT) && size) 1321 /* 1322 * Zero the buffer so the user always 1323 * gets back something deterministic. 1324 */ 1325 bzero(data, size); 1326 else if (com&IOC_VOID) 1327 *(caddr_t *)data = uap->cmarg; 1328 1329 switch (com) { 1330 1331 case HPUXFIOSNBIO: 1332 { 1333 char *ofp = &fdp->fd_ofileflags[uap->fdes]; 1334 int tmp; 1335 1336 if (*(int *)data) 1337 *ofp |= UF_FIONBIO_ON; 1338 else 1339 *ofp &= ~UF_FIONBIO_ON; 1340 /* 1341 * Only set/clear if O_NONBLOCK/FNDELAY not in effect 1342 */ 1343 if ((*ofp & (UF_NONBLOCK_ON|UF_FNDELAY_ON)) == 0) { 1344 tmp = *ofp & UF_FIONBIO_ON; 1345 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 1346 (caddr_t)&tmp, p); 1347 } 1348 break; 1349 } 1350 1351 case HPUXTIOCCONS: 1352 *(int *)data = 1; 1353 error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 1354 break; 1355 1356 /* BSD-style job control ioctls */ 1357 case HPUXTIOCLBIS: 1358 case HPUXTIOCLBIC: 1359 case HPUXTIOCLSET: 1360 *(int *)data &= HPUXLTOSTOP; 1361 if (*(int *)data & HPUXLTOSTOP) 1362 *(int *)data = LTOSTOP; 1363 /* fall into */ 1364 1365 /* simple mapping cases */ 1366 case HPUXTIOCLGET: 1367 case HPUXTIOCSLTC: 1368 case HPUXTIOCGLTC: 1369 case HPUXTIOCSPGRP: 1370 case HPUXTIOCGPGRP: 1371 case HPUXTIOCGWINSZ: 1372 case HPUXTIOCSWINSZ: 1373 error = (*fp->f_ops->fo_ioctl) 1374 (fp, hpuxtobsdioctl(com), data, p); 1375 if (error == 0 && com == HPUXTIOCLGET) { 1376 *(int *)data &= LTOSTOP; 1377 if (*(int *)data & LTOSTOP) 1378 *(int *)data = HPUXLTOSTOP; 1379 } 1380 break; 1381 1382 /* SYS 5 termio and POSIX termios */ 1383 case HPUXTCGETA: 1384 case HPUXTCSETA: 1385 case HPUXTCSETAW: 1386 case HPUXTCSETAF: 1387 case HPUXTCGETATTR: 1388 case HPUXTCSETATTR: 1389 case HPUXTCSETATTRD: 1390 case HPUXTCSETATTRF: 1391 error = hpuxtermio(uap->fdes, com, data, p); 1392 break; 1393 1394 default: 1395 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 1396 break; 1397 } 1398 /* 1399 * Copy any data to user, size was 1400 * already set and checked above. 1401 */ 1402 if (error == 0 && (com&IOC_OUT) && size) 1403 error = copyout(data, uap->cmarg, (u_int)size); 1404 if (memp) 1405 free(memp, M_IOCTLOPS); 1406 return (error); 1407 } 1408 1409 /* 1410 * Man page lies, behaviour here is based on observed behaviour. 1411 */ 1412 struct hpuxgetcontext_args { 1413 char *buf; 1414 int len; 1415 }; 1416 hpuxgetcontext(p, uap, retval) 1417 struct proc *p; 1418 struct hpuxgetcontext_args *uap; 1419 int *retval; 1420 { 1421 int error = 0; 1422 register int len; 1423 1424 #if defined(HP380) 1425 if (machineid == HP_380) { 1426 len = min(uap->len, sizeof(hpux040context)); 1427 if (len) 1428 error = copyout(hpux040context, uap->buf, len); 1429 if (error == 0) 1430 *retval = sizeof(hpux040context); 1431 return (error); 1432 } 1433 #endif 1434 len = min(uap->len, sizeof(hpuxcontext)); 1435 if (len) 1436 error = copyout(hpuxcontext, uap->buf, (u_int)len); 1437 if (error == 0) 1438 *retval = sizeof(hpuxcontext); 1439 return (error); 1440 } 1441 1442 /* 1443 * This is the equivalent of BSD getpgrp but with more restrictions. 1444 * Note we do not check the real uid or "saved" uid. 1445 */ 1446 struct hpuxgetpgrp2_args { 1447 int pid; 1448 }; 1449 hpuxgetpgrp2(cp, uap, retval) 1450 struct proc *cp; 1451 register struct hpuxgetpgrp2_args *uap; 1452 int *retval; 1453 { 1454 register struct proc *p; 1455 1456 if (uap->pid == 0) 1457 uap->pid = cp->p_pid; 1458 p = pfind(uap->pid); 1459 if (p == 0) 1460 return (ESRCH); 1461 if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1462 !inferior(p)) 1463 return (EPERM); 1464 *retval = p->p_pgid; 1465 return (0); 1466 } 1467 1468 /* 1469 * This is the equivalent of BSD setpgrp but with more restrictions. 1470 * Note we do not check the real uid or "saved" uid or pgrp. 1471 */ 1472 struct hpuxsetpgrp2_args { 1473 int pid; 1474 int pgrp; 1475 }; 1476 hpuxsetpgrp2(p, uap, retval) 1477 struct proc *p; 1478 struct hpuxsetpgrp2_args *uap; 1479 int *retval; 1480 { 1481 /* empirically determined */ 1482 if (uap->pgrp < 0 || uap->pgrp >= 30000) 1483 return (EINVAL); 1484 return (setpgid(p, uap, retval)); 1485 } 1486 1487 /* 1488 * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 1489 */ 1490 struct hpuxsetresuid_args { 1491 int ruid; 1492 int euid; 1493 int suid; 1494 }; 1495 hpuxsetresuid(p, uap, retval) 1496 struct proc *p; 1497 struct hpuxsetresuid_args *uap; 1498 int *retval; 1499 { 1500 return (osetreuid(p, uap, retval)); 1501 } 1502 1503 struct hpuxsetresgid_args { 1504 int rgid; 1505 int egid; 1506 int sgid; 1507 }; 1508 hpuxsetresgid(p, uap, retval) 1509 struct proc *p; 1510 struct hpuxsetresgid_args *uap; 1511 int *retval; 1512 { 1513 return (osetregid(p, uap, retval)); 1514 } 1515 1516 struct hpuxrlimit_args { 1517 u_int which; 1518 struct orlimit *rlp; 1519 }; 1520 hpuxgetrlimit(p, uap, retval) 1521 struct proc *p; 1522 struct hpuxrlimit_args *uap; 1523 int *retval; 1524 { 1525 if (uap->which > HPUXRLIMIT_NOFILE) 1526 return (EINVAL); 1527 if (uap->which == HPUXRLIMIT_NOFILE) 1528 uap->which = RLIMIT_NOFILE; 1529 return (ogetrlimit(p, uap, retval)); 1530 } 1531 1532 hpuxsetrlimit(p, uap, retval) 1533 struct proc *p; 1534 struct hpuxrlimit_args *uap; 1535 int *retval; 1536 { 1537 if (uap->which > HPUXRLIMIT_NOFILE) 1538 return (EINVAL); 1539 if (uap->which == HPUXRLIMIT_NOFILE) 1540 uap->which = RLIMIT_NOFILE; 1541 return (osetrlimit(p, uap, retval)); 1542 } 1543 1544 /* 1545 * XXX: simple recognition hack to see if we can make grmd work. 1546 */ 1547 struct hpuxlockf_args { 1548 int fd; 1549 int func; 1550 long size; 1551 }; 1552 hpuxlockf(p, uap, retval) 1553 struct proc *p; 1554 struct hpuxlockf_args *uap; 1555 int *retval; 1556 { 1557 return (0); 1558 } 1559 1560 struct hpuxgetaccess_args { 1561 char *path; 1562 int uid; 1563 int ngroups; 1564 int *gidset; 1565 void *label; 1566 void *privs; 1567 }; 1568 hpuxgetaccess(p, uap, retval) 1569 register struct proc *p; 1570 register struct hpuxgetaccess_args *uap; 1571 int *retval; 1572 { 1573 int lgroups[NGROUPS]; 1574 int error = 0; 1575 register struct ucred *cred; 1576 register struct vnode *vp; 1577 struct nameidata nd; 1578 1579 /* 1580 * Build an appropriate credential structure 1581 */ 1582 cred = crdup(p->p_ucred); 1583 switch (uap->uid) { 1584 case 65502: /* UID_EUID */ 1585 break; 1586 case 65503: /* UID_RUID */ 1587 cred->cr_uid = p->p_cred->p_ruid; 1588 break; 1589 case 65504: /* UID_SUID */ 1590 error = EINVAL; 1591 break; 1592 default: 1593 if (uap->uid > 65504) 1594 error = EINVAL; 1595 cred->cr_uid = uap->uid; 1596 break; 1597 } 1598 switch (uap->ngroups) { 1599 case -1: /* NGROUPS_EGID */ 1600 cred->cr_ngroups = 1; 1601 break; 1602 case -5: /* NGROUPS_EGID_SUPP */ 1603 break; 1604 case -2: /* NGROUPS_RGID */ 1605 cred->cr_ngroups = 1; 1606 cred->cr_gid = p->p_cred->p_rgid; 1607 break; 1608 case -6: /* NGROUPS_RGID_SUPP */ 1609 cred->cr_gid = p->p_cred->p_rgid; 1610 break; 1611 case -3: /* NGROUPS_SGID */ 1612 case -7: /* NGROUPS_SGID_SUPP */ 1613 error = EINVAL; 1614 break; 1615 case -4: /* NGROUPS_SUPP */ 1616 if (cred->cr_ngroups > 1) 1617 cred->cr_gid = cred->cr_groups[1]; 1618 else 1619 error = EINVAL; 1620 break; 1621 default: 1622 if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 1623 error = copyin((caddr_t)uap->gidset, 1624 (caddr_t)&lgroups[0], 1625 uap->ngroups * sizeof(lgroups[0])); 1626 else 1627 error = EINVAL; 1628 if (error == 0) { 1629 int gid; 1630 1631 for (gid = 0; gid < uap->ngroups; gid++) 1632 cred->cr_groups[gid] = lgroups[gid]; 1633 cred->cr_ngroups = uap->ngroups; 1634 } 1635 break; 1636 } 1637 /* 1638 * Lookup file using caller's effective IDs. 1639 */ 1640 if (error == 0) { 1641 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1642 uap->path, p); 1643 error = namei(&nd); 1644 } 1645 if (error) { 1646 crfree(cred); 1647 return (error); 1648 } 1649 /* 1650 * Use the constructed credentials for access checks. 1651 */ 1652 vp = nd.ni_vp; 1653 *retval = 0; 1654 if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 1655 *retval |= R_OK; 1656 if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 1657 *retval |= W_OK; 1658 /* XXX we return X_OK for root on VREG even if not */ 1659 if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 1660 *retval |= X_OK; 1661 vput(vp); 1662 crfree(cred); 1663 return (error); 1664 } 1665 1666 extern char kstack[]; 1667 #define UOFF(f) ((int)&((struct user *)0)->f) 1668 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1669 1670 /* simplified FP structure */ 1671 struct bsdfp { 1672 int save[54]; 1673 int reg[24]; 1674 int ctrl[3]; 1675 }; 1676 1677 /* 1678 * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 1679 */ 1680 hpuxtobsduoff(off, isps, p) 1681 int *off, *isps; 1682 struct proc *p; 1683 { 1684 register int *ar0 = p->p_md.md_regs; 1685 struct hpuxfp *hp; 1686 struct bsdfp *bp; 1687 register u_int raddr; 1688 1689 *isps = 0; 1690 1691 /* u_ar0 field; procxmt puts in U_ar0 */ 1692 if ((int)off == HPUOFF(hpuxu_ar0)) 1693 return(UOFF(U_ar0)); 1694 1695 #ifdef FPCOPROC 1696 /* FP registers from PCB */ 1697 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1698 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1699 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1700 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1701 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1702 return((int)&bp->reg[off - hp->hpfp_reg]); 1703 #endif 1704 1705 /* 1706 * Everything else we recognize comes from the kernel stack, 1707 * so we convert off to an absolute address (if not already) 1708 * for simplicity. 1709 */ 1710 if (off < (int *)ctob(UPAGES)) 1711 off = (int *)((u_int)off + (u_int)kstack); 1712 1713 /* 1714 * General registers. 1715 * We know that the HP-UX registers are in the same order as ours. 1716 * The only difference is that their PS is 2 bytes instead of a 1717 * padded 4 like ours throwing the alignment off. 1718 */ 1719 if (off >= ar0 && off < &ar0[18]) { 1720 /* 1721 * PS: return low word and high word of PC as HP-UX would 1722 * (e.g. &u.u_ar0[16.5]). 1723 * 1724 * XXX we don't do this since HP-UX adb doesn't rely on 1725 * it and passing such an offset to procxmt will cause 1726 * it to fail anyway. Instead, we just set the offset 1727 * to PS and let hpuxptrace() shift up the value returned. 1728 */ 1729 if (off == &ar0[PS]) { 1730 #if 0 1731 raddr = (u_int) &((short *)ar0)[PS*2+1]; 1732 #else 1733 raddr = (u_int) &ar0[(int)(off - ar0)]; 1734 #endif 1735 *isps = 1; 1736 } 1737 /* 1738 * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 1739 * is only 16 bits. 1740 */ 1741 else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1742 raddr = (u_int) &ar0[PC]; 1743 /* 1744 * D0-D7, A0-A7: easy 1745 */ 1746 else 1747 raddr = (u_int) &ar0[(int)(off - ar0)]; 1748 return((int)(raddr - (u_int)kstack)); 1749 } 1750 1751 /* everything else */ 1752 return(-1); 1753 } 1754 1755 /* 1756 * Kludge up a uarea dump so that HP-UX debuggers can find out 1757 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1758 * convert the entire user struct. 1759 */ 1760 hpuxdumpu(vp, cred) 1761 struct vnode *vp; 1762 struct ucred *cred; 1763 { 1764 struct proc *p = curproc; 1765 int error; 1766 struct hpuxuser *faku; 1767 struct bsdfp *bp; 1768 short *foop; 1769 1770 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1771 /* 1772 * Make sure there is no mistake about this 1773 * being a real user structure. 1774 */ 1775 bzero((caddr_t)faku, ctob(1)); 1776 /* 1777 * Fill in the process sizes. 1778 */ 1779 faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1780 faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1781 faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 1782 /* 1783 * Fill in the exec header for CDB. 1784 * This was saved back in exec(). As far as I can tell CDB 1785 * only uses this information to verify that a particular 1786 * core file goes with a particular binary. 1787 */ 1788 bcopy((caddr_t)p->p_addr->u_md.md_exec, 1789 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1790 /* 1791 * Adjust user's saved registers (on kernel stack) to reflect 1792 * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 1793 * so we have to move it up. 1794 */ 1795 faku->hpuxu_ar0 = p->p_md.md_regs; 1796 foop = (short *) p->p_md.md_regs; 1797 foop[32] = foop[33]; 1798 foop[33] = foop[34]; 1799 foop[34] = foop[35]; 1800 #ifdef FPCOPROC 1801 /* 1802 * Copy 68881 registers from our PCB format to HP-UX format 1803 */ 1804 bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 1805 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1806 sizeof(bp->save)); 1807 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1808 sizeof(bp->ctrl)); 1809 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1810 sizeof(bp->reg)); 1811 #endif 1812 /* 1813 * Slay the dragon 1814 */ 1815 faku->hpuxu_dragon = -1; 1816 /* 1817 * Dump this artfully constructed page in place of the 1818 * user struct page. 1819 */ 1820 error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1821 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1822 (int *)NULL, p); 1823 /* 1824 * Dump the remaining UPAGES-1 pages normally 1825 */ 1826 if (!error) 1827 error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 1828 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1829 IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 1830 free((caddr_t)faku, M_TEMP); 1831 return(error); 1832 } 1833 1834 /* 1835 * The remaining routines are essentially the same as those in kern_xxx.c 1836 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1837 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1838 * HP-UX compatibility still works even when COMPAT is not defined. 1839 * 1840 * These are still needed as of HP-UX 7.05. 1841 */ 1842 #ifdef COMPAT_OHPUX 1843 1844 #define HPUX_HZ 50 1845 1846 #include "sys/times.h" 1847 1848 /* from old timeb.h */ 1849 struct hpuxtimeb { 1850 time_t time; 1851 u_short millitm; 1852 short timezone; 1853 short dstflag; 1854 }; 1855 1856 /* ye ole stat structure */ 1857 struct ohpuxstat { 1858 u_short ohst_dev; 1859 u_short ohst_ino; 1860 u_short ohst_mode; 1861 short ohst_nlink; 1862 short ohst_uid; 1863 short ohst_gid; 1864 u_short ohst_rdev; 1865 int ohst_size; 1866 int ohst_atime; 1867 int ohst_mtime; 1868 int ohst_ctime; 1869 }; 1870 1871 /* 1872 * SYS V style setpgrp() 1873 */ 1874 ohpuxsetpgrp(p, uap, retval) 1875 register struct proc *p; 1876 int *uap, *retval; 1877 { 1878 if (p->p_pid != p->p_pgid) 1879 enterpgrp(p, p->p_pid, 0); 1880 *retval = p->p_pgid; 1881 return (0); 1882 } 1883 1884 struct ohpuxtime_args { 1885 long *tp; 1886 }; 1887 ohpuxtime(p, uap, retval) 1888 struct proc *p; 1889 register struct ohpuxtime_args *uap; 1890 int *retval; 1891 { 1892 int error = 0; 1893 1894 if (uap->tp) 1895 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1896 sizeof (long)); 1897 *(time_t *)retval = time.tv_sec; 1898 return (error); 1899 } 1900 1901 struct ohpuxstime_args { 1902 int time; 1903 }; 1904 ohpuxstime(p, uap, retval) 1905 struct proc *p; 1906 register struct ohpuxstime_args *uap; 1907 int *retval; 1908 { 1909 struct timeval tv; 1910 int s, error; 1911 1912 tv.tv_sec = uap->time; 1913 tv.tv_usec = 0; 1914 if (error = suser(p->p_ucred, &p->p_acflag)) 1915 return (error); 1916 1917 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1918 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1919 s = splhigh(); time = tv; splx(s); 1920 resettodr(); 1921 return (0); 1922 } 1923 1924 struct ohpuxftime_args { 1925 struct hpuxtimeb *tp; 1926 }; 1927 ohpuxftime(p, uap, retval) 1928 struct proc *p; 1929 register struct ohpuxftime_args *uap; 1930 int *retval; 1931 { 1932 struct hpuxtimeb tb; 1933 int s; 1934 1935 s = splhigh(); 1936 tb.time = time.tv_sec; 1937 tb.millitm = time.tv_usec / 1000; 1938 splx(s); 1939 tb.timezone = tz.tz_minuteswest; 1940 tb.dstflag = tz.tz_dsttime; 1941 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1942 } 1943 1944 struct ohpuxalarm_args { 1945 int deltat; 1946 }; 1947 ohpuxalarm(p, uap, retval) 1948 register struct proc *p; 1949 register struct ohpuxalarm_args *uap; 1950 int *retval; 1951 { 1952 int s = splhigh(); 1953 1954 untimeout(realitexpire, (caddr_t)p); 1955 timerclear(&p->p_realtimer.it_interval); 1956 *retval = 0; 1957 if (timerisset(&p->p_realtimer.it_value) && 1958 timercmp(&p->p_realtimer.it_value, &time, >)) 1959 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1960 if (uap->deltat == 0) { 1961 timerclear(&p->p_realtimer.it_value); 1962 splx(s); 1963 return (0); 1964 } 1965 p->p_realtimer.it_value = time; 1966 p->p_realtimer.it_value.tv_sec += uap->deltat; 1967 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1968 splx(s); 1969 return (0); 1970 } 1971 1972 struct ohpuxnice_args { 1973 int niceness; 1974 }; 1975 ohpuxnice(p, uap, retval) 1976 register struct proc *p; 1977 register struct ohpuxnice_args *uap; 1978 int *retval; 1979 { 1980 int error; 1981 1982 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1983 if (error == 0) 1984 *retval = p->p_nice - NZERO; 1985 return (error); 1986 } 1987 1988 struct ohpuxtimes_args { 1989 struct tms *tmsb; 1990 }; 1991 ohpuxtimes(p, uap, retval) 1992 struct proc *p; 1993 register struct ohpuxtimes_args *uap; 1994 int *retval; 1995 { 1996 struct timeval ru, rs; 1997 struct tms atms; 1998 int error; 1999 2000 calcru(p, &ru, &rs, NULL); 2001 atms.tms_utime = hpuxscale(&ru); 2002 atms.tms_stime = hpuxscale(&rs); 2003 atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 2004 atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 2005 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 2006 if (error == 0) 2007 *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 2008 return (error); 2009 } 2010 2011 /* 2012 * Doesn't exactly do what the documentation says. 2013 * What we really do is return 1/HPUX_HZ-th of a second since that 2014 * is what HP-UX returns. 2015 */ 2016 hpuxscale(tvp) 2017 register struct timeval *tvp; 2018 { 2019 return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 2020 } 2021 2022 /* 2023 * Set IUPD and IACC times on file. 2024 * Can't set ICHG. 2025 */ 2026 struct ohpuxutime_args { 2027 char *fname; 2028 time_t *tptr; 2029 }; 2030 ohpuxutime(p, uap, retval) 2031 struct proc *p; 2032 register struct ohpuxutime_args *uap; 2033 int *retval; 2034 { 2035 register struct vnode *vp; 2036 struct vattr vattr; 2037 time_t tv[2]; 2038 int error; 2039 struct nameidata nd; 2040 2041 if (uap->tptr) { 2042 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 2043 if (error) 2044 return (error); 2045 } else 2046 tv[0] = tv[1] = time.tv_sec; 2047 vattr_null(&vattr); 2048 vattr.va_atime.ts_sec = tv[0]; 2049 vattr.va_atime.ts_nsec = 0; 2050 vattr.va_mtime.ts_sec = tv[1]; 2051 vattr.va_mtime.ts_nsec = 0; 2052 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 2053 if (error = namei(&nd)) 2054 return (error); 2055 vp = nd.ni_vp; 2056 if (vp->v_mount->mnt_flag & MNT_RDONLY) 2057 error = EROFS; 2058 else 2059 error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 2060 vput(vp); 2061 return (error); 2062 } 2063 2064 ohpuxpause(p, uap, retval) 2065 struct proc *p; 2066 int *uap, *retval; 2067 { 2068 (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 2069 /* always return EINTR rather than ERESTART... */ 2070 return (EINTR); 2071 } 2072 2073 /* 2074 * The old fstat system call. 2075 */ 2076 struct ohpuxfstat_args { 2077 int fd; 2078 struct ohpuxstat *sb; 2079 }; 2080 ohpuxfstat(p, uap, retval) 2081 struct proc *p; 2082 register struct ohpuxfstat_args *uap; 2083 int *retval; 2084 { 2085 register struct filedesc *fdp = p->p_fd; 2086 struct file *fp; 2087 2088 if (((unsigned)uap->fd) >= fdp->fd_nfiles || 2089 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 2090 return (EBADF); 2091 if (fp->f_type != DTYPE_VNODE) 2092 return (EINVAL); 2093 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 2094 } 2095 2096 /* 2097 * Old stat system call. This version follows links. 2098 */ 2099 struct ohpuxstat_args { 2100 char *fname; 2101 struct ohpuxstat *sb; 2102 }; 2103 ohpuxstat(p, uap, retval) 2104 struct proc *p; 2105 register struct ohpuxstat_args *uap; 2106 int *retval; 2107 { 2108 int error; 2109 struct nameidata nd; 2110 2111 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 2112 if (error = namei(&nd)) 2113 return (error); 2114 error = ohpuxstat1(nd.ni_vp, uap->sb, p); 2115 vput(nd.ni_vp); 2116 return (error); 2117 } 2118 2119 int 2120 ohpuxstat1(vp, ub, p) 2121 struct vnode *vp; 2122 struct ohpuxstat *ub; 2123 struct proc *p; 2124 { 2125 struct ohpuxstat ohsb; 2126 struct stat sb; 2127 int error; 2128 2129 error = vn_stat(vp, &sb, p); 2130 if (error) 2131 return (error); 2132 2133 ohsb.ohst_dev = sb.st_dev; 2134 ohsb.ohst_ino = sb.st_ino; 2135 ohsb.ohst_mode = sb.st_mode; 2136 ohsb.ohst_nlink = sb.st_nlink; 2137 ohsb.ohst_uid = sb.st_uid; 2138 ohsb.ohst_gid = sb.st_gid; 2139 ohsb.ohst_rdev = sb.st_rdev; 2140 if (sb.st_size < (quad_t)1 << 32) 2141 ohsb.ohst_size = sb.st_size; 2142 else 2143 ohsb.ohst_size = -2; 2144 ohsb.ohst_atime = sb.st_atime; 2145 ohsb.ohst_mtime = sb.st_mtime; 2146 ohsb.ohst_ctime = sb.st_ctime; 2147 return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 2148 } 2149 #endif 2150 #endif 2151