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