141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 341486Smckusick * Copyright (c) 1990 The Regents of the University of California. 441486Smckusick * All rights reserved. 541486Smckusick * 641486Smckusick * This code is derived from software contributed to Berkeley by 741486Smckusick * the Systems Programming Group of the University of Utah Computer 841486Smckusick * Science Department. 941486Smckusick * 1041486Smckusick * %sccs.include.redist.c% 1141486Smckusick * 1254857Shibler * from: Utah $Hdr: hpux_compat.c 1.43 92/04/23$ 1341486Smckusick * 14*54917Storek * @(#)hpux_compat.c 7.27 (Berkeley) 07/10/92 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1854857Shibler * Various HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2349134Skarels #include "param.h" 2449134Skarels #include "systm.h" 2549134Skarels #include "signalvar.h" 2649134Skarels #include "kernel.h" 2749134Skarels #include "filedesc.h" 2849134Skarels #include "proc.h" 2949134Skarels #include "buf.h" 3049134Skarels #include "wait.h" 3149134Skarels #include "file.h" 3249134Skarels #include "namei.h" 3349134Skarels #include "vnode.h" 3449134Skarels #include "ioctl.h" 3549134Skarels #include "ptrace.h" 3649134Skarels #include "stat.h" 3749134Skarels #include "syslog.h" 3849134Skarels #include "malloc.h" 3949134Skarels #include "mount.h" 4049134Skarels #include "ipc.h" 4149134Skarels #include "user.h" 4241486Smckusick 4348478Skarels #include "machine/cpu.h" 4448478Skarels #include "machine/reg.h" 4548478Skarels #include "machine/psl.h" 4648478Skarels #include "machine/vmparam.h" 4741486Smckusick #include "hpux.h" 4841486Smckusick #include "hpux_termio.h" 4941486Smckusick 5041486Smckusick #ifdef DEBUG 5141486Smckusick int unimpresponse = 0; 5241486Smckusick #endif 5341486Smckusick 5441486Smckusick /* SYS5 style UTSNAME info */ 5541486Smckusick struct hpuxutsname protoutsname = { 5641486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5741486Smckusick }; 5841486Smckusick 5941486Smckusick /* 6.0 and later style context */ 6053922Shibler #if defined(HP380) 6153922Shibler char hpux040context[] = 6253922Shibler "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6353922Shibler #endif 6441486Smckusick #ifdef FPCOPROC 6541486Smckusick char hpuxcontext[] = 6641486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6741486Smckusick #else 6841486Smckusick char hpuxcontext[] = 6941486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 7041486Smckusick #endif 7141486Smckusick 7241486Smckusick /* YP domainname */ 7341486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7441486Smckusick int domainnamelen = 7; 7541486Smckusick 7641486Smckusick #define NERR 79 7741486Smckusick #define BERR 1000 7841486Smckusick 7941486Smckusick /* indexed by BSD errno */ 8041486Smckusick short bsdtohpuxerrnomap[NERR] = { 8141486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8241486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8341486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8441486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8541486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8641486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8741486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8841486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 8941486Smckusick }; 9041486Smckusick 9143452Shibler notimp(p, uap, retval, code, nargs) 9243452Shibler struct proc *p; 9343452Shibler int *uap, *retval; 9443452Shibler int code, nargs; 9541486Smckusick { 9643452Shibler int error = 0; 9741486Smckusick #ifdef DEBUG 9843452Shibler register int *argp = uap; 9941486Smckusick extern char *hpuxsyscallnames[]; 10041486Smckusick 10154857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10241486Smckusick if (nargs) 10341486Smckusick while (nargs--) 10441486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10541486Smckusick else 10641486Smckusick printf(")"); 10741486Smckusick printf("\n"); 10841486Smckusick switch (unimpresponse) { 10941486Smckusick case 0: 11043452Shibler error = nosys(p, uap, retval); 11141486Smckusick break; 11241486Smckusick case 1: 11343452Shibler error = EINVAL; 11441486Smckusick break; 11541486Smckusick } 11641486Smckusick #else 11743452Shibler error = nosys(p, uap, retval); 11841486Smckusick #endif 11943452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12044421Skarels return (error); 12141486Smckusick } 12241486Smckusick 123*54917Storek struct hpuxexecv_args { 124*54917Storek char *fname; 125*54917Storek char **argp; 126*54917Storek char **envp; 127*54917Storek }; 12848478Skarels hpuxexecv(p, uap, retval) 12948478Skarels struct proc *p; 130*54917Storek struct hpuxexecv_args *uap; 13148478Skarels int *retval; 13248478Skarels { 13348478Skarels extern int execve(); 13448478Skarels 13548478Skarels uap->envp = NULL; 13648478Skarels return (execve(p, uap, retval)); 13748478Skarels } 13848478Skarels 13941486Smckusick /* 14054857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 14141486Smckusick * (status pointer, options, rusage) into the kernel rather than 14242352Smckusick * handling it in the C library stub. We also need to map any 14354857Shibler * termination signal from BSD to HP-UX. 14441486Smckusick */ 145*54917Storek struct hpuxwait3_args { 146*54917Storek int *status; 147*54917Storek int options; 148*54917Storek int rusage; 149*54917Storek }; 15043452Shibler hpuxwait3(p, uap, retval) 15143452Shibler struct proc *p; 152*54917Storek struct hpuxwait3_args *uap; 15343452Shibler int *retval; 15443452Shibler { 15541486Smckusick /* rusage pointer must be zero */ 15643452Shibler if (uap->rusage) 15744421Skarels return (EINVAL); 15852381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 15952381Smckusick p->p_md.md_regs[R0] = uap->options; 16052381Smckusick p->p_md.md_regs[R1] = uap->rusage; 16144421Skarels return (hpuxwait(p, uap, retval)); 16241486Smckusick } 16341486Smckusick 164*54917Storek struct hpuxwait_args { 165*54917Storek int *status; 166*54917Storek }; 16743452Shibler hpuxwait(p, uap, retval) 16843452Shibler struct proc *p; 169*54917Storek struct hpuxwait_args *uap; 17043452Shibler int *retval; 17141486Smckusick { 17243452Shibler int sig, *statp, error; 17341486Smckusick 17441486Smckusick statp = uap->status; /* owait clobbers first arg */ 17543452Shibler error = owait(p, uap, retval); 17641486Smckusick /* 17741486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 17841486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 17941486Smckusick */ 18043452Shibler if (error == ERESTART) 18143452Shibler error = EINTR; 18243452Shibler if (error) 18344421Skarels return (error); 18443452Shibler sig = retval[1] & 0xFF; 18541486Smckusick if (sig == WSTOPPED) { 18643452Shibler sig = (retval[1] >> 8) & 0xFF; 18743452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 18841486Smckusick } else if (sig) 18943452Shibler retval[1] = (retval[1] & 0xFF00) | 19041486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 19141486Smckusick if (statp) 19243452Shibler if (suword((caddr_t)statp, retval[1])) 19343452Shibler error = EFAULT; 19444421Skarels return (error); 19541486Smckusick } 19641486Smckusick 197*54917Storek struct hpuxwaitpid_args { 198*54917Storek int pid; 199*54917Storek int *status; 200*54917Storek int options; 201*54917Storek struct rusage *rusage; /* wait4 arg */ 202*54917Storek }; 20343452Shibler hpuxwaitpid(p, uap, retval) 20443452Shibler struct proc *p; 205*54917Storek struct hpuxwaitpid_args *uap; 20643452Shibler int *retval; 20743452Shibler { 20843452Shibler int sig, *statp, error; 20942352Smckusick 21042352Smckusick uap->rusage = 0; 21143452Shibler error = wait4(p, uap, retval); 21242352Smckusick /* 21342352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21442352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21542352Smckusick */ 21643452Shibler if (error == ERESTART) 21743452Shibler error = EINTR; 21843452Shibler if (error) 21944421Skarels return (error); 22043452Shibler sig = retval[1] & 0xFF; 22142352Smckusick if (sig == WSTOPPED) { 22243452Shibler sig = (retval[1] >> 8) & 0xFF; 22343452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 22442352Smckusick } else if (sig) 22543452Shibler retval[1] = (retval[1] & 0xFF00) | 22642352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 22742352Smckusick if (statp) 22843452Shibler if (suword((caddr_t)statp, retval[1])) 22943452Shibler error = EFAULT; 23044421Skarels return (error); 23142352Smckusick } 23242352Smckusick 23341486Smckusick /* 23441486Smckusick * Must remap some bits in the mode mask. 23541486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 23641486Smckusick * O_SYNCIO (0100000) is removed entirely. 23741486Smckusick */ 238*54917Storek struct hpuxopen_args { 239*54917Storek char *fname; 240*54917Storek int mode; 241*54917Storek int crtmode; 242*54917Storek }; 24343067Skarels hpuxopen(p, uap, retval) 24443067Skarels struct proc *p; 245*54917Storek register struct hpuxopen_args *uap; 24643067Skarels int *retval; 24743067Skarels { 24841486Smckusick int mode; 24941486Smckusick 25041486Smckusick mode = uap->mode; 25141486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 25241486Smckusick if (mode & HPUXFCREAT) { 25341486Smckusick /* 25441486Smckusick * simulate the pre-NFS behavior that opening a 25541486Smckusick * file for READ+CREATE ignores the CREATE (unless 25641486Smckusick * EXCL is set in which case we will return the 25741486Smckusick * proper error). 25841486Smckusick */ 25948478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 26049950Smckusick uap->mode |= O_CREAT; 26141486Smckusick } 26241486Smckusick if (mode & HPUXFTRUNC) 26349950Smckusick uap->mode |= O_TRUNC; 26441486Smckusick if (mode & HPUXFEXCL) 26549950Smckusick uap->mode |= O_EXCL; 26644421Skarels return (open(p, uap, retval)); 26741486Smckusick } 26841486Smckusick 26949329Shibler /* XXX */ 27049329Shibler #define UF_FNDELAY_ON 0x20 27149329Shibler #define UF_FIONBIO_ON 0x40 27249329Shibler /* XXX */ 27349329Shibler 274*54917Storek struct hpuxfcntl_args { 275*54917Storek int fdes; 276*54917Storek int cmd; 277*54917Storek int arg; 278*54917Storek }; 27943452Shibler hpuxfcntl(p, uap, retval) 28043452Shibler struct proc *p; 281*54917Storek register struct hpuxfcntl_args *uap; 28243452Shibler int *retval; 28343452Shibler { 28443452Shibler int mode, error; 28549329Shibler char *fp; 28641486Smckusick 28749329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 28849329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 28949329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 29049329Shibler return (EBADF); 29149329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 29249329Shibler } 29341486Smckusick switch (uap->cmd) { 29441486Smckusick case F_SETFL: 29549950Smckusick if (uap->arg & FNONBLOCK) 29649329Shibler *fp |= UF_FNDELAY_ON; 29749329Shibler else { 29849329Shibler *fp &= ~UF_FNDELAY_ON; 29949329Shibler if (*fp & UF_FIONBIO_ON) 30049950Smckusick uap->arg |= FNONBLOCK; 30149329Shibler } 30241486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 30341486Smckusick break; 30441486Smckusick case F_GETFL: 30541486Smckusick case F_DUPFD: 30641486Smckusick case F_GETFD: 30741486Smckusick case F_SETFD: 30841486Smckusick break; 30941486Smckusick default: 31044421Skarels return (EINVAL); 31141486Smckusick } 31243452Shibler error = fcntl(p, uap, retval); 31349329Shibler if (error == 0 && uap->cmd == F_GETFL) { 31443452Shibler mode = *retval; 31549950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 31649950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 31749950Smckusick *retval &= ~FNONBLOCK; 31849950Smckusick if (mode & O_CREAT) 31943452Shibler *retval |= HPUXFCREAT; 32049950Smckusick if (mode & O_TRUNC) 32143452Shibler *retval |= HPUXFTRUNC; 32249950Smckusick if (mode & O_EXCL) 32343452Shibler *retval |= HPUXFEXCL; 32441486Smckusick } 32544421Skarels return (error); 32641486Smckusick } 32741486Smckusick 32841486Smckusick /* 32941486Smckusick * Read and write should return a 0 count when an operation 33049329Shibler * on a VNODE would block, not an error. 33149329Shibler * 33249329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 33349950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 33441486Smckusick */ 335*54917Storek struct hpuxread_args { 336*54917Storek int fd; 337*54917Storek }; 33843452Shibler hpuxread(p, uap, retval) 33943452Shibler struct proc *p; 340*54917Storek struct hpuxread_args *uap; 34143452Shibler int *retval; 34241486Smckusick { 34343452Shibler int error; 34441486Smckusick 34543452Shibler error = read(p, uap, retval); 34643452Shibler if (error == EWOULDBLOCK && 34749329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 34849329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 34943452Shibler error = 0; 35043452Shibler *retval = 0; 35141486Smckusick } 35244421Skarels return (error); 35341486Smckusick } 35441486Smckusick 355*54917Storek struct hpuxwrite_args { 356*54917Storek int fd; 357*54917Storek }; 35843452Shibler hpuxwrite(p, uap, retval) 35943452Shibler struct proc *p; 360*54917Storek struct hpuxwrite_args *uap; 36143452Shibler int *retval; 36241486Smckusick { 36343452Shibler int error; 36441486Smckusick 36543452Shibler error = write(p, uap, retval); 36643452Shibler if (error == EWOULDBLOCK && 36749329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 36849329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 36943452Shibler error = 0; 37043452Shibler *retval = 0; 37141486Smckusick } 37244421Skarels return (error); 37341486Smckusick } 37441486Smckusick 375*54917Storek struct hpuxreadv_args { 376*54917Storek int fd; 377*54917Storek }; 37843452Shibler hpuxreadv(p, uap, retval) 37943452Shibler struct proc *p; 380*54917Storek struct hpuxreadv_args *uap; 38143452Shibler int *retval; 38241486Smckusick { 38343452Shibler int error; 38441486Smckusick 38543452Shibler error = readv(p, uap, retval); 38643452Shibler if (error == EWOULDBLOCK && 38749329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 38849329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 38943452Shibler error = 0; 39043452Shibler *retval = 0; 39141486Smckusick } 39244421Skarels return (error); 39341486Smckusick } 39441486Smckusick 395*54917Storek struct hpuxwritev_args { 396*54917Storek int fd; 397*54917Storek }; 39843452Shibler hpuxwritev(p, uap, retval) 39943452Shibler struct proc *p; 400*54917Storek struct hpuxwritev_args *uap; 40143452Shibler int *retval; 40241486Smckusick { 40343452Shibler int error; 40441486Smckusick 40543452Shibler error = writev(p, uap, retval); 40643452Shibler if (error == EWOULDBLOCK && 40749329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 40849329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 40943452Shibler error = 0; 41043452Shibler *retval = 0; 41141486Smckusick } 41244421Skarels return (error); 41341486Smckusick } 41441486Smckusick 41541486Smckusick /* 41641486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 41754857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 41841486Smckusick */ 419*54917Storek struct hpuxdup_args { 420*54917Storek int i; 421*54917Storek }; 42243452Shibler hpuxdup(p, uap, retval) 42343452Shibler struct proc *p; 424*54917Storek register struct hpuxdup_args *uap; 42543452Shibler int *retval; 42641486Smckusick { 42745923Smckusick register struct filedesc *fdp = p->p_fd; 42841486Smckusick struct file *fp; 42943452Shibler int fd, error; 43041486Smckusick 43148478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 43248478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 43344421Skarels return (EBADF); 43448478Skarels if (error = fdalloc(p, 0, &fd)) 43544421Skarels return (error); 43648478Skarels fdp->fd_ofiles[fd] = fp; 43748478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 43845923Smckusick fp->f_count++; 43945923Smckusick if (fd > fdp->fd_lastfile) 44045923Smckusick fdp->fd_lastfile = fd; 44143452Shibler *retval = fd; 44244421Skarels return (0); 44341486Smckusick } 44441486Smckusick 445*54917Storek struct hpuxutssys_args { 446*54917Storek struct hpuxutsname *uts; 447*54917Storek int dev; 448*54917Storek int request; 449*54917Storek }; 45045753Smckusick hpuxutssys(p, uap, retval) 45143452Shibler struct proc *p; 452*54917Storek register struct hpuxutssys_args *uap; 45343452Shibler int *retval; 45443452Shibler { 45541486Smckusick register int i; 45643452Shibler int error; 45741486Smckusick 45841486Smckusick switch (uap->request) { 45941486Smckusick /* uname */ 46041486Smckusick case 0: 46141486Smckusick /* fill in machine type */ 46241486Smckusick switch (machineid) { 46341486Smckusick case HP_320: 46441486Smckusick protoutsname.machine[6] = '2'; 46541486Smckusick break; 46641486Smckusick /* includes 318 and 319 */ 46741486Smckusick case HP_330: 46841486Smckusick protoutsname.machine[6] = '3'; 46941486Smckusick break; 47041486Smckusick case HP_340: 47141486Smckusick protoutsname.machine[6] = '4'; 47241486Smckusick break; 47341486Smckusick case HP_350: 47441486Smckusick protoutsname.machine[6] = '5'; 47541486Smckusick break; 47641486Smckusick case HP_360: 47741486Smckusick protoutsname.machine[6] = '6'; 47841486Smckusick break; 47941486Smckusick case HP_370: 48041486Smckusick protoutsname.machine[6] = '7'; 48141486Smckusick break; 48243452Shibler /* includes 345 */ 48343452Shibler case HP_375: 48443452Shibler protoutsname.machine[6] = '7'; 48543452Shibler protoutsname.machine[7] = '5'; 48643452Shibler break; 48754857Shibler /* includes 425 */ 48854857Shibler case HP_380: 48954857Shibler protoutsname.machine[6] = '8'; 49054857Shibler break; 49141486Smckusick } 49241486Smckusick /* copy hostname (sans domain) to nodename */ 49349329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 49441486Smckusick protoutsname.nodename[i] = hostname[i]; 49549329Shibler protoutsname.nodename[i] = '\0'; 49643452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 49743452Shibler sizeof(struct hpuxutsname)); 49841486Smckusick break; 49945753Smckusick 50045753Smckusick /* gethostname */ 50145753Smckusick case 5: 50245753Smckusick /* uap->dev is length */ 50345753Smckusick if (uap->dev > hostnamelen + 1) 50445753Smckusick uap->dev = hostnamelen + 1; 50545753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 50645753Smckusick uap->dev); 50745753Smckusick break; 50845753Smckusick 50945753Smckusick case 1: /* ?? */ 51045753Smckusick case 2: /* ustat */ 51145753Smckusick case 3: /* ?? */ 51245753Smckusick case 4: /* sethostname */ 51341486Smckusick default: 51443452Shibler error = EINVAL; 51541486Smckusick break; 51641486Smckusick } 51744421Skarels return (error); 51841486Smckusick } 51941486Smckusick 520*54917Storek struct hpuxsysconf_args { 521*54917Storek int name; 522*54917Storek }; 52353922Shibler hpuxsysconf(p, uap, retval) 52453922Shibler struct proc *p; 525*54917Storek struct hpuxsysconf_args *uap; 52653922Shibler int *retval; 52753922Shibler { 52853922Shibler switch (uap->name) { 52953922Shibler 53053922Shibler /* open files */ 53153922Shibler case HPUX_SYSCONF_OPENMAX: 53253922Shibler *retval = NOFILE; 53353922Shibler break; 53453922Shibler 53553922Shibler /* architecture */ 53653922Shibler case HPUX_SYSCONF_CPUTYPE: 53753922Shibler switch (machineid) { 53853922Shibler case HP_320: 53953922Shibler case HP_330: 54053922Shibler case HP_350: 54153922Shibler *retval = HPUX_SYSCONF_CPUM020; 54253922Shibler break; 54353922Shibler case HP_340: 54453922Shibler case HP_360: 54553922Shibler case HP_370: 54653922Shibler case HP_375: 54753922Shibler *retval = HPUX_SYSCONF_CPUM030; 54853922Shibler break; 54953922Shibler case HP_380: 55053922Shibler *retval = HPUX_SYSCONF_CPUM040; 55153922Shibler break; 55253922Shibler } 55353922Shibler break; 55453922Shibler default: 55554857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 55653922Shibler return (EINVAL); 55753922Shibler } 55853922Shibler return (0); 55953922Shibler } 56053922Shibler 561*54917Storek struct hpuxstat_args { 562*54917Storek char *fname; 563*54917Storek struct hpuxstat *hsb; 564*54917Storek }; 56543452Shibler hpuxstat(p, uap, retval) 56643452Shibler struct proc *p; 567*54917Storek struct hpuxstat_args *uap; 56843452Shibler int *retval; 56943452Shibler { 57044421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 57141486Smckusick } 57241486Smckusick 573*54917Storek struct hpuxlstat_args { 574*54917Storek char *fname; 575*54917Storek struct hpuxstat *hsb; 576*54917Storek }; 57743452Shibler hpuxlstat(p, uap, retval) 57843452Shibler struct proc *p; 579*54917Storek struct hpuxlstat_args *uap; 58043452Shibler int *retval; 58141486Smckusick { 58244421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 58341486Smckusick } 58441486Smckusick 585*54917Storek struct hpuxfstat_args { 586*54917Storek int fdes; 587*54917Storek struct hpuxstat *hsb; 588*54917Storek }; 58943452Shibler hpuxfstat(p, uap, retval) 59043452Shibler struct proc *p; 591*54917Storek register struct hpuxfstat_args *uap; 59243452Shibler int *retval; 59341486Smckusick { 59445923Smckusick register struct filedesc *fdp = p->p_fd; 59541486Smckusick register struct file *fp; 59641486Smckusick struct stat sb; 59743452Shibler int error; 59841486Smckusick 59948478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 60048478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 60144421Skarels return (EBADF); 60243452Shibler 60341486Smckusick switch (fp->f_type) { 60441486Smckusick 60541486Smckusick case DTYPE_VNODE: 60643452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 60741486Smckusick break; 60841486Smckusick 60941486Smckusick case DTYPE_SOCKET: 61043452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 61141486Smckusick break; 61241486Smckusick 61341486Smckusick default: 61441486Smckusick panic("fstat"); 61541486Smckusick /*NOTREACHED*/ 61641486Smckusick } 61741486Smckusick /* is this right for sockets?? */ 61843452Shibler if (error == 0) 61943452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 62044421Skarels return (error); 62141486Smckusick } 62241486Smckusick 623*54917Storek struct hpuxulimit_args { 624*54917Storek int cmd; 625*54917Storek long newlimit; 626*54917Storek }; 62743452Shibler hpuxulimit(p, uap, retval) 62843452Shibler struct proc *p; 629*54917Storek register struct hpuxulimit_args *uap; 63053481Smckusick long *retval; 63143452Shibler { 63241486Smckusick struct rlimit *limp; 63343452Shibler int error = 0; 63441486Smckusick 63548478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 63641486Smckusick switch (uap->cmd) { 63741486Smckusick case 2: 63841486Smckusick uap->newlimit *= 512; 63941486Smckusick if (uap->newlimit > limp->rlim_max && 64048478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 64141486Smckusick break; 64241486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 64341486Smckusick /* else fall into... */ 64441486Smckusick 64541486Smckusick case 1: 64645753Smckusick *retval = limp->rlim_max / 512; 64741486Smckusick break; 64841486Smckusick 64941486Smckusick case 3: 65048478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 65148478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 65241486Smckusick break; 65341486Smckusick 65441486Smckusick default: 65543452Shibler error = EINVAL; 65641486Smckusick break; 65741486Smckusick } 65844421Skarels return (error); 65941486Smckusick } 66041486Smckusick 66141486Smckusick /* 66241486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 66341486Smckusick * values -16 (high) thru -1 (low). 66441486Smckusick */ 665*54917Storek struct hpuxrtprio_args { 666*54917Storek int pid; 667*54917Storek int prio; 668*54917Storek }; 66943452Shibler hpuxrtprio(cp, uap, retval) 67043452Shibler struct proc *cp; 671*54917Storek register struct hpuxrtprio_args *uap; 67243452Shibler int *retval; 67343452Shibler { 67441486Smckusick struct proc *p; 67543452Shibler int nice, error; 67641486Smckusick 67741486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 67843452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 67944421Skarels return (EINVAL); 68041486Smckusick if (uap->pid == 0) 68143452Shibler p = cp; 68243452Shibler else if ((p = pfind(uap->pid)) == 0) 68344421Skarels return (ESRCH); 68441486Smckusick nice = p->p_nice; 68541486Smckusick if (nice < NZERO) 68643452Shibler *retval = (nice + 16) << 3; 68741486Smckusick else 68843452Shibler *retval = RTPRIO_RTOFF; 68941486Smckusick switch (uap->prio) { 69041486Smckusick 69141486Smckusick case RTPRIO_NOCHG: 69244421Skarels return (0); 69341486Smckusick 69441486Smckusick case RTPRIO_RTOFF: 69541486Smckusick if (nice >= NZERO) 69644421Skarels return (0); 69741486Smckusick nice = NZERO; 69841486Smckusick break; 69941486Smckusick 70041486Smckusick default: 70141486Smckusick nice = (uap->prio >> 3) - 16; 70241486Smckusick break; 70341486Smckusick } 70443452Shibler error = donice(cp, p, nice); 70543452Shibler if (error == EACCES) 70643452Shibler error = EPERM; 70744421Skarels return (error); 70841486Smckusick } 70941486Smckusick 710*54917Storek struct hpuxadvise_args { 711*54917Storek int arg; 712*54917Storek }; 71343452Shibler hpuxadvise(p, uap, retval) 71443452Shibler struct proc *p; 715*54917Storek struct hpuxadvise_args *uap; 71643452Shibler int *retval; 71741486Smckusick { 71843452Shibler int error = 0; 71941486Smckusick 72041486Smckusick switch (uap->arg) { 72141486Smckusick case 0: 72249134Skarels p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; 72341486Smckusick break; 72441486Smckusick case 1: 72541486Smckusick ICIA(); 72641486Smckusick break; 72741486Smckusick case 2: 72841486Smckusick DCIA(); 72941486Smckusick break; 73041486Smckusick default: 73143452Shibler error = EINVAL; 73241486Smckusick break; 73341486Smckusick } 73444421Skarels return (error); 73541486Smckusick } 73641486Smckusick 737*54917Storek struct hpuxptrace_args { 738*54917Storek int req; 739*54917Storek int pid; 740*54917Storek int *addr; 741*54917Storek int data; 742*54917Storek }; 74343452Shibler hpuxptrace(p, uap, retval) 74443452Shibler struct proc *p; 745*54917Storek struct hpuxptrace_args *uap; 74643452Shibler int *retval; 74743452Shibler { 74843452Shibler int error; 74941486Smckusick 75041486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 75141486Smckusick if (uap->data) { 75241486Smckusick uap->data = hpuxtobsdsig(uap->data); 75341486Smckusick if (uap->data == 0) 75441486Smckusick uap->data = NSIG; 75541486Smckusick } 75641486Smckusick } 75743452Shibler error = ptrace(p, uap, retval); 75844421Skarels return (error); 75941486Smckusick } 76041486Smckusick 761*54917Storek struct hpuxgetdomainname_args { 762*54917Storek char *domainname; 763*54917Storek u_int len; 764*54917Storek }; 76543452Shibler hpuxgetdomainname(p, uap, retval) 76643452Shibler struct proc *p; 767*54917Storek register struct hpuxgetdomainname_args *uap; 76843452Shibler int *retval; 76943452Shibler { 77041486Smckusick if (uap->len > domainnamelen + 1) 77141486Smckusick uap->len = domainnamelen + 1; 77244421Skarels return (copyout(domainname, uap->domainname, uap->len)); 77341486Smckusick } 77441486Smckusick 775*54917Storek struct hpuxsetdomainname_args { 776*54917Storek char *domainname; 777*54917Storek u_int len; 778*54917Storek }; 77943452Shibler hpuxsetdomainname(p, uap, retval) 78043452Shibler struct proc *p; 781*54917Storek register struct hpuxsetdomainname_args *uap; 78243452Shibler int *retval; 78343452Shibler { 78443452Shibler int error; 78541486Smckusick 78648478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 78744421Skarels return (error); 78843452Shibler if (uap->len > sizeof (domainname) - 1) 78944421Skarels return (EINVAL); 79041486Smckusick domainnamelen = uap->len; 79143452Shibler error = copyin(uap->domainname, domainname, uap->len); 79241486Smckusick domainname[domainnamelen] = 0; 79344421Skarels return (error); 79441486Smckusick } 79541486Smckusick 79641486Smckusick #ifdef SYSVSHM 79754857Shibler #include "shm.h" 79854857Shibler 79943452Shibler hpuxshmat(p, uap, retval) 80043452Shibler struct proc *p; 80143452Shibler int *uap, *retval; 80241486Smckusick { 80344421Skarels return (shmat(p, uap, retval)); 80441486Smckusick } 80541486Smckusick 80643452Shibler hpuxshmdt(p, uap, retval) 80743452Shibler struct proc *p; 80843452Shibler int *uap, *retval; 80941486Smckusick { 81044421Skarels return (shmdt(p, uap, retval)); 81141486Smckusick } 81241486Smckusick 81343452Shibler hpuxshmget(p, uap, retval) 81443452Shibler struct proc *p; 81543452Shibler int *uap, *retval; 81641486Smckusick { 81744421Skarels return (shmget(p, uap, retval)); 81841486Smckusick } 81954857Shibler 82054857Shibler /* 82154857Shibler * Handle HP-UX specific commands. 82254857Shibler */ 823*54917Storek struct hpuxshmctl_args { 824*54917Storek int shmid; 825*54917Storek int cmd; 826*54917Storek caddr_t buf; 827*54917Storek }; 82854857Shibler hpuxshmctl(p, uap, retval) 82954857Shibler struct proc *p; 830*54917Storek struct hpuxshmctl_args *uap; 83154857Shibler int *retval; 83254857Shibler { 83354857Shibler register struct shmid_ds *shp; 83454857Shibler register struct ucred *cred = p->p_ucred; 83554857Shibler int error; 83654857Shibler 83754857Shibler if (error = shmvalid(uap->shmid)) 83854857Shibler return (error); 83954857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 84054857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 84154857Shibler /* don't really do anything, but make them think we did */ 84254857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 84354857Shibler cred->cr_uid != shp->shm_perm.cuid) 84454857Shibler return (EPERM); 84554857Shibler return (0); 84654857Shibler } 84754857Shibler return (shmctl(p, uap, retval)); 84854857Shibler } 84941486Smckusick #endif 85041486Smckusick 85141486Smckusick /* 85241486Smckusick * Fake semaphore routines, just don't return an error. 85341486Smckusick * Should be adequate for starbase to run. 85441486Smckusick */ 855*54917Storek struct hpuxsemctl_args { 856*54917Storek int semid; 857*54917Storek u_int semnum; 858*54917Storek int cmd; 859*54917Storek int arg; 860*54917Storek }; 86143452Shibler hpuxsemctl(p, uap, retval) 86243452Shibler struct proc *p; 863*54917Storek struct hpuxsemctl_args *uap; 86443452Shibler int *retval; 86543452Shibler { 86641486Smckusick /* XXX: should do something here */ 86744421Skarels return (0); 86841486Smckusick } 86941486Smckusick 870*54917Storek struct hpuxsemget_args { 871*54917Storek key_t key; 872*54917Storek int nsems; 873*54917Storek int semflg; 874*54917Storek }; 87543452Shibler hpuxsemget(p, uap, retval) 87643452Shibler struct proc *p; 877*54917Storek struct hpuxsemget_args *uap; 87843452Shibler int *retval; 87943452Shibler { 88041486Smckusick /* XXX: should do something here */ 88144421Skarels return (0); 88241486Smckusick } 88341486Smckusick 884*54917Storek struct hpuxsemop_args { 885*54917Storek int semid; 886*54917Storek struct sembuf *sops; 887*54917Storek u_int nsops; 888*54917Storek }; 88943452Shibler hpuxsemop(p, uap, retval) 89043452Shibler struct proc *p; 891*54917Storek struct hpuxsemop_args *uap; 89243452Shibler int *retval; 89343452Shibler { 89441486Smckusick /* XXX: should do something here */ 89544421Skarels return (0); 89641486Smckusick } 89741486Smckusick 89854857Shibler /* convert from BSD to HP-UX errno */ 89941486Smckusick bsdtohpuxerrno(err) 90041486Smckusick int err; 90141486Smckusick { 90241486Smckusick if (err < 0 || err >= NERR) 90341486Smckusick return(BERR); 90441486Smckusick return((int)bsdtohpuxerrnomap[err]); 90541486Smckusick } 90641486Smckusick 90741486Smckusick hpuxstat1(fname, hsb, follow) 90841486Smckusick char *fname; 90941486Smckusick struct hpuxstat *hsb; 91041486Smckusick int follow; 91141486Smckusick { 91248478Skarels int error; 91341486Smckusick struct stat sb; 91448478Skarels struct nameidata nd; 91541486Smckusick 91652330Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, curproc); 91752330Smckusick if (error = namei(&nd)) 91841486Smckusick return (error); 91952330Smckusick error = vn_stat(nd.ni_vp, &sb); 92052330Smckusick vput(nd.ni_vp); 92141486Smckusick if (error == 0) 92241486Smckusick error = bsdtohpuxstat(&sb, hsb); 92341486Smckusick return (error); 92441486Smckusick } 92541486Smckusick 92641486Smckusick #include "grf.h" 92753922Shibler #if NGRF > 0 92853922Shibler #ifdef __STDC__ 92953922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 93053922Shibler #else 93153922Shibler extern int grfopen(); 93253922Shibler #endif 93353922Shibler #endif 93441486Smckusick 93553922Shibler #define NHIL 1 /* XXX */ 93653922Shibler #if NHIL > 0 93753922Shibler #ifdef __STDC__ 93853922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 93953922Shibler #else 94053922Shibler extern int hilopen(); 94153922Shibler #endif 94253922Shibler #endif 94353922Shibler 94453922Shibler #include "conf.h" 94553922Shibler 94641486Smckusick bsdtohpuxstat(sb, hsb) 94741486Smckusick struct stat *sb; 94841486Smckusick struct hpuxstat *hsb; 94941486Smckusick { 95041486Smckusick struct hpuxstat ds; 95141486Smckusick 95241486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 95353481Smckusick ds.hst_dev = (u_short)sb->st_dev; 95441486Smckusick ds.hst_ino = (u_long)sb->st_ino; 95541486Smckusick ds.hst_mode = sb->st_mode; 95641486Smckusick ds.hst_nlink = sb->st_nlink; 95741486Smckusick ds.hst_uid = (u_short)sb->st_uid; 95841486Smckusick ds.hst_gid = (u_short)sb->st_gid; 95953922Shibler /* XXX: I don't want to talk about it... */ 96053922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 96141486Smckusick #if NGRF > 0 96253922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 96353922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 96441486Smckusick #endif 96553922Shibler #if NHIL > 0 96653922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 96753922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 96853922Shibler #endif 96953922Shibler ; 97053922Shibler } else 97141486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 97253481Smckusick if (sb->st_size < (quad_t)1 << 32) 97353481Smckusick ds.hst_size = (long)sb->st_size; 97453481Smckusick else 97553481Smckusick ds.hst_size = -2; 97641486Smckusick ds.hst_atime = sb->st_atime; 97741486Smckusick ds.hst_mtime = sb->st_mtime; 97841486Smckusick ds.hst_ctime = sb->st_ctime; 97941486Smckusick ds.hst_blksize = sb->st_blksize; 98041486Smckusick ds.hst_blocks = sb->st_blocks; 98141486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 98241486Smckusick } 98341486Smckusick 98441486Smckusick hpuxtobsdioctl(com) 98541486Smckusick int com; 98641486Smckusick { 98741486Smckusick switch (com) { 98841486Smckusick case HPUXTIOCSLTC: 98941486Smckusick com = TIOCSLTC; break; 99041486Smckusick case HPUXTIOCGLTC: 99141486Smckusick com = TIOCGLTC; break; 99241486Smckusick case HPUXTIOCSPGRP: 99341486Smckusick com = TIOCSPGRP; break; 99441486Smckusick case HPUXTIOCGPGRP: 99541486Smckusick com = TIOCGPGRP; break; 99641486Smckusick case HPUXTIOCLBIS: 99741486Smckusick com = TIOCLBIS; break; 99841486Smckusick case HPUXTIOCLBIC: 99941486Smckusick com = TIOCLBIC; break; 100041486Smckusick case HPUXTIOCLSET: 100141486Smckusick com = TIOCLSET; break; 100241486Smckusick case HPUXTIOCLGET: 100341486Smckusick com = TIOCLGET; break; 100441486Smckusick } 100541486Smckusick return(com); 100641486Smckusick } 100741486Smckusick 100841486Smckusick /* 100954857Shibler * HP-UX ioctl system call. The differences here are: 101041486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 101149329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 101241486Smckusick * the sgttyb struct is 2 bytes longer 101341486Smckusick */ 1014*54917Storek struct hpuxioctl_args { 1015*54917Storek int fdes; 1016*54917Storek int cmd; 1017*54917Storek caddr_t cmarg; 1018*54917Storek }; 101943452Shibler hpuxioctl(p, uap, retval) 102043452Shibler struct proc *p; 1021*54917Storek register struct hpuxioctl_args *uap; 102243452Shibler int *retval; 102343452Shibler { 102445923Smckusick register struct filedesc *fdp = p->p_fd; 102543452Shibler register struct file *fp; 102643452Shibler register int com, error; 102741486Smckusick register u_int size; 102841486Smckusick caddr_t memp = 0; 102941486Smckusick #define STK_PARAMS 128 103041486Smckusick char stkbuf[STK_PARAMS]; 103141486Smckusick caddr_t data = stkbuf; 103241486Smckusick 103341486Smckusick com = uap->cmd; 103441486Smckusick 103541486Smckusick /* XXX */ 103643452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 103745923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 103841486Smckusick 103948478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 104048478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 104144421Skarels return (EBADF); 104243452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 104344421Skarels return (EBADF); 104441486Smckusick 104541486Smckusick /* 104641486Smckusick * Interpret high order word to find 104741486Smckusick * amount of data to be copied to/from the 104841486Smckusick * user's address space. 104941486Smckusick */ 105041486Smckusick size = IOCPARM_LEN(com); 105143452Shibler if (size > IOCPARM_MAX) 105244421Skarels return (ENOTTY); 105341486Smckusick if (size > sizeof (stkbuf)) { 105443452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 105541486Smckusick data = memp; 105641486Smckusick } 105741486Smckusick if (com&IOC_IN) { 105841486Smckusick if (size) { 105943452Shibler error = copyin(uap->cmarg, data, (u_int)size); 106043452Shibler if (error) { 106141486Smckusick if (memp) 106241486Smckusick free(memp, M_IOCTLOPS); 106344421Skarels return (error); 106441486Smckusick } 106541486Smckusick } else 106641486Smckusick *(caddr_t *)data = uap->cmarg; 106741486Smckusick } else if ((com&IOC_OUT) && size) 106841486Smckusick /* 106943452Shibler * Zero the buffer so the user always 107043452Shibler * gets back something deterministic. 107141486Smckusick */ 107241486Smckusick bzero(data, size); 107341486Smckusick else if (com&IOC_VOID) 107441486Smckusick *(caddr_t *)data = uap->cmarg; 107541486Smckusick 107641486Smckusick switch (com) { 107741486Smckusick 107849329Shibler case HPUXFIOSNBIO: 107949329Shibler { 108049329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 108149329Shibler int tmp; 108249329Shibler 108349329Shibler if (*(int *)data) 108449329Shibler *ofp |= UF_FIONBIO_ON; 108549329Shibler else 108649329Shibler *ofp &= ~UF_FIONBIO_ON; 108749329Shibler /* 108849950Smckusick * Only set/clear if FNONBLOCK not in effect 108949329Shibler */ 109049329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 109149950Smckusick tmp = fp->f_flag & FNONBLOCK; 109249329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 109349329Shibler (caddr_t)&tmp, p); 109449329Shibler } 109549329Shibler break; 109649329Shibler } 109749329Shibler 109841486Smckusick case HPUXTIOCCONS: 109941486Smckusick *(int *)data = 1; 110048478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 110141486Smckusick break; 110241486Smckusick 110341486Smckusick /* BSD-style job control ioctls */ 110441486Smckusick case HPUXTIOCLBIS: 110541486Smckusick case HPUXTIOCLBIC: 110641486Smckusick case HPUXTIOCLSET: 110741486Smckusick *(int *)data &= HPUXLTOSTOP; 110841486Smckusick if (*(int *)data & HPUXLTOSTOP) 110941486Smckusick *(int *)data = LTOSTOP; 111041486Smckusick /* fall into */ 111141486Smckusick case HPUXTIOCLGET: 111241486Smckusick case HPUXTIOCSLTC: 111341486Smckusick case HPUXTIOCGLTC: 111441486Smckusick case HPUXTIOCSPGRP: 111541486Smckusick case HPUXTIOCGPGRP: 111648478Skarels error = (*fp->f_ops->fo_ioctl) 111748478Skarels (fp, hpuxtobsdioctl(com), data, p); 111843452Shibler if (error == 0 && com == HPUXTIOCLGET) { 111941486Smckusick *(int *)data &= LTOSTOP; 112041486Smckusick if (*(int *)data & LTOSTOP) 112141486Smckusick *(int *)data = HPUXLTOSTOP; 112241486Smckusick } 112341486Smckusick break; 112441486Smckusick 112541486Smckusick /* SYS 5 termio */ 112641486Smckusick case HPUXTCGETA: 112741486Smckusick case HPUXTCSETA: 112841486Smckusick case HPUXTCSETAW: 112941486Smckusick case HPUXTCSETAF: 113048478Skarels error = hpuxtermio(fp, com, data, p); 113141486Smckusick break; 113241486Smckusick 113341486Smckusick default: 113448478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 113541486Smckusick break; 113641486Smckusick } 113741486Smckusick /* 113841486Smckusick * Copy any data to user, size was 113941486Smckusick * already set and checked above. 114041486Smckusick */ 114143452Shibler if (error == 0 && (com&IOC_OUT) && size) 114243452Shibler error = copyout(data, uap->cmarg, (u_int)size); 114341486Smckusick if (memp) 114441486Smckusick free(memp, M_IOCTLOPS); 114544421Skarels return (error); 114641486Smckusick } 114741486Smckusick 114841486Smckusick /* 114941486Smckusick * Man page lies, behaviour here is based on observed behaviour. 115041486Smckusick */ 1151*54917Storek struct hpuxgetcontext_args { 1152*54917Storek char *buf; 1153*54917Storek int len; 1154*54917Storek }; 115543452Shibler hpuxgetcontext(p, uap, retval) 115643452Shibler struct proc *p; 1157*54917Storek struct hpuxgetcontext_args *uap; 115843452Shibler int *retval; 115943452Shibler { 116041486Smckusick int error = 0; 116141486Smckusick register int len; 116241486Smckusick 116353922Shibler #if defined(HP380) 116453922Shibler if (machineid == HP_380) { 116553922Shibler len = MIN(uap->len, sizeof(hpux040context)); 116653922Shibler if (len) 116753922Shibler error = copyout(hpux040context, uap->buf, len); 116853922Shibler if (error == 0) 116953922Shibler *retval = sizeof(hpux040context); 117053922Shibler return (error); 117153922Shibler } 117253922Shibler #endif 117341486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 117441486Smckusick if (len) 117541486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 117643452Shibler if (error == 0) 117743452Shibler *retval = sizeof(hpuxcontext); 117844421Skarels return (error); 117941486Smckusick } 118041486Smckusick 118141486Smckusick /* 118241486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 118341486Smckusick * Note we do not check the real uid or "saved" uid. 118441486Smckusick */ 1185*54917Storek struct hpuxgetpgrp2_args { 1186*54917Storek int pid; 1187*54917Storek }; 118843452Shibler hpuxgetpgrp2(cp, uap, retval) 118943452Shibler struct proc *cp; 1190*54917Storek register struct hpuxgetpgrp2_args *uap; 119143452Shibler int *retval; 119241486Smckusick { 119341486Smckusick register struct proc *p; 119441486Smckusick 119541486Smckusick if (uap->pid == 0) 119643452Shibler uap->pid = cp->p_pid; 119741486Smckusick p = pfind(uap->pid); 119843452Shibler if (p == 0) 119944421Skarels return (ESRCH); 120048478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 120148478Skarels !inferior(p)) 120244421Skarels return (EPERM); 120343452Shibler *retval = p->p_pgid; 120444421Skarels return (0); 120541486Smckusick } 120641486Smckusick 120741486Smckusick /* 120841486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 120941486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 121041486Smckusick */ 1211*54917Storek struct hpuxsetpgrp2_args { 1212*54917Storek int pid; 1213*54917Storek int pgrp; 1214*54917Storek }; 121543452Shibler hpuxsetpgrp2(p, uap, retval) 121643452Shibler struct proc *p; 1217*54917Storek struct hpuxsetpgrp2_args *uap; 121843452Shibler int *retval; 121943452Shibler { 122041486Smckusick /* empirically determined */ 122143452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 122244421Skarels return (EINVAL); 122348478Skarels return (setpgid(p, uap, retval)); 122441486Smckusick } 122541486Smckusick 122641486Smckusick /* 122754861Storek * XXX Same as old BSD setre[ug]id right now. Need to consider saved ids. 122845753Smckusick */ 1229*54917Storek struct hpuxsetresuid_args { 1230*54917Storek int ruid; 1231*54917Storek int euid; 1232*54917Storek int suid; 1233*54917Storek }; 123454861Storek /* ARGSUSED */ 123545753Smckusick hpuxsetresuid(p, uap, retval) 123654861Storek register struct proc *p; 1237*54917Storek struct hpuxsetresuid_args *uap; 123845753Smckusick int *retval; 123945753Smckusick { 124054861Storek register struct pcred *pc = p->p_cred; 124154861Storek register uid_t ruid, euid; 124254861Storek int error; 124354861Storek 124454861Storek if (uap->ruid == -1) 124554861Storek ruid = pc->p_ruid; 124654861Storek else 124754861Storek ruid = uap->ruid; 124854861Storek /* 124954861Storek * Allow setting real uid to previous effective, for swapping real and 125054861Storek * effective. This should be: 125154861Storek * 125254861Storek * if (ruid != pc->p_ruid && 125354861Storek * (error = suser(pc->pc_ucred, &p->p_acflag))) 125454861Storek */ 125554861Storek if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ && 125654861Storek (error = suser(pc->pc_ucred, &p->p_acflag))) 125754861Storek return (error); 125854861Storek if (uap->euid == -1) 125954861Storek euid = pc->pc_ucred->cr_uid; 126054861Storek else 126154861Storek euid = uap->euid; 126254861Storek if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && 126354861Storek euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag))) 126454861Storek return (error); 126554861Storek /* 126654861Storek * Everything's okay, do it. Copy credentials so other references do 126754861Storek * not see our changes. 126854861Storek */ 126954861Storek pc->pc_ucred = crcopy(pc->pc_ucred); 127054861Storek pc->pc_ucred->cr_uid = euid; 127154861Storek pc->p_ruid = ruid; 127254861Storek p->p_flag |= SUGID; 127354861Storek return (0); 127445753Smckusick } 127545753Smckusick 1276*54917Storek struct hpuxsetresgid_args { 1277*54917Storek int rgid; 1278*54917Storek int egid; 1279*54917Storek int sgid; 1280*54917Storek }; 128154861Storek /* ARGSUSED */ 128245753Smckusick hpuxsetresgid(p, uap, retval) 128354861Storek register struct proc *p; 1284*54917Storek struct hpuxsetresgid_args *uap; 128545753Smckusick int *retval; 128645753Smckusick { 128754861Storek register struct pcred *pc = p->p_cred; 128854861Storek register gid_t rgid, egid; 128954861Storek int error; 129054861Storek 129154861Storek if (uap->rgid == -1) 129254861Storek rgid = pc->p_rgid; 129354861Storek else 129454861Storek rgid = uap->rgid; 129554861Storek /* 129654861Storek * Allow setting real gid to previous effective, for swapping real and 129754861Storek * effective. This didn't really work correctly in 4.[23], but is 129854861Storek * preserved so old stuff doesn't fail. This should be: 129954861Storek * 130054861Storek * if (rgid != pc->p_rgid && 130154861Storek * (error = suser(pc->pc_ucred, &p->p_acflag))) 130254861Storek */ 130354861Storek if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ && 130454861Storek (error = suser(pc->pc_ucred, &p->p_acflag))) 130554861Storek return (error); 130654861Storek if (uap->egid == -1) 130754861Storek egid = pc->pc_ucred->cr_groups[0]; 130854861Storek else 130954861Storek egid = uap->egid; 131054861Storek if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && 131154861Storek egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag))) 131254861Storek return (error); 131354861Storek pc->pc_ucred = crcopy(pc->pc_ucred); 131454861Storek pc->pc_ucred->cr_groups[0] = egid; 131554861Storek pc->p_rgid = rgid; 131654861Storek p->p_flag |= SUGID; 131754861Storek return (0); 131845753Smckusick } 131945753Smckusick 132045753Smckusick /* 132145753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 132245753Smckusick */ 1323*54917Storek struct hpuxlockf_args { 1324*54917Storek int fd; 1325*54917Storek int func; 1326*54917Storek long size; 1327*54917Storek }; 132845753Smckusick hpuxlockf(p, uap, retval) 132945753Smckusick struct proc *p; 1330*54917Storek struct hpuxlockf_args *uap; 133145753Smckusick int *retval; 133245753Smckusick { 133345753Smckusick #ifdef DEBUG 133445753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 133545753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 133645753Smckusick #endif 133745753Smckusick return (0); 133845753Smckusick } 133945753Smckusick 1340*54917Storek struct hpuxgetaccess_args { 1341*54917Storek char *path; 1342*54917Storek int uid; 1343*54917Storek int ngroups; 1344*54917Storek int *gidset; 1345*54917Storek void *label; 1346*54917Storek void *privs; 1347*54917Storek }; 134845753Smckusick hpuxgetaccess(p, uap, retval) 134945753Smckusick register struct proc *p; 1350*54917Storek register struct hpuxgetaccess_args *uap; 135145753Smckusick int *retval; 135245753Smckusick { 135345753Smckusick int lgroups[NGROUPS]; 135445753Smckusick int error = 0; 135545753Smckusick register struct ucred *cred; 135645753Smckusick register struct vnode *vp; 135752330Smckusick struct nameidata nd; 135845753Smckusick 135945753Smckusick /* 136045753Smckusick * Build an appropriate credential structure 136145753Smckusick */ 136248478Skarels cred = crdup(p->p_ucred); 136345753Smckusick switch (uap->uid) { 136445753Smckusick case 65502: /* UID_EUID */ 136545753Smckusick break; 136645753Smckusick case 65503: /* UID_RUID */ 136748478Skarels cred->cr_uid = p->p_cred->p_ruid; 136845753Smckusick break; 136945753Smckusick case 65504: /* UID_SUID */ 137045753Smckusick error = EINVAL; 137145753Smckusick break; 137245753Smckusick default: 137345753Smckusick if (uap->uid > 65504) 137445753Smckusick error = EINVAL; 137545753Smckusick cred->cr_uid = uap->uid; 137645753Smckusick break; 137745753Smckusick } 137845753Smckusick switch (uap->ngroups) { 137945753Smckusick case -1: /* NGROUPS_EGID */ 138045753Smckusick cred->cr_ngroups = 1; 138145753Smckusick break; 138245753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 138345753Smckusick break; 138445753Smckusick case -2: /* NGROUPS_RGID */ 138545753Smckusick cred->cr_ngroups = 1; 138648478Skarels cred->cr_gid = p->p_cred->p_rgid; 138745753Smckusick break; 138845753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 138948478Skarels cred->cr_gid = p->p_cred->p_rgid; 139045753Smckusick break; 139145753Smckusick case -3: /* NGROUPS_SGID */ 139245753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 139345753Smckusick error = EINVAL; 139445753Smckusick break; 139545753Smckusick case -4: /* NGROUPS_SUPP */ 139645753Smckusick if (cred->cr_ngroups > 1) 139745753Smckusick cred->cr_gid = cred->cr_groups[1]; 139845753Smckusick else 139945753Smckusick error = EINVAL; 140045753Smckusick break; 140145753Smckusick default: 140245753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 140345753Smckusick error = copyin((caddr_t)uap->gidset, 140445753Smckusick (caddr_t)&lgroups[0], 140545753Smckusick uap->ngroups * sizeof(lgroups[0])); 140645753Smckusick else 140745753Smckusick error = EINVAL; 140845753Smckusick if (error == 0) { 140945753Smckusick int gid; 141045753Smckusick 141145753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 141245753Smckusick cred->cr_groups[gid] = lgroups[gid]; 141345753Smckusick cred->cr_ngroups = uap->ngroups; 141445753Smckusick } 141545753Smckusick break; 141645753Smckusick } 141745753Smckusick /* 141845753Smckusick * Lookup file using caller's effective IDs. 141945753Smckusick */ 142045753Smckusick if (error == 0) { 142152330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 142252330Smckusick uap->path, p); 142352330Smckusick error = namei(&nd); 142445753Smckusick } 142545753Smckusick if (error) { 142645753Smckusick crfree(cred); 142745753Smckusick return (error); 142845753Smckusick } 142945753Smckusick /* 143045753Smckusick * Use the constructed credentials for access checks. 143145753Smckusick */ 143252330Smckusick vp = nd.ni_vp; 143345753Smckusick *retval = 0; 143448478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 143545753Smckusick *retval |= R_OK; 143648478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 143745753Smckusick *retval |= W_OK; 143845753Smckusick /* XXX we return X_OK for root on VREG even if not */ 143948478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 144045753Smckusick *retval |= X_OK; 144145753Smckusick vput(vp); 144245753Smckusick crfree(cred); 144345753Smckusick return (error); 144445753Smckusick } 144545753Smckusick 144645753Smckusick /* 144754857Shibler * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 144841486Smckusick * No apologies offered, if you don't like it, rewrite it! 144941486Smckusick */ 145041486Smckusick 145149134Skarels extern char kstack[]; 145241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 145341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 145441486Smckusick 145541486Smckusick /* simplified FP structure */ 145641486Smckusick struct bsdfp { 145741486Smckusick int save[54]; 145841486Smckusick int reg[24]; 145941486Smckusick int ctrl[3]; 146041486Smckusick }; 146141486Smckusick 146241486Smckusick hpuxtobsduoff(off) 146341486Smckusick int *off; 146441486Smckusick { 146552381Smckusick register int *ar0 = curproc->p_md.md_regs; 146641486Smckusick struct hpuxfp *hp; 146741486Smckusick struct bsdfp *bp; 146841486Smckusick register u_int raddr; 146941486Smckusick 147048478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 147141486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 147248478Skarels return(UOFF(U_ar0)); 147341486Smckusick 147441486Smckusick #ifdef FPCOPROC 147541486Smckusick /* 68881 registers from PCB */ 147641486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 147741486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 147841486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 147941486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 148041486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 148141486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 148241486Smckusick #endif 148341486Smckusick 148441486Smckusick /* 148541486Smckusick * Everything else we recognize comes from the kernel stack, 148641486Smckusick * so we convert off to an absolute address (if not already) 148741486Smckusick * for simplicity. 148841486Smckusick */ 148941486Smckusick if (off < (int *)ctob(UPAGES)) 149049134Skarels off = (int *)((u_int)off + (u_int)kstack); 149141486Smckusick 149241486Smckusick /* 149341486Smckusick * 68020 registers. 149454857Shibler * We know that the HP-UX registers are in the same order as ours. 149541486Smckusick * The only difference is that their PS is 2 bytes instead of a 149641486Smckusick * padded 4 like ours throwing the alignment off. 149741486Smckusick */ 149848478Skarels if (off >= ar0 && off < &ar0[18]) { 149941486Smckusick /* 150041486Smckusick * PS: return low word and high word of PC as HP-UX would 150141486Smckusick * (e.g. &u.u_ar0[16.5]). 150241486Smckusick */ 150348478Skarels if (off == &ar0[PS]) 150448478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 150541486Smckusick /* 150641486Smckusick * PC: off will be &u.u_ar0[16.5] 150741486Smckusick */ 150848478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 150948478Skarels raddr = (u_int) &ar0[PC]; 151041486Smckusick /* 151141486Smckusick * D0-D7, A0-A7: easy 151241486Smckusick */ 151341486Smckusick else 151448478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 151549134Skarels return((int)(raddr - (u_int)kstack)); 151641486Smckusick } 151741486Smckusick 151841486Smckusick /* everything else */ 151941486Smckusick return(-1); 152041486Smckusick } 152141486Smckusick 152241486Smckusick /* 152354857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 152441486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 152541486Smckusick * convert the entire user struct. 152641486Smckusick */ 152741486Smckusick hpuxdumpu(vp, cred) 152841486Smckusick struct vnode *vp; 152941486Smckusick struct ucred *cred; 153041486Smckusick { 153148478Skarels struct proc *p = curproc; 153241486Smckusick int error; 153341486Smckusick struct hpuxuser *faku; 153441486Smckusick struct bsdfp *bp; 153541486Smckusick short *foop; 153641486Smckusick 153741486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 153841486Smckusick /* 153941486Smckusick * Make sure there is no mistake about this 154041486Smckusick * being a real user structure. 154141486Smckusick */ 154241486Smckusick bzero((caddr_t)faku, ctob(1)); 154341486Smckusick /* 154441486Smckusick * Fill in the process sizes. 154541486Smckusick */ 154648478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 154748478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 154848478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 154941486Smckusick /* 155041486Smckusick * Fill in the exec header for CDB. 155141486Smckusick * This was saved back in exec(). As far as I can tell CDB 155241486Smckusick * only uses this information to verify that a particular 155341486Smckusick * core file goes with a particular binary. 155441486Smckusick */ 155549134Skarels bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 155641486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 155741486Smckusick /* 155841486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 155954857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 156041486Smckusick * so we have to move it up. 156141486Smckusick */ 156252381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 156352381Smckusick foop = (short *) p->p_md.md_regs; 156441486Smckusick foop[32] = foop[33]; 156541486Smckusick foop[33] = foop[34]; 156641486Smckusick foop[34] = foop[35]; 156741486Smckusick #ifdef FPCOPROC 156841486Smckusick /* 156954857Shibler * Copy 68881 registers from our PCB format to HP-UX format 157041486Smckusick */ 157149134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 157241486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 157341486Smckusick sizeof(bp->save)); 157441486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 157541486Smckusick sizeof(bp->ctrl)); 157641486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 157741486Smckusick sizeof(bp->reg)); 157841486Smckusick #endif 157941486Smckusick /* 158041486Smckusick * Slay the dragon 158141486Smckusick */ 158241486Smckusick faku->hpuxu_dragon = -1; 158341486Smckusick /* 158441486Smckusick * Dump this artfully constructed page in place of the 158541486Smckusick * user struct page. 158641486Smckusick */ 158748478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 158848478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 158949134Skarels (int *)NULL, p); 159041486Smckusick /* 159141486Smckusick * Dump the remaining UPAGES-1 pages normally 159241486Smckusick */ 159341486Smckusick if (!error) 159449134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 159541486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 159649134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 159741486Smckusick free((caddr_t)faku, M_TEMP); 159841486Smckusick return(error); 159941486Smckusick } 160041486Smckusick 160141486Smckusick /* 160241486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 160341486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 160441486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 160541486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 160641486Smckusick */ 160745753Smckusick #define HPUX_HZ 50 160845753Smckusick 160945788Sbostic #include "sys/times.h" 161041486Smckusick 161141486Smckusick /* from old timeb.h */ 161241486Smckusick struct hpuxtimeb { 161341486Smckusick time_t time; 161441486Smckusick u_short millitm; 161541486Smckusick short timezone; 161641486Smckusick short dstflag; 161741486Smckusick }; 161841486Smckusick 161941486Smckusick /* ye ole stat structure */ 162041486Smckusick struct ohpuxstat { 162153481Smckusick u_short ohst_dev; 162241486Smckusick u_short ohst_ino; 162341486Smckusick u_short ohst_mode; 162441486Smckusick short ohst_nlink; 162541486Smckusick short ohst_uid; 162641486Smckusick short ohst_gid; 162753481Smckusick u_short ohst_rdev; 162841486Smckusick int ohst_size; 162941486Smckusick int ohst_atime; 163041486Smckusick int ohst_mtime; 163141486Smckusick int ohst_ctime; 163241486Smckusick }; 163341486Smckusick 163441486Smckusick /* 163541486Smckusick * SYS V style setpgrp() 163641486Smckusick */ 163743452Shibler ohpuxsetpgrp(p, uap, retval) 163843452Shibler register struct proc *p; 163943452Shibler int *uap, *retval; 164041486Smckusick { 164141486Smckusick if (p->p_pid != p->p_pgid) 164248478Skarels enterpgrp(p, p->p_pid, 0); 164343452Shibler *retval = p->p_pgid; 164445753Smckusick return (0); 164541486Smckusick } 164641486Smckusick 1647*54917Storek struct ohpuxtime_args { 1648*54917Storek long *tp; 1649*54917Storek }; 165043452Shibler ohpuxtime(p, uap, retval) 165143452Shibler struct proc *p; 1652*54917Storek register struct ohpuxtime_args *uap; 1653*54917Storek int *retval; 165441486Smckusick { 165545753Smckusick int error = 0; 165641486Smckusick 165741486Smckusick if (uap->tp) 165843452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 165943452Shibler sizeof (long)); 1660*54917Storek *(time_t *)retval = time.tv_sec; 166144421Skarels return (error); 166241486Smckusick } 166341486Smckusick 1664*54917Storek struct ohpuxstime_args { 1665*54917Storek int time; 1666*54917Storek }; 166743452Shibler ohpuxstime(p, uap, retval) 166843452Shibler struct proc *p; 1669*54917Storek register struct ohpuxstime_args *uap; 167043452Shibler int *retval; 167141486Smckusick { 167241486Smckusick struct timeval tv; 167343452Shibler int s, error; 167441486Smckusick 167541486Smckusick tv.tv_sec = uap->time; 167641486Smckusick tv.tv_usec = 0; 167748478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 167844421Skarels return (error); 167941486Smckusick 168041486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 168141486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 168241486Smckusick s = splhigh(); time = tv; splx(s); 168341486Smckusick resettodr(); 168444421Skarels return (0); 168541486Smckusick } 168641486Smckusick 1687*54917Storek struct ohpuxftime_args { 1688*54917Storek struct hpuxtimeb *tp; 1689*54917Storek }; 169043452Shibler ohpuxftime(p, uap, retval) 169143452Shibler struct proc *p; 1692*54917Storek register struct ohpuxftime_args *uap; 169343452Shibler int *retval; 169443452Shibler { 169541486Smckusick struct hpuxtimeb tb; 169641486Smckusick int s; 169741486Smckusick 169841486Smckusick s = splhigh(); 169941486Smckusick tb.time = time.tv_sec; 170041486Smckusick tb.millitm = time.tv_usec / 1000; 170141486Smckusick splx(s); 170241486Smckusick tb.timezone = tz.tz_minuteswest; 170341486Smckusick tb.dstflag = tz.tz_dsttime; 170444421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 170541486Smckusick } 170641486Smckusick 1707*54917Storek struct ohpuxalarm_args { 1708*54917Storek int deltat; 1709*54917Storek }; 171043452Shibler ohpuxalarm(p, uap, retval) 171143452Shibler register struct proc *p; 1712*54917Storek register struct ohpuxalarm_args *uap; 171343452Shibler int *retval; 171441486Smckusick { 171541486Smckusick int s = splhigh(); 171641486Smckusick 171741486Smckusick untimeout(realitexpire, (caddr_t)p); 171841486Smckusick timerclear(&p->p_realtimer.it_interval); 171943452Shibler *retval = 0; 172041486Smckusick if (timerisset(&p->p_realtimer.it_value) && 172141486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 172243452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 172341486Smckusick if (uap->deltat == 0) { 172441486Smckusick timerclear(&p->p_realtimer.it_value); 172541486Smckusick splx(s); 172644421Skarels return (0); 172741486Smckusick } 172841486Smckusick p->p_realtimer.it_value = time; 172941486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 173041486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 173141486Smckusick splx(s); 173244421Skarels return (0); 173341486Smckusick } 173441486Smckusick 1735*54917Storek struct ohpuxnice_args { 1736*54917Storek int niceness; 1737*54917Storek }; 173843452Shibler ohpuxnice(p, uap, retval) 173943452Shibler register struct proc *p; 1740*54917Storek register struct ohpuxnice_args *uap; 174143452Shibler int *retval; 174241486Smckusick { 174343452Shibler int error; 174441486Smckusick 174543452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 174643452Shibler if (error == 0) 174743452Shibler *retval = p->p_nice - NZERO; 174844421Skarels return (error); 174941486Smckusick } 175041486Smckusick 1751*54917Storek struct ohpuxtimes_args { 1752*54917Storek struct tms *tmsb; 1753*54917Storek }; 175443452Shibler ohpuxtimes(p, uap, retval) 175543452Shibler struct proc *p; 1756*54917Storek register struct ohpuxtimes_args *uap; 1757*54917Storek int *retval; 175841486Smckusick { 175954771Storek struct timeval ru, rs; 176041486Smckusick struct tms atms; 176143452Shibler int error; 176241486Smckusick 176354771Storek calcru(p, &ru, &rs, NULL); 176454771Storek atms.tms_utime = hpuxscale(&ru); 176554771Storek atms.tms_stime = hpuxscale(&rs); 176648478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 176748478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 176843452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 176943452Shibler if (error == 0) 1770*54917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 177144421Skarels return (error); 177241486Smckusick } 177341486Smckusick 177445753Smckusick /* 177545753Smckusick * Doesn't exactly do what the documentation says. 177645753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 177745753Smckusick * is what HP-UX returns. 177845753Smckusick */ 177945753Smckusick hpuxscale(tvp) 178041486Smckusick register struct timeval *tvp; 178141486Smckusick { 178245753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 178341486Smckusick } 178441486Smckusick 178541486Smckusick /* 178641486Smckusick * Set IUPD and IACC times on file. 178741486Smckusick * Can't set ICHG. 178841486Smckusick */ 1789*54917Storek struct ohpuxutime_args { 1790*54917Storek char *fname; 1791*54917Storek time_t *tptr; 1792*54917Storek }; 179343452Shibler ohpuxutime(p, uap, retval) 179443452Shibler struct proc *p; 1795*54917Storek register struct ohpuxutime_args *uap; 179643452Shibler int *retval; 179743452Shibler { 179848478Skarels register struct vnode *vp; 179941486Smckusick struct vattr vattr; 180041486Smckusick time_t tv[2]; 180143452Shibler int error; 180248478Skarels struct nameidata nd; 180341486Smckusick 180441486Smckusick if (uap->tptr) { 180543452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 180643452Shibler if (error) 180744421Skarels return (error); 180841486Smckusick } else 180941486Smckusick tv[0] = tv[1] = time.tv_sec; 181041486Smckusick vattr_null(&vattr); 181154107Smckusick vattr.va_atime.ts_sec = tv[0]; 181254107Smckusick vattr.va_atime.ts_nsec = 0; 181354107Smckusick vattr.va_mtime.ts_sec = tv[1]; 181454107Smckusick vattr.va_mtime.ts_nsec = 0; 181552330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 181652330Smckusick if (error = namei(&nd)) 181744421Skarels return (error); 181852330Smckusick vp = nd.ni_vp; 181942154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 182043452Shibler error = EROFS; 182141486Smckusick else 182252330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 182341486Smckusick vput(vp); 182444421Skarels return (error); 182541486Smckusick } 182641486Smckusick 182743452Shibler ohpuxpause(p, uap, retval) 182843452Shibler struct proc *p; 182943452Shibler int *uap, *retval; 183041486Smckusick { 183149134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 183242155Skarels /* always return EINTR rather than ERESTART... */ 183344421Skarels return (EINTR); 183441486Smckusick } 183541486Smckusick 183641486Smckusick /* 183741486Smckusick * The old fstat system call. 183841486Smckusick */ 1839*54917Storek struct ohpuxfstat_args { 1840*54917Storek int fd; 1841*54917Storek struct ohpuxstat *sb; 1842*54917Storek }; 184343452Shibler ohpuxfstat(p, uap, retval) 184443452Shibler struct proc *p; 1845*54917Storek register struct ohpuxfstat_args *uap; 184643452Shibler int *retval; 184743452Shibler { 184845923Smckusick register struct filedesc *fdp = p->p_fd; 184941486Smckusick struct file *fp; 185041486Smckusick 185148478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 185248478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 185344421Skarels return (EBADF); 185443452Shibler if (fp->f_type != DTYPE_VNODE) 185544421Skarels return (EINVAL); 185644421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 185741486Smckusick } 185841486Smckusick 185941486Smckusick /* 186041486Smckusick * Old stat system call. This version follows links. 186141486Smckusick */ 1862*54917Storek struct ohpuxstat_args { 1863*54917Storek char *fname; 1864*54917Storek struct ohpuxstat *sb; 1865*54917Storek }; 186643452Shibler ohpuxstat(p, uap, retval) 186743452Shibler struct proc *p; 1868*54917Storek register struct ohpuxstat_args *uap; 186943452Shibler int *retval; 187043452Shibler { 187143452Shibler int error; 187248478Skarels struct nameidata nd; 187341486Smckusick 187452330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 187552330Smckusick if (error = namei(&nd)) 187644421Skarels return (error); 187752330Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb); 187852330Smckusick vput(nd.ni_vp); 187944421Skarels return (error); 188041486Smckusick } 188141486Smckusick 188241486Smckusick int 188341486Smckusick ohpuxstat1(vp, ub) 188441486Smckusick register struct vnode *vp; 188541486Smckusick struct ohpuxstat *ub; 188641486Smckusick { 188741486Smckusick struct ohpuxstat ds; 188841486Smckusick struct vattr vattr; 188941486Smckusick register int error; 189041486Smckusick 189148478Skarels error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 189241486Smckusick if (error) 189341486Smckusick return(error); 189441486Smckusick /* 189541486Smckusick * Copy from inode table 189641486Smckusick */ 189741486Smckusick ds.ohst_dev = vattr.va_fsid; 189841486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 189941486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 190041486Smckusick ds.ohst_nlink = vattr.va_nlink; 190141486Smckusick ds.ohst_uid = (short)vattr.va_uid; 190241486Smckusick ds.ohst_gid = (short)vattr.va_gid; 190353481Smckusick ds.ohst_rdev = (u_short)vattr.va_rdev; 190441486Smckusick ds.ohst_size = (int)vattr.va_size; 190554107Smckusick ds.ohst_atime = (int)vattr.va_atime.ts_sec; 190654107Smckusick ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 190754107Smckusick ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 190841486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 190941486Smckusick } 191041486Smckusick #endif 1911