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 * 1257307Shibler * from: Utah $Hdr: hpux_compat.c 1.55 92/12/26$ 1341486Smckusick * 14*60110Smckusick * @(#)hpux_compat.c 7.35 (Berkeley) 05/17/93 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1854857Shibler * Various HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2259982Smckusick #ifndef COMPAT_43 2359982Smckusick #define COMPAT_43 2459982Smckusick #endif 2541486Smckusick 2656506Sbostic #include <sys/param.h> 2756506Sbostic #include <sys/systm.h> 2856506Sbostic #include <sys/signalvar.h> 2956506Sbostic #include <sys/kernel.h> 3056506Sbostic #include <sys/filedesc.h> 3156506Sbostic #include <sys/proc.h> 3256506Sbostic #include <sys/buf.h> 3356506Sbostic #include <sys/wait.h> 3456506Sbostic #include <sys/file.h> 3556506Sbostic #include <sys/namei.h> 3656506Sbostic #include <sys/vnode.h> 3756506Sbostic #include <sys/ioctl.h> 3856506Sbostic #include <sys/ptrace.h> 3956506Sbostic #include <sys/stat.h> 4056506Sbostic #include <sys/syslog.h> 4156506Sbostic #include <sys/malloc.h> 4256506Sbostic #include <sys/mount.h> 4356506Sbostic #include <sys/ipc.h> 4456506Sbostic #include <sys/user.h> 4557307Shibler #include <sys/mman.h> 4641486Smckusick 4756506Sbostic #include <machine/cpu.h> 4856506Sbostic #include <machine/reg.h> 4956506Sbostic #include <machine/psl.h> 5056506Sbostic #include <machine/vmparam.h> 5156506Sbostic #include <hp/hpux/hpux.h> 5256506Sbostic #include <hp/hpux/hpux_termio.h> 5356506Sbostic 5441486Smckusick #ifdef DEBUG 5541486Smckusick int unimpresponse = 0; 5641486Smckusick #endif 5741486Smckusick 5841486Smckusick /* SYS5 style UTSNAME info */ 5941486Smckusick struct hpuxutsname protoutsname = { 6057307Shibler "4.4bsd", "", "0.5", "B", "9000/3?0", "" 6141486Smckusick }; 6241486Smckusick 6341486Smckusick /* 6.0 and later style context */ 6453922Shibler #if defined(HP380) 6553922Shibler char hpux040context[] = 6653922Shibler "standalone HP-MC68040 HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6753922Shibler #endif 6841486Smckusick #ifdef FPCOPROC 6941486Smckusick char hpuxcontext[] = 7041486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 7141486Smckusick #else 7241486Smckusick char hpuxcontext[] = 7341486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 7441486Smckusick #endif 7541486Smckusick 7641486Smckusick /* YP domainname */ 7741486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7841486Smckusick int domainnamelen = 7; 7941486Smckusick 8041486Smckusick #define NERR 79 8141486Smckusick #define BERR 1000 8241486Smckusick 8341486Smckusick /* indexed by BSD errno */ 8441486Smckusick short bsdtohpuxerrnomap[NERR] = { 8541486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8641486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 8741486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8841486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8941486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 9041486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 9141486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 9241486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 9341486Smckusick }; 9441486Smckusick 9543452Shibler notimp(p, uap, retval, code, nargs) 9643452Shibler struct proc *p; 9743452Shibler int *uap, *retval; 9843452Shibler int code, nargs; 9941486Smckusick { 10043452Shibler int error = 0; 10141486Smckusick #ifdef DEBUG 10243452Shibler register int *argp = uap; 10341486Smckusick extern char *hpuxsyscallnames[]; 10441486Smckusick 10554857Shibler printf("HP-UX %s(", hpuxsyscallnames[code]); 10641486Smckusick if (nargs) 10741486Smckusick while (nargs--) 10841486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10941486Smckusick else 11041486Smckusick printf(")"); 11141486Smckusick printf("\n"); 11241486Smckusick switch (unimpresponse) { 11341486Smckusick case 0: 11443452Shibler error = nosys(p, uap, retval); 11541486Smckusick break; 11641486Smckusick case 1: 11743452Shibler error = EINVAL; 11841486Smckusick break; 11941486Smckusick } 12041486Smckusick #else 12143452Shibler error = nosys(p, uap, retval); 12241486Smckusick #endif 12343452Shibler uprintf("HP-UX system call %d not implemented\n", code); 12444421Skarels return (error); 12541486Smckusick } 12641486Smckusick 12754917Storek struct hpuxexecv_args { 12854917Storek char *fname; 12954917Storek char **argp; 13054917Storek char **envp; 13154917Storek }; 13248478Skarels hpuxexecv(p, uap, retval) 13348478Skarels struct proc *p; 13454917Storek struct hpuxexecv_args *uap; 13548478Skarels int *retval; 13648478Skarels { 13748478Skarels extern int execve(); 13848478Skarels 13948478Skarels uap->envp = NULL; 14048478Skarels return (execve(p, uap, retval)); 14148478Skarels } 14248478Skarels 14341486Smckusick /* 14454857Shibler * HP-UX versions of wait and wait3 actually pass the parameters 14541486Smckusick * (status pointer, options, rusage) into the kernel rather than 14642352Smckusick * handling it in the C library stub. We also need to map any 14754857Shibler * termination signal from BSD to HP-UX. 14841486Smckusick */ 14954917Storek struct hpuxwait3_args { 15054917Storek int *status; 15154917Storek int options; 15254917Storek int rusage; 15354917Storek }; 15443452Shibler hpuxwait3(p, uap, retval) 15543452Shibler struct proc *p; 15654917Storek struct hpuxwait3_args *uap; 15743452Shibler int *retval; 15843452Shibler { 15941486Smckusick /* rusage pointer must be zero */ 16043452Shibler if (uap->rusage) 16144421Skarels return (EINVAL); 16252381Smckusick p->p_md.md_regs[PS] = PSL_ALLCC; 16352381Smckusick p->p_md.md_regs[R0] = uap->options; 16452381Smckusick p->p_md.md_regs[R1] = uap->rusage; 16544421Skarels return (hpuxwait(p, uap, retval)); 16641486Smckusick } 16741486Smckusick 16854917Storek struct hpuxwait_args { 16954917Storek int *status; 17054917Storek }; 17143452Shibler hpuxwait(p, uap, retval) 17243452Shibler struct proc *p; 17354917Storek struct hpuxwait_args *uap; 17443452Shibler int *retval; 17541486Smckusick { 17643452Shibler int sig, *statp, error; 17741486Smckusick 17841486Smckusick statp = uap->status; /* owait clobbers first arg */ 17943452Shibler error = owait(p, uap, retval); 18041486Smckusick /* 18141486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 18241486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 18341486Smckusick */ 18443452Shibler if (error == ERESTART) 18543452Shibler error = EINTR; 18643452Shibler if (error) 18744421Skarels return (error); 18843452Shibler sig = retval[1] & 0xFF; 18941486Smckusick if (sig == WSTOPPED) { 19043452Shibler sig = (retval[1] >> 8) & 0xFF; 19143452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 19241486Smckusick } else if (sig) 19343452Shibler retval[1] = (retval[1] & 0xFF00) | 19441486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 19541486Smckusick if (statp) 19643452Shibler if (suword((caddr_t)statp, retval[1])) 19743452Shibler error = EFAULT; 19844421Skarels return (error); 19941486Smckusick } 20041486Smckusick 20154917Storek struct hpuxwaitpid_args { 20254917Storek int pid; 20354917Storek int *status; 20454917Storek int options; 20554917Storek struct rusage *rusage; /* wait4 arg */ 20654917Storek }; 20743452Shibler hpuxwaitpid(p, uap, retval) 20843452Shibler struct proc *p; 20954917Storek struct hpuxwaitpid_args *uap; 21043452Shibler int *retval; 21143452Shibler { 21255832Shibler int rv, sig, xstat, error; 21342352Smckusick 21442352Smckusick uap->rusage = 0; 21543452Shibler error = wait4(p, uap, retval); 21642352Smckusick /* 21742352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 21842352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 21942352Smckusick */ 22043452Shibler if (error == ERESTART) 22143452Shibler error = EINTR; 22243452Shibler if (error) 22344421Skarels return (error); 22455832Shibler if (uap->status) { 22555832Shibler /* 22655832Shibler * Wait4 already wrote the status out to user space, 22755832Shibler * pull it back, change the signal portion, and write 22855832Shibler * it back out. 22955832Shibler */ 23055832Shibler rv = fuword((caddr_t)uap->status); 23155832Shibler if (WIFSTOPPED(rv)) { 23255832Shibler sig = WSTOPSIG(rv); 23355832Shibler rv = W_STOPCODE(bsdtohpuxsig(sig)); 23455832Shibler } else if (WIFSIGNALED(rv)) { 23555832Shibler sig = WTERMSIG(rv); 23655832Shibler xstat = WEXITSTATUS(rv); 23755832Shibler rv = W_EXITCODE(xstat, bsdtohpuxsig(sig)) | 23855832Shibler WCOREDUMP(rv); 23955832Shibler } 24055832Shibler (void)suword((caddr_t)uap->status, rv); 24155832Shibler } 24244421Skarels return (error); 24342352Smckusick } 24442352Smckusick 24541486Smckusick /* 24641486Smckusick * Must remap some bits in the mode mask. 24741486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 24841486Smckusick * O_SYNCIO (0100000) is removed entirely. 24941486Smckusick */ 25054917Storek struct hpuxopen_args { 25154917Storek char *fname; 25254917Storek int mode; 25354917Storek int crtmode; 25454917Storek }; 25543067Skarels hpuxopen(p, uap, retval) 25643067Skarels struct proc *p; 25754917Storek register struct hpuxopen_args *uap; 25843067Skarels int *retval; 25943067Skarels { 26041486Smckusick int mode; 26141486Smckusick 26241486Smckusick mode = uap->mode; 26341486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 26441486Smckusick if (mode & HPUXFCREAT) { 26541486Smckusick /* 26641486Smckusick * simulate the pre-NFS behavior that opening a 26741486Smckusick * file for READ+CREATE ignores the CREATE (unless 26841486Smckusick * EXCL is set in which case we will return the 26941486Smckusick * proper error). 27041486Smckusick */ 27148478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 27249950Smckusick uap->mode |= O_CREAT; 27341486Smckusick } 27441486Smckusick if (mode & HPUXFTRUNC) 27549950Smckusick uap->mode |= O_TRUNC; 27641486Smckusick if (mode & HPUXFEXCL) 27749950Smckusick uap->mode |= O_EXCL; 27844421Skarels return (open(p, uap, retval)); 27941486Smckusick } 28041486Smckusick 28155832Shibler /* 28255832Shibler * Old creat system call. 28355832Shibler */ 28455832Shibler struct hpuxcreat_args { 28555832Shibler char *fname; 28655832Shibler int fmode; 28755832Shibler }; 28855832Shibler hpuxcreat(p, uap, retval) 28955832Shibler struct proc *p; 29055832Shibler register struct hpuxcreat_args *uap; 29155832Shibler int *retval; 29255832Shibler { 29355832Shibler struct nargs { 29455832Shibler char *fname; 29555832Shibler int mode; 29655832Shibler int crtmode; 29755832Shibler } openuap; 29855832Shibler 29955832Shibler openuap.fname = uap->fname; 30055832Shibler openuap.crtmode = uap->fmode; 30155832Shibler openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 30255832Shibler return (open(p, &openuap, retval)); 30355832Shibler } 30455832Shibler 30549329Shibler /* XXX */ 30649329Shibler #define UF_FNDELAY_ON 0x20 30749329Shibler #define UF_FIONBIO_ON 0x40 30849329Shibler /* XXX */ 30949329Shibler 31054917Storek struct hpuxfcntl_args { 31154917Storek int fdes; 31254917Storek int cmd; 31354917Storek int arg; 31454917Storek }; 31543452Shibler hpuxfcntl(p, uap, retval) 31643452Shibler struct proc *p; 31754917Storek register struct hpuxfcntl_args *uap; 31843452Shibler int *retval; 31943452Shibler { 32043452Shibler int mode, error; 32149329Shibler char *fp; 32241486Smckusick 32349329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 32449329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 32549329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 32649329Shibler return (EBADF); 32749329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 32849329Shibler } 32941486Smckusick switch (uap->cmd) { 33041486Smckusick case F_SETFL: 33149950Smckusick if (uap->arg & FNONBLOCK) 33249329Shibler *fp |= UF_FNDELAY_ON; 33349329Shibler else { 33449329Shibler *fp &= ~UF_FNDELAY_ON; 33549329Shibler if (*fp & UF_FIONBIO_ON) 33649950Smckusick uap->arg |= FNONBLOCK; 33749329Shibler } 33841486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 33941486Smckusick break; 34041486Smckusick case F_GETFL: 34141486Smckusick case F_DUPFD: 34241486Smckusick case F_GETFD: 34341486Smckusick case F_SETFD: 34441486Smckusick break; 34541486Smckusick default: 34644421Skarels return (EINVAL); 34741486Smckusick } 34843452Shibler error = fcntl(p, uap, retval); 34949329Shibler if (error == 0 && uap->cmd == F_GETFL) { 35043452Shibler mode = *retval; 35149950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 35249950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 35349950Smckusick *retval &= ~FNONBLOCK; 35449950Smckusick if (mode & O_CREAT) 35543452Shibler *retval |= HPUXFCREAT; 35649950Smckusick if (mode & O_TRUNC) 35743452Shibler *retval |= HPUXFTRUNC; 35849950Smckusick if (mode & O_EXCL) 35943452Shibler *retval |= HPUXFEXCL; 36041486Smckusick } 36144421Skarels return (error); 36241486Smckusick } 36341486Smckusick 36441486Smckusick /* 36541486Smckusick * Read and write should return a 0 count when an operation 36649329Shibler * on a VNODE would block, not an error. 36749329Shibler * 36849329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 36949950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 37041486Smckusick */ 37154917Storek struct hpuxread_args { 37254917Storek int fd; 37354917Storek }; 37443452Shibler hpuxread(p, uap, retval) 37543452Shibler struct proc *p; 37654917Storek struct hpuxread_args *uap; 37743452Shibler int *retval; 37841486Smckusick { 37943452Shibler int error; 38041486Smckusick 38143452Shibler error = read(p, uap, retval); 38243452Shibler if (error == EWOULDBLOCK && 38349329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 38449329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 38543452Shibler error = 0; 38643452Shibler *retval = 0; 38741486Smckusick } 38844421Skarels return (error); 38941486Smckusick } 39041486Smckusick 39154917Storek struct hpuxwrite_args { 39254917Storek int fd; 39354917Storek }; 39443452Shibler hpuxwrite(p, uap, retval) 39543452Shibler struct proc *p; 39654917Storek struct hpuxwrite_args *uap; 39743452Shibler int *retval; 39841486Smckusick { 39943452Shibler int error; 40041486Smckusick 40143452Shibler error = write(p, uap, retval); 40243452Shibler if (error == EWOULDBLOCK && 40349329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 40449329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 40543452Shibler error = 0; 40643452Shibler *retval = 0; 40741486Smckusick } 40844421Skarels return (error); 40941486Smckusick } 41041486Smckusick 41154917Storek struct hpuxreadv_args { 41254917Storek int fd; 41354917Storek }; 41443452Shibler hpuxreadv(p, uap, retval) 41543452Shibler struct proc *p; 41654917Storek struct hpuxreadv_args *uap; 41743452Shibler int *retval; 41841486Smckusick { 41943452Shibler int error; 42041486Smckusick 42143452Shibler error = readv(p, uap, retval); 42243452Shibler if (error == EWOULDBLOCK && 42349329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 42449329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 42543452Shibler error = 0; 42643452Shibler *retval = 0; 42741486Smckusick } 42844421Skarels return (error); 42941486Smckusick } 43041486Smckusick 43154917Storek struct hpuxwritev_args { 43254917Storek int fd; 43354917Storek }; 43443452Shibler hpuxwritev(p, uap, retval) 43543452Shibler struct proc *p; 43654917Storek struct hpuxwritev_args *uap; 43743452Shibler int *retval; 43841486Smckusick { 43943452Shibler int error; 44041486Smckusick 44143452Shibler error = writev(p, uap, retval); 44243452Shibler if (error == EWOULDBLOCK && 44349329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 44449329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 44543452Shibler error = 0; 44643452Shibler *retval = 0; 44741486Smckusick } 44844421Skarels return (error); 44941486Smckusick } 45041486Smckusick 45141486Smckusick /* 45241486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 45354857Shibler * and hence allows two arguments. HP-UX dup has only one arg. 45441486Smckusick */ 45554917Storek struct hpuxdup_args { 45654917Storek int i; 45754917Storek }; 45843452Shibler hpuxdup(p, uap, retval) 45943452Shibler struct proc *p; 46054917Storek register struct hpuxdup_args *uap; 46143452Shibler int *retval; 46241486Smckusick { 46345923Smckusick register struct filedesc *fdp = p->p_fd; 46441486Smckusick struct file *fp; 46543452Shibler int fd, error; 46641486Smckusick 46748478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 46848478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 46944421Skarels return (EBADF); 47048478Skarels if (error = fdalloc(p, 0, &fd)) 47144421Skarels return (error); 47248478Skarels fdp->fd_ofiles[fd] = fp; 47348478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 47445923Smckusick fp->f_count++; 47545923Smckusick if (fd > fdp->fd_lastfile) 47645923Smckusick fdp->fd_lastfile = fd; 47743452Shibler *retval = fd; 47844421Skarels return (0); 47941486Smckusick } 48041486Smckusick 48154917Storek struct hpuxutssys_args { 48254917Storek struct hpuxutsname *uts; 48354917Storek int dev; 48454917Storek int request; 48554917Storek }; 48645753Smckusick hpuxutssys(p, uap, retval) 48743452Shibler struct proc *p; 48854917Storek register struct hpuxutssys_args *uap; 48943452Shibler int *retval; 49043452Shibler { 49141486Smckusick register int i; 49243452Shibler int error; 49341486Smckusick 49441486Smckusick switch (uap->request) { 49541486Smckusick /* uname */ 49641486Smckusick case 0: 49741486Smckusick /* fill in machine type */ 49841486Smckusick switch (machineid) { 49941486Smckusick case HP_320: 50041486Smckusick protoutsname.machine[6] = '2'; 50141486Smckusick break; 50241486Smckusick /* includes 318 and 319 */ 50341486Smckusick case HP_330: 50441486Smckusick protoutsname.machine[6] = '3'; 50541486Smckusick break; 50641486Smckusick case HP_340: 50741486Smckusick protoutsname.machine[6] = '4'; 50841486Smckusick break; 50941486Smckusick case HP_350: 51041486Smckusick protoutsname.machine[6] = '5'; 51141486Smckusick break; 51241486Smckusick case HP_360: 51341486Smckusick protoutsname.machine[6] = '6'; 51441486Smckusick break; 51541486Smckusick case HP_370: 51641486Smckusick protoutsname.machine[6] = '7'; 51741486Smckusick break; 51843452Shibler /* includes 345 */ 51943452Shibler case HP_375: 52043452Shibler protoutsname.machine[6] = '7'; 52143452Shibler protoutsname.machine[7] = '5'; 52243452Shibler break; 52354857Shibler /* includes 425 */ 52454857Shibler case HP_380: 52554857Shibler protoutsname.machine[6] = '8'; 52654857Shibler break; 52757307Shibler case HP_433: 52857307Shibler protoutsname.machine[5] = '4'; 52957307Shibler protoutsname.machine[6] = '3'; 53057307Shibler protoutsname.machine[7] = '3'; 53157307Shibler break; 53241486Smckusick } 53341486Smckusick /* copy hostname (sans domain) to nodename */ 53449329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 53541486Smckusick protoutsname.nodename[i] = hostname[i]; 53649329Shibler protoutsname.nodename[i] = '\0'; 53743452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 53843452Shibler sizeof(struct hpuxutsname)); 53941486Smckusick break; 54045753Smckusick 54145753Smckusick /* gethostname */ 54245753Smckusick case 5: 54345753Smckusick /* uap->dev is length */ 54445753Smckusick if (uap->dev > hostnamelen + 1) 54545753Smckusick uap->dev = hostnamelen + 1; 54645753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 54745753Smckusick uap->dev); 54845753Smckusick break; 54945753Smckusick 55045753Smckusick case 1: /* ?? */ 55145753Smckusick case 2: /* ustat */ 55245753Smckusick case 3: /* ?? */ 55345753Smckusick case 4: /* sethostname */ 55441486Smckusick default: 55543452Shibler error = EINVAL; 55641486Smckusick break; 55741486Smckusick } 55844421Skarels return (error); 55941486Smckusick } 56041486Smckusick 56154917Storek struct hpuxsysconf_args { 56254917Storek int name; 56354917Storek }; 56453922Shibler hpuxsysconf(p, uap, retval) 56553922Shibler struct proc *p; 56654917Storek struct hpuxsysconf_args *uap; 56753922Shibler int *retval; 56853922Shibler { 56953922Shibler switch (uap->name) { 57053922Shibler 57153922Shibler /* open files */ 57253922Shibler case HPUX_SYSCONF_OPENMAX: 57353922Shibler *retval = NOFILE; 57453922Shibler break; 57553922Shibler 57653922Shibler /* architecture */ 57753922Shibler case HPUX_SYSCONF_CPUTYPE: 57853922Shibler switch (machineid) { 57953922Shibler case HP_320: 58053922Shibler case HP_330: 58153922Shibler case HP_350: 58253922Shibler *retval = HPUX_SYSCONF_CPUM020; 58353922Shibler break; 58453922Shibler case HP_340: 58553922Shibler case HP_360: 58653922Shibler case HP_370: 58753922Shibler case HP_375: 58853922Shibler *retval = HPUX_SYSCONF_CPUM030; 58953922Shibler break; 59053922Shibler case HP_380: 59157307Shibler case HP_433: 59253922Shibler *retval = HPUX_SYSCONF_CPUM040; 59353922Shibler break; 59453922Shibler } 59553922Shibler break; 59653922Shibler default: 59754857Shibler uprintf("HP-UX sysconf(%d) not implemented\n", uap->name); 59853922Shibler return (EINVAL); 59953922Shibler } 60053922Shibler return (0); 60153922Shibler } 60253922Shibler 60354917Storek struct hpuxstat_args { 60454917Storek char *fname; 60554917Storek struct hpuxstat *hsb; 60654917Storek }; 60743452Shibler hpuxstat(p, uap, retval) 60843452Shibler struct proc *p; 60954917Storek struct hpuxstat_args *uap; 61043452Shibler int *retval; 61143452Shibler { 61255282Smckusick return (hpuxstat1(uap->fname, uap->hsb, FOLLOW, p)); 61341486Smckusick } 61441486Smckusick 61554917Storek struct hpuxlstat_args { 61654917Storek char *fname; 61754917Storek struct hpuxstat *hsb; 61854917Storek }; 61943452Shibler hpuxlstat(p, uap, retval) 62043452Shibler struct proc *p; 62154917Storek struct hpuxlstat_args *uap; 62243452Shibler int *retval; 62341486Smckusick { 62455282Smckusick return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW, p)); 62541486Smckusick } 62641486Smckusick 62754917Storek struct hpuxfstat_args { 62854917Storek int fdes; 62954917Storek struct hpuxstat *hsb; 63054917Storek }; 63143452Shibler hpuxfstat(p, uap, retval) 63243452Shibler struct proc *p; 63354917Storek register struct hpuxfstat_args *uap; 63443452Shibler int *retval; 63541486Smckusick { 63645923Smckusick register struct filedesc *fdp = p->p_fd; 63741486Smckusick register struct file *fp; 63841486Smckusick struct stat sb; 63943452Shibler int error; 64041486Smckusick 64148478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 64248478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 64344421Skarels return (EBADF); 64443452Shibler 64541486Smckusick switch (fp->f_type) { 64641486Smckusick 64741486Smckusick case DTYPE_VNODE: 64855282Smckusick error = vn_stat((struct vnode *)fp->f_data, &sb, p); 64941486Smckusick break; 65041486Smckusick 65141486Smckusick case DTYPE_SOCKET: 65255282Smckusick error = soo_stat((struct socket *)fp->f_data, &sb, p); 65341486Smckusick break; 65441486Smckusick 65541486Smckusick default: 65641486Smckusick panic("fstat"); 65741486Smckusick /*NOTREACHED*/ 65841486Smckusick } 65941486Smckusick /* is this right for sockets?? */ 66043452Shibler if (error == 0) 66143452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 66244421Skarels return (error); 66341486Smckusick } 66441486Smckusick 66554917Storek struct hpuxulimit_args { 66654917Storek int cmd; 66754917Storek long newlimit; 66854917Storek }; 66943452Shibler hpuxulimit(p, uap, retval) 67043452Shibler struct proc *p; 67154917Storek register struct hpuxulimit_args *uap; 67253481Smckusick long *retval; 67343452Shibler { 67441486Smckusick struct rlimit *limp; 67543452Shibler int error = 0; 67641486Smckusick 67748478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 67841486Smckusick switch (uap->cmd) { 67941486Smckusick case 2: 68041486Smckusick uap->newlimit *= 512; 68141486Smckusick if (uap->newlimit > limp->rlim_max && 68248478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 68341486Smckusick break; 68441486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 68541486Smckusick /* else fall into... */ 68641486Smckusick 68741486Smckusick case 1: 68845753Smckusick *retval = limp->rlim_max / 512; 68941486Smckusick break; 69041486Smckusick 69141486Smckusick case 3: 69248478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 69348478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 69441486Smckusick break; 69541486Smckusick 69641486Smckusick default: 69743452Shibler error = EINVAL; 69841486Smckusick break; 69941486Smckusick } 70044421Skarels return (error); 70141486Smckusick } 70241486Smckusick 70341486Smckusick /* 70441486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 70541486Smckusick * values -16 (high) thru -1 (low). 70641486Smckusick */ 70754917Storek struct hpuxrtprio_args { 70854917Storek int pid; 70954917Storek int prio; 71054917Storek }; 71143452Shibler hpuxrtprio(cp, uap, retval) 71243452Shibler struct proc *cp; 71354917Storek register struct hpuxrtprio_args *uap; 71443452Shibler int *retval; 71543452Shibler { 71641486Smckusick struct proc *p; 71743452Shibler int nice, error; 71841486Smckusick 71941486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 72043452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 72144421Skarels return (EINVAL); 72241486Smckusick if (uap->pid == 0) 72343452Shibler p = cp; 72443452Shibler else if ((p = pfind(uap->pid)) == 0) 72544421Skarels return (ESRCH); 72641486Smckusick nice = p->p_nice; 72741486Smckusick if (nice < NZERO) 72843452Shibler *retval = (nice + 16) << 3; 72941486Smckusick else 73043452Shibler *retval = RTPRIO_RTOFF; 73141486Smckusick switch (uap->prio) { 73241486Smckusick 73341486Smckusick case RTPRIO_NOCHG: 73444421Skarels return (0); 73541486Smckusick 73641486Smckusick case RTPRIO_RTOFF: 73741486Smckusick if (nice >= NZERO) 73844421Skarels return (0); 73941486Smckusick nice = NZERO; 74041486Smckusick break; 74141486Smckusick 74241486Smckusick default: 74341486Smckusick nice = (uap->prio >> 3) - 16; 74441486Smckusick break; 74541486Smckusick } 74643452Shibler error = donice(cp, p, nice); 74743452Shibler if (error == EACCES) 74843452Shibler error = EPERM; 74944421Skarels return (error); 75041486Smckusick } 75141486Smckusick 75254917Storek struct hpuxadvise_args { 75354917Storek int arg; 75454917Storek }; 75543452Shibler hpuxadvise(p, uap, retval) 75643452Shibler struct proc *p; 75754917Storek struct hpuxadvise_args *uap; 75843452Shibler int *retval; 75941486Smckusick { 76043452Shibler int error = 0; 76141486Smckusick 76241486Smckusick switch (uap->arg) { 76341486Smckusick case 0: 76457307Shibler p->p_md.md_flags |= MDP_HPUXMMAP; 76541486Smckusick break; 76641486Smckusick case 1: 76741486Smckusick ICIA(); 76841486Smckusick break; 76941486Smckusick case 2: 77041486Smckusick DCIA(); 77141486Smckusick break; 77241486Smckusick default: 77343452Shibler error = EINVAL; 77441486Smckusick break; 77541486Smckusick } 77644421Skarels return (error); 77741486Smckusick } 77841486Smckusick 77954917Storek struct hpuxptrace_args { 78054917Storek int req; 78154917Storek int pid; 78254917Storek int *addr; 78354917Storek int data; 78454917Storek }; 78543452Shibler hpuxptrace(p, uap, retval) 78643452Shibler struct proc *p; 78754917Storek struct hpuxptrace_args *uap; 78843452Shibler int *retval; 78943452Shibler { 79057307Shibler int error, isps = 0; 79157307Shibler struct proc *cp; 79241486Smckusick 79357307Shibler switch (uap->req) { 79457307Shibler /* map signal */ 79557307Shibler case PT_STEP: 79657307Shibler case PT_CONTINUE: 79741486Smckusick if (uap->data) { 79841486Smckusick uap->data = hpuxtobsdsig(uap->data); 79941486Smckusick if (uap->data == 0) 80041486Smckusick uap->data = NSIG; 80141486Smckusick } 80257307Shibler break; 80357307Shibler /* map u-area offset */ 80457307Shibler case PT_READ_U: 80557307Shibler case PT_WRITE_U: 80657307Shibler /* 80757307Shibler * Big, cheezy hack: hpuxtobsduoff is really intended 80857307Shibler * to be called in the child context (procxmt) but we 80957307Shibler * do it here in the parent context to avoid hacks in 81057307Shibler * the MI sys_process.c file. This works only because 81157307Shibler * we can access the child's md_regs pointer and it 81257307Shibler * has the correct value (the child has already trapped 81357307Shibler * into the kernel). 81457307Shibler */ 81557307Shibler if ((cp = pfind(uap->pid)) == 0) 81657307Shibler return (ESRCH); 81757307Shibler uap->addr = (int *) hpuxtobsduoff(uap->addr, &isps, cp); 81857307Shibler 81957307Shibler /* 82057307Shibler * Since HP-UX PS is only 16-bits in ar0, requests 82157307Shibler * to write PS actually contain the PS in the high word 82257307Shibler * and the high half of the PC (the following register) 82357307Shibler * in the low word. Move the PS value to where BSD 82457307Shibler * expects it. 82557307Shibler */ 82657307Shibler if (isps && uap->req == PT_WRITE_U) 82757307Shibler uap->data >>= 16; 82857307Shibler break; 82941486Smckusick } 83043452Shibler error = ptrace(p, uap, retval); 83157307Shibler /* 83257307Shibler * Align PS as HP-UX expects it (see WRITE_U comment above). 83357307Shibler * Note that we do not return the high part of PC like HP-UX 83457307Shibler * would, but the HP-UX debuggers don't require it. 83557307Shibler */ 83657307Shibler if (isps && error == 0 && uap->req == PT_READ_U) 83757307Shibler *retval <<= 16; 83844421Skarels return (error); 83941486Smckusick } 84041486Smckusick 84154917Storek struct hpuxgetdomainname_args { 84254917Storek char *domainname; 84354917Storek u_int len; 84454917Storek }; 84543452Shibler hpuxgetdomainname(p, uap, retval) 84643452Shibler struct proc *p; 84754917Storek register struct hpuxgetdomainname_args *uap; 84843452Shibler int *retval; 84943452Shibler { 85041486Smckusick if (uap->len > domainnamelen + 1) 85141486Smckusick uap->len = domainnamelen + 1; 85244421Skarels return (copyout(domainname, uap->domainname, uap->len)); 85341486Smckusick } 85441486Smckusick 85554917Storek struct hpuxsetdomainname_args { 85654917Storek char *domainname; 85754917Storek u_int len; 85854917Storek }; 85943452Shibler hpuxsetdomainname(p, uap, retval) 86043452Shibler struct proc *p; 86154917Storek register struct hpuxsetdomainname_args *uap; 86243452Shibler int *retval; 86343452Shibler { 86443452Shibler int error; 86541486Smckusick 86648478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 86744421Skarels return (error); 86843452Shibler if (uap->len > sizeof (domainname) - 1) 86944421Skarels return (EINVAL); 87041486Smckusick domainnamelen = uap->len; 87143452Shibler error = copyin(uap->domainname, domainname, uap->len); 87241486Smckusick domainname[domainnamelen] = 0; 87344421Skarels return (error); 87441486Smckusick } 87541486Smckusick 87641486Smckusick #ifdef SYSVSHM 87756506Sbostic #include <sys/shm.h> 87854857Shibler 87943452Shibler hpuxshmat(p, uap, retval) 88043452Shibler struct proc *p; 88143452Shibler int *uap, *retval; 88241486Smckusick { 88344421Skarels return (shmat(p, uap, retval)); 88441486Smckusick } 88541486Smckusick 88643452Shibler hpuxshmdt(p, uap, retval) 88743452Shibler struct proc *p; 88843452Shibler int *uap, *retval; 88941486Smckusick { 89044421Skarels return (shmdt(p, uap, retval)); 89141486Smckusick } 89241486Smckusick 89343452Shibler hpuxshmget(p, uap, retval) 89443452Shibler struct proc *p; 89543452Shibler int *uap, *retval; 89641486Smckusick { 89744421Skarels return (shmget(p, uap, retval)); 89841486Smckusick } 89954857Shibler 90054857Shibler /* 90154857Shibler * Handle HP-UX specific commands. 90254857Shibler */ 90354917Storek struct hpuxshmctl_args { 90454917Storek int shmid; 90554917Storek int cmd; 90654917Storek caddr_t buf; 90754917Storek }; 90854857Shibler hpuxshmctl(p, uap, retval) 90954857Shibler struct proc *p; 91054917Storek struct hpuxshmctl_args *uap; 91154857Shibler int *retval; 91254857Shibler { 91354857Shibler register struct shmid_ds *shp; 91454857Shibler register struct ucred *cred = p->p_ucred; 91554857Shibler int error; 91654857Shibler 91754857Shibler if (error = shmvalid(uap->shmid)) 91854857Shibler return (error); 91954857Shibler shp = &shmsegs[uap->shmid % SHMMMNI]; 92054857Shibler if (uap->cmd == SHM_LOCK || uap->cmd == SHM_UNLOCK) { 92154857Shibler /* don't really do anything, but make them think we did */ 92254857Shibler if (cred->cr_uid && cred->cr_uid != shp->shm_perm.uid && 92354857Shibler cred->cr_uid != shp->shm_perm.cuid) 92454857Shibler return (EPERM); 92554857Shibler return (0); 92654857Shibler } 92754857Shibler return (shmctl(p, uap, retval)); 92854857Shibler } 92941486Smckusick #endif 93041486Smckusick 93141486Smckusick /* 93241486Smckusick * Fake semaphore routines, just don't return an error. 93341486Smckusick * Should be adequate for starbase to run. 93441486Smckusick */ 93554917Storek struct hpuxsemctl_args { 93654917Storek int semid; 93754917Storek u_int semnum; 93854917Storek int cmd; 93954917Storek int arg; 94054917Storek }; 94143452Shibler hpuxsemctl(p, uap, retval) 94243452Shibler struct proc *p; 94354917Storek struct hpuxsemctl_args *uap; 94443452Shibler int *retval; 94543452Shibler { 94641486Smckusick /* XXX: should do something here */ 94744421Skarels return (0); 94841486Smckusick } 94941486Smckusick 95054917Storek struct hpuxsemget_args { 95154917Storek key_t key; 95254917Storek int nsems; 95354917Storek int semflg; 95454917Storek }; 95543452Shibler hpuxsemget(p, uap, retval) 95643452Shibler struct proc *p; 95754917Storek struct hpuxsemget_args *uap; 95843452Shibler int *retval; 95943452Shibler { 96041486Smckusick /* XXX: should do something here */ 96144421Skarels return (0); 96241486Smckusick } 96341486Smckusick 96454917Storek struct hpuxsemop_args { 96554917Storek int semid; 96654917Storek struct sembuf *sops; 96754917Storek u_int nsops; 96854917Storek }; 96943452Shibler hpuxsemop(p, uap, retval) 97043452Shibler struct proc *p; 97154917Storek struct hpuxsemop_args *uap; 97243452Shibler int *retval; 97343452Shibler { 97441486Smckusick /* XXX: should do something here */ 97544421Skarels return (0); 97641486Smckusick } 97741486Smckusick 97857307Shibler /* 97957307Shibler * HP-UX mmap() emulation (mainly for shared library support). 98057307Shibler */ 98157307Shibler struct hpuxmmap_args { 98257307Shibler caddr_t addr; 98357307Shibler int len; 98457307Shibler int prot; 98557307Shibler int flags; 98657307Shibler int fd; 98757307Shibler long pos; 98857307Shibler }; 98957307Shibler hpuxmmap(p, uap, retval) 99057307Shibler struct proc *p; 99157307Shibler struct hpuxmmap_args *uap; 99257307Shibler int *retval; 99357307Shibler { 99457307Shibler struct mmap_args { 99557307Shibler caddr_t addr; 99657307Shibler int len; 99757307Shibler int prot; 99857307Shibler int flags; 99957307Shibler int fd; 100057307Shibler long pad; 100157307Shibler off_t pos; 100257307Shibler } nargs; 100357307Shibler 100457307Shibler nargs.addr = uap->addr; 100557307Shibler nargs.len = uap->len; 100657307Shibler nargs.prot = uap->prot; 100757307Shibler nargs.flags = uap->flags & 100857307Shibler ~(HPUXMAP_FIXED|HPUXMAP_REPLACE|HPUXMAP_ANON); 100957307Shibler if (uap->flags & HPUXMAP_FIXED) 101057307Shibler nargs.flags |= MAP_FIXED; 101157307Shibler if (uap->flags & HPUXMAP_ANON) 101257307Shibler nargs.flags |= MAP_ANON; 101357307Shibler nargs.fd = (nargs.flags & MAP_ANON) ? -1 : uap->fd; 101457307Shibler nargs.pos = uap->pos; 101557307Shibler return (smmap(p, &nargs, retval)); 101657307Shibler } 101757307Shibler 101854857Shibler /* convert from BSD to HP-UX errno */ 101941486Smckusick bsdtohpuxerrno(err) 102041486Smckusick int err; 102141486Smckusick { 102241486Smckusick if (err < 0 || err >= NERR) 102341486Smckusick return(BERR); 102441486Smckusick return((int)bsdtohpuxerrnomap[err]); 102541486Smckusick } 102641486Smckusick 102755282Smckusick hpuxstat1(fname, hsb, follow, p) 102841486Smckusick char *fname; 102941486Smckusick struct hpuxstat *hsb; 103041486Smckusick int follow; 103155282Smckusick struct proc *p; 103241486Smckusick { 103348478Skarels int error; 103441486Smckusick struct stat sb; 103548478Skarels struct nameidata nd; 103641486Smckusick 103755282Smckusick NDINIT(&nd, LOOKUP, follow | LOCKLEAF, UIO_USERSPACE, fname, p); 103852330Smckusick if (error = namei(&nd)) 103941486Smckusick return (error); 104055282Smckusick error = vn_stat(nd.ni_vp, &sb, p); 104152330Smckusick vput(nd.ni_vp); 104241486Smckusick if (error == 0) 104341486Smckusick error = bsdtohpuxstat(&sb, hsb); 104441486Smckusick return (error); 104541486Smckusick } 104641486Smckusick 104741486Smckusick #include "grf.h" 104853922Shibler #if NGRF > 0 104953922Shibler #ifdef __STDC__ 105053922Shibler extern int grfopen(dev_t dev, int oflags, int devtype, struct proc *p); 105153922Shibler #else 105253922Shibler extern int grfopen(); 105353922Shibler #endif 105453922Shibler #endif 105541486Smckusick 105653922Shibler #define NHIL 1 /* XXX */ 105753922Shibler #if NHIL > 0 105853922Shibler #ifdef __STDC__ 105953922Shibler extern int hilopen(dev_t dev, int oflags, int devtype, struct proc *p); 106053922Shibler #else 106153922Shibler extern int hilopen(); 106253922Shibler #endif 106353922Shibler #endif 106453922Shibler 106556506Sbostic #include <sys/conf.h> 106653922Shibler 106741486Smckusick bsdtohpuxstat(sb, hsb) 106841486Smckusick struct stat *sb; 106941486Smckusick struct hpuxstat *hsb; 107041486Smckusick { 107141486Smckusick struct hpuxstat ds; 107241486Smckusick 107341486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 107453481Smckusick ds.hst_dev = (u_short)sb->st_dev; 107541486Smckusick ds.hst_ino = (u_long)sb->st_ino; 107641486Smckusick ds.hst_mode = sb->st_mode; 107741486Smckusick ds.hst_nlink = sb->st_nlink; 107841486Smckusick ds.hst_uid = (u_short)sb->st_uid; 107941486Smckusick ds.hst_gid = (u_short)sb->st_gid; 108057307Shibler ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 108157307Shibler 108253922Shibler /* XXX: I don't want to talk about it... */ 108353922Shibler if ((sb->st_mode & S_IFMT) == S_IFCHR) { 108441486Smckusick #if NGRF > 0 108553922Shibler if (cdevsw[major(sb->st_rdev)].d_open == grfopen) 108653922Shibler ds.hst_rdev = grfdevno(sb->st_rdev); 108741486Smckusick #endif 108853922Shibler #if NHIL > 0 108953922Shibler if (cdevsw[major(sb->st_rdev)].d_open == hilopen) 109053922Shibler ds.hst_rdev = hildevno(sb->st_rdev); 109153922Shibler #endif 109253922Shibler ; 109357307Shibler } 109453481Smckusick if (sb->st_size < (quad_t)1 << 32) 109553481Smckusick ds.hst_size = (long)sb->st_size; 109653481Smckusick else 109753481Smckusick ds.hst_size = -2; 109841486Smckusick ds.hst_atime = sb->st_atime; 109941486Smckusick ds.hst_mtime = sb->st_mtime; 110041486Smckusick ds.hst_ctime = sb->st_ctime; 110141486Smckusick ds.hst_blksize = sb->st_blksize; 110241486Smckusick ds.hst_blocks = sb->st_blocks; 110341486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 110441486Smckusick } 110541486Smckusick 110641486Smckusick hpuxtobsdioctl(com) 110741486Smckusick int com; 110841486Smckusick { 110941486Smckusick switch (com) { 111041486Smckusick case HPUXTIOCSLTC: 111141486Smckusick com = TIOCSLTC; break; 111241486Smckusick case HPUXTIOCGLTC: 111341486Smckusick com = TIOCGLTC; break; 111441486Smckusick case HPUXTIOCSPGRP: 111541486Smckusick com = TIOCSPGRP; break; 111641486Smckusick case HPUXTIOCGPGRP: 111741486Smckusick com = TIOCGPGRP; break; 111841486Smckusick case HPUXTIOCLBIS: 111941486Smckusick com = TIOCLBIS; break; 112041486Smckusick case HPUXTIOCLBIC: 112141486Smckusick com = TIOCLBIC; break; 112241486Smckusick case HPUXTIOCLSET: 112341486Smckusick com = TIOCLSET; break; 112441486Smckusick case HPUXTIOCLGET: 112541486Smckusick com = TIOCLGET; break; 112641486Smckusick } 112741486Smckusick return(com); 112841486Smckusick } 112941486Smckusick 113041486Smckusick /* 113154857Shibler * HP-UX ioctl system call. The differences here are: 113241486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 113349329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 113441486Smckusick * the sgttyb struct is 2 bytes longer 113541486Smckusick */ 113654917Storek struct hpuxioctl_args { 113754917Storek int fdes; 113854917Storek int cmd; 113954917Storek caddr_t cmarg; 114054917Storek }; 114143452Shibler hpuxioctl(p, uap, retval) 114243452Shibler struct proc *p; 114354917Storek register struct hpuxioctl_args *uap; 114443452Shibler int *retval; 114543452Shibler { 114645923Smckusick register struct filedesc *fdp = p->p_fd; 114743452Shibler register struct file *fp; 114843452Shibler register int com, error; 114941486Smckusick register u_int size; 115041486Smckusick caddr_t memp = 0; 115141486Smckusick #define STK_PARAMS 128 115241486Smckusick char stkbuf[STK_PARAMS]; 115341486Smckusick caddr_t data = stkbuf; 115441486Smckusick 115541486Smckusick com = uap->cmd; 115641486Smckusick 115741486Smckusick /* XXX */ 115843452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 115945923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 116041486Smckusick 116148478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 116248478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 116344421Skarels return (EBADF); 116443452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 116544421Skarels return (EBADF); 116641486Smckusick 116741486Smckusick /* 116841486Smckusick * Interpret high order word to find 116941486Smckusick * amount of data to be copied to/from the 117041486Smckusick * user's address space. 117141486Smckusick */ 117241486Smckusick size = IOCPARM_LEN(com); 117343452Shibler if (size > IOCPARM_MAX) 117444421Skarels return (ENOTTY); 117541486Smckusick if (size > sizeof (stkbuf)) { 117643452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 117741486Smckusick data = memp; 117841486Smckusick } 117941486Smckusick if (com&IOC_IN) { 118041486Smckusick if (size) { 118143452Shibler error = copyin(uap->cmarg, data, (u_int)size); 118243452Shibler if (error) { 118341486Smckusick if (memp) 118441486Smckusick free(memp, M_IOCTLOPS); 118544421Skarels return (error); 118641486Smckusick } 118741486Smckusick } else 118841486Smckusick *(caddr_t *)data = uap->cmarg; 118941486Smckusick } else if ((com&IOC_OUT) && size) 119041486Smckusick /* 119143452Shibler * Zero the buffer so the user always 119243452Shibler * gets back something deterministic. 119341486Smckusick */ 119441486Smckusick bzero(data, size); 119541486Smckusick else if (com&IOC_VOID) 119641486Smckusick *(caddr_t *)data = uap->cmarg; 119741486Smckusick 119841486Smckusick switch (com) { 119941486Smckusick 120049329Shibler case HPUXFIOSNBIO: 120149329Shibler { 120249329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 120349329Shibler int tmp; 120449329Shibler 120549329Shibler if (*(int *)data) 120649329Shibler *ofp |= UF_FIONBIO_ON; 120749329Shibler else 120849329Shibler *ofp &= ~UF_FIONBIO_ON; 120949329Shibler /* 121049950Smckusick * Only set/clear if FNONBLOCK not in effect 121149329Shibler */ 121249329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 121349950Smckusick tmp = fp->f_flag & FNONBLOCK; 121449329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 121549329Shibler (caddr_t)&tmp, p); 121649329Shibler } 121749329Shibler break; 121849329Shibler } 121949329Shibler 122041486Smckusick case HPUXTIOCCONS: 122141486Smckusick *(int *)data = 1; 122248478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 122341486Smckusick break; 122441486Smckusick 122541486Smckusick /* BSD-style job control ioctls */ 122641486Smckusick case HPUXTIOCLBIS: 122741486Smckusick case HPUXTIOCLBIC: 122841486Smckusick case HPUXTIOCLSET: 122941486Smckusick *(int *)data &= HPUXLTOSTOP; 123041486Smckusick if (*(int *)data & HPUXLTOSTOP) 123141486Smckusick *(int *)data = LTOSTOP; 123241486Smckusick /* fall into */ 123341486Smckusick case HPUXTIOCLGET: 123441486Smckusick case HPUXTIOCSLTC: 123541486Smckusick case HPUXTIOCGLTC: 123641486Smckusick case HPUXTIOCSPGRP: 123741486Smckusick case HPUXTIOCGPGRP: 123848478Skarels error = (*fp->f_ops->fo_ioctl) 123948478Skarels (fp, hpuxtobsdioctl(com), data, p); 124043452Shibler if (error == 0 && com == HPUXTIOCLGET) { 124141486Smckusick *(int *)data &= LTOSTOP; 124241486Smckusick if (*(int *)data & LTOSTOP) 124341486Smckusick *(int *)data = HPUXLTOSTOP; 124441486Smckusick } 124541486Smckusick break; 124641486Smckusick 124755832Shibler /* SYS 5 termio and POSIX termios */ 124841486Smckusick case HPUXTCGETA: 124941486Smckusick case HPUXTCSETA: 125041486Smckusick case HPUXTCSETAW: 125141486Smckusick case HPUXTCSETAF: 125255832Shibler case HPUXTCGETATTR: 125355832Shibler case HPUXTCSETATTR: 125455832Shibler case HPUXTCSETATTRD: 125555832Shibler case HPUXTCSETATTRF: 125648478Skarels error = hpuxtermio(fp, com, data, p); 125741486Smckusick break; 125841486Smckusick 125941486Smckusick default: 126048478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 126141486Smckusick break; 126241486Smckusick } 126341486Smckusick /* 126441486Smckusick * Copy any data to user, size was 126541486Smckusick * already set and checked above. 126641486Smckusick */ 126743452Shibler if (error == 0 && (com&IOC_OUT) && size) 126843452Shibler error = copyout(data, uap->cmarg, (u_int)size); 126941486Smckusick if (memp) 127041486Smckusick free(memp, M_IOCTLOPS); 127144421Skarels return (error); 127241486Smckusick } 127341486Smckusick 127441486Smckusick /* 127541486Smckusick * Man page lies, behaviour here is based on observed behaviour. 127641486Smckusick */ 127754917Storek struct hpuxgetcontext_args { 127854917Storek char *buf; 127954917Storek int len; 128054917Storek }; 128143452Shibler hpuxgetcontext(p, uap, retval) 128243452Shibler struct proc *p; 128354917Storek struct hpuxgetcontext_args *uap; 128443452Shibler int *retval; 128543452Shibler { 128641486Smckusick int error = 0; 128741486Smckusick register int len; 128841486Smckusick 128953922Shibler #if defined(HP380) 129053922Shibler if (machineid == HP_380) { 129155072Spendry len = min(uap->len, sizeof(hpux040context)); 129253922Shibler if (len) 129353922Shibler error = copyout(hpux040context, uap->buf, len); 129453922Shibler if (error == 0) 129553922Shibler *retval = sizeof(hpux040context); 129653922Shibler return (error); 129753922Shibler } 129853922Shibler #endif 129955072Spendry len = min(uap->len, sizeof(hpuxcontext)); 130041486Smckusick if (len) 130141486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 130243452Shibler if (error == 0) 130343452Shibler *retval = sizeof(hpuxcontext); 130444421Skarels return (error); 130541486Smckusick } 130641486Smckusick 130741486Smckusick /* 130841486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 130941486Smckusick * Note we do not check the real uid or "saved" uid. 131041486Smckusick */ 131154917Storek struct hpuxgetpgrp2_args { 131254917Storek int pid; 131354917Storek }; 131443452Shibler hpuxgetpgrp2(cp, uap, retval) 131543452Shibler struct proc *cp; 131654917Storek register struct hpuxgetpgrp2_args *uap; 131743452Shibler int *retval; 131841486Smckusick { 131941486Smckusick register struct proc *p; 132041486Smckusick 132141486Smckusick if (uap->pid == 0) 132243452Shibler uap->pid = cp->p_pid; 132341486Smckusick p = pfind(uap->pid); 132443452Shibler if (p == 0) 132544421Skarels return (ESRCH); 132648478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 132748478Skarels !inferior(p)) 132844421Skarels return (EPERM); 132943452Shibler *retval = p->p_pgid; 133044421Skarels return (0); 133141486Smckusick } 133241486Smckusick 133341486Smckusick /* 133441486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 133541486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 133641486Smckusick */ 133754917Storek struct hpuxsetpgrp2_args { 133854917Storek int pid; 133954917Storek int pgrp; 134054917Storek }; 134143452Shibler hpuxsetpgrp2(p, uap, retval) 134243452Shibler struct proc *p; 134354917Storek struct hpuxsetpgrp2_args *uap; 134443452Shibler int *retval; 134543452Shibler { 134641486Smckusick /* empirically determined */ 134743452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 134844421Skarels return (EINVAL); 134948478Skarels return (setpgid(p, uap, retval)); 135041486Smckusick } 135141486Smckusick 135241486Smckusick /* 135355165Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 135445753Smckusick */ 135554917Storek struct hpuxsetresuid_args { 135654917Storek int ruid; 135754917Storek int euid; 135854917Storek int suid; 135954917Storek }; 136045753Smckusick hpuxsetresuid(p, uap, retval) 136155165Smckusick struct proc *p; 136254917Storek struct hpuxsetresuid_args *uap; 136345753Smckusick int *retval; 136445753Smckusick { 136555165Smckusick return (osetreuid(p, uap, retval)); 136645753Smckusick } 136745753Smckusick 136854917Storek struct hpuxsetresgid_args { 136954917Storek int rgid; 137054917Storek int egid; 137154917Storek int sgid; 137254917Storek }; 137345753Smckusick hpuxsetresgid(p, uap, retval) 137455165Smckusick struct proc *p; 137554917Storek struct hpuxsetresgid_args *uap; 137645753Smckusick int *retval; 137745753Smckusick { 137855165Smckusick return (osetregid(p, uap, retval)); 137945753Smckusick } 138045753Smckusick 138157307Shibler struct hpuxrlimit_args { 138257307Shibler u_int which; 138357307Shibler struct orlimit *rlp; 138457307Shibler }; 138557307Shibler hpuxgetrlimit(p, uap, retval) 138657307Shibler struct proc *p; 138757307Shibler struct hpuxrlimit_args *uap; 138857307Shibler int *retval; 138957307Shibler { 139057307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 139157307Shibler return (EINVAL); 139257307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 139357307Shibler uap->which = RLIMIT_NOFILE; 1394*60110Smckusick return (ogetrlimit(p, uap, retval)); 139557307Shibler } 139657307Shibler 139757307Shibler hpuxsetrlimit(p, uap, retval) 139857307Shibler struct proc *p; 139957307Shibler struct hpuxrlimit_args *uap; 140057307Shibler int *retval; 140157307Shibler { 140257307Shibler if (uap->which > HPUXRLIMIT_NOFILE) 140357307Shibler return (EINVAL); 140457307Shibler if (uap->which == HPUXRLIMIT_NOFILE) 140557307Shibler uap->which = RLIMIT_NOFILE; 1406*60110Smckusick return (osetrlimit(p, uap, retval)); 140757307Shibler } 140857307Shibler 140945753Smckusick /* 141045753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 141145753Smckusick */ 141254917Storek struct hpuxlockf_args { 141354917Storek int fd; 141454917Storek int func; 141554917Storek long size; 141654917Storek }; 141745753Smckusick hpuxlockf(p, uap, retval) 141845753Smckusick struct proc *p; 141954917Storek struct hpuxlockf_args *uap; 142045753Smckusick int *retval; 142145753Smckusick { 142245753Smckusick return (0); 142345753Smckusick } 142445753Smckusick 142554917Storek struct hpuxgetaccess_args { 142654917Storek char *path; 142754917Storek int uid; 142854917Storek int ngroups; 142954917Storek int *gidset; 143054917Storek void *label; 143154917Storek void *privs; 143254917Storek }; 143345753Smckusick hpuxgetaccess(p, uap, retval) 143445753Smckusick register struct proc *p; 143554917Storek register struct hpuxgetaccess_args *uap; 143645753Smckusick int *retval; 143745753Smckusick { 143845753Smckusick int lgroups[NGROUPS]; 143945753Smckusick int error = 0; 144045753Smckusick register struct ucred *cred; 144145753Smckusick register struct vnode *vp; 144252330Smckusick struct nameidata nd; 144345753Smckusick 144445753Smckusick /* 144545753Smckusick * Build an appropriate credential structure 144645753Smckusick */ 144748478Skarels cred = crdup(p->p_ucred); 144845753Smckusick switch (uap->uid) { 144945753Smckusick case 65502: /* UID_EUID */ 145045753Smckusick break; 145145753Smckusick case 65503: /* UID_RUID */ 145248478Skarels cred->cr_uid = p->p_cred->p_ruid; 145345753Smckusick break; 145445753Smckusick case 65504: /* UID_SUID */ 145545753Smckusick error = EINVAL; 145645753Smckusick break; 145745753Smckusick default: 145845753Smckusick if (uap->uid > 65504) 145945753Smckusick error = EINVAL; 146045753Smckusick cred->cr_uid = uap->uid; 146145753Smckusick break; 146245753Smckusick } 146345753Smckusick switch (uap->ngroups) { 146445753Smckusick case -1: /* NGROUPS_EGID */ 146545753Smckusick cred->cr_ngroups = 1; 146645753Smckusick break; 146745753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 146845753Smckusick break; 146945753Smckusick case -2: /* NGROUPS_RGID */ 147045753Smckusick cred->cr_ngroups = 1; 147148478Skarels cred->cr_gid = p->p_cred->p_rgid; 147245753Smckusick break; 147345753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 147448478Skarels cred->cr_gid = p->p_cred->p_rgid; 147545753Smckusick break; 147645753Smckusick case -3: /* NGROUPS_SGID */ 147745753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 147845753Smckusick error = EINVAL; 147945753Smckusick break; 148045753Smckusick case -4: /* NGROUPS_SUPP */ 148145753Smckusick if (cred->cr_ngroups > 1) 148245753Smckusick cred->cr_gid = cred->cr_groups[1]; 148345753Smckusick else 148445753Smckusick error = EINVAL; 148545753Smckusick break; 148645753Smckusick default: 148745753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 148845753Smckusick error = copyin((caddr_t)uap->gidset, 148945753Smckusick (caddr_t)&lgroups[0], 149045753Smckusick uap->ngroups * sizeof(lgroups[0])); 149145753Smckusick else 149245753Smckusick error = EINVAL; 149345753Smckusick if (error == 0) { 149445753Smckusick int gid; 149545753Smckusick 149645753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 149745753Smckusick cred->cr_groups[gid] = lgroups[gid]; 149845753Smckusick cred->cr_ngroups = uap->ngroups; 149945753Smckusick } 150045753Smckusick break; 150145753Smckusick } 150245753Smckusick /* 150345753Smckusick * Lookup file using caller's effective IDs. 150445753Smckusick */ 150545753Smckusick if (error == 0) { 150652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 150752330Smckusick uap->path, p); 150852330Smckusick error = namei(&nd); 150945753Smckusick } 151045753Smckusick if (error) { 151145753Smckusick crfree(cred); 151245753Smckusick return (error); 151345753Smckusick } 151445753Smckusick /* 151545753Smckusick * Use the constructed credentials for access checks. 151645753Smckusick */ 151752330Smckusick vp = nd.ni_vp; 151845753Smckusick *retval = 0; 151948478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 152045753Smckusick *retval |= R_OK; 152148478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 152245753Smckusick *retval |= W_OK; 152345753Smckusick /* XXX we return X_OK for root on VREG even if not */ 152448478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 152545753Smckusick *retval |= X_OK; 152645753Smckusick vput(vp); 152745753Smckusick crfree(cred); 152845753Smckusick return (error); 152945753Smckusick } 153045753Smckusick 153149134Skarels extern char kstack[]; 153241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 153341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 153441486Smckusick 153541486Smckusick /* simplified FP structure */ 153641486Smckusick struct bsdfp { 153741486Smckusick int save[54]; 153841486Smckusick int reg[24]; 153941486Smckusick int ctrl[3]; 154041486Smckusick }; 154141486Smckusick 154257307Shibler /* 154357307Shibler * Brutal hack! Map HP-UX u-area offsets into BSD k-stack offsets. 154457307Shibler */ 154557307Shibler hpuxtobsduoff(off, isps, p) 154657307Shibler int *off, *isps; 154757307Shibler struct proc *p; 154841486Smckusick { 154957307Shibler register int *ar0 = p->p_md.md_regs; 155041486Smckusick struct hpuxfp *hp; 155141486Smckusick struct bsdfp *bp; 155241486Smckusick register u_int raddr; 155341486Smckusick 155457307Shibler *isps = 0; 155557307Shibler 155648478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 155741486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 155848478Skarels return(UOFF(U_ar0)); 155941486Smckusick 156041486Smckusick #ifdef FPCOPROC 156157307Shibler /* FP registers from PCB */ 156241486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 156341486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 156441486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 156541486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 156641486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 156741486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 156841486Smckusick #endif 156941486Smckusick 157041486Smckusick /* 157141486Smckusick * Everything else we recognize comes from the kernel stack, 157241486Smckusick * so we convert off to an absolute address (if not already) 157341486Smckusick * for simplicity. 157441486Smckusick */ 157541486Smckusick if (off < (int *)ctob(UPAGES)) 157649134Skarels off = (int *)((u_int)off + (u_int)kstack); 157741486Smckusick 157841486Smckusick /* 157957307Shibler * General registers. 158054857Shibler * We know that the HP-UX registers are in the same order as ours. 158141486Smckusick * The only difference is that their PS is 2 bytes instead of a 158241486Smckusick * padded 4 like ours throwing the alignment off. 158341486Smckusick */ 158448478Skarels if (off >= ar0 && off < &ar0[18]) { 158541486Smckusick /* 158641486Smckusick * PS: return low word and high word of PC as HP-UX would 158741486Smckusick * (e.g. &u.u_ar0[16.5]). 158857307Shibler * 158957307Shibler * XXX we don't do this since HP-UX adb doesn't rely on 159057307Shibler * it and passing such an offset to procxmt will cause 159157307Shibler * it to fail anyway. Instead, we just set the offset 159257307Shibler * to PS and let hpuxptrace() shift up the value returned. 159341486Smckusick */ 159457307Shibler if (off == &ar0[PS]) { 159557307Shibler #if 0 159648478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 159757307Shibler #else 159857307Shibler raddr = (u_int) &ar0[(int)(off - ar0)]; 159957307Shibler #endif 160057307Shibler *isps = 1; 160157307Shibler } 160241486Smckusick /* 160357307Shibler * PC: off will be &u.u_ar0[16.5] since HP-UX saved PS 160457307Shibler * is only 16 bits. 160541486Smckusick */ 160648478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 160748478Skarels raddr = (u_int) &ar0[PC]; 160841486Smckusick /* 160941486Smckusick * D0-D7, A0-A7: easy 161041486Smckusick */ 161141486Smckusick else 161248478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 161349134Skarels return((int)(raddr - (u_int)kstack)); 161441486Smckusick } 161541486Smckusick 161641486Smckusick /* everything else */ 161741486Smckusick return(-1); 161841486Smckusick } 161941486Smckusick 162041486Smckusick /* 162154857Shibler * Kludge up a uarea dump so that HP-UX debuggers can find out 162241486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 162341486Smckusick * convert the entire user struct. 162441486Smckusick */ 162541486Smckusick hpuxdumpu(vp, cred) 162641486Smckusick struct vnode *vp; 162741486Smckusick struct ucred *cred; 162841486Smckusick { 162948478Skarels struct proc *p = curproc; 163041486Smckusick int error; 163141486Smckusick struct hpuxuser *faku; 163241486Smckusick struct bsdfp *bp; 163341486Smckusick short *foop; 163441486Smckusick 163541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 163641486Smckusick /* 163741486Smckusick * Make sure there is no mistake about this 163841486Smckusick * being a real user structure. 163941486Smckusick */ 164041486Smckusick bzero((caddr_t)faku, ctob(1)); 164141486Smckusick /* 164241486Smckusick * Fill in the process sizes. 164341486Smckusick */ 164448478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 164548478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 164648478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 164741486Smckusick /* 164841486Smckusick * Fill in the exec header for CDB. 164941486Smckusick * This was saved back in exec(). As far as I can tell CDB 165041486Smckusick * only uses this information to verify that a particular 165141486Smckusick * core file goes with a particular binary. 165241486Smckusick */ 165357307Shibler bcopy((caddr_t)p->p_addr->u_md.md_exec, 165441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 165541486Smckusick /* 165641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 165754857Shibler * HP-UX order. Note that HP-UX saves the SR as 2 bytes not 4 165841486Smckusick * so we have to move it up. 165941486Smckusick */ 166052381Smckusick faku->hpuxu_ar0 = p->p_md.md_regs; 166152381Smckusick foop = (short *) p->p_md.md_regs; 166241486Smckusick foop[32] = foop[33]; 166341486Smckusick foop[33] = foop[34]; 166441486Smckusick foop[34] = foop[35]; 166541486Smckusick #ifdef FPCOPROC 166641486Smckusick /* 166754857Shibler * Copy 68881 registers from our PCB format to HP-UX format 166841486Smckusick */ 166949134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 167041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 167141486Smckusick sizeof(bp->save)); 167241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 167341486Smckusick sizeof(bp->ctrl)); 167441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 167541486Smckusick sizeof(bp->reg)); 167641486Smckusick #endif 167741486Smckusick /* 167841486Smckusick * Slay the dragon 167941486Smckusick */ 168041486Smckusick faku->hpuxu_dragon = -1; 168141486Smckusick /* 168241486Smckusick * Dump this artfully constructed page in place of the 168341486Smckusick * user struct page. 168441486Smckusick */ 168548478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 168648478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 168749134Skarels (int *)NULL, p); 168841486Smckusick /* 168941486Smckusick * Dump the remaining UPAGES-1 pages normally 169041486Smckusick */ 169141486Smckusick if (!error) 169249134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 169341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 169449134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 169541486Smckusick free((caddr_t)faku, M_TEMP); 169641486Smckusick return(error); 169741486Smckusick } 169841486Smckusick 169941486Smckusick /* 170041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 170141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 170241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 170341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 170457307Shibler * 170557307Shibler * These are still needed as of HP-UX 7.05. 170641486Smckusick */ 170755832Shibler #ifdef COMPAT_OHPUX 170855832Shibler 170945753Smckusick #define HPUX_HZ 50 171045753Smckusick 171157307Shibler #include "sys/times.h" 171241486Smckusick 171341486Smckusick /* from old timeb.h */ 171441486Smckusick struct hpuxtimeb { 171541486Smckusick time_t time; 171641486Smckusick u_short millitm; 171741486Smckusick short timezone; 171841486Smckusick short dstflag; 171941486Smckusick }; 172041486Smckusick 172141486Smckusick /* ye ole stat structure */ 172241486Smckusick struct ohpuxstat { 172353481Smckusick u_short ohst_dev; 172441486Smckusick u_short ohst_ino; 172541486Smckusick u_short ohst_mode; 172641486Smckusick short ohst_nlink; 172741486Smckusick short ohst_uid; 172841486Smckusick short ohst_gid; 172953481Smckusick u_short ohst_rdev; 173041486Smckusick int ohst_size; 173141486Smckusick int ohst_atime; 173241486Smckusick int ohst_mtime; 173341486Smckusick int ohst_ctime; 173441486Smckusick }; 173541486Smckusick 173641486Smckusick /* 173741486Smckusick * SYS V style setpgrp() 173841486Smckusick */ 173943452Shibler ohpuxsetpgrp(p, uap, retval) 174043452Shibler register struct proc *p; 174143452Shibler int *uap, *retval; 174241486Smckusick { 174341486Smckusick if (p->p_pid != p->p_pgid) 174448478Skarels enterpgrp(p, p->p_pid, 0); 174543452Shibler *retval = p->p_pgid; 174645753Smckusick return (0); 174741486Smckusick } 174841486Smckusick 174954917Storek struct ohpuxtime_args { 175054917Storek long *tp; 175154917Storek }; 175243452Shibler ohpuxtime(p, uap, retval) 175343452Shibler struct proc *p; 175454917Storek register struct ohpuxtime_args *uap; 175554917Storek int *retval; 175641486Smckusick { 175745753Smckusick int error = 0; 175841486Smckusick 175941486Smckusick if (uap->tp) 176043452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 176143452Shibler sizeof (long)); 176254917Storek *(time_t *)retval = time.tv_sec; 176344421Skarels return (error); 176441486Smckusick } 176541486Smckusick 176654917Storek struct ohpuxstime_args { 176754917Storek int time; 176854917Storek }; 176943452Shibler ohpuxstime(p, uap, retval) 177043452Shibler struct proc *p; 177154917Storek register struct ohpuxstime_args *uap; 177243452Shibler int *retval; 177341486Smckusick { 177441486Smckusick struct timeval tv; 177543452Shibler int s, error; 177641486Smckusick 177741486Smckusick tv.tv_sec = uap->time; 177841486Smckusick tv.tv_usec = 0; 177948478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 178044421Skarels return (error); 178141486Smckusick 178241486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 178341486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 178441486Smckusick s = splhigh(); time = tv; splx(s); 178541486Smckusick resettodr(); 178644421Skarels return (0); 178741486Smckusick } 178841486Smckusick 178954917Storek struct ohpuxftime_args { 179054917Storek struct hpuxtimeb *tp; 179154917Storek }; 179243452Shibler ohpuxftime(p, uap, retval) 179343452Shibler struct proc *p; 179454917Storek register struct ohpuxftime_args *uap; 179543452Shibler int *retval; 179643452Shibler { 179741486Smckusick struct hpuxtimeb tb; 179841486Smckusick int s; 179941486Smckusick 180041486Smckusick s = splhigh(); 180141486Smckusick tb.time = time.tv_sec; 180241486Smckusick tb.millitm = time.tv_usec / 1000; 180341486Smckusick splx(s); 180441486Smckusick tb.timezone = tz.tz_minuteswest; 180541486Smckusick tb.dstflag = tz.tz_dsttime; 180644421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 180741486Smckusick } 180841486Smckusick 180954917Storek struct ohpuxalarm_args { 181054917Storek int deltat; 181154917Storek }; 181243452Shibler ohpuxalarm(p, uap, retval) 181343452Shibler register struct proc *p; 181454917Storek register struct ohpuxalarm_args *uap; 181543452Shibler int *retval; 181641486Smckusick { 181741486Smckusick int s = splhigh(); 181841486Smckusick 181941486Smckusick untimeout(realitexpire, (caddr_t)p); 182041486Smckusick timerclear(&p->p_realtimer.it_interval); 182143452Shibler *retval = 0; 182241486Smckusick if (timerisset(&p->p_realtimer.it_value) && 182341486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 182443452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 182541486Smckusick if (uap->deltat == 0) { 182641486Smckusick timerclear(&p->p_realtimer.it_value); 182741486Smckusick splx(s); 182844421Skarels return (0); 182941486Smckusick } 183041486Smckusick p->p_realtimer.it_value = time; 183141486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 183241486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 183341486Smckusick splx(s); 183444421Skarels return (0); 183541486Smckusick } 183641486Smckusick 183754917Storek struct ohpuxnice_args { 183854917Storek int niceness; 183954917Storek }; 184043452Shibler ohpuxnice(p, uap, retval) 184143452Shibler register struct proc *p; 184254917Storek register struct ohpuxnice_args *uap; 184343452Shibler int *retval; 184441486Smckusick { 184543452Shibler int error; 184641486Smckusick 184743452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 184843452Shibler if (error == 0) 184943452Shibler *retval = p->p_nice - NZERO; 185044421Skarels return (error); 185141486Smckusick } 185241486Smckusick 185354917Storek struct ohpuxtimes_args { 185454917Storek struct tms *tmsb; 185554917Storek }; 185643452Shibler ohpuxtimes(p, uap, retval) 185743452Shibler struct proc *p; 185854917Storek register struct ohpuxtimes_args *uap; 185954917Storek int *retval; 186041486Smckusick { 186154771Storek struct timeval ru, rs; 186241486Smckusick struct tms atms; 186343452Shibler int error; 186441486Smckusick 186554771Storek calcru(p, &ru, &rs, NULL); 186654771Storek atms.tms_utime = hpuxscale(&ru); 186754771Storek atms.tms_stime = hpuxscale(&rs); 186848478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 186948478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 187043452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 187143452Shibler if (error == 0) 187254917Storek *(time_t *)retval = hpuxscale(&time) - hpuxscale(&boottime); 187344421Skarels return (error); 187441486Smckusick } 187541486Smckusick 187645753Smckusick /* 187745753Smckusick * Doesn't exactly do what the documentation says. 187845753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 187945753Smckusick * is what HP-UX returns. 188045753Smckusick */ 188145753Smckusick hpuxscale(tvp) 188241486Smckusick register struct timeval *tvp; 188341486Smckusick { 188445753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 188541486Smckusick } 188641486Smckusick 188741486Smckusick /* 188841486Smckusick * Set IUPD and IACC times on file. 188941486Smckusick * Can't set ICHG. 189041486Smckusick */ 189154917Storek struct ohpuxutime_args { 189254917Storek char *fname; 189354917Storek time_t *tptr; 189454917Storek }; 189543452Shibler ohpuxutime(p, uap, retval) 189643452Shibler struct proc *p; 189754917Storek register struct ohpuxutime_args *uap; 189843452Shibler int *retval; 189943452Shibler { 190048478Skarels register struct vnode *vp; 190141486Smckusick struct vattr vattr; 190241486Smckusick time_t tv[2]; 190343452Shibler int error; 190448478Skarels struct nameidata nd; 190541486Smckusick 190641486Smckusick if (uap->tptr) { 190743452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 190843452Shibler if (error) 190944421Skarels return (error); 191041486Smckusick } else 191141486Smckusick tv[0] = tv[1] = time.tv_sec; 191241486Smckusick vattr_null(&vattr); 191354107Smckusick vattr.va_atime.ts_sec = tv[0]; 191454107Smckusick vattr.va_atime.ts_nsec = 0; 191554107Smckusick vattr.va_mtime.ts_sec = tv[1]; 191654107Smckusick vattr.va_mtime.ts_nsec = 0; 191752330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 191852330Smckusick if (error = namei(&nd)) 191944421Skarels return (error); 192052330Smckusick vp = nd.ni_vp; 192142154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 192243452Shibler error = EROFS; 192341486Smckusick else 192452330Smckusick error = VOP_SETATTR(vp, &vattr, nd.ni_cnd.cn_cred, p); 192541486Smckusick vput(vp); 192644421Skarels return (error); 192741486Smckusick } 192841486Smckusick 192943452Shibler ohpuxpause(p, uap, retval) 193043452Shibler struct proc *p; 193143452Shibler int *uap, *retval; 193241486Smckusick { 193349134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 193442155Skarels /* always return EINTR rather than ERESTART... */ 193544421Skarels return (EINTR); 193641486Smckusick } 193741486Smckusick 193841486Smckusick /* 193941486Smckusick * The old fstat system call. 194041486Smckusick */ 194154917Storek struct ohpuxfstat_args { 194254917Storek int fd; 194354917Storek struct ohpuxstat *sb; 194454917Storek }; 194543452Shibler ohpuxfstat(p, uap, retval) 194643452Shibler struct proc *p; 194754917Storek register struct ohpuxfstat_args *uap; 194843452Shibler int *retval; 194943452Shibler { 195045923Smckusick register struct filedesc *fdp = p->p_fd; 195141486Smckusick struct file *fp; 195241486Smckusick 195348478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 195448478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 195544421Skarels return (EBADF); 195643452Shibler if (fp->f_type != DTYPE_VNODE) 195744421Skarels return (EINVAL); 195855282Smckusick return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb, p)); 195941486Smckusick } 196041486Smckusick 196141486Smckusick /* 196241486Smckusick * Old stat system call. This version follows links. 196341486Smckusick */ 196454917Storek struct ohpuxstat_args { 196554917Storek char *fname; 196654917Storek struct ohpuxstat *sb; 196754917Storek }; 196843452Shibler ohpuxstat(p, uap, retval) 196943452Shibler struct proc *p; 197054917Storek register struct ohpuxstat_args *uap; 197143452Shibler int *retval; 197243452Shibler { 197343452Shibler int error; 197448478Skarels struct nameidata nd; 197541486Smckusick 197652330Smckusick NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 197752330Smckusick if (error = namei(&nd)) 197844421Skarels return (error); 197955282Smckusick error = ohpuxstat1(nd.ni_vp, uap->sb, p); 198052330Smckusick vput(nd.ni_vp); 198144421Skarels return (error); 198241486Smckusick } 198341486Smckusick 198441486Smckusick int 198555282Smckusick ohpuxstat1(vp, ub, p) 198657307Shibler struct vnode *vp; 198741486Smckusick struct ohpuxstat *ub; 198855282Smckusick struct proc *p; 198941486Smckusick { 199057307Shibler struct ohpuxstat ohsb; 199157307Shibler struct stat sb; 199257307Shibler int error; 199341486Smckusick 199457307Shibler error = vn_stat(vp, &sb, p); 199541486Smckusick if (error) 199657307Shibler return (error); 199757307Shibler 199857307Shibler ohsb.ohst_dev = sb.st_dev; 199957307Shibler ohsb.ohst_ino = sb.st_ino; 200057307Shibler ohsb.ohst_mode = sb.st_mode; 200157307Shibler ohsb.ohst_nlink = sb.st_nlink; 200257307Shibler ohsb.ohst_uid = sb.st_uid; 200357307Shibler ohsb.ohst_gid = sb.st_gid; 200457307Shibler ohsb.ohst_rdev = sb.st_rdev; 200557307Shibler if (sb.st_size < (quad_t)1 << 32) 200657307Shibler ohsb.ohst_size = sb.st_size; 200757307Shibler else 200857307Shibler ohsb.ohst_size = -2; 200957307Shibler ohsb.ohst_atime = sb.st_atime; 201057307Shibler ohsb.ohst_mtime = sb.st_mtime; 201157307Shibler ohsb.ohst_ctime = sb.st_ctime; 201257307Shibler return (copyout((caddr_t)&ohsb, (caddr_t)ub, sizeof(ohsb))); 201341486Smckusick } 201441486Smckusick #endif 201555832Shibler #endif 2016