1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: hpux_compat.c 1.33 89/08/23$ 13 * 14 * @(#)hpux_compat.c 7.9 (Berkeley) 06/28/90 15 */ 16 17 /* 18 * Various HPUX compatibility routines 19 */ 20 21 #ifdef HPUXCOMPAT 22 23 #include "param.h" 24 #include "systm.h" 25 #include "user.h" 26 #include "kernel.h" 27 #include "proc.h" 28 #include "buf.h" 29 #include "wait.h" 30 #include "file.h" 31 #include "vnode.h" 32 #include "ioctl.h" 33 #include "uio.h" 34 #include "ptrace.h" 35 #include "stat.h" 36 #include "syslog.h" 37 #include "malloc.h" 38 #include "mount.h" 39 #include "ipc.h" 40 41 #include "machine/cpu.h" 42 #include "machine/reg.h" 43 #include "machine/psl.h" 44 #include "machine/vmparam.h" 45 #include "hpux.h" 46 #include "hpux_termio.h" 47 48 #ifdef DEBUG 49 int unimpresponse = 0; 50 #endif 51 52 /* "tick" value for HZ==50 */ 53 int hpuxtick = 1000000 / 50; 54 55 /* SYS5 style UTSNAME info */ 56 struct hpuxutsname protoutsname = { 57 "4.4bsd", "", "2.0", "B", "9000/3?0", "" 58 }; 59 60 /* 6.0 and later style context */ 61 #ifdef FPCOPROC 62 char hpuxcontext[] = 63 "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 64 #else 65 char hpuxcontext[] = 66 "standalone HP-MC68020 HP-MC68010 localroot default"; 67 #endif 68 69 /* YP domainname */ 70 char domainname[MAXHOSTNAMELEN] = "unknown"; 71 int domainnamelen = 7; 72 73 #define NERR 79 74 #define BERR 1000 75 76 /* indexed by BSD errno */ 77 short bsdtohpuxerrnomap[NERR] = { 78 /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 79 /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 80 /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 81 /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 82 /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 83 /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 84 /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 85 /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 86 }; 87 88 notimp(p, uap, retval, code, nargs) 89 struct proc *p; 90 int *uap, *retval; 91 int code, nargs; 92 { 93 int error = 0; 94 #ifdef DEBUG 95 register int *argp = uap; 96 extern char *hpuxsyscallnames[]; 97 98 printf("HPUX %s(", hpuxsyscallnames[code]); 99 if (nargs) 100 while (nargs--) 101 printf("%x%c", *argp++, nargs? ',' : ')'); 102 else 103 printf(")"); 104 printf("\n"); 105 switch (unimpresponse) { 106 case 0: 107 error = nosys(p, uap, retval); 108 break; 109 case 1: 110 error = EINVAL; 111 break; 112 } 113 #else 114 error = nosys(p, uap, retval); 115 #endif 116 uprintf("HP-UX system call %d not implemented\n", code); 117 return (error); 118 } 119 120 /* 121 * HPUX versions of wait and wait3 actually pass the parameters 122 * (status pointer, options, rusage) into the kernel rather than 123 * handling it in the C library stub. We also need to map any 124 * termination signal from BSD to HPUX. 125 */ 126 hpuxwait3(p, uap, retval) 127 struct proc *p; 128 struct args { 129 int *status; 130 int options; 131 int rusage; 132 } *uap; 133 int *retval; 134 { 135 /* rusage pointer must be zero */ 136 if (uap->rusage) 137 return (EINVAL); 138 u.u_ar0[PS] = PSL_ALLCC; 139 u.u_ar0[R0] = uap->options; 140 u.u_ar0[R1] = uap->rusage; 141 return (hpuxwait(p, uap, retval)); 142 } 143 144 hpuxwait(p, uap, retval) 145 struct proc *p; 146 struct args { 147 int *status; 148 } *uap; 149 int *retval; 150 { 151 int sig, *statp, error; 152 153 statp = uap->status; /* owait clobbers first arg */ 154 error = owait(p, uap, retval); 155 /* 156 * HP-UX wait always returns EINTR when interrupted by a signal 157 * (well, unless its emulating a BSD process, but we don't bother...) 158 */ 159 if (error == ERESTART) 160 error = EINTR; 161 if (error) 162 return (error); 163 sig = retval[1] & 0xFF; 164 if (sig == WSTOPPED) { 165 sig = (retval[1] >> 8) & 0xFF; 166 retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 167 } else if (sig) 168 retval[1] = (retval[1] & 0xFF00) | 169 bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 170 if (statp) 171 if (suword((caddr_t)statp, retval[1])) 172 error = EFAULT; 173 return (error); 174 } 175 176 hpuxwaitpid(p, uap, retval) 177 struct proc *p; 178 struct args { 179 int pid; 180 int *status; 181 int options; 182 struct rusage *rusage; /* wait4 arg */ 183 } *uap; 184 int *retval; 185 { 186 int sig, *statp, error; 187 188 uap->rusage = 0; 189 error = wait4(p, uap, retval); 190 /* 191 * HP-UX wait always returns EINTR when interrupted by a signal 192 * (well, unless its emulating a BSD process, but we don't bother...) 193 */ 194 if (error == ERESTART) 195 error = EINTR; 196 if (error) 197 return (error); 198 sig = retval[1] & 0xFF; 199 if (sig == WSTOPPED) { 200 sig = (retval[1] >> 8) & 0xFF; 201 retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 202 } else if (sig) 203 retval[1] = (retval[1] & 0xFF00) | 204 bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 205 if (statp) 206 if (suword((caddr_t)statp, retval[1])) 207 error = EFAULT; 208 return (error); 209 } 210 211 /* 212 * Must remap some bits in the mode mask. 213 * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 214 * O_SYNCIO (0100000) is removed entirely. 215 */ 216 hpuxopen(p, uap, retval) 217 struct proc *p; 218 register struct args { 219 char *fname; 220 int mode; 221 int crtmode; 222 } *uap; 223 int *retval; 224 { 225 int mode; 226 227 mode = uap->mode; 228 uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 229 if (mode & HPUXFCREAT) { 230 /* 231 * simulate the pre-NFS behavior that opening a 232 * file for READ+CREATE ignores the CREATE (unless 233 * EXCL is set in which case we will return the 234 * proper error). 235 */ 236 if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 237 uap->mode |= FCREAT; 238 } 239 if (mode & HPUXFTRUNC) 240 uap->mode |= FTRUNC; 241 if (mode & HPUXFEXCL) 242 uap->mode |= FEXCL; 243 return (open(p, uap, retval)); 244 } 245 246 hpuxfcntl(p, uap, retval) 247 struct proc *p; 248 register struct args { 249 int fdes; 250 int cmd; 251 int arg; 252 } *uap; 253 int *retval; 254 { 255 int mode, error; 256 257 switch (uap->cmd) { 258 case F_SETFL: 259 uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 260 break; 261 case F_GETFL: 262 case F_DUPFD: 263 case F_GETFD: 264 case F_SETFD: 265 break; 266 default: 267 return (EINVAL); 268 } 269 error = fcntl(p, uap, retval); 270 if (error == 0 && uap->arg == F_GETFL) { 271 mode = *retval; 272 *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 273 if (mode & FCREAT) 274 *retval |= HPUXFCREAT; 275 if (mode & FTRUNC) 276 *retval |= HPUXFTRUNC; 277 if (mode & FEXCL) 278 *retval |= HPUXFEXCL; 279 } 280 return (error); 281 } 282 283 /* 284 * Read and write should return a 0 count when an operation 285 * on a VNODE would block, not an error. Sockets appear to 286 * return EWOULDBLOCK (at least in 6.2). This is probably 287 * not entirely correct, since the behavior is only defined 288 * for pipes and tty type devices. 289 */ 290 hpuxread(p, uap, retval) 291 struct proc *p; 292 struct args { 293 int fd; 294 } *uap; 295 int *retval; 296 { 297 int error; 298 299 error = read(p, uap, retval); 300 if (error == EWOULDBLOCK && 301 u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 302 error = 0; 303 *retval = 0; 304 } 305 return (error); 306 } 307 308 hpuxwrite(p, uap, retval) 309 struct proc *p; 310 struct args { 311 int fd; 312 } *uap; 313 int *retval; 314 { 315 int error; 316 317 error = write(p, uap, retval); 318 if (error == EWOULDBLOCK && 319 u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 320 error = 0; 321 *retval = 0; 322 } 323 return (error); 324 } 325 326 hpuxreadv(p, uap, retval) 327 struct proc *p; 328 struct args { 329 int fd; 330 } *uap; 331 int *retval; 332 { 333 int error; 334 335 error = readv(p, uap, retval); 336 if (error == EWOULDBLOCK && 337 u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 338 error = 0; 339 *retval = 0; 340 } 341 return (error); 342 } 343 344 hpuxwritev(p, uap, retval) 345 struct proc *p; 346 struct args { 347 int fd; 348 } *uap; 349 int *retval; 350 { 351 int error; 352 353 error = writev(p, uap, retval); 354 if (error == EWOULDBLOCK && 355 u.u_ofile[uap->fd]->f_type == DTYPE_VNODE) { 356 error = 0; 357 *retval = 0; 358 } 359 return (error); 360 } 361 362 /* 363 * 4.3bsd dup allows dup2 to come in on the same syscall entry 364 * and hence allows two arguments. HPUX dup has only one arg. 365 */ 366 hpuxdup(p, uap, retval) 367 struct proc *p; 368 register struct args { 369 int i; 370 } *uap; 371 int *retval; 372 { 373 struct file *fp; 374 int fd, error; 375 376 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 377 return (EBADF); 378 if (error = ufalloc(0, &fd)) 379 return (error); 380 *retval = fd; 381 u.u_ofile[fd] = fp; 382 u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; 383 fp->f_count++; 384 if (fd > u.u_lastfile) 385 u.u_lastfile = fd; 386 return (0); 387 } 388 389 hpuxuname(p, uap, retval) 390 struct proc *p; 391 register struct args { 392 struct hpuxutsname *uts; 393 int dev; 394 int request; 395 } *uap; 396 int *retval; 397 { 398 register int i; 399 int error; 400 401 switch (uap->request) { 402 /* uname */ 403 case 0: 404 /* fill in machine type */ 405 switch (machineid) { 406 case HP_320: 407 protoutsname.machine[6] = '2'; 408 break; 409 /* includes 318 and 319 */ 410 case HP_330: 411 protoutsname.machine[6] = '3'; 412 break; 413 case HP_340: 414 protoutsname.machine[6] = '4'; 415 break; 416 case HP_350: 417 protoutsname.machine[6] = '5'; 418 break; 419 case HP_360: 420 protoutsname.machine[6] = '6'; 421 break; 422 case HP_370: 423 protoutsname.machine[6] = '7'; 424 break; 425 /* includes 345 */ 426 case HP_375: 427 protoutsname.machine[6] = '7'; 428 protoutsname.machine[7] = '5'; 429 break; 430 } 431 /* copy hostname (sans domain) to nodename */ 432 for (i = 0; i < 9 && hostname[i] != '.'; i++) 433 protoutsname.nodename[i] = hostname[i]; 434 error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 435 sizeof(struct hpuxutsname)); 436 break; 437 /* ustat - who cares? */ 438 case 2: 439 default: 440 error = EINVAL; 441 break; 442 } 443 return (error); 444 } 445 446 hpuxstat(p, uap, retval) 447 struct proc *p; 448 struct args { 449 char *fname; 450 struct hpuxstat *hsb; 451 } *uap; 452 int *retval; 453 { 454 return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 455 } 456 457 hpuxlstat(p, uap, retval) 458 struct proc *p; 459 struct args { 460 char *fname; 461 struct hpuxstat *hsb; 462 } *uap; 463 int *retval; 464 { 465 return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 466 } 467 468 hpuxfstat(p, uap, retval) 469 struct proc *p; 470 register struct args { 471 int fdes; 472 struct hpuxstat *hsb; 473 } *uap; 474 int *retval; 475 { 476 register struct file *fp; 477 struct stat sb; 478 int error; 479 480 if ((unsigned)uap->fdes >= NOFILE || 481 (fp = u.u_ofile[uap->fdes]) == NULL) 482 return (EBADF); 483 484 switch (fp->f_type) { 485 486 case DTYPE_VNODE: 487 error = vn_stat((struct vnode *)fp->f_data, &sb); 488 break; 489 490 case DTYPE_SOCKET: 491 error = soo_stat((struct socket *)fp->f_data, &sb); 492 break; 493 494 default: 495 panic("fstat"); 496 /*NOTREACHED*/ 497 } 498 /* is this right for sockets?? */ 499 if (error == 0) 500 error = bsdtohpuxstat(&sb, uap->hsb); 501 return (error); 502 } 503 504 hpuxulimit(p, uap, retval) 505 struct proc *p; 506 register struct args { 507 int cmd; 508 long newlimit; 509 } *uap; 510 off_t *retval; 511 { 512 struct rlimit *limp; 513 int error = 0; 514 515 limp = &u.u_rlimit[RLIMIT_FSIZE]; 516 switch (uap->cmd) { 517 case 2: 518 uap->newlimit *= 512; 519 if (uap->newlimit > limp->rlim_max && 520 (error = suser(u.u_cred, &u.u_acflag))) 521 break; 522 limp->rlim_cur = limp->rlim_max = uap->newlimit; 523 /* else fall into... */ 524 525 case 1: 526 *retval = limp->rlim_max / 512; /* XXX */ 527 break; 528 529 case 3: 530 limp = &u.u_rlimit[RLIMIT_DATA]; 531 *retval = ctob(u.u_tsize) + limp->rlim_max; /* XXX */ 532 break; 533 534 default: 535 error = EINVAL; 536 break; 537 } 538 return (error); 539 } 540 541 /* 542 * Map "real time" priorities 0 (high) thru 127 (low) into nice 543 * values -16 (high) thru -1 (low). 544 */ 545 hpuxrtprio(cp, uap, retval) 546 struct proc *cp; 547 register struct args { 548 int pid; 549 int prio; 550 } *uap; 551 int *retval; 552 { 553 struct proc *p; 554 int nice, error; 555 556 if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 557 uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 558 return (EINVAL); 559 if (uap->pid == 0) 560 p = cp; 561 else if ((p = pfind(uap->pid)) == 0) 562 return (ESRCH); 563 nice = p->p_nice; 564 if (nice < NZERO) 565 *retval = (nice + 16) << 3; 566 else 567 *retval = RTPRIO_RTOFF; 568 switch (uap->prio) { 569 570 case RTPRIO_NOCHG: 571 return (0); 572 573 case RTPRIO_RTOFF: 574 if (nice >= NZERO) 575 return (0); 576 nice = NZERO; 577 break; 578 579 default: 580 nice = (uap->prio >> 3) - 16; 581 break; 582 } 583 error = donice(cp, p, nice); 584 if (error == EACCES) 585 error = EPERM; 586 return (error); 587 } 588 589 hpuxadvise(p, uap, retval) 590 struct proc *p; 591 struct args { 592 int arg; 593 } *uap; 594 int *retval; 595 { 596 int error = 0; 597 598 switch (uap->arg) { 599 case 0: 600 u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 601 break; 602 case 1: 603 ICIA(); 604 break; 605 case 2: 606 DCIA(); 607 break; 608 default: 609 error = EINVAL; 610 break; 611 } 612 return (error); 613 } 614 615 hpuxptrace(p, uap, retval) 616 struct proc *p; 617 struct args { 618 int req; 619 int pid; 620 int *addr; 621 int data; 622 } *uap; 623 int *retval; 624 { 625 int error; 626 627 if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 628 if (uap->data) { 629 uap->data = hpuxtobsdsig(uap->data); 630 if (uap->data == 0) 631 uap->data = NSIG; 632 } 633 } 634 error = ptrace(p, uap, retval); 635 return (error); 636 } 637 638 hpuxgetdomainname(p, uap, retval) 639 struct proc *p; 640 register struct args { 641 char *domainname; 642 u_int len; 643 } *uap; 644 int *retval; 645 { 646 if (uap->len > domainnamelen + 1) 647 uap->len = domainnamelen + 1; 648 return (copyout(domainname, uap->domainname, uap->len)); 649 } 650 651 hpuxsetdomainname(p, uap, retval) 652 struct proc *p; 653 register struct args { 654 char *domainname; 655 u_int len; 656 } *uap; 657 int *retval; 658 { 659 int error; 660 661 if (error = suser(u.u_cred, &u.u_acflag)) 662 return (error); 663 if (uap->len > sizeof (domainname) - 1) 664 return (EINVAL); 665 domainnamelen = uap->len; 666 error = copyin(uap->domainname, domainname, uap->len); 667 domainname[domainnamelen] = 0; 668 return (error); 669 } 670 671 #ifdef SYSVSHM 672 hpuxshmat(p, uap, retval) 673 struct proc *p; 674 int *uap, *retval; 675 { 676 return (shmat(p, uap, retval)); 677 } 678 679 hpuxshmctl(p, uap, retval) 680 struct proc *p; 681 int *uap, *retval; 682 { 683 return (shmctl(p, uap, retval)); 684 } 685 686 hpuxshmdt(p, uap, retval) 687 struct proc *p; 688 int *uap, *retval; 689 { 690 return (shmdt(p, uap, retval)); 691 } 692 693 hpuxshmget(p, uap, retval) 694 struct proc *p; 695 int *uap, *retval; 696 { 697 return (shmget(p, uap, retval)); 698 } 699 #endif 700 701 /* 702 * Fake semaphore routines, just don't return an error. 703 * Should be adequate for starbase to run. 704 */ 705 hpuxsemctl(p, uap, retval) 706 struct proc *p; 707 struct args { 708 int semid; 709 u_int semnum; 710 int cmd; 711 int arg; 712 } *uap; 713 int *retval; 714 { 715 /* XXX: should do something here */ 716 return (0); 717 } 718 719 hpuxsemget(p, uap, retval) 720 struct proc *p; 721 struct args { 722 key_t key; 723 int nsems; 724 int semflg; 725 } *uap; 726 int *retval; 727 { 728 /* XXX: should do something here */ 729 return (0); 730 } 731 732 hpuxsemop(p, uap, retval) 733 struct proc *p; 734 struct args { 735 int semid; 736 struct sembuf *sops; 737 u_int nsops; 738 } *uap; 739 int *retval; 740 { 741 /* XXX: should do something here */ 742 return (0); 743 } 744 745 /* convert from BSD to HPUX errno */ 746 bsdtohpuxerrno(err) 747 int err; 748 { 749 if (err < 0 || err >= NERR) 750 return(BERR); 751 return((int)bsdtohpuxerrnomap[err]); 752 } 753 754 hpuxstat1(fname, hsb, follow) 755 char *fname; 756 struct hpuxstat *hsb; 757 int follow; 758 { 759 register struct nameidata *ndp = &u.u_nd; 760 struct stat sb; 761 int error; 762 763 ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 764 ndp->ni_segflg = UIO_USERSPACE; 765 ndp->ni_dirp = fname; 766 if (error = namei(ndp)) 767 return (error); 768 error = vn_stat(ndp->ni_vp, &sb); 769 vput(ndp->ni_vp); 770 if (error == 0) 771 error = bsdtohpuxstat(&sb, hsb); 772 return (error); 773 } 774 775 #include "grf.h" 776 777 bsdtohpuxstat(sb, hsb) 778 struct stat *sb; 779 struct hpuxstat *hsb; 780 { 781 struct hpuxstat ds; 782 783 bzero((caddr_t)&ds, sizeof(ds)); 784 ds.hst_dev = sb->st_dev; 785 ds.hst_ino = (u_long)sb->st_ino; 786 ds.hst_mode = sb->st_mode; 787 ds.hst_nlink = sb->st_nlink; 788 ds.hst_uid = (u_short)sb->st_uid; 789 ds.hst_gid = (u_short)sb->st_gid; 790 #if NGRF > 0 791 /* XXX: I don't want to talk about it... */ 792 if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 793 ds.hst_rdev = grfdevno(sb->st_rdev); 794 else 795 #endif 796 ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 797 ds.hst_size = sb->st_size; 798 ds.hst_atime = sb->st_atime; 799 ds.hst_mtime = sb->st_mtime; 800 ds.hst_ctime = sb->st_ctime; 801 ds.hst_blksize = sb->st_blksize; 802 ds.hst_blocks = sb->st_blocks; 803 return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 804 } 805 806 hpuxtobsdioctl(com) 807 int com; 808 { 809 switch (com) { 810 case HPUXTIOCSLTC: 811 com = TIOCSLTC; break; 812 case HPUXTIOCGLTC: 813 com = TIOCGLTC; break; 814 case HPUXTIOCSPGRP: 815 com = TIOCSPGRP; break; 816 case HPUXTIOCGPGRP: 817 com = TIOCGPGRP; break; 818 case HPUXTIOCLBIS: 819 com = TIOCLBIS; break; 820 case HPUXTIOCLBIC: 821 com = TIOCLBIC; break; 822 case HPUXTIOCLSET: 823 com = TIOCLSET; break; 824 case HPUXTIOCLGET: 825 com = TIOCLGET; break; 826 } 827 return(com); 828 } 829 830 /* 831 * HPUX ioctl system call. The differences here are: 832 * IOC_IN also means IOC_VOID if the size portion is zero. 833 * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 834 * the sgttyb struct is 2 bytes longer 835 */ 836 hpuxioctl(p, uap, retval) 837 struct proc *p; 838 register struct args { 839 int fdes; 840 int cmd; 841 caddr_t cmarg; 842 } *uap; 843 int *retval; 844 { 845 register struct file *fp; 846 register int com, error; 847 register u_int size; 848 caddr_t memp = 0; 849 #define STK_PARAMS 128 850 char stkbuf[STK_PARAMS]; 851 caddr_t data = stkbuf; 852 853 com = uap->cmd; 854 855 /* XXX */ 856 if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 857 return (getsettty(uap->fdes, com, uap->cmarg)); 858 859 if ((unsigned)uap->fdes >= NOFILE || 860 (fp = u.u_ofile[uap->fdes]) == NULL) 861 return (EBADF); 862 if ((fp->f_flag & (FREAD|FWRITE)) == 0) 863 return (EBADF); 864 865 /* 866 * Interpret high order word to find 867 * amount of data to be copied to/from the 868 * user's address space. 869 */ 870 size = IOCPARM_LEN(com); 871 if (size > IOCPARM_MAX) 872 return (ENOTTY); 873 if (size > sizeof (stkbuf)) { 874 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 875 data = memp; 876 } 877 if (com&IOC_IN) { 878 if (size) { 879 error = copyin(uap->cmarg, data, (u_int)size); 880 if (error) { 881 if (memp) 882 free(memp, M_IOCTLOPS); 883 return (error); 884 } 885 } else 886 *(caddr_t *)data = uap->cmarg; 887 } else if ((com&IOC_OUT) && size) 888 /* 889 * Zero the buffer so the user always 890 * gets back something deterministic. 891 */ 892 bzero(data, size); 893 else if (com&IOC_VOID) 894 *(caddr_t *)data = uap->cmarg; 895 896 switch (com) { 897 898 case HPUXTIOCCONS: 899 *(int *)data = 1; 900 error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 901 break; 902 903 /* BSD-style job control ioctls */ 904 case HPUXTIOCLBIS: 905 case HPUXTIOCLBIC: 906 case HPUXTIOCLSET: 907 *(int *)data &= HPUXLTOSTOP; 908 if (*(int *)data & HPUXLTOSTOP) 909 *(int *)data = LTOSTOP; 910 /* fall into */ 911 case HPUXTIOCLGET: 912 case HPUXTIOCSLTC: 913 case HPUXTIOCGLTC: 914 case HPUXTIOCSPGRP: 915 case HPUXTIOCGPGRP: 916 error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 917 if (error == 0 && com == HPUXTIOCLGET) { 918 *(int *)data &= LTOSTOP; 919 if (*(int *)data & LTOSTOP) 920 *(int *)data = HPUXLTOSTOP; 921 } 922 break; 923 924 /* SYS 5 termio */ 925 case HPUXTCGETA: 926 case HPUXTCSETA: 927 case HPUXTCSETAW: 928 case HPUXTCSETAF: 929 error = hpuxtermio(fp, com, data); 930 break; 931 932 default: 933 error = (*fp->f_ops->fo_ioctl)(fp, com, data); 934 break; 935 } 936 /* 937 * Copy any data to user, size was 938 * already set and checked above. 939 */ 940 if (error == 0 && (com&IOC_OUT) && size) 941 error = copyout(data, uap->cmarg, (u_int)size); 942 if (memp) 943 free(memp, M_IOCTLOPS); 944 return (error); 945 } 946 947 /* 948 * Man page lies, behaviour here is based on observed behaviour. 949 */ 950 hpuxgetcontext(p, uap, retval) 951 struct proc *p; 952 struct args { 953 char *buf; 954 int len; 955 } *uap; 956 int *retval; 957 { 958 int error = 0; 959 register int len; 960 961 len = MIN(uap->len, sizeof(hpuxcontext)); 962 if (len) 963 error = copyout(hpuxcontext, uap->buf, (u_int)len); 964 if (error == 0) 965 *retval = sizeof(hpuxcontext); 966 return (error); 967 } 968 969 /* 970 * XXX: simple recognition hack to see if we can make grmd work. 971 */ 972 hpuxlockf(p, uap, retval) 973 struct proc *p; 974 struct args { 975 int fd; 976 int func; 977 long size; 978 } *uap; 979 int *retval; 980 { 981 #ifdef DEBUG 982 log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 983 p->p_pid, uap->fd, uap->func, uap->size); 984 #endif 985 return (0); 986 } 987 988 /* 989 * This is the equivalent of BSD getpgrp but with more restrictions. 990 * Note we do not check the real uid or "saved" uid. 991 */ 992 hpuxgetpgrp2(cp, uap, retval) 993 struct proc *cp; 994 register struct args { 995 int pid; 996 } *uap; 997 int *retval; 998 { 999 register struct proc *p; 1000 1001 if (uap->pid == 0) 1002 uap->pid = cp->p_pid; 1003 p = pfind(uap->pid); 1004 if (p == 0) 1005 return (ESRCH); 1006 if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) 1007 return (EPERM); 1008 *retval = p->p_pgid; 1009 return (0); 1010 } 1011 1012 /* 1013 * This is the equivalent of BSD setpgrp but with more restrictions. 1014 * Note we do not check the real uid or "saved" uid or pgrp. 1015 */ 1016 hpuxsetpgrp2(p, uap, retval) 1017 struct proc *p; 1018 struct args { 1019 int pid; 1020 int pgrp; 1021 } *uap; 1022 int *retval; 1023 { 1024 /* empirically determined */ 1025 if (uap->pgrp < 0 || uap->pgrp >= 30000) 1026 return (EINVAL); 1027 return (setpgrp(p, uap, retval)); 1028 } 1029 1030 /* 1031 * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 1032 * No apologies offered, if you don't like it, rewrite it! 1033 */ 1034 1035 #define UOFF(f) ((int)&((struct user *)0)->f) 1036 #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 1037 1038 /* simplified FP structure */ 1039 struct bsdfp { 1040 int save[54]; 1041 int reg[24]; 1042 int ctrl[3]; 1043 }; 1044 1045 hpuxtobsduoff(off) 1046 int *off; 1047 { 1048 struct hpuxfp *hp; 1049 struct bsdfp *bp; 1050 register u_int raddr; 1051 1052 /* u_ar0 field */ 1053 if ((int)off == HPUOFF(hpuxu_ar0)) 1054 return(UOFF(u_ar0)); 1055 1056 #ifdef FPCOPROC 1057 /* 68881 registers from PCB */ 1058 hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 1059 bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 1060 if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 1061 return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 1062 if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 1063 return((int)&bp->reg[off - hp->hpfp_reg]); 1064 #endif 1065 1066 /* 1067 * Everything else we recognize comes from the kernel stack, 1068 * so we convert off to an absolute address (if not already) 1069 * for simplicity. 1070 */ 1071 if (off < (int *)ctob(UPAGES)) 1072 off = (int *)((u_int)off + (u_int)&u); 1073 1074 /* 1075 * 68020 registers. 1076 * We know that the HPUX registers are in the same order as ours. 1077 * The only difference is that their PS is 2 bytes instead of a 1078 * padded 4 like ours throwing the alignment off. 1079 */ 1080 if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 1081 /* 1082 * PS: return low word and high word of PC as HP-UX would 1083 * (e.g. &u.u_ar0[16.5]). 1084 */ 1085 if (off == &u.u_ar0[PS]) 1086 raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 1087 /* 1088 * PC: off will be &u.u_ar0[16.5] 1089 */ 1090 else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 1091 raddr = (u_int) &u.u_ar0[PC]; 1092 /* 1093 * D0-D7, A0-A7: easy 1094 */ 1095 else 1096 raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 1097 return((int)(raddr - (u_int)&u)); 1098 } 1099 1100 /* everything else */ 1101 return(-1); 1102 } 1103 1104 /* 1105 * Kludge up a uarea dump so that HPUX debuggers can find out 1106 * what they need. IMPORTANT NOTE: we do not EVEN attempt to 1107 * convert the entire user struct. 1108 */ 1109 hpuxdumpu(vp, cred) 1110 struct vnode *vp; 1111 struct ucred *cred; 1112 { 1113 int error; 1114 struct hpuxuser *faku; 1115 struct bsdfp *bp; 1116 short *foop; 1117 1118 faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 1119 /* 1120 * Make sure there is no mistake about this 1121 * being a real user structure. 1122 */ 1123 bzero((caddr_t)faku, ctob(1)); 1124 /* 1125 * Fill in the process sizes. 1126 */ 1127 faku->hpuxu_tsize = u.u_tsize; 1128 faku->hpuxu_dsize = u.u_dsize; 1129 faku->hpuxu_ssize = u.u_ssize; 1130 /* 1131 * Fill in the exec header for CDB. 1132 * This was saved back in exec(). As far as I can tell CDB 1133 * only uses this information to verify that a particular 1134 * core file goes with a particular binary. 1135 */ 1136 bcopy((caddr_t)u.u_pcb.pcb_exec, 1137 (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 1138 /* 1139 * Adjust user's saved registers (on kernel stack) to reflect 1140 * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 1141 * so we have to move it up. 1142 */ 1143 faku->hpuxu_ar0 = u.u_ar0; 1144 foop = (short *) u.u_ar0; 1145 foop[32] = foop[33]; 1146 foop[33] = foop[34]; 1147 foop[34] = foop[35]; 1148 #ifdef FPCOPROC 1149 /* 1150 * Copy 68881 registers from our PCB format to HPUX format 1151 */ 1152 bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 1153 bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 1154 sizeof(bp->save)); 1155 bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 1156 sizeof(bp->ctrl)); 1157 bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 1158 sizeof(bp->reg)); 1159 #endif 1160 /* 1161 * Slay the dragon 1162 */ 1163 faku->hpuxu_dragon = -1; 1164 /* 1165 * Dump this artfully constructed page in place of the 1166 * user struct page. 1167 */ 1168 error = vn_rdwr(UIO_WRITE, vp, 1169 (caddr_t)faku, ctob(1), (off_t)0, 1170 UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 1171 /* 1172 * Dump the remaining UPAGES-1 pages normally 1173 */ 1174 if (!error) 1175 error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 1176 ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1177 IO_NODELOCKED|IO_UNIT, cred, (int *)0); 1178 free((caddr_t)faku, M_TEMP); 1179 return(error); 1180 } 1181 1182 /* 1183 * The remaining routines are essentially the same as those in kern_xxx.c 1184 * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 1185 * to avoid HPUXCOMPAT dependencies in those files and to make sure that 1186 * HP-UX compatibility still works even when COMPAT is not defined. 1187 */ 1188 /* #ifdef COMPAT */ 1189 1190 #include "../sys/times.h" 1191 1192 /* from old timeb.h */ 1193 struct hpuxtimeb { 1194 time_t time; 1195 u_short millitm; 1196 short timezone; 1197 short dstflag; 1198 }; 1199 1200 /* ye ole stat structure */ 1201 struct ohpuxstat { 1202 dev_t ohst_dev; 1203 u_short ohst_ino; 1204 u_short ohst_mode; 1205 short ohst_nlink; 1206 short ohst_uid; 1207 short ohst_gid; 1208 dev_t ohst_rdev; 1209 int ohst_size; 1210 int ohst_atime; 1211 int ohst_mtime; 1212 int ohst_ctime; 1213 }; 1214 1215 /* 1216 * SYS V style setpgrp() 1217 */ 1218 ohpuxsetpgrp(p, uap, retval) 1219 register struct proc *p; 1220 int *uap, *retval; 1221 { 1222 if (p->p_pid != p->p_pgid) 1223 pgmv(p, p->p_pid, 0); 1224 *retval = p->p_pgid; 1225 } 1226 1227 ohpuxtime(p, uap, retval) 1228 struct proc *p; 1229 register struct args { 1230 long *tp; 1231 } *uap; 1232 time_t *retval; 1233 { 1234 int error; 1235 1236 if (uap->tp) 1237 error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 1238 sizeof (long)); 1239 *retval = time.tv_sec; /* XXX */ 1240 return (error); 1241 } 1242 1243 ohpuxstime(p, uap, retval) 1244 struct proc *p; 1245 register struct args { 1246 int time; 1247 } *uap; 1248 int *retval; 1249 { 1250 struct timeval tv; 1251 int s, error; 1252 1253 tv.tv_sec = uap->time; 1254 tv.tv_usec = 0; 1255 if (error = suser(u.u_cred, &u.u_acflag)) 1256 return (error); 1257 1258 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1259 boottime.tv_sec += tv.tv_sec - time.tv_sec; 1260 s = splhigh(); time = tv; splx(s); 1261 resettodr(); 1262 return (0); 1263 } 1264 1265 ohpuxftime(p, uap, retval) 1266 struct proc *p; 1267 register struct args { 1268 struct hpuxtimeb *tp; 1269 } *uap; 1270 int *retval; 1271 { 1272 struct hpuxtimeb tb; 1273 int s; 1274 1275 s = splhigh(); 1276 tb.time = time.tv_sec; 1277 tb.millitm = time.tv_usec / 1000; 1278 splx(s); 1279 tb.timezone = tz.tz_minuteswest; 1280 tb.dstflag = tz.tz_dsttime; 1281 return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 1282 } 1283 1284 ohpuxalarm(p, uap, retval) 1285 register struct proc *p; 1286 register struct args { 1287 int deltat; 1288 } *uap; 1289 int *retval; 1290 { 1291 int s = splhigh(); 1292 1293 untimeout(realitexpire, (caddr_t)p); 1294 timerclear(&p->p_realtimer.it_interval); 1295 *retval = 0; 1296 if (timerisset(&p->p_realtimer.it_value) && 1297 timercmp(&p->p_realtimer.it_value, &time, >)) 1298 *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 1299 if (uap->deltat == 0) { 1300 timerclear(&p->p_realtimer.it_value); 1301 splx(s); 1302 return (0); 1303 } 1304 p->p_realtimer.it_value = time; 1305 p->p_realtimer.it_value.tv_sec += uap->deltat; 1306 timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 1307 splx(s); 1308 return (0); 1309 } 1310 1311 ohpuxnice(p, uap, retval) 1312 register struct proc *p; 1313 register struct args { 1314 int niceness; 1315 } *uap; 1316 int *retval; 1317 { 1318 int error; 1319 1320 error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 1321 if (error == 0) 1322 *retval = p->p_nice - NZERO; 1323 return (error); 1324 } 1325 1326 ohpuxtimes(p, uap, retval) 1327 struct proc *p; 1328 register struct args { 1329 struct tms *tmsb; 1330 } *uap; 1331 time_t *retval; 1332 { 1333 struct tms atms; 1334 int error; 1335 1336 atms.tms_utime = scale50(&u.u_ru.ru_utime); 1337 atms.tms_stime = scale50(&u.u_ru.ru_stime); 1338 atms.tms_cutime = scale50(&u.u_cru.ru_utime); 1339 atms.tms_cstime = scale50(&u.u_cru.ru_stime); 1340 error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 1341 if (error == 0) 1342 *retval = scale50(&time) - scale50(&boottime); /* XXX */ 1343 return (error); 1344 } 1345 1346 scale50(tvp) 1347 register struct timeval *tvp; 1348 { 1349 extern int hpuxtick; 1350 1351 /* 1352 * Doesn't exactly do what the documentation says. 1353 * What we really do is return 50th of a second since that 1354 * is what HZ is on all bobcats I know of. 1355 */ 1356 return ((tvp->tv_sec * 50 + tvp->tv_usec / hpuxtick)); 1357 } 1358 1359 /* 1360 * Set IUPD and IACC times on file. 1361 * Can't set ICHG. 1362 */ 1363 ohpuxutime(p, uap, retval) 1364 struct proc *p; 1365 register struct a { 1366 char *fname; 1367 time_t *tptr; 1368 } *uap; 1369 int *retval; 1370 { 1371 struct vattr vattr; 1372 time_t tv[2]; 1373 register struct vnode *vp; 1374 register struct nameidata *ndp = &u.u_nd; 1375 int error; 1376 1377 if (uap->tptr) { 1378 error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 1379 if (error) 1380 return (error); 1381 } else 1382 tv[0] = tv[1] = time.tv_sec; 1383 ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 1384 ndp->ni_segflg = UIO_USERSPACE; 1385 ndp->ni_dirp = uap->fname; 1386 vattr_null(&vattr); 1387 vattr.va_atime.tv_sec = tv[0]; 1388 vattr.va_atime.tv_usec = 0; 1389 vattr.va_mtime.tv_sec = tv[1]; 1390 vattr.va_mtime.tv_usec = 0; 1391 if (error = namei(ndp)) 1392 return (error); 1393 vp = ndp->ni_vp; 1394 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1395 error = EROFS; 1396 else 1397 error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 1398 vput(vp); 1399 return (error); 1400 } 1401 1402 ohpuxpause(p, uap, retval) 1403 struct proc *p; 1404 int *uap, *retval; 1405 { 1406 (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 1407 /* always return EINTR rather than ERESTART... */ 1408 return (EINTR); 1409 } 1410 1411 /* 1412 * The old fstat system call. 1413 */ 1414 ohpuxfstat(p, uap, retval) 1415 struct proc *p; 1416 register struct args { 1417 int fd; 1418 struct ohpuxstat *sb; 1419 } *uap; 1420 int *retval; 1421 { 1422 struct file *fp; 1423 1424 if ((unsigned)uap->fd >= NOFILE || (fp = u.u_ofile[uap->fd]) == NULL) 1425 return (EBADF); 1426 if (fp->f_type != DTYPE_VNODE) 1427 return (EINVAL); 1428 return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 1429 } 1430 1431 /* 1432 * Old stat system call. This version follows links. 1433 */ 1434 ohpuxstat(p, uap, retval) 1435 struct proc *p; 1436 register struct args { 1437 char *fname; 1438 struct ohpuxstat *sb; 1439 } *uap; 1440 int *retval; 1441 { 1442 register struct nameidata *ndp = &u.u_nd; 1443 int error; 1444 1445 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 1446 ndp->ni_segflg = UIO_USERSPACE; 1447 ndp->ni_dirp = uap->fname; 1448 if (error = namei(ndp)) 1449 return (error); 1450 error = ohpuxstat1(ndp->ni_vp, uap->sb); 1451 vput(ndp->ni_vp); 1452 return (error); 1453 } 1454 1455 int 1456 ohpuxstat1(vp, ub) 1457 register struct vnode *vp; 1458 struct ohpuxstat *ub; 1459 { 1460 struct ohpuxstat ds; 1461 struct vattr vattr; 1462 register int error; 1463 1464 error = VOP_GETATTR(vp, &vattr, u.u_cred); 1465 if (error) 1466 return(error); 1467 /* 1468 * Copy from inode table 1469 */ 1470 ds.ohst_dev = vattr.va_fsid; 1471 ds.ohst_ino = (short)vattr.va_fileid; 1472 ds.ohst_mode = (u_short)vattr.va_mode; 1473 ds.ohst_nlink = vattr.va_nlink; 1474 ds.ohst_uid = (short)vattr.va_uid; 1475 ds.ohst_gid = (short)vattr.va_gid; 1476 ds.ohst_rdev = (dev_t)vattr.va_rdev; 1477 ds.ohst_size = (int)vattr.va_size; 1478 ds.ohst_atime = (int)vattr.va_atime.tv_sec; 1479 ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 1480 ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 1481 return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 1482 } 1483 /* #endif */ 1484 1485 #endif 1486