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