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