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*55832Shibler * @(#)hpux_compat.c 7.31 (Berkeley) 08/03/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 12354917Storek struct hpuxexecv_args { 12454917Storek char *fname; 12554917Storek char **argp; 12654917Storek char **envp; 12754917Storek }; 12848478Skarels hpuxexecv(p, uap, retval) 12948478Skarels struct proc *p; 13054917Storek 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 */ 14554917Storek struct hpuxwait3_args { 14654917Storek int *status; 14754917Storek int options; 14854917Storek int rusage; 14954917Storek }; 15043452Shibler hpuxwait3(p, uap, retval) 15143452Shibler struct proc *p; 15254917Storek 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 16454917Storek struct hpuxwait_args { 16554917Storek int *status; 16654917Storek }; 16743452Shibler hpuxwait(p, uap, retval) 16843452Shibler struct proc *p; 16954917Storek 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 19754917Storek struct hpuxwaitpid_args { 19854917Storek int pid; 19954917Storek int *status; 20054917Storek int options; 20154917Storek struct rusage *rusage; /* wait4 arg */ 20254917Storek }; 20343452Shibler hpuxwaitpid(p, uap, retval) 20443452Shibler struct proc *p; 20554917Storek struct hpuxwaitpid_args *uap; 20643452Shibler int *retval; 20743452Shibler { 208*55832Shibler int rv, sig, xstat, 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); 220*55832Shibler if (uap->status) { 221*55832Shibler /* 222*55832Shibler * Wait4 already wrote the status out to user space, 223*55832Shibler * pull it back, change the signal portion, and write 224*55832Shibler * it back out. 225*55832Shibler */ 226*55832Shibler rv = fuword((caddr_t)uap->status); 227*55832Shibler if (WIFSTOPPED(rv)) { 228*55832Shibler sig = WSTOPSIG(rv); 229*55832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 230*55832Shibler } else if (WIFSIGNALED(rv)) { 231*55832Shibler sig = WTERMSIG(rv); 232*55832Shibler xstat = WEXITSTATUS(rv); 233*55832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 234*55832Shibler WCOREDUMP(rv); 235*55832Shibler } 236*55832Shibler (void)suword((caddr_t)uap->status, rv); 237*55832Shibler } 23844421Skarels return (error); 23942352Smckusick } 24042352Smckusick 24141486Smckusick /* 24241486Smckusick * Must remap some bits in the mode mask. 24341486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 24441486Smckusick * O_SYNCIO (0100000) is removed entirely. 24541486Smckusick */ 24654917Storek struct hpuxopen_args { 24754917Storek char *fname; 24854917Storek int mode; 24954917Storek int crtmode; 25054917Storek }; 25143067Skarels hpuxopen(p, uap, retval) 25243067Skarels struct proc *p; 25354917Storek register struct hpuxopen_args *uap; 25443067Skarels int *retval; 25543067Skarels { 25641486Smckusick int mode; 25741486Smckusick 25841486Smckusick mode = uap->mode; 25941486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 26041486Smckusick if (mode & HPUXFCREAT) { 26141486Smckusick /* 26241486Smckusick * simulate the pre-NFS behavior that opening a 26341486Smckusick * file for READ+CREATE ignores the CREATE (unless 26441486Smckusick * EXCL is set in which case we will return the 26541486Smckusick * proper error). 26641486Smckusick */ 26748478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 26849950Smckusick uap->mode |= O_CREAT; 26941486Smckusick } 27041486Smckusick if (mode & HPUXFTRUNC) 27149950Smckusick uap->mode |= O_TRUNC; 27241486Smckusick if (mode & HPUXFEXCL) 27349950Smckusick uap->mode |= O_EXCL; 27444421Skarels return (open(p, uap, retval)); 27541486Smckusick } 27641486Smckusick 277*55832Shibler /* 278*55832Shibler * Old creat system call. 279*55832Shibler */ 280*55832Shibler struct hpuxcreat_args { 281*55832Shibler char *fname; 282*55832Shibler int fmode; 283*55832Shibler }; 284*55832Shibler hpuxcreat(p, uap, retval) 285*55832Shibler struct proc *p; 286*55832Shibler register struct hpuxcreat_args *uap; 287*55832Shibler int *retval; 288*55832Shibler { 289*55832Shibler struct nargs { 290*55832Shibler char *fname; 291*55832Shibler int mode; 292*55832Shibler int crtmode; 293*55832Shibler } openuap; 294*55832Shibler 295*55832Shibler openuap.fname = uap->fname; 296*55832Shibler openuap.crtmode = uap->fmode; 297*55832Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 298*55832Shibler return (open(p, &openuap, retval)); 299*55832Shibler } 300*55832Shibler 30149329Shibler /* XXX */ 30249329Shibler #define UF_FNDELAY_ON 0x20 30349329Shibler #define UF_FIONBIO_ON 0x40 30449329Shibler /* XXX */ 30549329Shibler 30654917Storek struct hpuxfcntl_args { 30754917Storek int fdes; 30854917Storek int cmd; 30954917Storek int arg; 31054917Storek }; 31143452Shibler hpuxfcntl(p, uap, retval) 31243452Shibler struct proc *p; 31354917Storek register struct hpuxfcntl_args *uap; 31443452Shibler int *retval; 31543452Shibler { 31643452Shibler int mode, error; 31749329Shibler char *fp; 31841486Smckusick 31949329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 32049329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 32149329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 32249329Shibler return (EBADF); 32349329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 32449329Shibler } 32541486Smckusick switch (uap->cmd) { 32641486Smckusick case F_SETFL: 32749950Smckusick if (uap->arg & FNONBLOCK) 32849329Shibler *fp |= UF_FNDELAY_ON; 32949329Shibler else { 33049329Shibler *fp &= ~UF_FNDELAY_ON; 33149329Shibler if (*fp & UF_FIONBIO_ON) 33249950Smckusick uap->arg |= FNONBLOCK; 33349329Shibler } 33441486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 33541486Smckusick break; 33641486Smckusick case F_GETFL: 33741486Smckusick case F_DUPFD: 33841486Smckusick case F_GETFD: 33941486Smckusick case F_SETFD: 34041486Smckusick break; 34141486Smckusick default: 34244421Skarels return (EINVAL); 34341486Smckusick } 34443452Shibler error = fcntl(p, uap, retval); 34549329Shibler if (error == 0 && uap->cmd == F_GETFL) { 34643452Shibler mode = *retval; 34749950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 34849950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 34949950Smckusick *retval &= ~FNONBLOCK; 35049950Smckusick if (mode & O_CREAT) 35143452Shibler *retval |= HPUXFCREAT; 35249950Smckusick if (mode & O_TRUNC) 35343452Shibler *retval |= HPUXFTRUNC; 35449950Smckusick if (mode & O_EXCL) 35543452Shibler *retval |= HPUXFEXCL; 35641486Smckusick } 35744421Skarels return (error); 35841486Smckusick } 35941486Smckusick 36041486Smckusick /* 36141486Smckusick * Read and write should return a 0 count when an operation 36249329Shibler * on a VNODE would block, not an error. 36349329Shibler * 36449329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 36549950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 36641486Smckusick */ 36754917Storek struct hpuxread_args { 36854917Storek int fd; 36954917Storek }; 37043452Shibler hpuxread(p, uap, retval) 37143452Shibler struct proc *p; 37254917Storek struct hpuxread_args *uap; 37343452Shibler int *retval; 37441486Smckusick { 37543452Shibler int error; 37641486Smckusick 37743452Shibler error = read(p, uap, retval); 37843452Shibler if (error == EWOULDBLOCK && 37949329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 38049329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 38143452Shibler error = 0; 38243452Shibler *retval = 0; 38341486Smckusick } 38444421Skarels return (error); 38541486Smckusick } 38641486Smckusick 38754917Storek struct hpuxwrite_args { 38854917Storek int fd; 38954917Storek }; 39043452Shibler hpuxwrite(p, uap, retval) 39143452Shibler struct proc *p; 39254917Storek struct hpuxwrite_args *uap; 39343452Shibler int *retval; 39441486Smckusick { 39543452Shibler int error; 39641486Smckusick 39743452Shibler error = write(p, uap, retval); 39843452Shibler if (error == EWOULDBLOCK && 39949329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 40049329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 40143452Shibler error = 0; 40243452Shibler *retval = 0; 40341486Smckusick } 40444421Skarels return (error); 40541486Smckusick } 40641486Smckusick 40754917Storek struct hpuxreadv_args { 40854917Storek int fd; 40954917Storek }; 41043452Shibler hpuxreadv(p, uap, retval) 41143452Shibler struct proc *p; 41254917Storek struct hpuxreadv_args *uap; 41343452Shibler int *retval; 41441486Smckusick { 41543452Shibler int error; 41641486Smckusick 41743452Shibler error = readv(p, uap, retval); 41843452Shibler if (error == EWOULDBLOCK && 41949329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 42049329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 42143452Shibler error = 0; 42243452Shibler *retval = 0; 42341486Smckusick } 42444421Skarels return (error); 42541486Smckusick } 42641486Smckusick 42754917Storek struct hpuxwritev_args { 42854917Storek int fd; 42954917Storek }; 43043452Shibler hpuxwritev(p, uap, retval) 43143452Shibler struct proc *p; 43254917Storek struct hpuxwritev_args *uap; 43343452Shibler int *retval; 43441486Smckusick { 43543452Shibler int error; 43641486Smckusick 43743452Shibler error = writev(p, uap, retval); 43843452Shibler if (error == EWOULDBLOCK && 43949329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 44049329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 44143452Shibler error = 0; 44243452Shibler *retval = 0; 44341486Smckusick } 44444421Skarels return (error); 44541486Smckusick } 44641486Smckusick 44741486Smckusick /* 44841486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 44954857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 45041486Smckusick */ 45154917Storek struct hpuxdup_args { 45254917Storek int i; 45354917Storek }; 45443452Shibler hpuxdup(p, uap, retval) 45543452Shibler struct proc *p; 45654917Storek register struct hpuxdup_args *uap; 45743452Shibler int *retval; 45841486Smckusick { 45945923Smckusick register struct filedesc *fdp = p->p_fd; 46041486Smckusick struct file *fp; 46143452Shibler int fd, error; 46241486Smckusick 46348478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 46448478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 46544421Skarels return (EBADF); 46648478Skarels if (error = fdalloc(p, 0, &fd)) 46744421Skarels return (error); 46848478Skarels fdp->fd_ofiles[fd] = fp; 46948478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 47045923Smckusick fp->f_count++; 47145923Smckusick if (fd > fdp->fd_lastfile) 47245923Smckusick fdp->fd_lastfile = fd; 47343452Shibler *retval = fd; 47444421Skarels return (0); 47541486Smckusick } 47641486Smckusick 47754917Storek struct hpuxutssys_args { 47854917Storek struct hpuxutsname *uts; 47954917Storek int dev; 48054917Storek int request; 48154917Storek }; 48245753Smckusick hpuxutssys(p, uap, retval) 48343452Shibler struct proc *p; 48454917Storek register struct hpuxutssys_args *uap; 48543452Shibler int *retval; 48643452Shibler { 48741486Smckusick register int i; 48843452Shibler int error; 48941486Smckusick 49041486Smckusick switch (uap->request) { 49141486Smckusick /* uname */ 49241486Smckusick case 0: 49341486Smckusick /* fill in machine type */ 49441486Smckusick switch (machineid) { 49541486Smckusick case HP_320: 49641486Smckusick protoutsname.machine[6] = '2'; 49741486Smckusick break; 49841486Smckusick /* includes 318 and 319 */ 49941486Smckusick case HP_330: 50041486Smckusick protoutsname.machine[6] = '3'; 50141486Smckusick break; 50241486Smckusick case HP_340: 50341486Smckusick protoutsname.machine[6] = '4'; 50441486Smckusick break; 50541486Smckusick case HP_350: 50641486Smckusick protoutsname.machine[6] = '5'; 50741486Smckusick break; 50841486Smckusick case HP_360: 50941486Smckusick protoutsname.machine[6] = '6'; 51041486Smckusick break; 51141486Smckusick case HP_370: 51241486Smckusick protoutsname.machine[6] = '7'; 51341486Smckusick break; 51443452Shibler /* includes 345 */ 51543452Shibler case HP_375: 51643452Shibler protoutsname.machine[6] = '7'; 51743452Shibler protoutsname.machine[7] = '5'; 51843452Shibler break; 51954857Shibler /* includes 425 */ 52054857Shibler case HP_380: 52154857Shibler protoutsname.machine[6] = '8'; 52254857Shibler break; 52341486Smckusick } 52441486Smckusick /* copy hostname (sans domain) to nodename */ 52549329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 52641486Smckusick protoutsname.nodename[i] = hostname[i]; 52749329Shibler protoutsname.nodename[i] = '\0'; 52843452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 52943452Shibler sizeof(struct hpuxutsname)); 53041486Smckusick break; 53145753Smckusick 53245753Smckusick /* gethostname */ 53345753Smckusick case 5: 53445753Smckusick /* uap->dev is length */ 53545753Smckusick if (uap->dev > hostnamelen + 1) 53645753Smckusick uap->dev = hostnamelen + 1; 53745753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 53845753Smckusick uap->dev); 53945753Smckusick break; 54045753Smckusick 54145753Smckusick case 1: /* ?? */ 54245753Smckusick case 2: /* ustat */ 54345753Smckusick case 3: /* ?? */ 54445753Smckusick case 4: /* sethostname */ 54541486Smckusick default: 54643452Shibler error = EINVAL; 54741486Smckusick break; 54841486Smckusick } 54944421Skarels return (error); 55041486Smckusick } 55141486Smckusick 55254917Storek struct hpuxsysconf_args { 55354917Storek int name; 55454917Storek }; 55553922Shibler hpuxsysconf(p, uap, retval) 55653922Shibler struct proc *p; 55754917Storek struct hpuxsysconf_args *uap; 55853922Shibler int *retval; 55953922Shibler { 56053922Shibler switch (uap->name) { 56153922Shibler 56253922Shibler /* open files */ 56353922Shibler case HPUX_SYSCONF_OPENMAX: 56453922Shibler *retval = NOFILE; 56553922Shibler break; 56653922Shibler 56753922Shibler /* architecture */ 56853922Shibler case HPUX_SYSCONF_CPUTYPE: 56953922Shibler switch (machineid) { 57053922Shibler case HP_320: 57153922Shibler case HP_330: 57253922Shibler case HP_350: 57353922Shibler *retval = HPUX_SYSCONF_CPUM020; 57453922Shibler break; 57553922Shibler case HP_340: 57653922Shibler case HP_360: 57753922Shibler case HP_370: 57853922Shibler case HP_375: 57953922Shibler *retval = HPUX_SYSCONF_CPUM030; 58053922Shibler break; 58153922Shibler case HP_380: 58253922Shibler *retval = HPUX_SYSCONF_CPUM040; 58353922Shibler break; 58453922Shibler } 58553922Shibler break; 58653922Shibler default: 58754857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 58853922Shibler return (EINVAL); 58953922Shibler } 59053922Shibler return (0); 59153922Shibler } 59253922Shibler 59354917Storek struct hpuxstat_args { 59454917Storek char *fname; 59554917Storek struct hpuxstat *hsb; 59654917Storek }; 59743452Shibler hpuxstat(p, uap, retval) 59843452Shibler struct proc *p; 59954917Storek struct hpuxstat_args *uap; 60043452Shibler int *retval; 60143452Shibler { 60255282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 60341486Smckusick } 60441486Smckusick 60554917Storek struct hpuxlstat_args { 60654917Storek char *fname; 60754917Storek struct hpuxstat *hsb; 60854917Storek }; 60943452Shibler hpuxlstat(p, uap, retval) 61043452Shibler struct proc *p; 61154917Storek struct hpuxlstat_args *uap; 61243452Shibler int *retval; 61341486Smckusick { 61455282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 61541486Smckusick } 61641486Smckusick 61754917Storek struct hpuxfstat_args { 61854917Storek int fdes; 61954917Storek struct hpuxstat *hsb; 62054917Storek }; 62143452Shibler hpuxfstat(p, uap, retval) 62243452Shibler struct proc *p; 62354917Storek register struct hpuxfstat_args *uap; 62443452Shibler int *retval; 62541486Smckusick { 62645923Smckusick register struct filedesc *fdp = p->p_fd; 62741486Smckusick register struct file *fp; 62841486Smckusick struct stat sb; 62943452Shibler int error; 63041486Smckusick 63148478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 63248478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 63344421Skarels return (EBADF); 63443452Shibler 63541486Smckusick switch (fp->f_type) { 63641486Smckusick 63741486Smckusick case DTYPE_VNODE: 63855282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 63941486Smckusick break; 64041486Smckusick 64141486Smckusick case DTYPE_SOCKET: 64255282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 64341486Smckusick break; 64441486Smckusick 64541486Smckusick default: 64641486Smckusick panic("fstat"); 64741486Smckusick /*NOTREACHED*/ 64841486Smckusick } 64941486Smckusick /* is this right for sockets?? */ 65043452Shibler if (error == 0) 65143452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 65244421Skarels return (error); 65341486Smckusick } 65441486Smckusick 65554917Storek struct hpuxulimit_args { 65654917Storek int cmd; 65754917Storek long newlimit; 65854917Storek }; 65943452Shibler hpuxulimit(p, uap, retval) 66043452Shibler struct proc *p; 66154917Storek register struct hpuxulimit_args *uap; 66253481Smckusick long *retval; 66343452Shibler { 66441486Smckusick struct rlimit *limp; 66543452Shibler int error = 0; 66641486Smckusick 66748478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 66841486Smckusick switch (uap->cmd) { 66941486Smckusick case 2: 67041486Smckusick uap->newlimit *= 512; 67141486Smckusick if (uap->newlimit > limp->rlim_max && 67248478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 67341486Smckusick break; 67441486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 67541486Smckusick /* else fall into... */ 67641486Smckusick 67741486Smckusick case 1: 67845753Smckusick *retval = limp->rlim_max / 512; 67941486Smckusick break; 68041486Smckusick 68141486Smckusick case 3: 68248478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 68348478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 68441486Smckusick break; 68541486Smckusick 68641486Smckusick default: 68743452Shibler error = EINVAL; 68841486Smckusick break; 68941486Smckusick } 69044421Skarels return (error); 69141486Smckusick } 69241486Smckusick 69341486Smckusick /* 69441486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 69541486Smckusick * values -16 (high) thru -1 (low). 69641486Smckusick */ 69754917Storek struct hpuxrtprio_args { 69854917Storek int pid; 69954917Storek int prio; 70054917Storek }; 70143452Shibler hpuxrtprio(cp, uap, retval) 70243452Shibler struct proc *cp; 70354917Storek register struct hpuxrtprio_args *uap; 70443452Shibler int *retval; 70543452Shibler { 70641486Smckusick struct proc *p; 70743452Shibler int nice, error; 70841486Smckusick 70941486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 71043452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 71144421Skarels return (EINVAL); 71241486Smckusick if (uap->pid == 0) 71343452Shibler p = cp; 71443452Shibler else if ((p = pfind(uap->pid)) == 0) 71544421Skarels return (ESRCH); 71641486Smckusick nice = p->p_nice; 71741486Smckusick if (nice < NZERO) 71843452Shibler *retval = (nice + 16) << 3; 71941486Smckusick else 72043452Shibler *retval = RTPRIO_RTOFF; 72141486Smckusick switch (uap->prio) { 72241486Smckusick 72341486Smckusick case RTPRIO_NOCHG: 72444421Skarels return (0); 72541486Smckusick 72641486Smckusick case RTPRIO_RTOFF: 72741486Smckusick if (nice >= NZERO) 72844421Skarels return (0); 72941486Smckusick nice = NZERO; 73041486Smckusick break; 73141486Smckusick 73241486Smckusick default: 73341486Smckusick nice = (uap->prio >> 3) - 16; 73441486Smckusick break; 73541486Smckusick } 73643452Shibler error = donice(cp, p, nice); 73743452Shibler if (error == EACCES) 73843452Shibler error = EPERM; 73944421Skarels return (error); 74041486Smckusick } 74141486Smckusick 74254917Storek struct hpuxadvise_args { 74354917Storek int arg; 74454917Storek }; 74543452Shibler hpuxadvise(p, uap, retval) 74643452Shibler struct proc *p; 74754917Storek struct hpuxadvise_args *uap; 74843452Shibler int *retval; 74941486Smckusick { 75043452Shibler int error = 0; 75141486Smckusick 75241486Smckusick switch (uap->arg) { 75341486Smckusick case 0: 75449134Skarels p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; 75541486Smckusick break; 75641486Smckusick case 1: 75741486Smckusick ICIA(); 75841486Smckusick break; 75941486Smckusick case 2: 76041486Smckusick DCIA(); 76141486Smckusick break; 76241486Smckusick default: 76343452Shibler error = EINVAL; 76441486Smckusick break; 76541486Smckusick } 76644421Skarels return (error); 76741486Smckusick } 76841486Smckusick 76954917Storek struct hpuxptrace_args { 77054917Storek int req; 77154917Storek int pid; 77254917Storek int *addr; 77354917Storek int data; 77454917Storek }; 77543452Shibler hpuxptrace(p, uap, retval) 77643452Shibler struct proc *p; 77754917Storek struct hpuxptrace_args *uap; 77843452Shibler int *retval; 77943452Shibler { 78043452Shibler int error; 78141486Smckusick 78241486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 78341486Smckusick if (uap->data) { 78441486Smckusick uap->data = hpuxtobsdsig(uap->data); 78541486Smckusick if (uap->data == 0) 78641486Smckusick uap->data = NSIG; 78741486Smckusick } 78841486Smckusick } 78943452Shibler error = ptrace(p, uap, retval); 79044421Skarels return (error); 79141486Smckusick } 79241486Smckusick 79354917Storek struct hpuxgetdomainname_args { 79454917Storek char *domainname; 79554917Storek u_int len; 79654917Storek }; 79743452Shibler hpuxgetdomainname(p, uap, retval) 79843452Shibler struct proc *p; 79954917Storek register struct hpuxgetdomainname_args *uap; 80043452Shibler int *retval; 80143452Shibler { 80241486Smckusick if (uap->len > domainnamelen + 1) 80341486Smckusick uap->len = domainnamelen + 1; 80444421Skarels return (copyout(domainname, uap->domainname, uap->len)); 80541486Smckusick } 80641486Smckusick 80754917Storek struct hpuxsetdomainname_args { 80854917Storek char *domainname; 80954917Storek u_int len; 81054917Storek }; 81143452Shibler hpuxsetdomainname(p, uap, retval) 81243452Shibler struct proc *p; 81354917Storek register struct hpuxsetdomainname_args *uap; 81443452Shibler int *retval; 81543452Shibler { 81643452Shibler int error; 81741486Smckusick 81848478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 81944421Skarels return (error); 82043452Shibler if (uap->len > sizeof (domainname) - 1) 82144421Skarels return (EINVAL); 82241486Smckusick domainnamelen = uap->len; 82343452Shibler error = copyin(uap->domainname, domainname, uap->len); 82441486Smckusick domainname[domainnamelen] = 0; 82544421Skarels return (error); 82641486Smckusick } 82741486Smckusick 82841486Smckusick #ifdef SYSVSHM 82954857Shibler #include "shm.h" 83054857Shibler 83143452Shibler hpuxshmat(p, uap, retval) 83243452Shibler struct proc *p; 83343452Shibler int *uap, *retval; 83441486Smckusick { 83544421Skarels return (shmat(p, uap, retval)); 83641486Smckusick } 83741486Smckusick 83843452Shibler hpuxshmdt(p, uap, retval) 83943452Shibler struct proc *p; 84043452Shibler int *uap, *retval; 84141486Smckusick { 84244421Skarels return (shmdt(p, uap, retval)); 84341486Smckusick } 84441486Smckusick 84543452Shibler hpuxshmget(p, uap, retval) 84643452Shibler struct proc *p; 84743452Shibler int *uap, *retval; 84841486Smckusick { 84944421Skarels return (shmget(p, uap, retval)); 85041486Smckusick } 85154857Shibler 85254857Shibler /* 85354857Shibler * Handle HP-UX specific commands. 85454857Shibler */ 85554917Storek struct hpuxshmctl_args { 85654917Storek int shmid; 85754917Storek int cmd; 85854917Storek caddr_t buf; 85954917Storek }; 86054857Shibler hpuxshmctl(p, uap, retval) 86154857Shibler struct proc *p; 86254917Storek struct hpuxshmctl_args *uap; 86354857Shibler int *retval; 86454857Shibler { 86554857Shibler register struct shmid_ds *shp; 86654857Shibler register struct ucred *cred = p->p_ucred; 86754857Shibler int error; 86854857Shibler 86954857Shibler if (error = shmvalid(uap->shmid)) 87054857Shibler return (error); 87154857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 87254857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 87354857Shibler /* don't really do anything, but make them think we did */ 87454857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 87554857Shibler cred->cr_uid != shp->shm_perm.cuid) 87654857Shibler return (EPERM); 87754857Shibler return (0); 87854857Shibler } 87954857Shibler return (shmctl(p, uap, retval)); 88054857Shibler } 88141486Smckusick #endif 88241486Smckusick 88341486Smckusick /* 88441486Smckusick * Fake semaphore routines, just don't return an error. 88541486Smckusick * Should be adequate for starbase to run. 88641486Smckusick */ 88754917Storek struct hpuxsemctl_args { 88854917Storek int semid; 88954917Storek u_int semnum; 89054917Storek int cmd; 89154917Storek int arg; 89254917Storek }; 89343452Shibler hpuxsemctl(p, uap, retval) 89443452Shibler struct proc *p; 89554917Storek struct hpuxsemctl_args *uap; 89643452Shibler int *retval; 89743452Shibler { 89841486Smckusick /* XXX: should do something here */ 89944421Skarels return (0); 90041486Smckusick } 90141486Smckusick 90254917Storek struct hpuxsemget_args { 90354917Storek key_t key; 90454917Storek int nsems; 90554917Storek int semflg; 90654917Storek }; 90743452Shibler hpuxsemget(p, uap, retval) 90843452Shibler struct proc *p; 90954917Storek struct hpuxsemget_args *uap; 91043452Shibler int *retval; 91143452Shibler { 91241486Smckusick /* XXX: should do something here */ 91344421Skarels return (0); 91441486Smckusick } 91541486Smckusick 91654917Storek struct hpuxsemop_args { 91754917Storek int semid; 91854917Storek struct sembuf *sops; 91954917Storek u_int nsops; 92054917Storek }; 92143452Shibler hpuxsemop(p, uap, retval) 92243452Shibler struct proc *p; 92354917Storek struct hpuxsemop_args *uap; 92443452Shibler int *retval; 92543452Shibler { 92641486Smckusick /* XXX: should do something here */ 92744421Skarels return (0); 92841486Smckusick } 92941486Smckusick 93054857Shibler /* convert from BSD to HP-UX errno */ 93141486Smckusick bsdtohpuxerrno(err) 93241486Smckusick int err; 93341486Smckusick { 93441486Smckusick if (err < 0 || err >= NERR) 93541486Smckusick return(BERR); 93641486Smckusick return((int)bsdtohpuxerrnomap[err]); 93741486Smckusick } 93841486Smckusick 93955282Smckusick hpuxstat1(fname, hsb, follow, p) 94041486Smckusick char *fname; 94141486Smckusick struct hpuxstat *hsb; 94241486Smckusick int follow; 94355282Smckusick struct proc *p; 94441486Smckusick { 94548478Skarels int error; 94641486Smckusick struct stat sb; 94748478Skarels struct nameidata nd; 94841486Smckusick 94955282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 95052330Smckusick if (error = namei(&nd)) 95141486Smckusick return (error); 95255282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 95352330Smckusick vput(nd.ni_vp); 95441486Smckusick if (error == 0) 95541486Smckusick error = bsdtohpuxstat(&sb, hsb); 95641486Smckusick return (error); 95741486Smckusick } 95841486Smckusick 95941486Smckusick #include "grf.h" 96053922Shibler #if NGRF > 0 96153922Shibler #ifdef __STDC__ 96253922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 96353922Shibler #else 96453922Shibler extern int grfopen(); 96553922Shibler #endif 96653922Shibler #endif 96741486Smckusick 96853922Shibler #define NHIL 1 /* XXX */ 96953922Shibler #if NHIL > 0 97053922Shibler #ifdef __STDC__ 97153922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 97253922Shibler #else 97353922Shibler extern int hilopen(); 97453922Shibler #endif 97553922Shibler #endif 97653922Shibler 97753922Shibler #include "conf.h" 97853922Shibler 97941486Smckusick bsdtohpuxstat(sb, hsb) 98041486Smckusick struct stat *sb; 98141486Smckusick struct hpuxstat *hsb; 98241486Smckusick { 98341486Smckusick struct hpuxstat ds; 98441486Smckusick 98541486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 98653481Smckusick ds.hst_dev = (u_short)sb->st_dev; 98741486Smckusick ds.hst_ino = (u_long)sb->st_ino; 98841486Smckusick ds.hst_mode = sb->st_mode; 98941486Smckusick ds.hst_nlink = sb->st_nlink; 99041486Smckusick ds.hst_uid = (u_short)sb->st_uid; 99141486Smckusick ds.hst_gid = (u_short)sb->st_gid; 99253922Shibler /* XXX: I don't want to talk about it... */ 99353922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 99441486Smckusick #if NGRF > 0 99553922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 99653922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 99741486Smckusick #endif 99853922Shibler #if NHIL > 0 99953922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 100053922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 100153922Shibler #endif 100253922Shibler ; 100353922Shibler } else 100441486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 100553481Smckusick if (sb->st_size < (quad_t)1 << 32) 100653481Smckusick ds.hst_size = (long)sb->st_size; 100753481Smckusick else 100853481Smckusick ds.hst_size = -2; 100941486Smckusick ds.hst_atime = sb->st_atime; 101041486Smckusick ds.hst_mtime = sb->st_mtime; 101141486Smckusick ds.hst_ctime = sb->st_ctime; 101241486Smckusick ds.hst_blksize = sb->st_blksize; 101341486Smckusick ds.hst_blocks = sb->st_blocks; 101441486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 101541486Smckusick } 101641486Smckusick 101741486Smckusick hpuxtobsdioctl(com) 101841486Smckusick int com; 101941486Smckusick { 102041486Smckusick switch (com) { 102141486Smckusick case HPUXTIOCSLTC: 102241486Smckusick com = TIOCSLTC; break; 102341486Smckusick case HPUXTIOCGLTC: 102441486Smckusick com = TIOCGLTC; break; 102541486Smckusick case HPUXTIOCSPGRP: 102641486Smckusick com = TIOCSPGRP; break; 102741486Smckusick case HPUXTIOCGPGRP: 102841486Smckusick com = TIOCGPGRP; break; 102941486Smckusick case HPUXTIOCLBIS: 103041486Smckusick com = TIOCLBIS; break; 103141486Smckusick case HPUXTIOCLBIC: 103241486Smckusick com = TIOCLBIC; break; 103341486Smckusick case HPUXTIOCLSET: 103441486Smckusick com = TIOCLSET; break; 103541486Smckusick case HPUXTIOCLGET: 103641486Smckusick com = TIOCLGET; break; 103741486Smckusick } 103841486Smckusick return(com); 103941486Smckusick } 104041486Smckusick 104141486Smckusick /* 104254857Shibler * HP-UX ioctl system call. The differences here are: 104341486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 104449329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 104541486Smckusick * the sgttyb struct is 2 bytes longer 104641486Smckusick */ 104754917Storek struct hpuxioctl_args { 104854917Storek int fdes; 104954917Storek int cmd; 105054917Storek caddr_t cmarg; 105154917Storek }; 105243452Shibler hpuxioctl(p, uap, retval) 105343452Shibler struct proc *p; 105454917Storek register struct hpuxioctl_args *uap; 105543452Shibler int *retval; 105643452Shibler { 105745923Smckusick register struct filedesc *fdp = p->p_fd; 105843452Shibler register struct file *fp; 105943452Shibler register int com, error; 106041486Smckusick register u_int size; 106141486Smckusick caddr_t memp = 0; 106241486Smckusick #define STK_PARAMS 128 106341486Smckusick char stkbuf[STK_PARAMS]; 106441486Smckusick caddr_t data = stkbuf; 106541486Smckusick 106641486Smckusick com = uap->cmd; 106741486Smckusick 106841486Smckusick /* XXX */ 106943452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 107045923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 107141486Smckusick 107248478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 107348478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 107444421Skarels return (EBADF); 107543452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 107644421Skarels return (EBADF); 107741486Smckusick 107841486Smckusick /* 107941486Smckusick * Interpret high order word to find 108041486Smckusick * amount of data to be copied to/from the 108141486Smckusick * user's address space. 108241486Smckusick */ 108341486Smckusick size = IOCPARM_LEN(com); 108443452Shibler if (size > IOCPARM_MAX) 108544421Skarels return (ENOTTY); 108641486Smckusick if (size > sizeof (stkbuf)) { 108743452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 108841486Smckusick data = memp; 108941486Smckusick } 109041486Smckusick if (com&IOC_IN) { 109141486Smckusick if (size) { 109243452Shibler error = copyin(uap->cmarg, data, (u_int)size); 109343452Shibler if (error) { 109441486Smckusick if (memp) 109541486Smckusick free(memp, M_IOCTLOPS); 109644421Skarels return (error); 109741486Smckusick } 109841486Smckusick } else 109941486Smckusick *(caddr_t *)data = uap->cmarg; 110041486Smckusick } else if ((com&IOC_OUT) && size) 110141486Smckusick /* 110243452Shibler * Zero the buffer so the user always 110343452Shibler * gets back something deterministic. 110441486Smckusick */ 110541486Smckusick bzero(data, size); 110641486Smckusick else if (com&IOC_VOID) 110741486Smckusick *(caddr_t *)data = uap->cmarg; 110841486Smckusick 110941486Smckusick switch (com) { 111041486Smckusick 111149329Shibler case HPUXFIOSNBIO: 111249329Shibler { 111349329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 111449329Shibler int tmp; 111549329Shibler 111649329Shibler if (*(int *)data) 111749329Shibler *ofp |= UF_FIONBIO_ON; 111849329Shibler else 111949329Shibler *ofp &= ~UF_FIONBIO_ON; 112049329Shibler /* 112149950Smckusick * Only set/clear if FNONBLOCK not in effect 112249329Shibler */ 112349329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 112449950Smckusick tmp = fp->f_flag & FNONBLOCK; 112549329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 112649329Shibler (caddr_t)&tmp, p); 112749329Shibler } 112849329Shibler break; 112949329Shibler } 113049329Shibler 113141486Smckusick case HPUXTIOCCONS: 113241486Smckusick *(int *)data = 1; 113348478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 113441486Smckusick break; 113541486Smckusick 113641486Smckusick /* BSD-style job control ioctls */ 113741486Smckusick case HPUXTIOCLBIS: 113841486Smckusick case HPUXTIOCLBIC: 113941486Smckusick case HPUXTIOCLSET: 114041486Smckusick *(int *)data &= HPUXLTOSTOP; 114141486Smckusick if (*(int *)data & HPUXLTOSTOP) 114241486Smckusick *(int *)data = LTOSTOP; 114341486Smckusick /* fall into */ 114441486Smckusick case HPUXTIOCLGET: 114541486Smckusick case HPUXTIOCSLTC: 114641486Smckusick case HPUXTIOCGLTC: 114741486Smckusick case HPUXTIOCSPGRP: 114841486Smckusick case HPUXTIOCGPGRP: 114948478Skarels error = (*fp->f_ops->fo_ioctl) 115048478Skarels (fp, hpuxtobsdioctl(com), data, p); 115143452Shibler if (error == 0 && com == HPUXTIOCLGET) { 115241486Smckusick *(int *)data &= LTOSTOP; 115341486Smckusick if (*(int *)data & LTOSTOP) 115441486Smckusick *(int *)data = HPUXLTOSTOP; 115541486Smckusick } 115641486Smckusick break; 115741486Smckusick 1158*55832Shibler /* SYS 5 termio and POSIX termios */ 115941486Smckusick case HPUXTCGETA: 116041486Smckusick case HPUXTCSETA: 116141486Smckusick case HPUXTCSETAW: 116241486Smckusick case HPUXTCSETAF: 1163*55832Shibler case HPUXTCGETATTR: 1164*55832Shibler case HPUXTCSETATTR: 1165*55832Shibler case HPUXTCSETATTRD: 1166*55832Shibler case HPUXTCSETATTRF: 116748478Skarels error = hpuxtermio(fp, com, data, p); 116841486Smckusick break; 116941486Smckusick 117041486Smckusick default: 117148478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 117241486Smckusick break; 117341486Smckusick } 117441486Smckusick /* 117541486Smckusick * Copy any data to user, size was 117641486Smckusick * already set and checked above. 117741486Smckusick */ 117843452Shibler if (error == 0 && (com&IOC_OUT) && size) 117943452Shibler error = copyout(data, uap->cmarg, (u_int)size); 118041486Smckusick if (memp) 118141486Smckusick free(memp, M_IOCTLOPS); 118244421Skarels return (error); 118341486Smckusick } 118441486Smckusick 118541486Smckusick /* 118641486Smckusick * Man page lies, behaviour here is based on observed behaviour. 118741486Smckusick */ 118854917Storek struct hpuxgetcontext_args { 118954917Storek char *buf; 119054917Storek int len; 119154917Storek }; 119243452Shibler hpuxgetcontext(p, uap, retval) 119343452Shibler struct proc *p; 119454917Storek struct hpuxgetcontext_args *uap; 119543452Shibler int *retval; 119643452Shibler { 119741486Smckusick int error = 0; 119841486Smckusick register int len; 119941486Smckusick 120053922Shibler #if defined(HP380) 120153922Shibler if (machineid == HP_380) { 120255072Spendry len = min(uap->len, sizeof(hpux040context)); 120353922Shibler if (len) 120453922Shibler error = copyout(hpux040context, uap->buf, len); 120553922Shibler if (error == 0) 120653922Shibler *retval = sizeof(hpux040context); 120753922Shibler return (error); 120853922Shibler } 120953922Shibler #endif 121055072Spendry len = min(uap->len, sizeof(hpuxcontext)); 121141486Smckusick if (len) 121241486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 121343452Shibler if (error == 0) 121443452Shibler *retval = sizeof(hpuxcontext); 121544421Skarels return (error); 121641486Smckusick } 121741486Smckusick 121841486Smckusick /* 121941486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 122041486Smckusick * Note we do not check the real uid or "saved" uid. 122141486Smckusick */ 122254917Storek struct hpuxgetpgrp2_args { 122354917Storek int pid; 122454917Storek }; 122543452Shibler hpuxgetpgrp2(cp, uap, retval) 122643452Shibler struct proc *cp; 122754917Storek register struct hpuxgetpgrp2_args *uap; 122843452Shibler int *retval; 122941486Smckusick { 123041486Smckusick register struct proc *p; 123141486Smckusick 123241486Smckusick if (uap->pid == 0) 123343452Shibler uap->pid = cp->p_pid; 123441486Smckusick p = pfind(uap->pid); 123543452Shibler if (p == 0) 123644421Skarels return (ESRCH); 123748478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 123848478Skarels !inferior(p)) 123944421Skarels return (EPERM); 124043452Shibler *retval = p->p_pgid; 124144421Skarels return (0); 124241486Smckusick } 124341486Smckusick 124441486Smckusick /* 124541486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 124641486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 124741486Smckusick */ 124854917Storek struct hpuxsetpgrp2_args { 124954917Storek int pid; 125054917Storek int pgrp; 125154917Storek }; 125243452Shibler hpuxsetpgrp2(p, uap, retval) 125343452Shibler struct proc *p; 125454917Storek struct hpuxsetpgrp2_args *uap; 125543452Shibler int *retval; 125643452Shibler { 125741486Smckusick /* empirically determined */ 125843452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 125944421Skarels return (EINVAL); 126048478Skarels return (setpgid(p, uap, retval)); 126141486Smckusick } 126241486Smckusick 126341486Smckusick /* 126455165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 126545753Smckusick */ 126654917Storek struct hpuxsetresuid_args { 126754917Storek int ruid; 126854917Storek int euid; 126954917Storek int suid; 127054917Storek }; 127145753Smckusick hpuxsetresuid(p, uap, retval) 127255165Smckusick struct proc *p; 127354917Storek struct hpuxsetresuid_args *uap; 127445753Smckusick int *retval; 127545753Smckusick { 127655165Smckusick return (osetreuid(p, uap, retval)); 127745753Smckusick } 127845753Smckusick 127954917Storek struct hpuxsetresgid_args { 128054917Storek int rgid; 128154917Storek int egid; 128254917Storek int sgid; 128354917Storek }; 128445753Smckusick hpuxsetresgid(p, uap, retval) 128555165Smckusick struct proc *p; 128654917Storek struct hpuxsetresgid_args *uap; 128745753Smckusick int *retval; 128845753Smckusick { 128955165Smckusick return (osetregid(p, uap, retval)); 129045753Smckusick } 129145753Smckusick 129245753Smckusick /* 129345753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 129445753Smckusick */ 129554917Storek struct hpuxlockf_args { 129654917Storek int fd; 129754917Storek int func; 129854917Storek long size; 129954917Storek }; 130045753Smckusick hpuxlockf(p, uap, retval) 130145753Smckusick struct proc *p; 130254917Storek struct hpuxlockf_args *uap; 130345753Smckusick int *retval; 130445753Smckusick { 130545753Smckusick return (0); 130645753Smckusick } 130745753Smckusick 130854917Storek struct hpuxgetaccess_args { 130954917Storek char *path; 131054917Storek int uid; 131154917Storek int ngroups; 131254917Storek int *gidset; 131354917Storek void *label; 131454917Storek void *privs; 131554917Storek }; 131645753Smckusick hpuxgetaccess(p, uap, retval) 131745753Smckusick register struct proc *p; 131854917Storek register struct hpuxgetaccess_args *uap; 131945753Smckusick int *retval; 132045753Smckusick { 132145753Smckusick int lgroups[NGROUPS]; 132245753Smckusick int error = 0; 132345753Smckusick register struct ucred *cred; 132445753Smckusick register struct vnode *vp; 132552330Smckusick struct nameidata nd; 132645753Smckusick 132745753Smckusick /* 132845753Smckusick * Build an appropriate credential structure 132945753Smckusick */ 133048478Skarels cred = crdup(p->p_ucred); 133145753Smckusick switch (uap->uid) { 133245753Smckusick case 65502: /* UID_EUID */ 133345753Smckusick break; 133445753Smckusick case 65503: /* UID_RUID */ 133548478Skarels cred->cr_uid = p->p_cred->p_ruid; 133645753Smckusick break; 133745753Smckusick case 65504: /* UID_SUID */ 133845753Smckusick error = EINVAL; 133945753Smckusick break; 134045753Smckusick default: 134145753Smckusick if (uap->uid > 65504) 134245753Smckusick error = EINVAL; 134345753Smckusick cred->cr_uid = uap->uid; 134445753Smckusick break; 134545753Smckusick } 134645753Smckusick switch (uap->ngroups) { 134745753Smckusick case -1: /* NGROUPS_EGID */ 134845753Smckusick cred->cr_ngroups = 1; 134945753Smckusick break; 135045753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 135145753Smckusick break; 135245753Smckusick case -2: /* NGROUPS_RGID */ 135345753Smckusick cred->cr_ngroups = 1; 135448478Skarels cred->cr_gid = p->p_cred->p_rgid; 135545753Smckusick break; 135645753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 135748478Skarels cred->cr_gid = p->p_cred->p_rgid; 135845753Smckusick break; 135945753Smckusick case -3: /* NGROUPS_SGID */ 136045753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 136145753Smckusick error = EINVAL; 136245753Smckusick break; 136345753Smckusick case -4: /* NGROUPS_SUPP */ 136445753Smckusick if (cred->cr_ngroups > 1) 136545753Smckusick cred->cr_gid = cred->cr_groups[1]; 136645753Smckusick else 136745753Smckusick error = EINVAL; 136845753Smckusick break; 136945753Smckusick default: 137045753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 137145753Smckusick error = copyin((caddr_t)uap->gidset, 137245753Smckusick (caddr_t)&lgroups[0], 137345753Smckusick uap->ngroups * sizeof(lgroups[0])); 137445753Smckusick else 137545753Smckusick error = EINVAL; 137645753Smckusick if (error == 0) { 137745753Smckusick int gid; 137845753Smckusick 137945753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 138045753Smckusick cred->cr_groups[gid] = lgroups[gid]; 138145753Smckusick cred->cr_ngroups = uap->ngroups; 138245753Smckusick } 138345753Smckusick break; 138445753Smckusick } 138545753Smckusick /* 138645753Smckusick * Lookup file using caller's effective IDs. 138745753Smckusick */ 138845753Smckusick if (error == 0) { 138952330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 139052330Smckusick uap->path, p); 139152330Smckusick error = namei(&nd); 139245753Smckusick } 139345753Smckusick if (error) { 139445753Smckusick crfree(cred); 139545753Smckusick return (error); 139645753Smckusick } 139745753Smckusick /* 139845753Smckusick * Use the constructed credentials for access checks. 139945753Smckusick */ 140052330Smckusick vp = nd.ni_vp; 140145753Smckusick *retval = 0; 140248478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 140345753Smckusick *retval |= R_OK; 140448478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 140545753Smckusick *retval |= W_OK; 140645753Smckusick /* XXX we return X_OK for root on VREG even if not */ 140748478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 140845753Smckusick *retval |= X_OK; 140945753Smckusick vput(vp); 141045753Smckusick crfree(cred); 141145753Smckusick return (error); 141245753Smckusick } 141345753Smckusick 141445753Smckusick /* 141554857Shibler * Brutal hack! Map HP-UX u-area offsets into BSD u offsets. 141641486Smckusick * No apologies offered, if you don't like it, rewrite it! 141741486Smckusick */ 141841486Smckusick 141949134Skarels extern char kstack[]; 142041486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 142141486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 142241486Smckusick 142341486Smckusick /* simplified FP structure */ 142441486Smckusick struct bsdfp { 142541486Smckusick int save[54]; 142641486Smckusick int reg[24]; 142741486Smckusick int ctrl[3]; 142841486Smckusick }; 142941486Smckusick 143041486Smckusick hpuxtobsduoff(off) 143141486Smckusick int *off; 143241486Smckusick { 143352381Smckusick register int *ar0 = curproc->p_md.md_regs; 143441486Smckusick struct hpuxfp *hp; 143541486Smckusick struct bsdfp *bp; 143641486Smckusick register u_int raddr; 143741486Smckusick 143848478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 143941486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 144048478Skarels return(UOFF(U_ar0)); 144141486Smckusick 144241486Smckusick #ifdef FPCOPROC 144341486Smckusick /* 68881 registers from PCB */ 144441486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 144541486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 144641486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 144741486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 144841486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 144941486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 145041486Smckusick #endif 145141486Smckusick 145241486Smckusick /* 145341486Smckusick * Everything else we recognize comes from the kernel stack, 145441486Smckusick * so we convert off to an absolute address (if not already) 145541486Smckusick * for simplicity. 145641486Smckusick */ 145741486Smckusick if (off < (int *)ctob(UPAGES)) 145849134Skarels off = (int *)((u_int)off + (u_int)kstack); 145941486Smckusick 146041486Smckusick /* 146141486Smckusick * 68020 registers. 146254857Shibler * We know that the HP-UX registers are in the same order as ours. 146341486Smckusick * The only difference is that their PS is 2 bytes instead of a 146441486Smckusick * padded 4 like ours throwing the alignment off. 146541486Smckusick */ 146648478Skarels if (off >= ar0 && off < &ar0[18]) { 146741486Smckusick /* 146841486Smckusick * PS: return low word and high word of PC as HP-UX would 146941486Smckusick * (e.g. &u.u_ar0[16.5]). 147041486Smckusick */ 147148478Skarels if (off == &ar0[PS]) 147248478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 147341486Smckusick /* 147441486Smckusick * PC: off will be &u.u_ar0[16.5] 147541486Smckusick */ 147648478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 147748478Skarels raddr = (u_int) &ar0[PC]; 147841486Smckusick /* 147941486Smckusick * D0-D7, A0-A7: easy 148041486Smckusick */ 148141486Smckusick else 148248478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 148349134Skarels return((int)(raddr - (u_int)kstack)); 148441486Smckusick } 148541486Smckusick 148641486Smckusick /* everything else */ 148741486Smckusick return(-1); 148841486Smckusick } 148941486Smckusick 149041486Smckusick /* 149154857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 149241486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 149341486Smckusick * convert the entire user struct. 149441486Smckusick */ 149541486Smckusick hpuxdumpu(vp, cred) 149641486Smckusick struct vnode *vp; 149741486Smckusick struct ucred *cred; 149841486Smckusick { 149948478Skarels struct proc *p = curproc; 150041486Smckusick int error; 150141486Smckusick struct hpuxuser *faku; 150241486Smckusick struct bsdfp *bp; 150341486Smckusick short *foop; 150441486Smckusick 150541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 150641486Smckusick /* 150741486Smckusick * Make sure there is no mistake about this 150841486Smckusick * being a real user structure. 150941486Smckusick */ 151041486Smckusick bzero((caddr_t)faku, ctob(1)); 151141486Smckusick /* 151241486Smckusick * Fill in the process sizes. 151341486Smckusick */ 151448478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 151548478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 151648478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 151741486Smckusick /* 151841486Smckusick * Fill in the exec header for CDB. 151941486Smckusick * This was saved back in exec(). As far as I can tell CDB 152041486Smckusick * only uses this information to verify that a particular 152141486Smckusick * core file goes with a particular binary. 152241486Smckusick */ 152349134Skarels bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 152441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 152541486Smckusick /* 152641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 152754857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 152841486Smckusick * so we have to move it up. 152941486Smckusick */ 153052381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 153152381Smckusick foop = (short *) p->p_md.md_regs; 153241486Smckusick foop[32] = foop[33]; 153341486Smckusick foop[33] = foop[34]; 153441486Smckusick foop[34] = foop[35]; 153541486Smckusick #ifdef FPCOPROC 153641486Smckusick /* 153754857Shibler * Copy 68881 registers from our PCB format to HP-UX format 153841486Smckusick */ 153949134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 154041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 154141486Smckusick sizeof(bp->save)); 154241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 154341486Smckusick sizeof(bp->ctrl)); 154441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 154541486Smckusick sizeof(bp->reg)); 154641486Smckusick #endif 154741486Smckusick /* 154841486Smckusick * Slay the dragon 154941486Smckusick */ 155041486Smckusick faku->hpuxu_dragon = -1; 155141486Smckusick /* 155241486Smckusick * Dump this artfully constructed page in place of the 155341486Smckusick * user struct page. 155441486Smckusick */ 155548478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 155648478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 155749134Skarels (int *)NULL, p); 155841486Smckusick /* 155941486Smckusick * Dump the remaining UPAGES-1 pages normally 156041486Smckusick */ 156141486Smckusick if (!error) 156249134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 156341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 156449134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 156541486Smckusick free((caddr_t)faku, M_TEMP); 156641486Smckusick return(error); 156741486Smckusick } 156841486Smckusick 156941486Smckusick /* 157041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 157141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 157241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 157341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 157441486Smckusick */ 1575*55832Shibler #ifdef COMPAT_OHPUX 1576*55832Shibler 157745753Smckusick #define HPUX_HZ 50 157845753Smckusick 157945788Sbostic #include "sys/times.h" 158041486Smckusick 158141486Smckusick /* from old timeb.h */ 158241486Smckusick struct hpuxtimeb { 158341486Smckusick time_t time; 158441486Smckusick u_short millitm; 158541486Smckusick short timezone; 158641486Smckusick short dstflag; 158741486Smckusick }; 158841486Smckusick 158941486Smckusick /* ye ole stat structure */ 159041486Smckusick struct ohpuxstat { 159153481Smckusick u_short ohst_dev; 159241486Smckusick u_short ohst_ino; 159341486Smckusick u_short ohst_mode; 159441486Smckusick short ohst_nlink; 159541486Smckusick short ohst_uid; 159641486Smckusick short ohst_gid; 159753481Smckusick u_short ohst_rdev; 159841486Smckusick int ohst_size; 159941486Smckusick int ohst_atime; 160041486Smckusick int ohst_mtime; 160141486Smckusick int ohst_ctime; 160241486Smckusick }; 160341486Smckusick 160441486Smckusick /* 160541486Smckusick * SYS V style setpgrp() 160641486Smckusick */ 160743452Shibler ohpuxsetpgrp(p, uap, retval) 160843452Shibler register struct proc *p; 160943452Shibler int *uap, *retval; 161041486Smckusick { 161141486Smckusick if (p->p_pid != p->p_pgid) 161248478Skarels enterpgrp(p, p->p_pid, 0); 161343452Shibler *retval = p->p_pgid; 161445753Smckusick return (0); 161541486Smckusick } 161641486Smckusick 161754917Storek struct ohpuxtime_args { 161854917Storek long *tp; 161954917Storek }; 162043452Shibler ohpuxtime(p, uap, retval) 162143452Shibler struct proc *p; 162254917Storek register struct ohpuxtime_args *uap; 162354917Storek int *retval; 162441486Smckusick { 162545753Smckusick int error = 0; 162641486Smckusick 162741486Smckusick if (uap->tp) 162843452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 162943452Shibler sizeof (long)); 163054917Storek *(time_t *)retval = time.tv_sec; 163144421Skarels return (error); 163241486Smckusick } 163341486Smckusick 163454917Storek struct ohpuxstime_args { 163554917Storek int time; 163654917Storek }; 163743452Shibler ohpuxstime(p, uap, retval) 163843452Shibler struct proc *p; 163954917Storek register struct ohpuxstime_args *uap; 164043452Shibler int *retval; 164141486Smckusick { 164241486Smckusick struct timeval tv; 164343452Shibler int s, error; 164441486Smckusick 164541486Smckusick tv.tv_sec = uap->time; 164641486Smckusick tv.tv_usec = 0; 164748478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 164844421Skarels return (error); 164941486Smckusick 165041486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 165141486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 165241486Smckusick s = splhigh(); time = tv; splx(s); 165341486Smckusick resettodr(); 165444421Skarels return (0); 165541486Smckusick } 165641486Smckusick 165754917Storek struct ohpuxftime_args { 165854917Storek struct hpuxtimeb *tp; 165954917Storek }; 166043452Shibler ohpuxftime(p, uap, retval) 166143452Shibler struct proc *p; 166254917Storek register struct ohpuxftime_args *uap; 166343452Shibler int *retval; 166443452Shibler { 166541486Smckusick struct hpuxtimeb tb; 166641486Smckusick int s; 166741486Smckusick 166841486Smckusick s = splhigh(); 166941486Smckusick tb.time = time.tv_sec; 167041486Smckusick tb.millitm = time.tv_usec / 1000; 167141486Smckusick splx(s); 167241486Smckusick tb.timezone = tz.tz_minuteswest; 167341486Smckusick tb.dstflag = tz.tz_dsttime; 167444421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 167541486Smckusick } 167641486Smckusick 167754917Storek struct ohpuxalarm_args { 167854917Storek int deltat; 167954917Storek }; 168043452Shibler ohpuxalarm(p, uap, retval) 168143452Shibler register struct proc *p; 168254917Storek register struct ohpuxalarm_args *uap; 168343452Shibler int *retval; 168441486Smckusick { 168541486Smckusick int s = splhigh(); 168641486Smckusick 168741486Smckusick untimeout(realitexpire, (caddr_t)p); 168841486Smckusick timerclear(&p->p_realtimer.it_interval); 168943452Shibler *retval = 0; 169041486Smckusick if (timerisset(&p->p_realtimer.it_value) && 169141486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 169243452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 169341486Smckusick if (uap->deltat == 0) { 169441486Smckusick timerclear(&p->p_realtimer.it_value); 169541486Smckusick splx(s); 169644421Skarels return (0); 169741486Smckusick } 169841486Smckusick p->p_realtimer.it_value = time; 169941486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 170041486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 170141486Smckusick splx(s); 170244421Skarels return (0); 170341486Smckusick } 170441486Smckusick 170554917Storek struct ohpuxnice_args { 170654917Storek int niceness; 170754917Storek }; 170843452Shibler ohpuxnice(p, uap, retval) 170943452Shibler register struct proc *p; 171054917Storek register struct ohpuxnice_args *uap; 171143452Shibler int *retval; 171241486Smckusick { 171343452Shibler int error; 171441486Smckusick 171543452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 171643452Shibler if (error == 0) 171743452Shibler *retval = p->p_nice - NZERO; 171844421Skarels return (error); 171941486Smckusick } 172041486Smckusick 172154917Storek struct ohpuxtimes_args { 172254917Storek struct tms *tmsb; 172354917Storek }; 172443452Shibler ohpuxtimes(p, uap, retval) 172543452Shibler struct proc *p; 172654917Storek register struct ohpuxtimes_args *uap; 172754917Storek int *retval; 172841486Smckusick { 172954771Storek struct timeval ru, rs; 173041486Smckusick struct tms atms; 173143452Shibler int error; 173241486Smckusick 173354771Storek calcru(p, &ru, &rs, NULL); 173454771Storek atms.tms_utime = hpuxscale(&ru); 173554771Storek atms.tms_stime = hpuxscale(&rs); 173648478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 173748478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 173843452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 173943452Shibler if (error == 0) 174054917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 174144421Skarels return (error); 174241486Smckusick } 174341486Smckusick 174445753Smckusick /* 174545753Smckusick * Doesn't exactly do what the documentation says. 174645753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 174745753Smckusick * is what HP-UX returns. 174845753Smckusick */ 174945753Smckusick hpuxscale(tvp) 175041486Smckusick register struct timeval *tvp; 175141486Smckusick { 175245753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 175341486Smckusick } 175441486Smckusick 175541486Smckusick /* 175641486Smckusick * Set IUPD and IACC times on file. 175741486Smckusick * Can't set ICHG. 175841486Smckusick */ 175954917Storek struct ohpuxutime_args { 176054917Storek char *fname; 176154917Storek time_t *tptr; 176254917Storek }; 176343452Shibler ohpuxutime(p, uap, retval) 176443452Shibler struct proc *p; 176554917Storek register struct ohpuxutime_args *uap; 176643452Shibler int *retval; 176743452Shibler { 176848478Skarels register struct vnode *vp; 176941486Smckusick struct vattr vattr; 177041486Smckusick time_t tv[2]; 177143452Shibler int error; 177248478Skarels struct nameidata nd; 177341486Smckusick 177441486Smckusick if (uap->tptr) { 177543452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 177643452Shibler if (error) 177744421Skarels return (error); 177841486Smckusick } else 177941486Smckusick tv[0] = tv[1] = time.tv_sec; 178041486Smckusick vattr_null(&vattr); 178154107Smckusick vattr.va_atime.ts_sec = tv[0]; 178254107Smckusick vattr.va_atime.ts_nsec = 0; 178354107Smckusick vattr.va_mtime.ts_sec = tv[1]; 178454107Smckusick vattr.va_mtime.ts_nsec = 0; 178552330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 178652330Smckusick if (error = namei(&nd)) 178744421Skarels return (error); 178852330Smckusick vp = nd.ni_vp; 178942154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 179043452Shibler error = EROFS; 179141486Smckusick else 179252330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 179341486Smckusick vput(vp); 179444421Skarels return (error); 179541486Smckusick } 179641486Smckusick 179743452Shibler ohpuxpause(p, uap, retval) 179843452Shibler struct proc *p; 179943452Shibler int *uap, *retval; 180041486Smckusick { 180149134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 180242155Skarels /* always return EINTR rather than ERESTART... */ 180344421Skarels return (EINTR); 180441486Smckusick } 180541486Smckusick 180641486Smckusick /* 180741486Smckusick * The old fstat system call. 180841486Smckusick */ 180954917Storek struct ohpuxfstat_args { 181054917Storek int fd; 181154917Storek struct ohpuxstat *sb; 181254917Storek }; 181343452Shibler ohpuxfstat(p, uap, retval) 181443452Shibler struct proc *p; 181554917Storek register struct ohpuxfstat_args *uap; 181643452Shibler int *retval; 181743452Shibler { 181845923Smckusick register struct filedesc *fdp = p->p_fd; 181941486Smckusick struct file *fp; 182041486Smckusick 182148478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 182248478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 182344421Skarels return (EBADF); 182443452Shibler if (fp->f_type != DTYPE_VNODE) 182544421Skarels return (EINVAL); 182655282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 182741486Smckusick } 182841486Smckusick 182941486Smckusick /* 183041486Smckusick * Old stat system call. This version follows links. 183141486Smckusick */ 183254917Storek struct ohpuxstat_args { 183354917Storek char *fname; 183454917Storek struct ohpuxstat *sb; 183554917Storek }; 183643452Shibler ohpuxstat(p, uap, retval) 183743452Shibler struct proc *p; 183854917Storek register struct ohpuxstat_args *uap; 183943452Shibler int *retval; 184043452Shibler { 184143452Shibler int error; 184248478Skarels struct nameidata nd; 184341486Smckusick 184452330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 184552330Smckusick if (error = namei(&nd)) 184644421Skarels return (error); 184755282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 184852330Smckusick vput(nd.ni_vp); 184944421Skarels return (error); 185041486Smckusick } 185141486Smckusick 185241486Smckusick int 185355282Smckusick ohpuxstat1(vp, ub, p) 185441486Smckusick register struct vnode *vp; 185541486Smckusick struct ohpuxstat *ub; 185655282Smckusick struct proc *p; 185741486Smckusick { 185841486Smckusick struct ohpuxstat ds; 185941486Smckusick struct vattr vattr; 186041486Smckusick register int error; 186141486Smckusick 186255282Smckusick error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); 186341486Smckusick if (error) 186441486Smckusick return(error); 186541486Smckusick /* 186641486Smckusick * Copy from inode table 186741486Smckusick */ 186841486Smckusick ds.ohst_dev = vattr.va_fsid; 186941486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 187041486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 187141486Smckusick ds.ohst_nlink = vattr.va_nlink; 187241486Smckusick ds.ohst_uid = (short)vattr.va_uid; 187341486Smckusick ds.ohst_gid = (short)vattr.va_gid; 187453481Smckusick ds.ohst_rdev = (u_short)vattr.va_rdev; 187541486Smckusick ds.ohst_size = (int)vattr.va_size; 187654107Smckusick ds.ohst_atime = (int)vattr.va_atime.ts_sec; 187754107Smckusick ds.ohst_mtime = (int)vattr.va_mtime.ts_sec; 187854107Smckusick ds.ohst_ctime = (int)vattr.va_ctime.ts_sec; 187941486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 188041486Smckusick } 188141486Smckusick #endif 1882*55832Shibler #endif 1883