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