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*54861Storek * @(#)hpux_compat.c 7.26 (Berkeley) 07/09/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 12348478Skarels hpuxexecv(p, uap, retval) 12448478Skarels struct proc *p; 12548478Skarels struct args { 12648478Skarels char *fname; 12748478Skarels char **argp; 12848478Skarels char **envp; 12948478Skarels } *uap; 13048478Skarels int *retval; 13148478Skarels { 13248478Skarels extern int execve(); 13348478Skarels 13448478Skarels uap->envp = NULL; 13548478Skarels return (execve(p, uap, retval)); 13648478Skarels } 13748478Skarels 13841486Smckusick /* 13954857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 14041486Smckusick * (status pointer, options, rusage) into the kernel rather than 14142352Smckusick * handling it in the C library stub. We also need to map any 14254857Shibler * termination signal from BSD to HP-UX. 14341486Smckusick */ 14443452Shibler hpuxwait3(p, uap, retval) 14543452Shibler struct proc *p; 14643452Shibler struct args { 14741486Smckusick int *status; 14841486Smckusick int options; 14941486Smckusick int rusage; 15043452Shibler } *uap; 15143452Shibler int *retval; 15243452Shibler { 15341486Smckusick /* rusage pointer must be zero */ 15443452Shibler if (uap->rusage) 15544421Skarels return (EINVAL); 15652381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 15752381Smckusick p->p_md.md_regs[R0] = uap->options; 15852381Smckusick p->p_md.md_regs[R1] = uap->rusage; 15944421Skarels return (hpuxwait(p, uap, retval)); 16041486Smckusick } 16141486Smckusick 16243452Shibler hpuxwait(p, uap, retval) 16343452Shibler struct proc *p; 16443452Shibler struct args { 16543452Shibler int *status; 16643452Shibler } *uap; 16743452Shibler int *retval; 16841486Smckusick { 16943452Shibler int sig, *statp, error; 17041486Smckusick 17141486Smckusick statp = uap->status; /* owait clobbers first arg */ 17243452Shibler error = owait(p, uap, retval); 17341486Smckusick /* 17441486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 17541486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 17641486Smckusick */ 17743452Shibler if (error == ERESTART) 17843452Shibler error = EINTR; 17943452Shibler if (error) 18044421Skarels return (error); 18143452Shibler sig = retval[1] & 0xFF; 18241486Smckusick if (sig == WSTOPPED) { 18343452Shibler sig = (retval[1] >> 8) & 0xFF; 18443452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 18541486Smckusick } else if (sig) 18643452Shibler retval[1] = (retval[1] & 0xFF00) | 18741486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 18841486Smckusick if (statp) 18943452Shibler if (suword((caddr_t)statp, retval[1])) 19043452Shibler error = EFAULT; 19144421Skarels return (error); 19241486Smckusick } 19341486Smckusick 19443452Shibler hpuxwaitpid(p, uap, retval) 19543452Shibler struct proc *p; 19643452Shibler struct args { 19742352Smckusick int pid; 19842352Smckusick int *status; 19942352Smckusick int options; 20042352Smckusick struct rusage *rusage; /* wait4 arg */ 20143452Shibler } *uap; 20243452Shibler int *retval; 20343452Shibler { 20443452Shibler int sig, *statp, error; 20542352Smckusick 20642352Smckusick uap->rusage = 0; 20743452Shibler error = wait4(p, uap, retval); 20842352Smckusick /* 20942352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21042352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21142352Smckusick */ 21243452Shibler if (error == ERESTART) 21343452Shibler error = EINTR; 21443452Shibler if (error) 21544421Skarels return (error); 21643452Shibler sig = retval[1] & 0xFF; 21742352Smckusick if (sig == WSTOPPED) { 21843452Shibler sig = (retval[1] >> 8) & 0xFF; 21943452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 22042352Smckusick } else if (sig) 22143452Shibler retval[1] = (retval[1] & 0xFF00) | 22242352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 22342352Smckusick if (statp) 22443452Shibler if (suword((caddr_t)statp, retval[1])) 22543452Shibler error = EFAULT; 22644421Skarels return (error); 22742352Smckusick } 22842352Smckusick 22941486Smckusick /* 23041486Smckusick * Must remap some bits in the mode mask. 23141486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 23241486Smckusick * O_SYNCIO (0100000) is removed entirely. 23341486Smckusick */ 23443067Skarels hpuxopen(p, uap, retval) 23543067Skarels struct proc *p; 23643452Shibler register struct args { 23741486Smckusick char *fname; 23841486Smckusick int mode; 23941486Smckusick int crtmode; 24043067Skarels } *uap; 24143067Skarels int *retval; 24243067Skarels { 24341486Smckusick int mode; 24441486Smckusick 24541486Smckusick mode = uap->mode; 24641486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 24741486Smckusick if (mode & HPUXFCREAT) { 24841486Smckusick /* 24941486Smckusick * simulate the pre-NFS behavior that opening a 25041486Smckusick * file for READ+CREATE ignores the CREATE (unless 25141486Smckusick * EXCL is set in which case we will return the 25241486Smckusick * proper error). 25341486Smckusick */ 25448478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 25549950Smckusick uap->mode |= O_CREAT; 25641486Smckusick } 25741486Smckusick if (mode & HPUXFTRUNC) 25849950Smckusick uap->mode |= O_TRUNC; 25941486Smckusick if (mode & HPUXFEXCL) 26049950Smckusick uap->mode |= O_EXCL; 26144421Skarels return (open(p, uap, retval)); 26241486Smckusick } 26341486Smckusick 26449329Shibler /* XXX */ 26549329Shibler #define UF_FNDELAY_ON 0x20 26649329Shibler #define UF_FIONBIO_ON 0x40 26749329Shibler /* XXX */ 26849329Shibler 26943452Shibler hpuxfcntl(p, uap, retval) 27043452Shibler struct proc *p; 27143452Shibler register struct args { 27241486Smckusick int fdes; 27341486Smckusick int cmd; 27441486Smckusick int arg; 27543452Shibler } *uap; 27643452Shibler int *retval; 27743452Shibler { 27843452Shibler int mode, error; 27949329Shibler char *fp; 28041486Smckusick 28149329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 28249329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 28349329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 28449329Shibler return (EBADF); 28549329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 28649329Shibler } 28741486Smckusick switch (uap->cmd) { 28841486Smckusick case F_SETFL: 28949950Smckusick if (uap->arg & FNONBLOCK) 29049329Shibler *fp |= UF_FNDELAY_ON; 29149329Shibler else { 29249329Shibler *fp &= ~UF_FNDELAY_ON; 29349329Shibler if (*fp & UF_FIONBIO_ON) 29449950Smckusick uap->arg |= FNONBLOCK; 29549329Shibler } 29641486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 29741486Smckusick break; 29841486Smckusick case F_GETFL: 29941486Smckusick case F_DUPFD: 30041486Smckusick case F_GETFD: 30141486Smckusick case F_SETFD: 30241486Smckusick break; 30341486Smckusick default: 30444421Skarels return (EINVAL); 30541486Smckusick } 30643452Shibler error = fcntl(p, uap, retval); 30749329Shibler if (error == 0 && uap->cmd == F_GETFL) { 30843452Shibler mode = *retval; 30949950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 31049950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 31149950Smckusick *retval &= ~FNONBLOCK; 31249950Smckusick if (mode & O_CREAT) 31343452Shibler *retval |= HPUXFCREAT; 31449950Smckusick if (mode & O_TRUNC) 31543452Shibler *retval |= HPUXFTRUNC; 31649950Smckusick if (mode & O_EXCL) 31743452Shibler *retval |= HPUXFEXCL; 31841486Smckusick } 31944421Skarels return (error); 32041486Smckusick } 32141486Smckusick 32241486Smckusick /* 32341486Smckusick * Read and write should return a 0 count when an operation 32449329Shibler * on a VNODE would block, not an error. 32549329Shibler * 32649329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 32749950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 32841486Smckusick */ 32943452Shibler hpuxread(p, uap, retval) 33043452Shibler struct proc *p; 33143452Shibler struct args { 33243452Shibler int fd; 33343452Shibler } *uap; 33443452Shibler int *retval; 33541486Smckusick { 33643452Shibler int error; 33741486Smckusick 33843452Shibler error = read(p, uap, retval); 33943452Shibler if (error == EWOULDBLOCK && 34049329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 34149329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 34243452Shibler error = 0; 34343452Shibler *retval = 0; 34441486Smckusick } 34544421Skarels return (error); 34641486Smckusick } 34741486Smckusick 34843452Shibler hpuxwrite(p, uap, retval) 34943452Shibler struct proc *p; 35043452Shibler struct args { 35143452Shibler int fd; 35243452Shibler } *uap; 35343452Shibler int *retval; 35441486Smckusick { 35543452Shibler int error; 35641486Smckusick 35743452Shibler error = write(p, uap, retval); 35843452Shibler if (error == EWOULDBLOCK && 35949329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 36049329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 36143452Shibler error = 0; 36243452Shibler *retval = 0; 36341486Smckusick } 36444421Skarels return (error); 36541486Smckusick } 36641486Smckusick 36743452Shibler hpuxreadv(p, uap, retval) 36843452Shibler struct proc *p; 36943452Shibler struct args { 37043452Shibler int fd; 37143452Shibler } *uap; 37243452Shibler int *retval; 37341486Smckusick { 37443452Shibler int error; 37541486Smckusick 37643452Shibler error = readv(p, uap, retval); 37743452Shibler if (error == EWOULDBLOCK && 37849329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 37949329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 38043452Shibler error = 0; 38143452Shibler *retval = 0; 38241486Smckusick } 38344421Skarels return (error); 38441486Smckusick } 38541486Smckusick 38643452Shibler hpuxwritev(p, uap, retval) 38743452Shibler struct proc *p; 38843452Shibler struct args { 38943452Shibler int fd; 39043452Shibler } *uap; 39143452Shibler int *retval; 39241486Smckusick { 39343452Shibler int error; 39441486Smckusick 39543452Shibler error = writev(p, uap, retval); 39643452Shibler if (error == EWOULDBLOCK && 39749329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 39849329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 39943452Shibler error = 0; 40043452Shibler *retval = 0; 40141486Smckusick } 40244421Skarels return (error); 40341486Smckusick } 40441486Smckusick 40541486Smckusick /* 40641486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 40754857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 40841486Smckusick */ 40943452Shibler hpuxdup(p, uap, retval) 41043452Shibler struct proc *p; 41143452Shibler register struct args { 41243452Shibler int i; 41343452Shibler } *uap; 41443452Shibler int *retval; 41541486Smckusick { 41645923Smckusick register struct filedesc *fdp = p->p_fd; 41741486Smckusick struct file *fp; 41843452Shibler int fd, error; 41941486Smckusick 42048478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 42148478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 42244421Skarels return (EBADF); 42348478Skarels if (error = fdalloc(p, 0, &fd)) 42444421Skarels return (error); 42548478Skarels fdp->fd_ofiles[fd] = fp; 42648478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 42745923Smckusick fp->f_count++; 42845923Smckusick if (fd > fdp->fd_lastfile) 42945923Smckusick fdp->fd_lastfile = fd; 43043452Shibler *retval = fd; 43144421Skarels return (0); 43241486Smckusick } 43341486Smckusick 43445753Smckusick hpuxutssys(p, uap, retval) 43543452Shibler struct proc *p; 43643452Shibler register struct args { 43741486Smckusick struct hpuxutsname *uts; 43841486Smckusick int dev; 43941486Smckusick int request; 44043452Shibler } *uap; 44143452Shibler int *retval; 44243452Shibler { 44341486Smckusick register int i; 44443452Shibler int error; 44541486Smckusick 44641486Smckusick switch (uap->request) { 44741486Smckusick /* uname */ 44841486Smckusick case 0: 44941486Smckusick /* fill in machine type */ 45041486Smckusick switch (machineid) { 45141486Smckusick case HP_320: 45241486Smckusick protoutsname.machine[6] = '2'; 45341486Smckusick break; 45441486Smckusick /* includes 318 and 319 */ 45541486Smckusick case HP_330: 45641486Smckusick protoutsname.machine[6] = '3'; 45741486Smckusick break; 45841486Smckusick case HP_340: 45941486Smckusick protoutsname.machine[6] = '4'; 46041486Smckusick break; 46141486Smckusick case HP_350: 46241486Smckusick protoutsname.machine[6] = '5'; 46341486Smckusick break; 46441486Smckusick case HP_360: 46541486Smckusick protoutsname.machine[6] = '6'; 46641486Smckusick break; 46741486Smckusick case HP_370: 46841486Smckusick protoutsname.machine[6] = '7'; 46941486Smckusick break; 47043452Shibler /* includes 345 */ 47143452Shibler case HP_375: 47243452Shibler protoutsname.machine[6] = '7'; 47343452Shibler protoutsname.machine[7] = '5'; 47443452Shibler break; 47554857Shibler /* includes 425 */ 47654857Shibler case HP_380: 47754857Shibler protoutsname.machine[6] = '8'; 47854857Shibler break; 47941486Smckusick } 48041486Smckusick /* copy hostname (sans domain) to nodename */ 48149329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 48241486Smckusick protoutsname.nodename[i] = hostname[i]; 48349329Shibler protoutsname.nodename[i] = '\0'; 48443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 48543452Shibler sizeof(struct hpuxutsname)); 48641486Smckusick break; 48745753Smckusick 48845753Smckusick /* gethostname */ 48945753Smckusick case 5: 49045753Smckusick /* uap->dev is length */ 49145753Smckusick if (uap->dev > hostnamelen + 1) 49245753Smckusick uap->dev = hostnamelen + 1; 49345753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 49445753Smckusick uap->dev); 49545753Smckusick break; 49645753Smckusick 49745753Smckusick case 1: /* ?? */ 49845753Smckusick case 2: /* ustat */ 49945753Smckusick case 3: /* ?? */ 50045753Smckusick case 4: /* sethostname */ 50141486Smckusick default: 50243452Shibler error = EINVAL; 50341486Smckusick break; 50441486Smckusick } 50544421Skarels return (error); 50641486Smckusick } 50741486Smckusick 50853922Shibler hpuxsysconf(p, uap, retval) 50953922Shibler struct proc *p; 51053922Shibler struct args { 51153922Shibler int name; 51253922Shibler } *uap; 51353922Shibler int *retval; 51453922Shibler { 51553922Shibler switch (uap->name) { 51653922Shibler 51753922Shibler /* open files */ 51853922Shibler case HPUX_SYSCONF_OPENMAX: 51953922Shibler *retval = NOFILE; 52053922Shibler break; 52153922Shibler 52253922Shibler /* architecture */ 52353922Shibler case HPUX_SYSCONF_CPUTYPE: 52453922Shibler switch (machineid) { 52553922Shibler case HP_320: 52653922Shibler case HP_330: 52753922Shibler case HP_350: 52853922Shibler *retval = HPUX_SYSCONF_CPUM020; 52953922Shibler break; 53053922Shibler case HP_340: 53153922Shibler case HP_360: 53253922Shibler case HP_370: 53353922Shibler case HP_375: 53453922Shibler *retval = HPUX_SYSCONF_CPUM030; 53553922Shibler break; 53653922Shibler case HP_380: 53753922Shibler *retval = HPUX_SYSCONF_CPUM040; 53853922Shibler break; 53953922Shibler } 54053922Shibler break; 54153922Shibler default: 54254857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 54353922Shibler return (EINVAL); 54453922Shibler } 54553922Shibler return (0); 54653922Shibler } 54753922Shibler 54843452Shibler hpuxstat(p, uap, retval) 54943452Shibler struct proc *p; 55043452Shibler struct args { 55141486Smckusick char *fname; 55241486Smckusick struct hpuxstat *hsb; 55343452Shibler } *uap; 55443452Shibler int *retval; 55543452Shibler { 55644421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 55741486Smckusick } 55841486Smckusick 55943452Shibler hpuxlstat(p, uap, retval) 56043452Shibler struct proc *p; 56143452Shibler struct args { 56243452Shibler char *fname; 56343452Shibler struct hpuxstat *hsb; 56443452Shibler } *uap; 56543452Shibler int *retval; 56641486Smckusick { 56744421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 56841486Smckusick } 56941486Smckusick 57043452Shibler hpuxfstat(p, uap, retval) 57143452Shibler struct proc *p; 57243452Shibler register struct args { 57343452Shibler int fdes; 57443452Shibler struct hpuxstat *hsb; 57543452Shibler } *uap; 57643452Shibler int *retval; 57741486Smckusick { 57845923Smckusick register struct filedesc *fdp = p->p_fd; 57941486Smckusick register struct file *fp; 58041486Smckusick struct stat sb; 58143452Shibler int error; 58241486Smckusick 58348478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 58448478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 58544421Skarels return (EBADF); 58643452Shibler 58741486Smckusick switch (fp->f_type) { 58841486Smckusick 58941486Smckusick case DTYPE_VNODE: 59043452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 59141486Smckusick break; 59241486Smckusick 59341486Smckusick case DTYPE_SOCKET: 59443452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 59541486Smckusick break; 59641486Smckusick 59741486Smckusick default: 59841486Smckusick panic("fstat"); 59941486Smckusick /*NOTREACHED*/ 60041486Smckusick } 60141486Smckusick /* is this right for sockets?? */ 60243452Shibler if (error == 0) 60343452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 60444421Skarels return (error); 60541486Smckusick } 60641486Smckusick 60743452Shibler hpuxulimit(p, uap, retval) 60843452Shibler struct proc *p; 60943452Shibler register struct args { 61041486Smckusick int cmd; 61141486Smckusick long newlimit; 61243452Shibler } *uap; 61353481Smckusick long *retval; 61443452Shibler { 61541486Smckusick struct rlimit *limp; 61643452Shibler int error = 0; 61741486Smckusick 61848478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 61941486Smckusick switch (uap->cmd) { 62041486Smckusick case 2: 62141486Smckusick uap->newlimit *= 512; 62241486Smckusick if (uap->newlimit > limp->rlim_max && 62348478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 62441486Smckusick break; 62541486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 62641486Smckusick /* else fall into... */ 62741486Smckusick 62841486Smckusick case 1: 62945753Smckusick *retval = limp->rlim_max / 512; 63041486Smckusick break; 63141486Smckusick 63241486Smckusick case 3: 63348478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 63448478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 63541486Smckusick break; 63641486Smckusick 63741486Smckusick default: 63843452Shibler error = EINVAL; 63941486Smckusick break; 64041486Smckusick } 64144421Skarels return (error); 64241486Smckusick } 64341486Smckusick 64441486Smckusick /* 64541486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 64641486Smckusick * values -16 (high) thru -1 (low). 64741486Smckusick */ 64843452Shibler hpuxrtprio(cp, uap, retval) 64943452Shibler struct proc *cp; 65043452Shibler register struct args { 65141486Smckusick int pid; 65241486Smckusick int prio; 65343452Shibler } *uap; 65443452Shibler int *retval; 65543452Shibler { 65641486Smckusick struct proc *p; 65743452Shibler int nice, error; 65841486Smckusick 65941486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 66043452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 66144421Skarels return (EINVAL); 66241486Smckusick if (uap->pid == 0) 66343452Shibler p = cp; 66443452Shibler else if ((p = pfind(uap->pid)) == 0) 66544421Skarels return (ESRCH); 66641486Smckusick nice = p->p_nice; 66741486Smckusick if (nice < NZERO) 66843452Shibler *retval = (nice + 16) << 3; 66941486Smckusick else 67043452Shibler *retval = RTPRIO_RTOFF; 67141486Smckusick switch (uap->prio) { 67241486Smckusick 67341486Smckusick case RTPRIO_NOCHG: 67444421Skarels return (0); 67541486Smckusick 67641486Smckusick case RTPRIO_RTOFF: 67741486Smckusick if (nice >= NZERO) 67844421Skarels return (0); 67941486Smckusick nice = NZERO; 68041486Smckusick break; 68141486Smckusick 68241486Smckusick default: 68341486Smckusick nice = (uap->prio >> 3) - 16; 68441486Smckusick break; 68541486Smckusick } 68643452Shibler error = donice(cp, p, nice); 68743452Shibler if (error == EACCES) 68843452Shibler error = EPERM; 68944421Skarels return (error); 69041486Smckusick } 69141486Smckusick 69243452Shibler hpuxadvise(p, uap, retval) 69343452Shibler struct proc *p; 69443452Shibler struct args { 69543452Shibler int arg; 69643452Shibler } *uap; 69743452Shibler int *retval; 69841486Smckusick { 69943452Shibler int error = 0; 70041486Smckusick 70141486Smckusick switch (uap->arg) { 70241486Smckusick case 0: 70349134Skarels p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; 70441486Smckusick break; 70541486Smckusick case 1: 70641486Smckusick ICIA(); 70741486Smckusick break; 70841486Smckusick case 2: 70941486Smckusick DCIA(); 71041486Smckusick break; 71141486Smckusick default: 71243452Shibler error = EINVAL; 71341486Smckusick break; 71441486Smckusick } 71544421Skarels return (error); 71641486Smckusick } 71741486Smckusick 71843452Shibler hpuxptrace(p, uap, retval) 71943452Shibler struct proc *p; 72043452Shibler struct args { 72141486Smckusick int req; 72241486Smckusick int pid; 72341486Smckusick int *addr; 72441486Smckusick int data; 72543452Shibler } *uap; 72643452Shibler int *retval; 72743452Shibler { 72843452Shibler int error; 72941486Smckusick 73041486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 73141486Smckusick if (uap->data) { 73241486Smckusick uap->data = hpuxtobsdsig(uap->data); 73341486Smckusick if (uap->data == 0) 73441486Smckusick uap->data = NSIG; 73541486Smckusick } 73641486Smckusick } 73743452Shibler error = ptrace(p, uap, retval); 73844421Skarels return (error); 73941486Smckusick } 74041486Smckusick 74143452Shibler hpuxgetdomainname(p, uap, retval) 74243452Shibler struct proc *p; 74343452Shibler register struct args { 74441486Smckusick char *domainname; 74541486Smckusick u_int len; 74643452Shibler } *uap; 74743452Shibler int *retval; 74843452Shibler { 74941486Smckusick if (uap->len > domainnamelen + 1) 75041486Smckusick uap->len = domainnamelen + 1; 75144421Skarels return (copyout(domainname, uap->domainname, uap->len)); 75241486Smckusick } 75341486Smckusick 75443452Shibler hpuxsetdomainname(p, uap, retval) 75543452Shibler struct proc *p; 75643452Shibler register struct args { 75741486Smckusick char *domainname; 75841486Smckusick u_int len; 75943452Shibler } *uap; 76043452Shibler int *retval; 76143452Shibler { 76243452Shibler int error; 76341486Smckusick 76448478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 76544421Skarels return (error); 76643452Shibler if (uap->len > sizeof (domainname) - 1) 76744421Skarels return (EINVAL); 76841486Smckusick domainnamelen = uap->len; 76943452Shibler error = copyin(uap->domainname, domainname, uap->len); 77041486Smckusick domainname[domainnamelen] = 0; 77144421Skarels return (error); 77241486Smckusick } 77341486Smckusick 77441486Smckusick #ifdef SYSVSHM 77554857Shibler #include "shm.h" 77654857Shibler 77743452Shibler hpuxshmat(p, uap, retval) 77843452Shibler struct proc *p; 77943452Shibler int *uap, *retval; 78041486Smckusick { 78144421Skarels return (shmat(p, uap, retval)); 78241486Smckusick } 78341486Smckusick 78443452Shibler hpuxshmdt(p, uap, retval) 78543452Shibler struct proc *p; 78643452Shibler int *uap, *retval; 78741486Smckusick { 78844421Skarels return (shmdt(p, uap, retval)); 78941486Smckusick } 79041486Smckusick 79143452Shibler hpuxshmget(p, uap, retval) 79243452Shibler struct proc *p; 79343452Shibler int *uap, *retval; 79441486Smckusick { 79544421Skarels return (shmget(p, uap, retval)); 79641486Smckusick } 79754857Shibler 79854857Shibler /* 79954857Shibler * Handle HP-UX specific commands. 80054857Shibler */ 80154857Shibler hpuxshmctl(p, uap, retval) 80254857Shibler struct proc *p; 80354857Shibler struct args { 80454857Shibler int shmid; 80554857Shibler int cmd; 80654857Shibler caddr_t buf; 80754857Shibler } *uap; 80854857Shibler int *retval; 80954857Shibler { 81054857Shibler register struct shmid_ds *shp; 81154857Shibler register struct ucred *cred = p->p_ucred; 81254857Shibler int error; 81354857Shibler 81454857Shibler if (error = shmvalid(uap->shmid)) 81554857Shibler return (error); 81654857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 81754857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 81854857Shibler /* don't really do anything, but make them think we did */ 81954857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 82054857Shibler cred->cr_uid != shp->shm_perm.cuid) 82154857Shibler return (EPERM); 82254857Shibler return (0); 82354857Shibler } 82454857Shibler return (shmctl(p, uap, retval)); 82554857Shibler } 82641486Smckusick #endif 82741486Smckusick 82841486Smckusick /* 82941486Smckusick * Fake semaphore routines, just don't return an error. 83041486Smckusick * Should be adequate for starbase to run. 83141486Smckusick */ 83243452Shibler hpuxsemctl(p, uap, retval) 83343452Shibler struct proc *p; 83443452Shibler struct args { 83541486Smckusick int semid; 83641486Smckusick u_int semnum; 83741486Smckusick int cmd; 83841486Smckusick int arg; 83943452Shibler } *uap; 84043452Shibler int *retval; 84143452Shibler { 84241486Smckusick /* XXX: should do something here */ 84344421Skarels return (0); 84441486Smckusick } 84541486Smckusick 84643452Shibler hpuxsemget(p, uap, retval) 84743452Shibler struct proc *p; 84843452Shibler struct args { 84941486Smckusick key_t key; 85041486Smckusick int nsems; 85141486Smckusick int semflg; 85243452Shibler } *uap; 85343452Shibler int *retval; 85443452Shibler { 85541486Smckusick /* XXX: should do something here */ 85644421Skarels return (0); 85741486Smckusick } 85841486Smckusick 85943452Shibler hpuxsemop(p, uap, retval) 86043452Shibler struct proc *p; 86143452Shibler struct args { 86241486Smckusick int semid; 86341486Smckusick struct sembuf *sops; 86441486Smckusick u_int nsops; 86543452Shibler } *uap; 86643452Shibler int *retval; 86743452Shibler { 86841486Smckusick /* XXX: should do something here */ 86944421Skarels return (0); 87041486Smckusick } 87141486Smckusick 87254857Shibler /* convert from BSD to HP-UX errno */ 87341486Smckusick bsdtohpuxerrno(err) 87441486Smckusick int err; 87541486Smckusick { 87641486Smckusick if (err < 0 || err >= NERR) 87741486Smckusick return(BERR); 87841486Smckusick return((int)bsdtohpuxerrnomap[err]); 87941486Smckusick } 88041486Smckusick 88141486Smckusick hpuxstat1(fname, hsb, follow) 88241486Smckusick char *fname; 88341486Smckusick struct hpuxstat *hsb; 88441486Smckusick int follow; 88541486Smckusick { 88648478Skarels int error; 88741486Smckusick struct stat sb; 88848478Skarels struct nameidata nd; 88941486Smckusick 89052330Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, curproc); 89152330Smckusick if (error = namei(&nd)) 89241486Smckusick return (error); 89352330Smckusick error = vn_stat(nd.ni_vp, &sb); 89452330Smckusick vput(nd.ni_vp); 89541486Smckusick if (error == 0) 89641486Smckusick error = bsdtohpuxstat(&sb, hsb); 89741486Smckusick return (error); 89841486Smckusick } 89941486Smckusick 90041486Smckusick #include "grf.h" 90153922Shibler #if NGRF > 0 90253922Shibler #ifdef __STDC__ 90353922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 90453922Shibler #else 90553922Shibler extern int grfopen(); 90653922Shibler #endif 90753922Shibler #endif 90841486Smckusick 90953922Shibler #define NHIL 1 /* XXX */ 91053922Shibler #if NHIL > 0 91153922Shibler #ifdef __STDC__ 91253922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 91353922Shibler #else 91453922Shibler extern int hilopen(); 91553922Shibler #endif 91653922Shibler #endif 91753922Shibler 91853922Shibler #include "conf.h" 91953922Shibler 92041486Smckusick bsdtohpuxstat(sb, hsb) 92141486Smckusick struct stat *sb; 92241486Smckusick struct hpuxstat *hsb; 92341486Smckusick { 92441486Smckusick struct hpuxstat ds; 92541486Smckusick 92641486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 92753481Smckusick ds.hst_dev = (u_short)sb->st_dev; 92841486Smckusick ds.hst_ino = (u_long)sb->st_ino; 92941486Smckusick ds.hst_mode = sb->st_mode; 93041486Smckusick ds.hst_nlink = sb->st_nlink; 93141486Smckusick ds.hst_uid = (u_short)sb->st_uid; 93241486Smckusick ds.hst_gid = (u_short)sb->st_gid; 93353922Shibler /* XXX: I don't want to talk about it... */ 93453922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 93541486Smckusick #if NGRF > 0 93653922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 93753922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 93841486Smckusick #endif 93953922Shibler #if NHIL > 0 94053922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 94153922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 94253922Shibler #endif 94353922Shibler ; 94453922Shibler } else 94541486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 94653481Smckusick if (sb->st_size < (quad_t)1 << 32) 94753481Smckusick ds.hst_size = (long)sb->st_size; 94853481Smckusick else 94953481Smckusick ds.hst_size = -2; 95041486Smckusick ds.hst_atime = sb->st_atime; 95141486Smckusick ds.hst_mtime = sb->st_mtime; 95241486Smckusick ds.hst_ctime = sb->st_ctime; 95341486Smckusick ds.hst_blksize = sb->st_blksize; 95441486Smckusick ds.hst_blocks = sb->st_blocks; 95541486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 95641486Smckusick } 95741486Smckusick 95841486Smckusick hpuxtobsdioctl(com) 95941486Smckusick int com; 96041486Smckusick { 96141486Smckusick switch (com) { 96241486Smckusick case HPUXTIOCSLTC: 96341486Smckusick com = TIOCSLTC; break; 96441486Smckusick case HPUXTIOCGLTC: 96541486Smckusick com = TIOCGLTC; break; 96641486Smckusick case HPUXTIOCSPGRP: 96741486Smckusick com = TIOCSPGRP; break; 96841486Smckusick case HPUXTIOCGPGRP: 96941486Smckusick com = TIOCGPGRP; break; 97041486Smckusick case HPUXTIOCLBIS: 97141486Smckusick com = TIOCLBIS; break; 97241486Smckusick case HPUXTIOCLBIC: 97341486Smckusick com = TIOCLBIC; break; 97441486Smckusick case HPUXTIOCLSET: 97541486Smckusick com = TIOCLSET; break; 97641486Smckusick case HPUXTIOCLGET: 97741486Smckusick com = TIOCLGET; break; 97841486Smckusick } 97941486Smckusick return(com); 98041486Smckusick } 98141486Smckusick 98241486Smckusick /* 98354857Shibler * HP-UX ioctl system call. The differences here are: 98441486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 98549329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 98641486Smckusick * the sgttyb struct is 2 bytes longer 98741486Smckusick */ 98843452Shibler hpuxioctl(p, uap, retval) 98943452Shibler struct proc *p; 99043452Shibler register struct args { 99141486Smckusick int fdes; 99241486Smckusick int cmd; 99341486Smckusick caddr_t cmarg; 99443452Shibler } *uap; 99543452Shibler int *retval; 99643452Shibler { 99745923Smckusick register struct filedesc *fdp = p->p_fd; 99843452Shibler register struct file *fp; 99943452Shibler register int com, error; 100041486Smckusick register u_int size; 100141486Smckusick caddr_t memp = 0; 100241486Smckusick #define STK_PARAMS 128 100341486Smckusick char stkbuf[STK_PARAMS]; 100441486Smckusick caddr_t data = stkbuf; 100541486Smckusick 100641486Smckusick com = uap->cmd; 100741486Smckusick 100841486Smckusick /* XXX */ 100943452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 101045923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 101141486Smckusick 101248478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 101348478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 101444421Skarels return (EBADF); 101543452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 101644421Skarels return (EBADF); 101741486Smckusick 101841486Smckusick /* 101941486Smckusick * Interpret high order word to find 102041486Smckusick * amount of data to be copied to/from the 102141486Smckusick * user's address space. 102241486Smckusick */ 102341486Smckusick size = IOCPARM_LEN(com); 102443452Shibler if (size > IOCPARM_MAX) 102544421Skarels return (ENOTTY); 102641486Smckusick if (size > sizeof (stkbuf)) { 102743452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 102841486Smckusick data = memp; 102941486Smckusick } 103041486Smckusick if (com&IOC_IN) { 103141486Smckusick if (size) { 103243452Shibler error = copyin(uap->cmarg, data, (u_int)size); 103343452Shibler if (error) { 103441486Smckusick if (memp) 103541486Smckusick free(memp, M_IOCTLOPS); 103644421Skarels return (error); 103741486Smckusick } 103841486Smckusick } else 103941486Smckusick *(caddr_t *)data = uap->cmarg; 104041486Smckusick } else if ((com&IOC_OUT) && size) 104141486Smckusick /* 104243452Shibler * Zero the buffer so the user always 104343452Shibler * gets back something deterministic. 104441486Smckusick */ 104541486Smckusick bzero(data, size); 104641486Smckusick else if (com&IOC_VOID) 104741486Smckusick *(caddr_t *)data = uap->cmarg; 104841486Smckusick 104941486Smckusick switch (com) { 105041486Smckusick 105149329Shibler case HPUXFIOSNBIO: 105249329Shibler { 105349329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 105449329Shibler int tmp; 105549329Shibler 105649329Shibler if (*(int *)data) 105749329Shibler *ofp |= UF_FIONBIO_ON; 105849329Shibler else 105949329Shibler *ofp &= ~UF_FIONBIO_ON; 106049329Shibler /* 106149950Smckusick * Only set/clear if FNONBLOCK not in effect 106249329Shibler */ 106349329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 106449950Smckusick tmp = fp->f_flag & FNONBLOCK; 106549329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 106649329Shibler (caddr_t)&tmp, p); 106749329Shibler } 106849329Shibler break; 106949329Shibler } 107049329Shibler 107141486Smckusick case HPUXTIOCCONS: 107241486Smckusick *(int *)data = 1; 107348478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 107441486Smckusick break; 107541486Smckusick 107641486Smckusick /* BSD-style job control ioctls */ 107741486Smckusick case HPUXTIOCLBIS: 107841486Smckusick case HPUXTIOCLBIC: 107941486Smckusick case HPUXTIOCLSET: 108041486Smckusick *(int *)data &= HPUXLTOSTOP; 108141486Smckusick if (*(int *)data & HPUXLTOSTOP) 108241486Smckusick *(int *)data = LTOSTOP; 108341486Smckusick /* fall into */ 108441486Smckusick case HPUXTIOCLGET: 108541486Smckusick case HPUXTIOCSLTC: 108641486Smckusick case HPUXTIOCGLTC: 108741486Smckusick case HPUXTIOCSPGRP: 108841486Smckusick case HPUXTIOCGPGRP: 108948478Skarels error = (*fp->f_ops->fo_ioctl) 109048478Skarels (fp, hpuxtobsdioctl(com), data, p); 109143452Shibler if (error == 0 && com == HPUXTIOCLGET) { 109241486Smckusick *(int *)data &= LTOSTOP; 109341486Smckusick if (*(int *)data & LTOSTOP) 109441486Smckusick *(int *)data = HPUXLTOSTOP; 109541486Smckusick } 109641486Smckusick break; 109741486Smckusick 109841486Smckusick /* SYS 5 termio */ 109941486Smckusick case HPUXTCGETA: 110041486Smckusick case HPUXTCSETA: 110141486Smckusick case HPUXTCSETAW: 110241486Smckusick case HPUXTCSETAF: 110348478Skarels error = hpuxtermio(fp, com, data, p); 110441486Smckusick break; 110541486Smckusick 110641486Smckusick default: 110748478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 110841486Smckusick break; 110941486Smckusick } 111041486Smckusick /* 111141486Smckusick * Copy any data to user, size was 111241486Smckusick * already set and checked above. 111341486Smckusick */ 111443452Shibler if (error == 0 && (com&IOC_OUT) && size) 111543452Shibler error = copyout(data, uap->cmarg, (u_int)size); 111641486Smckusick if (memp) 111741486Smckusick free(memp, M_IOCTLOPS); 111844421Skarels return (error); 111941486Smckusick } 112041486Smckusick 112141486Smckusick /* 112241486Smckusick * Man page lies, behaviour here is based on observed behaviour. 112341486Smckusick */ 112443452Shibler hpuxgetcontext(p, uap, retval) 112543452Shibler struct proc *p; 112643452Shibler struct args { 112741486Smckusick char *buf; 112841486Smckusick int len; 112943452Shibler } *uap; 113043452Shibler int *retval; 113143452Shibler { 113241486Smckusick int error = 0; 113341486Smckusick register int len; 113441486Smckusick 113553922Shibler #if defined(HP380) 113653922Shibler if (machineid == HP_380) { 113753922Shibler len = MIN(uap->len, sizeof(hpux040context)); 113853922Shibler if (len) 113953922Shibler error = copyout(hpux040context, uap->buf, len); 114053922Shibler if (error == 0) 114153922Shibler *retval = sizeof(hpux040context); 114253922Shibler return (error); 114353922Shibler } 114453922Shibler #endif 114541486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 114641486Smckusick if (len) 114741486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 114843452Shibler if (error == 0) 114943452Shibler *retval = sizeof(hpuxcontext); 115044421Skarels return (error); 115141486Smckusick } 115241486Smckusick 115341486Smckusick /* 115441486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 115541486Smckusick * Note we do not check the real uid or "saved" uid. 115641486Smckusick */ 115743452Shibler hpuxgetpgrp2(cp, uap, retval) 115843452Shibler struct proc *cp; 115943452Shibler register struct args { 116043452Shibler int pid; 116143452Shibler } *uap; 116243452Shibler int *retval; 116341486Smckusick { 116441486Smckusick register struct proc *p; 116541486Smckusick 116641486Smckusick if (uap->pid == 0) 116743452Shibler uap->pid = cp->p_pid; 116841486Smckusick p = pfind(uap->pid); 116943452Shibler if (p == 0) 117044421Skarels return (ESRCH); 117148478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 117248478Skarels !inferior(p)) 117344421Skarels return (EPERM); 117443452Shibler *retval = p->p_pgid; 117544421Skarels return (0); 117641486Smckusick } 117741486Smckusick 117841486Smckusick /* 117941486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 118041486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 118141486Smckusick */ 118243452Shibler hpuxsetpgrp2(p, uap, retval) 118343452Shibler struct proc *p; 118443452Shibler struct args { 118541486Smckusick int pid; 118641486Smckusick int pgrp; 118743452Shibler } *uap; 118843452Shibler int *retval; 118943452Shibler { 119041486Smckusick /* empirically determined */ 119143452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 119244421Skarels return (EINVAL); 119348478Skarels return (setpgid(p, uap, retval)); 119441486Smckusick } 119541486Smckusick 119641486Smckusick /* 1197*54861Storek * XXX Same as old BSD setre[ug]id right now. Need to consider saved ids. 119845753Smckusick */ 1199*54861Storek /* ARGSUSED */ 120045753Smckusick hpuxsetresuid(p, uap, retval) 1201*54861Storek register struct proc *p; 120245753Smckusick struct args { 120345753Smckusick int ruid; 120445753Smckusick int euid; 120545753Smckusick int suid; 120645753Smckusick } *uap; 120745753Smckusick int *retval; 120845753Smckusick { 1209*54861Storek register struct pcred *pc = p->p_cred; 1210*54861Storek register uid_t ruid, euid; 1211*54861Storek int error; 1212*54861Storek 1213*54861Storek if (uap->ruid == -1) 1214*54861Storek ruid = pc->p_ruid; 1215*54861Storek else 1216*54861Storek ruid = uap->ruid; 1217*54861Storek /* 1218*54861Storek * Allow setting real uid to previous effective, for swapping real and 1219*54861Storek * effective. This should be: 1220*54861Storek * 1221*54861Storek * if (ruid != pc->p_ruid && 1222*54861Storek * (error = suser(pc->pc_ucred, &p->p_acflag))) 1223*54861Storek */ 1224*54861Storek if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ && 1225*54861Storek (error = suser(pc->pc_ucred, &p->p_acflag))) 1226*54861Storek return (error); 1227*54861Storek if (uap->euid == -1) 1228*54861Storek euid = pc->pc_ucred->cr_uid; 1229*54861Storek else 1230*54861Storek euid = uap->euid; 1231*54861Storek if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && 1232*54861Storek euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag))) 1233*54861Storek return (error); 1234*54861Storek /* 1235*54861Storek * Everything's okay, do it. Copy credentials so other references do 1236*54861Storek * not see our changes. 1237*54861Storek */ 1238*54861Storek pc->pc_ucred = crcopy(pc->pc_ucred); 1239*54861Storek pc->pc_ucred->cr_uid = euid; 1240*54861Storek pc->p_ruid = ruid; 1241*54861Storek p->p_flag |= SUGID; 1242*54861Storek return (0); 124345753Smckusick } 124445753Smckusick 1245*54861Storek /* ARGSUSED */ 124645753Smckusick hpuxsetresgid(p, uap, retval) 1247*54861Storek register struct proc *p; 124845753Smckusick struct args { 124945753Smckusick int rgid; 125045753Smckusick int egid; 125145753Smckusick int sgid; 125245753Smckusick } *uap; 125345753Smckusick int *retval; 125445753Smckusick { 1255*54861Storek register struct pcred *pc = p->p_cred; 1256*54861Storek register gid_t rgid, egid; 1257*54861Storek int error; 1258*54861Storek 1259*54861Storek if (uap->rgid == -1) 1260*54861Storek rgid = pc->p_rgid; 1261*54861Storek else 1262*54861Storek rgid = uap->rgid; 1263*54861Storek /* 1264*54861Storek * Allow setting real gid to previous effective, for swapping real and 1265*54861Storek * effective. This didn't really work correctly in 4.[23], but is 1266*54861Storek * preserved so old stuff doesn't fail. This should be: 1267*54861Storek * 1268*54861Storek * if (rgid != pc->p_rgid && 1269*54861Storek * (error = suser(pc->pc_ucred, &p->p_acflag))) 1270*54861Storek */ 1271*54861Storek if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ && 1272*54861Storek (error = suser(pc->pc_ucred, &p->p_acflag))) 1273*54861Storek return (error); 1274*54861Storek if (uap->egid == -1) 1275*54861Storek egid = pc->pc_ucred->cr_groups[0]; 1276*54861Storek else 1277*54861Storek egid = uap->egid; 1278*54861Storek if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && 1279*54861Storek egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag))) 1280*54861Storek return (error); 1281*54861Storek pc->pc_ucred = crcopy(pc->pc_ucred); 1282*54861Storek pc->pc_ucred->cr_groups[0] = egid; 1283*54861Storek pc->p_rgid = rgid; 1284*54861Storek p->p_flag |= SUGID; 1285*54861Storek return (0); 128645753Smckusick } 128745753Smckusick 128845753Smckusick /* 128945753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 129045753Smckusick */ 129145753Smckusick hpuxlockf(p, uap, retval) 129245753Smckusick struct proc *p; 129345753Smckusick struct args { 129445753Smckusick int fd; 129545753Smckusick int func; 129645753Smckusick long size; 129745753Smckusick } *uap; 129845753Smckusick int *retval; 129945753Smckusick { 130045753Smckusick #ifdef DEBUG 130145753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 130245753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 130345753Smckusick #endif 130445753Smckusick return (0); 130545753Smckusick } 130645753Smckusick 130745753Smckusick hpuxgetaccess(p, uap, retval) 130845753Smckusick register struct proc *p; 130945753Smckusick register struct args { 131045753Smckusick char *path; 131145753Smckusick int uid; 131245753Smckusick int ngroups; 131345753Smckusick int *gidset; 131445753Smckusick void *label; 131545753Smckusick void *privs; 131645753Smckusick } *uap; 131745753Smckusick int *retval; 131845753Smckusick { 131945753Smckusick int lgroups[NGROUPS]; 132045753Smckusick int error = 0; 132145753Smckusick register struct ucred *cred; 132245753Smckusick register struct vnode *vp; 132352330Smckusick struct nameidata nd; 132445753Smckusick 132545753Smckusick /* 132645753Smckusick * Build an appropriate credential structure 132745753Smckusick */ 132848478Skarels cred = crdup(p->p_ucred); 132945753Smckusick switch (uap->uid) { 133045753Smckusick case 65502: /* UID_EUID */ 133145753Smckusick break; 133245753Smckusick case 65503: /* UID_RUID */ 133348478Skarels cred->cr_uid = p->p_cred->p_ruid; 133445753Smckusick break; 133545753Smckusick case 65504: /* UID_SUID */ 133645753Smckusick error = EINVAL; 133745753Smckusick break; 133845753Smckusick default: 133945753Smckusick if (uap->uid > 65504) 134045753Smckusick error = EINVAL; 134145753Smckusick cred->cr_uid = uap->uid; 134245753Smckusick break; 134345753Smckusick } 134445753Smckusick switch (uap->ngroups) { 134545753Smckusick case -1: /* NGROUPS_EGID */ 134645753Smckusick cred->cr_ngroups = 1; 134745753Smckusick break; 134845753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 134945753Smckusick break; 135045753Smckusick case -2: /* NGROUPS_RGID */ 135145753Smckusick cred->cr_ngroups = 1; 135248478Skarels cred->cr_gid = p->p_cred->p_rgid; 135345753Smckusick break; 135445753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 135548478Skarels cred->cr_gid = p->p_cred->p_rgid; 135645753Smckusick break; 135745753Smckusick case -3: /* NGROUPS_SGID */ 135845753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 135945753Smckusick error = EINVAL; 136045753Smckusick break; 136145753Smckusick case -4: /* NGROUPS_SUPP */ 136245753Smckusick if (cred->cr_ngroups > 1) 136345753Smckusick cred->cr_gid = cred->cr_groups[1]; 136445753Smckusick else 136545753Smckusick error = EINVAL; 136645753Smckusick break; 136745753Smckusick default: 136845753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 136945753Smckusick error = copyin((caddr_t)uap->gidset, 137045753Smckusick (caddr_t)&lgroups[0], 137145753Smckusick uap->ngroups * sizeof(lgroups[0])); 137245753Smckusick else 137345753Smckusick error = EINVAL; 137445753Smckusick if (error == 0) { 137545753Smckusick int gid; 137645753Smckusick 137745753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 137845753Smckusick cred->cr_groups[gid] = lgroups[gid]; 137945753Smckusick cred->cr_ngroups = uap->ngroups; 138045753Smckusick } 138145753Smckusick break; 138245753Smckusick } 138345753Smckusick /* 138445753Smckusick * Lookup file using caller's effective IDs. 138545753Smckusick */ 138645753Smckusick if (error == 0) { 138752330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 138852330Smckusick uap->path, p); 138952330Smckusick error = namei(&nd); 139045753Smckusick } 139145753Smckusick if (error) { 139245753Smckusick crfree(cred); 139345753Smckusick return (error); 139445753Smckusick } 139545753Smckusick /* 139645753Smckusick * Use the constructed credentials for access checks. 139745753Smckusick */ 139852330Smckusick vp = nd.ni_vp; 139945753Smckusick *retval = 0; 140048478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 140145753Smckusick *retval |= R_OK; 140248478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 140345753Smckusick *retval |= W_OK; 140445753Smckusick /* XXX we return X_OK for root on VREG even if not */ 140548478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 140645753Smckusick *retval |= X_OK; 140745753Smckusick vput(vp); 140845753Smckusick crfree(cred); 140945753Smckusick return (error); 141045753Smckusick } 141145753Smckusick 141245753Smckusick /* 141354857Shibler * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 141441486Smckusick * No apologies offered, if you don't like it, rewrite it! 141541486Smckusick */ 141641486Smckusick 141749134Skarels extern char kstack[]; 141841486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 141941486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 142041486Smckusick 142141486Smckusick /* simplified FP structure */ 142241486Smckusick struct bsdfp { 142341486Smckusick int save[54]; 142441486Smckusick int reg[24]; 142541486Smckusick int ctrl[3]; 142641486Smckusick }; 142741486Smckusick 142841486Smckusick hpuxtobsduoff(off) 142941486Smckusick int *off; 143041486Smckusick { 143152381Smckusick register int *ar0 = curproc->p_md.md_regs; 143241486Smckusick struct hpuxfp *hp; 143341486Smckusick struct bsdfp *bp; 143441486Smckusick register u_int raddr; 143541486Smckusick 143648478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 143741486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 143848478Skarels return(UOFF(U_ar0)); 143941486Smckusick 144041486Smckusick #ifdef FPCOPROC 144141486Smckusick /* 68881 registers from PCB */ 144241486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 144341486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 144441486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 144541486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 144641486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 144741486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 144841486Smckusick #endif 144941486Smckusick 145041486Smckusick /* 145141486Smckusick * Everything else we recognize comes from the kernel stack, 145241486Smckusick * so we convert off to an absolute address (if not already) 145341486Smckusick * for simplicity. 145441486Smckusick */ 145541486Smckusick if (off < (int *)ctob(UPAGES)) 145649134Skarels off = (int *)((u_int)off + (u_int)kstack); 145741486Smckusick 145841486Smckusick /* 145941486Smckusick * 68020 registers. 146054857Shibler * We know that the HP-UX registers are in the same order as ours. 146141486Smckusick * The only difference is that their PS is 2 bytes instead of a 146241486Smckusick * padded 4 like ours throwing the alignment off. 146341486Smckusick */ 146448478Skarels if (off >= ar0 && off < &ar0[18]) { 146541486Smckusick /* 146641486Smckusick * PS: return low word and high word of PC as HP-UX would 146741486Smckusick * (e.g. &u.u_ar0[16.5]). 146841486Smckusick */ 146948478Skarels if (off == &ar0[PS]) 147048478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 147141486Smckusick /* 147241486Smckusick * PC: off will be &u.u_ar0[16.5] 147341486Smckusick */ 147448478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 147548478Skarels raddr = (u_int) &ar0[PC]; 147641486Smckusick /* 147741486Smckusick * D0-D7, A0-A7: easy 147841486Smckusick */ 147941486Smckusick else 148048478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 148149134Skarels return((int)(raddr - (u_int)kstack)); 148241486Smckusick } 148341486Smckusick 148441486Smckusick /* everything else */ 148541486Smckusick return(-1); 148641486Smckusick } 148741486Smckusick 148841486Smckusick /* 148954857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 149041486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 149141486Smckusick * convert the entire user struct. 149241486Smckusick */ 149341486Smckusick hpuxdumpu(vp, cred) 149441486Smckusick struct vnode *vp; 149541486Smckusick struct ucred *cred; 149641486Smckusick { 149748478Skarels struct proc *p = curproc; 149841486Smckusick int error; 149941486Smckusick struct hpuxuser *faku; 150041486Smckusick struct bsdfp *bp; 150141486Smckusick short *foop; 150241486Smckusick 150341486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 150441486Smckusick /* 150541486Smckusick * Make sure there is no mistake about this 150641486Smckusick * being a real user structure. 150741486Smckusick */ 150841486Smckusick bzero((caddr_t)faku, ctob(1)); 150941486Smckusick /* 151041486Smckusick * Fill in the process sizes. 151141486Smckusick */ 151248478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 151348478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 151448478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 151541486Smckusick /* 151641486Smckusick * Fill in the exec header for CDB. 151741486Smckusick * This was saved back in exec(). As far as I can tell CDB 151841486Smckusick * only uses this information to verify that a particular 151941486Smckusick * core file goes with a particular binary. 152041486Smckusick */ 152149134Skarels bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 152241486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 152341486Smckusick /* 152441486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 152554857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 152641486Smckusick * so we have to move it up. 152741486Smckusick */ 152852381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 152952381Smckusick foop = (short *) p->p_md.md_regs; 153041486Smckusick foop[32] = foop[33]; 153141486Smckusick foop[33] = foop[34]; 153241486Smckusick foop[34] = foop[35]; 153341486Smckusick #ifdef FPCOPROC 153441486Smckusick /* 153554857Shibler * Copy 68881 registers from our PCB format to HP-UX format 153641486Smckusick */ 153749134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 153841486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 153941486Smckusick sizeof(bp->save)); 154041486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 154141486Smckusick sizeof(bp->ctrl)); 154241486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 154341486Smckusick sizeof(bp->reg)); 154441486Smckusick #endif 154541486Smckusick /* 154641486Smckusick * Slay the dragon 154741486Smckusick */ 154841486Smckusick faku->hpuxu_dragon = -1; 154941486Smckusick /* 155041486Smckusick * Dump this artfully constructed page in place of the 155141486Smckusick * user struct page. 155241486Smckusick */ 155348478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 155448478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 155549134Skarels (int *)NULL, p); 155641486Smckusick /* 155741486Smckusick * Dump the remaining UPAGES-1 pages normally 155841486Smckusick */ 155941486Smckusick if (!error) 156049134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 156141486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 156249134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 156341486Smckusick free((caddr_t)faku, M_TEMP); 156441486Smckusick return(error); 156541486Smckusick } 156641486Smckusick 156741486Smckusick /* 156841486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 156941486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 157041486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 157141486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 157241486Smckusick */ 157345753Smckusick #define HPUX_HZ 50 157445753Smckusick 157545788Sbostic #include "sys/times.h" 157641486Smckusick 157741486Smckusick /* from old timeb.h */ 157841486Smckusick struct hpuxtimeb { 157941486Smckusick time_t time; 158041486Smckusick u_short millitm; 158141486Smckusick short timezone; 158241486Smckusick short dstflag; 158341486Smckusick }; 158441486Smckusick 158541486Smckusick /* ye ole stat structure */ 158641486Smckusick struct ohpuxstat { 158753481Smckusick u_short ohst_dev; 158841486Smckusick u_short ohst_ino; 158941486Smckusick u_short ohst_mode; 159041486Smckusick short ohst_nlink; 159141486Smckusick short ohst_uid; 159241486Smckusick short ohst_gid; 159353481Smckusick u_short ohst_rdev; 159441486Smckusick int ohst_size; 159541486Smckusick int ohst_atime; 159641486Smckusick int ohst_mtime; 159741486Smckusick int ohst_ctime; 159841486Smckusick }; 159941486Smckusick 160041486Smckusick /* 160141486Smckusick * SYS V style setpgrp() 160241486Smckusick */ 160343452Shibler ohpuxsetpgrp(p, uap, retval) 160443452Shibler register struct proc *p; 160543452Shibler int *uap, *retval; 160641486Smckusick { 160741486Smckusick if (p->p_pid != p->p_pgid) 160848478Skarels enterpgrp(p, p->p_pid, 0); 160943452Shibler *retval = p->p_pgid; 161045753Smckusick return (0); 161141486Smckusick } 161241486Smckusick 161343452Shibler ohpuxtime(p, uap, retval) 161443452Shibler struct proc *p; 161543452Shibler register struct args { 161643452Shibler long *tp; 161743452Shibler } *uap; 161843713Smckusick time_t *retval; 161941486Smckusick { 162045753Smckusick int error = 0; 162141486Smckusick 162241486Smckusick if (uap->tp) 162343452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 162443452Shibler sizeof (long)); 162545753Smckusick *retval = time.tv_sec; 162644421Skarels return (error); 162741486Smckusick } 162841486Smckusick 162943452Shibler ohpuxstime(p, uap, retval) 163043452Shibler struct proc *p; 163143452Shibler register struct args { 163243452Shibler int time; 163343452Shibler } *uap; 163443452Shibler int *retval; 163541486Smckusick { 163641486Smckusick struct timeval tv; 163743452Shibler int s, error; 163841486Smckusick 163941486Smckusick tv.tv_sec = uap->time; 164041486Smckusick tv.tv_usec = 0; 164148478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 164244421Skarels return (error); 164341486Smckusick 164441486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 164541486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 164641486Smckusick s = splhigh(); time = tv; splx(s); 164741486Smckusick resettodr(); 164844421Skarels return (0); 164941486Smckusick } 165041486Smckusick 165143452Shibler ohpuxftime(p, uap, retval) 165243452Shibler struct proc *p; 165343452Shibler register struct args { 165441486Smckusick struct hpuxtimeb *tp; 165541486Smckusick } *uap; 165643452Shibler int *retval; 165743452Shibler { 165841486Smckusick struct hpuxtimeb tb; 165941486Smckusick int s; 166041486Smckusick 166141486Smckusick s = splhigh(); 166241486Smckusick tb.time = time.tv_sec; 166341486Smckusick tb.millitm = time.tv_usec / 1000; 166441486Smckusick splx(s); 166541486Smckusick tb.timezone = tz.tz_minuteswest; 166641486Smckusick tb.dstflag = tz.tz_dsttime; 166744421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 166841486Smckusick } 166941486Smckusick 167043452Shibler ohpuxalarm(p, uap, retval) 167143452Shibler register struct proc *p; 167243452Shibler register struct args { 167343452Shibler int deltat; 167443452Shibler } *uap; 167543452Shibler int *retval; 167641486Smckusick { 167741486Smckusick int s = splhigh(); 167841486Smckusick 167941486Smckusick untimeout(realitexpire, (caddr_t)p); 168041486Smckusick timerclear(&p->p_realtimer.it_interval); 168143452Shibler *retval = 0; 168241486Smckusick if (timerisset(&p->p_realtimer.it_value) && 168341486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 168443452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 168541486Smckusick if (uap->deltat == 0) { 168641486Smckusick timerclear(&p->p_realtimer.it_value); 168741486Smckusick splx(s); 168844421Skarels return (0); 168941486Smckusick } 169041486Smckusick p->p_realtimer.it_value = time; 169141486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 169241486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 169341486Smckusick splx(s); 169444421Skarels return (0); 169541486Smckusick } 169641486Smckusick 169743452Shibler ohpuxnice(p, uap, retval) 169843452Shibler register struct proc *p; 169943452Shibler register struct args { 170043452Shibler int niceness; 170143452Shibler } *uap; 170243452Shibler int *retval; 170341486Smckusick { 170443452Shibler int error; 170541486Smckusick 170643452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 170743452Shibler if (error == 0) 170843452Shibler *retval = p->p_nice - NZERO; 170944421Skarels return (error); 171041486Smckusick } 171141486Smckusick 171243452Shibler ohpuxtimes(p, uap, retval) 171343452Shibler struct proc *p; 171443452Shibler register struct args { 171543452Shibler struct tms *tmsb; 171643452Shibler } *uap; 171743713Smckusick time_t *retval; 171841486Smckusick { 171954771Storek struct timeval ru, rs; 172041486Smckusick struct tms atms; 172143452Shibler int error; 172241486Smckusick 172354771Storek calcru(p, &ru, &rs, NULL); 172454771Storek atms.tms_utime = hpuxscale(&ru); 172554771Storek atms.tms_stime = hpuxscale(&rs); 172648478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 172748478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 172843452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 172943452Shibler if (error == 0) 173045753Smckusick *retval = hpuxscale(&time) - hpuxscale(&boottime); 173144421Skarels return (error); 173241486Smckusick } 173341486Smckusick 173445753Smckusick /* 173545753Smckusick * Doesn't exactly do what the documentation says. 173645753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 173745753Smckusick * is what HP-UX returns. 173845753Smckusick */ 173945753Smckusick hpuxscale(tvp) 174041486Smckusick register struct timeval *tvp; 174141486Smckusick { 174245753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 174341486Smckusick } 174441486Smckusick 174541486Smckusick /* 174641486Smckusick * Set IUPD and IACC times on file. 174741486Smckusick * Can't set ICHG. 174841486Smckusick */ 174943452Shibler ohpuxutime(p, uap, retval) 175043452Shibler struct proc *p; 175141486Smckusick register struct a { 175241486Smckusick char *fname; 175341486Smckusick time_t *tptr; 175443452Shibler } *uap; 175543452Shibler int *retval; 175643452Shibler { 175748478Skarels register struct vnode *vp; 175841486Smckusick struct vattr vattr; 175941486Smckusick time_t tv[2]; 176043452Shibler int error; 176148478Skarels struct nameidata nd; 176241486Smckusick 176341486Smckusick if (uap->tptr) { 176443452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 176543452Shibler if (error) 176644421Skarels return (error); 176741486Smckusick } else 176841486Smckusick tv[0] = tv[1] = time.tv_sec; 176941486Smckusick vattr_null(&vattr); 177054107Smckusick vattr.va_atime.ts_sec = tv[0]; 177154107Smckusick vattr.va_atime.ts_nsec = 0; 177254107Smckusick vattr.va_mtime.ts_sec = tv[1]; 177354107Smckusick vattr.va_mtime.ts_nsec = 0; 177452330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 177552330Smckusick if (error = namei(&nd)) 177644421Skarels return (error); 177752330Smckusick vp = nd.ni_vp; 177842154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 177943452Shibler error = EROFS; 178041486Smckusick else 178152330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 178241486Smckusick vput(vp); 178344421Skarels return (error); 178441486Smckusick } 178541486Smckusick 178643452Shibler ohpuxpause(p, uap, retval) 178743452Shibler struct proc *p; 178843452Shibler int *uap, *retval; 178941486Smckusick { 179049134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 179142155Skarels /* always return EINTR rather than ERESTART... */ 179244421Skarels return (EINTR); 179341486Smckusick } 179441486Smckusick 179541486Smckusick /* 179641486Smckusick * The old fstat system call. 179741486Smckusick */ 179843452Shibler ohpuxfstat(p, uap, retval) 179943452Shibler struct proc *p; 180043452Shibler register struct args { 180141486Smckusick int fd; 180241486Smckusick struct ohpuxstat *sb; 180343452Shibler } *uap; 180443452Shibler int *retval; 180543452Shibler { 180645923Smckusick register struct filedesc *fdp = p->p_fd; 180741486Smckusick struct file *fp; 180841486Smckusick 180948478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 181048478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 181144421Skarels return (EBADF); 181243452Shibler if (fp->f_type != DTYPE_VNODE) 181344421Skarels return (EINVAL); 181444421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 181541486Smckusick } 181641486Smckusick 181741486Smckusick /* 181841486Smckusick * Old stat system call. This version follows links. 181941486Smckusick */ 182043452Shibler ohpuxstat(p, uap, retval) 182143452Shibler struct proc *p; 182243452Shibler register struct args { 182341486Smckusick char *fname; 182441486Smckusick struct ohpuxstat *sb; 182543452Shibler } *uap; 182643452Shibler int *retval; 182743452Shibler { 182843452Shibler int error; 182948478Skarels struct nameidata nd; 183041486Smckusick 183152330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 183252330Smckusick if (error = namei(&nd)) 183344421Skarels return (error); 183452330Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb); 183552330Smckusick vput(nd.ni_vp); 183644421Skarels return (error); 183741486Smckusick } 183841486Smckusick 183941486Smckusick int 184041486Smckusick ohpuxstat1(vp, ub) 184141486Smckusick register struct vnode *vp; 184241486Smckusick struct ohpuxstat *ub; 184341486Smckusick { 184441486Smckusick struct ohpuxstat ds; 184541486Smckusick struct vattr vattr; 184641486Smckusick register int error; 184741486Smckusick 184848478Skarels error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 184941486Smckusick if (error) 185041486Smckusick return(error); 185141486Smckusick /* 185241486Smckusick * Copy from inode table 185341486Smckusick */ 185441486Smckusick ds.ohst_dev = vattr.va_fsid; 185541486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 185641486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 185741486Smckusick ds.ohst_nlink = vattr.va_nlink; 185841486Smckusick ds.ohst_uid = (short)vattr.va_uid; 185941486Smckusick ds.ohst_gid = (short)vattr.va_gid; 186053481Smckusick ds.ohst_rdev = (u_short)vattr.va_rdev; 186141486Smckusick ds.ohst_size = (int)vattr.va_size; 186254107Smckusick ds.ohst_atime = (int)vattr.va_atime.ts_sec; 186354107Smckusick ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 186454107Smckusick ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 186541486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 186641486Smckusick } 186741486Smckusick #endif 1868