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 * 1245753Smckusick * from: Utah $Hdr: hpux_compat.c 1.3 90/09/17$ 1341486Smckusick * 14*45923Smckusick * @(#)hpux_compat.c 7.12 (Berkeley) 01/11/91 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Various HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2345788Sbostic #include "sys/param.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/user.h" 2645788Sbostic #include "sys/kernel.h" 27*45923Smckusick #include "sys/filedesc.h" 2845788Sbostic #include "sys/proc.h" 2945788Sbostic #include "sys/buf.h" 3045788Sbostic #include "sys/wait.h" 3145788Sbostic #include "sys/file.h" 3245788Sbostic #include "sys/vnode.h" 3345788Sbostic #include "sys/ioctl.h" 3445788Sbostic #include "sys/uio.h" 3545788Sbostic #include "sys/ptrace.h" 3645788Sbostic #include "sys/stat.h" 3745788Sbostic #include "sys/syslog.h" 3845788Sbostic #include "sys/malloc.h" 3945788Sbostic #include "sys/mount.h" 4045788Sbostic #include "sys/ipc.h" 4141486Smckusick 4245788Sbostic #include "../include/cpu.h" 4345788Sbostic #include "../include/reg.h" 4445788Sbostic #include "../include/psl.h" 4545788Sbostic #include "../include/vmparam.h" 4641486Smckusick #include "hpux.h" 4741486Smckusick #include "hpux_termio.h" 4841486Smckusick 4941486Smckusick #ifdef DEBUG 5041486Smckusick int unimpresponse = 0; 5141486Smckusick #endif 5241486Smckusick 5341486Smckusick /* SYS5 style UTSNAME info */ 5441486Smckusick struct hpuxutsname protoutsname = { 5541486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5641486Smckusick }; 5741486Smckusick 5841486Smckusick /* 6.0 and later style context */ 5941486Smckusick #ifdef FPCOPROC 6041486Smckusick char hpuxcontext[] = 6141486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6241486Smckusick #else 6341486Smckusick char hpuxcontext[] = 6441486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 6541486Smckusick #endif 6641486Smckusick 6741486Smckusick /* YP domainname */ 6841486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 6941486Smckusick int domainnamelen = 7; 7041486Smckusick 7141486Smckusick #define NERR 79 7241486Smckusick #define BERR 1000 7341486Smckusick 7441486Smckusick /* indexed by BSD errno */ 7541486Smckusick short bsdtohpuxerrnomap[NERR] = { 7641486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7741486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 7841486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 7941486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8041486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8141486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8241486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8341486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 8441486Smckusick }; 8541486Smckusick 8643452Shibler notimp(p, uap, retval, code, nargs) 8743452Shibler struct proc *p; 8843452Shibler int *uap, *retval; 8943452Shibler int code, nargs; 9041486Smckusick { 9143452Shibler int error = 0; 9241486Smckusick #ifdef DEBUG 9343452Shibler register int *argp = uap; 9441486Smckusick extern char *hpuxsyscallnames[]; 9541486Smckusick 9641486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9741486Smckusick if (nargs) 9841486Smckusick while (nargs--) 9941486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10041486Smckusick else 10141486Smckusick printf(")"); 10241486Smckusick printf("\n"); 10341486Smckusick switch (unimpresponse) { 10441486Smckusick case 0: 10543452Shibler error = nosys(p, uap, retval); 10641486Smckusick break; 10741486Smckusick case 1: 10843452Shibler error = EINVAL; 10941486Smckusick break; 11041486Smckusick } 11141486Smckusick #else 11243452Shibler error = nosys(p, uap, retval); 11341486Smckusick #endif 11443452Shibler uprintf("HP-UX system call %d not implemented\n", code); 11544421Skarels return (error); 11641486Smckusick } 11741486Smckusick 11841486Smckusick /* 11941486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 12041486Smckusick * (status pointer, options, rusage) into the kernel rather than 12142352Smckusick * handling it in the C library stub. We also need to map any 12242352Smckusick * termination signal from BSD to HPUX. 12341486Smckusick */ 12443452Shibler hpuxwait3(p, uap, retval) 12543452Shibler struct proc *p; 12643452Shibler struct args { 12741486Smckusick int *status; 12841486Smckusick int options; 12941486Smckusick int rusage; 13043452Shibler } *uap; 13143452Shibler int *retval; 13243452Shibler { 13341486Smckusick /* rusage pointer must be zero */ 13443452Shibler if (uap->rusage) 13544421Skarels return (EINVAL); 13641486Smckusick u.u_ar0[PS] = PSL_ALLCC; 13741486Smckusick u.u_ar0[R0] = uap->options; 13841486Smckusick u.u_ar0[R1] = uap->rusage; 13944421Skarels return (hpuxwait(p, uap, retval)); 14041486Smckusick } 14141486Smckusick 14243452Shibler hpuxwait(p, uap, retval) 14343452Shibler struct proc *p; 14443452Shibler struct args { 14543452Shibler int *status; 14643452Shibler } *uap; 14743452Shibler int *retval; 14841486Smckusick { 14943452Shibler int sig, *statp, error; 15041486Smckusick 15141486Smckusick statp = uap->status; /* owait clobbers first arg */ 15243452Shibler error = owait(p, uap, retval); 15341486Smckusick /* 15441486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 15541486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 15641486Smckusick */ 15743452Shibler if (error == ERESTART) 15843452Shibler error = EINTR; 15943452Shibler if (error) 16044421Skarels return (error); 16143452Shibler sig = retval[1] & 0xFF; 16241486Smckusick if (sig == WSTOPPED) { 16343452Shibler sig = (retval[1] >> 8) & 0xFF; 16443452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 16541486Smckusick } else if (sig) 16643452Shibler retval[1] = (retval[1] & 0xFF00) | 16741486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 16841486Smckusick if (statp) 16943452Shibler if (suword((caddr_t)statp, retval[1])) 17043452Shibler error = EFAULT; 17144421Skarels return (error); 17241486Smckusick } 17341486Smckusick 17443452Shibler hpuxwaitpid(p, uap, retval) 17543452Shibler struct proc *p; 17643452Shibler struct args { 17742352Smckusick int pid; 17842352Smckusick int *status; 17942352Smckusick int options; 18042352Smckusick struct rusage *rusage; /* wait4 arg */ 18143452Shibler } *uap; 18243452Shibler int *retval; 18343452Shibler { 18443452Shibler int sig, *statp, error; 18542352Smckusick 18642352Smckusick uap->rusage = 0; 18743452Shibler error = wait4(p, uap, retval); 18842352Smckusick /* 18942352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 19042352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 19142352Smckusick */ 19243452Shibler if (error == ERESTART) 19343452Shibler error = EINTR; 19443452Shibler if (error) 19544421Skarels return (error); 19643452Shibler sig = retval[1] & 0xFF; 19742352Smckusick if (sig == WSTOPPED) { 19843452Shibler sig = (retval[1] >> 8) & 0xFF; 19943452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 20042352Smckusick } else if (sig) 20143452Shibler retval[1] = (retval[1] & 0xFF00) | 20242352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 20342352Smckusick if (statp) 20443452Shibler if (suword((caddr_t)statp, retval[1])) 20543452Shibler error = EFAULT; 20644421Skarels return (error); 20742352Smckusick } 20842352Smckusick 20941486Smckusick /* 21041486Smckusick * Must remap some bits in the mode mask. 21141486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 21241486Smckusick * O_SYNCIO (0100000) is removed entirely. 21341486Smckusick */ 21443067Skarels hpuxopen(p, uap, retval) 21543067Skarels struct proc *p; 21643452Shibler register struct args { 21741486Smckusick char *fname; 21841486Smckusick int mode; 21941486Smckusick int crtmode; 22043067Skarels } *uap; 22143067Skarels int *retval; 22243067Skarels { 22341486Smckusick int mode; 22441486Smckusick 22541486Smckusick mode = uap->mode; 22641486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 22741486Smckusick if (mode & HPUXFCREAT) { 22841486Smckusick /* 22941486Smckusick * simulate the pre-NFS behavior that opening a 23041486Smckusick * file for READ+CREATE ignores the CREATE (unless 23141486Smckusick * EXCL is set in which case we will return the 23241486Smckusick * proper error). 23341486Smckusick */ 23441486Smckusick if ((mode & HPUXFEXCL) || ((mode-FOPEN) & FWRITE)) 23541486Smckusick uap->mode |= FCREAT; 23641486Smckusick } 23741486Smckusick if (mode & HPUXFTRUNC) 23841486Smckusick uap->mode |= FTRUNC; 23941486Smckusick if (mode & HPUXFEXCL) 24041486Smckusick uap->mode |= FEXCL; 24144421Skarels return (open(p, uap, retval)); 24241486Smckusick } 24341486Smckusick 24443452Shibler hpuxfcntl(p, uap, retval) 24543452Shibler struct proc *p; 24643452Shibler register struct args { 24741486Smckusick int fdes; 24841486Smckusick int cmd; 24941486Smckusick int arg; 25043452Shibler } *uap; 25143452Shibler int *retval; 25243452Shibler { 25343452Shibler int mode, error; 25441486Smckusick 25541486Smckusick switch (uap->cmd) { 25641486Smckusick case F_SETFL: 25741486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 25841486Smckusick break; 25941486Smckusick case F_GETFL: 26041486Smckusick case F_DUPFD: 26141486Smckusick case F_GETFD: 26241486Smckusick case F_SETFD: 26341486Smckusick break; 26441486Smckusick default: 26544421Skarels return (EINVAL); 26641486Smckusick } 26743452Shibler error = fcntl(p, uap, retval); 26843452Shibler if (error == 0 && uap->arg == F_GETFL) { 26943452Shibler mode = *retval; 27043452Shibler *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 27141486Smckusick if (mode & FCREAT) 27243452Shibler *retval |= HPUXFCREAT; 27341486Smckusick if (mode & FTRUNC) 27443452Shibler *retval |= HPUXFTRUNC; 27541486Smckusick if (mode & FEXCL) 27643452Shibler *retval |= HPUXFEXCL; 27741486Smckusick } 27844421Skarels return (error); 27941486Smckusick } 28041486Smckusick 28141486Smckusick /* 28241486Smckusick * Read and write should return a 0 count when an operation 28341486Smckusick * on a VNODE would block, not an error. Sockets appear to 28441486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 28541486Smckusick * not entirely correct, since the behavior is only defined 28641486Smckusick * for pipes and tty type devices. 28741486Smckusick */ 28843452Shibler hpuxread(p, uap, retval) 28943452Shibler struct proc *p; 29043452Shibler struct args { 29143452Shibler int fd; 29243452Shibler } *uap; 29343452Shibler int *retval; 29441486Smckusick { 29543452Shibler int error; 29641486Smckusick 29743452Shibler error = read(p, uap, retval); 29843452Shibler if (error == EWOULDBLOCK && 299*45923Smckusick (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) { 30043452Shibler error = 0; 30143452Shibler *retval = 0; 30241486Smckusick } 30344421Skarels return (error); 30441486Smckusick } 30541486Smckusick 30643452Shibler hpuxwrite(p, uap, retval) 30743452Shibler struct proc *p; 30843452Shibler struct args { 30943452Shibler int fd; 31043452Shibler } *uap; 31143452Shibler int *retval; 31241486Smckusick { 31343452Shibler int error; 31441486Smckusick 31543452Shibler error = write(p, uap, retval); 31643452Shibler if (error == EWOULDBLOCK && 317*45923Smckusick (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) { 31843452Shibler error = 0; 31943452Shibler *retval = 0; 32041486Smckusick } 32144421Skarels return (error); 32241486Smckusick } 32341486Smckusick 32443452Shibler hpuxreadv(p, uap, retval) 32543452Shibler struct proc *p; 32643452Shibler struct args { 32743452Shibler int fd; 32843452Shibler } *uap; 32943452Shibler int *retval; 33041486Smckusick { 33143452Shibler int error; 33241486Smckusick 33343452Shibler error = readv(p, uap, retval); 33443452Shibler if (error == EWOULDBLOCK && 335*45923Smckusick (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) { 33643452Shibler error = 0; 33743452Shibler *retval = 0; 33841486Smckusick } 33944421Skarels return (error); 34041486Smckusick } 34141486Smckusick 34243452Shibler hpuxwritev(p, uap, retval) 34343452Shibler struct proc *p; 34443452Shibler struct args { 34543452Shibler int fd; 34643452Shibler } *uap; 34743452Shibler int *retval; 34841486Smckusick { 34943452Shibler int error; 35041486Smckusick 35143452Shibler error = writev(p, uap, retval); 35243452Shibler if (error == EWOULDBLOCK && 353*45923Smckusick (OFILE(p->p_fd, uap->fd))->f_type == DTYPE_VNODE) { 35443452Shibler error = 0; 35543452Shibler *retval = 0; 35641486Smckusick } 35744421Skarels return (error); 35841486Smckusick } 35941486Smckusick 36041486Smckusick /* 36141486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 36241486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 36341486Smckusick */ 36443452Shibler hpuxdup(p, uap, retval) 36543452Shibler struct proc *p; 36643452Shibler register struct args { 36743452Shibler int i; 36843452Shibler } *uap; 36943452Shibler int *retval; 37041486Smckusick { 371*45923Smckusick register struct filedesc *fdp = p->p_fd; 37241486Smckusick struct file *fp; 37343452Shibler int fd, error; 37441486Smckusick 375*45923Smckusick if (((unsigned)uap->i) >= fdp->fd_maxfiles || 376*45923Smckusick (fp = OFILE(fdp, uap->i)) == NULL) 37744421Skarels return (EBADF); 378*45923Smckusick if (error = ufalloc(fdp, 0, &fd)) 37944421Skarels return (error); 380*45923Smckusick OFILE(fdp, fd) = fp; 381*45923Smckusick OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE; 382*45923Smckusick fp->f_count++; 383*45923Smckusick if (fd > fdp->fd_lastfile) 384*45923Smckusick fdp->fd_lastfile = fd; 38543452Shibler *retval = fd; 38644421Skarels return (0); 38741486Smckusick } 38841486Smckusick 38945753Smckusick hpuxutssys(p, uap, retval) 39043452Shibler struct proc *p; 39143452Shibler register struct args { 39241486Smckusick struct hpuxutsname *uts; 39341486Smckusick int dev; 39441486Smckusick int request; 39543452Shibler } *uap; 39643452Shibler int *retval; 39743452Shibler { 39841486Smckusick register int i; 39943452Shibler int error; 40041486Smckusick 40141486Smckusick switch (uap->request) { 40241486Smckusick /* uname */ 40341486Smckusick case 0: 40441486Smckusick /* fill in machine type */ 40541486Smckusick switch (machineid) { 40641486Smckusick case HP_320: 40741486Smckusick protoutsname.machine[6] = '2'; 40841486Smckusick break; 40941486Smckusick /* includes 318 and 319 */ 41041486Smckusick case HP_330: 41141486Smckusick protoutsname.machine[6] = '3'; 41241486Smckusick break; 41341486Smckusick case HP_340: 41441486Smckusick protoutsname.machine[6] = '4'; 41541486Smckusick break; 41641486Smckusick case HP_350: 41741486Smckusick protoutsname.machine[6] = '5'; 41841486Smckusick break; 41941486Smckusick case HP_360: 42041486Smckusick protoutsname.machine[6] = '6'; 42141486Smckusick break; 42241486Smckusick case HP_370: 42341486Smckusick protoutsname.machine[6] = '7'; 42441486Smckusick break; 42543452Shibler /* includes 345 */ 42643452Shibler case HP_375: 42743452Shibler protoutsname.machine[6] = '7'; 42843452Shibler protoutsname.machine[7] = '5'; 42943452Shibler break; 43041486Smckusick } 43141486Smckusick /* copy hostname (sans domain) to nodename */ 43241486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 43341486Smckusick protoutsname.nodename[i] = hostname[i]; 43443452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 43543452Shibler sizeof(struct hpuxutsname)); 43641486Smckusick break; 43745753Smckusick 43845753Smckusick /* gethostname */ 43945753Smckusick case 5: 44045753Smckusick /* uap->dev is length */ 44145753Smckusick if (uap->dev > hostnamelen + 1) 44245753Smckusick uap->dev = hostnamelen + 1; 44345753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 44445753Smckusick uap->dev); 44545753Smckusick break; 44645753Smckusick 44745753Smckusick case 1: /* ?? */ 44845753Smckusick case 2: /* ustat */ 44945753Smckusick case 3: /* ?? */ 45045753Smckusick case 4: /* sethostname */ 45141486Smckusick default: 45243452Shibler error = EINVAL; 45341486Smckusick break; 45441486Smckusick } 45544421Skarels return (error); 45641486Smckusick } 45741486Smckusick 45843452Shibler hpuxstat(p, uap, retval) 45943452Shibler struct proc *p; 46043452Shibler struct args { 46141486Smckusick char *fname; 46241486Smckusick struct hpuxstat *hsb; 46343452Shibler } *uap; 46443452Shibler int *retval; 46543452Shibler { 46644421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 46741486Smckusick } 46841486Smckusick 46943452Shibler hpuxlstat(p, uap, retval) 47043452Shibler struct proc *p; 47143452Shibler struct args { 47243452Shibler char *fname; 47343452Shibler struct hpuxstat *hsb; 47443452Shibler } *uap; 47543452Shibler int *retval; 47641486Smckusick { 47744421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 47841486Smckusick } 47941486Smckusick 48043452Shibler hpuxfstat(p, uap, retval) 48143452Shibler struct proc *p; 48243452Shibler register struct args { 48343452Shibler int fdes; 48443452Shibler struct hpuxstat *hsb; 48543452Shibler } *uap; 48643452Shibler int *retval; 48741486Smckusick { 488*45923Smckusick register struct filedesc *fdp = p->p_fd; 48941486Smckusick register struct file *fp; 49041486Smckusick struct stat sb; 49143452Shibler int error; 49241486Smckusick 493*45923Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 494*45923Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 49544421Skarels return (EBADF); 49643452Shibler 49741486Smckusick switch (fp->f_type) { 49841486Smckusick 49941486Smckusick case DTYPE_VNODE: 50043452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 50141486Smckusick break; 50241486Smckusick 50341486Smckusick case DTYPE_SOCKET: 50443452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 50541486Smckusick break; 50641486Smckusick 50741486Smckusick default: 50841486Smckusick panic("fstat"); 50941486Smckusick /*NOTREACHED*/ 51041486Smckusick } 51141486Smckusick /* is this right for sockets?? */ 51243452Shibler if (error == 0) 51343452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 51444421Skarels return (error); 51541486Smckusick } 51641486Smckusick 51743452Shibler hpuxulimit(p, uap, retval) 51843452Shibler struct proc *p; 51943452Shibler register struct args { 52041486Smckusick int cmd; 52141486Smckusick long newlimit; 52243452Shibler } *uap; 52343713Smckusick off_t *retval; 52443452Shibler { 52541486Smckusick struct rlimit *limp; 52643452Shibler int error = 0; 52741486Smckusick 52841486Smckusick limp = &u.u_rlimit[RLIMIT_FSIZE]; 52941486Smckusick switch (uap->cmd) { 53041486Smckusick case 2: 53141486Smckusick uap->newlimit *= 512; 53241486Smckusick if (uap->newlimit > limp->rlim_max && 53343452Shibler (error = suser(u.u_cred, &u.u_acflag))) 53441486Smckusick break; 53541486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 53641486Smckusick /* else fall into... */ 53741486Smckusick 53841486Smckusick case 1: 53945753Smckusick *retval = limp->rlim_max / 512; 54041486Smckusick break; 54141486Smckusick 54241486Smckusick case 3: 54341486Smckusick limp = &u.u_rlimit[RLIMIT_DATA]; 54445753Smckusick *retval = ctob(u.u_tsize) + limp->rlim_max; 54541486Smckusick break; 54641486Smckusick 54741486Smckusick default: 54843452Shibler error = EINVAL; 54941486Smckusick break; 55041486Smckusick } 55144421Skarels return (error); 55241486Smckusick } 55341486Smckusick 55441486Smckusick /* 55541486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 55641486Smckusick * values -16 (high) thru -1 (low). 55741486Smckusick */ 55843452Shibler hpuxrtprio(cp, uap, retval) 55943452Shibler struct proc *cp; 56043452Shibler register struct args { 56141486Smckusick int pid; 56241486Smckusick int prio; 56343452Shibler } *uap; 56443452Shibler int *retval; 56543452Shibler { 56641486Smckusick struct proc *p; 56743452Shibler int nice, error; 56841486Smckusick 56941486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 57043452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 57144421Skarels return (EINVAL); 57241486Smckusick if (uap->pid == 0) 57343452Shibler p = cp; 57443452Shibler else if ((p = pfind(uap->pid)) == 0) 57544421Skarels return (ESRCH); 57641486Smckusick nice = p->p_nice; 57741486Smckusick if (nice < NZERO) 57843452Shibler *retval = (nice + 16) << 3; 57941486Smckusick else 58043452Shibler *retval = RTPRIO_RTOFF; 58141486Smckusick switch (uap->prio) { 58241486Smckusick 58341486Smckusick case RTPRIO_NOCHG: 58444421Skarels return (0); 58541486Smckusick 58641486Smckusick case RTPRIO_RTOFF: 58741486Smckusick if (nice >= NZERO) 58844421Skarels return (0); 58941486Smckusick nice = NZERO; 59041486Smckusick break; 59141486Smckusick 59241486Smckusick default: 59341486Smckusick nice = (uap->prio >> 3) - 16; 59441486Smckusick break; 59541486Smckusick } 59643452Shibler error = donice(cp, p, nice); 59743452Shibler if (error == EACCES) 59843452Shibler error = EPERM; 59944421Skarels return (error); 60041486Smckusick } 60141486Smckusick 60243452Shibler hpuxadvise(p, uap, retval) 60343452Shibler struct proc *p; 60443452Shibler struct args { 60543452Shibler int arg; 60643452Shibler } *uap; 60743452Shibler int *retval; 60841486Smckusick { 60943452Shibler int error = 0; 61041486Smckusick 61141486Smckusick switch (uap->arg) { 61241486Smckusick case 0: 61341486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 61441486Smckusick break; 61541486Smckusick case 1: 61641486Smckusick ICIA(); 61741486Smckusick break; 61841486Smckusick case 2: 61941486Smckusick DCIA(); 62041486Smckusick break; 62141486Smckusick default: 62243452Shibler error = EINVAL; 62341486Smckusick break; 62441486Smckusick } 62544421Skarels return (error); 62641486Smckusick } 62741486Smckusick 62843452Shibler hpuxptrace(p, uap, retval) 62943452Shibler struct proc *p; 63043452Shibler struct args { 63141486Smckusick int req; 63241486Smckusick int pid; 63341486Smckusick int *addr; 63441486Smckusick int data; 63543452Shibler } *uap; 63643452Shibler int *retval; 63743452Shibler { 63843452Shibler int error; 63941486Smckusick 64041486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 64141486Smckusick if (uap->data) { 64241486Smckusick uap->data = hpuxtobsdsig(uap->data); 64341486Smckusick if (uap->data == 0) 64441486Smckusick uap->data = NSIG; 64541486Smckusick } 64641486Smckusick } 64743452Shibler error = ptrace(p, uap, retval); 64844421Skarels return (error); 64941486Smckusick } 65041486Smckusick 65143452Shibler hpuxgetdomainname(p, uap, retval) 65243452Shibler struct proc *p; 65343452Shibler register struct args { 65441486Smckusick char *domainname; 65541486Smckusick u_int len; 65643452Shibler } *uap; 65743452Shibler int *retval; 65843452Shibler { 65941486Smckusick if (uap->len > domainnamelen + 1) 66041486Smckusick uap->len = domainnamelen + 1; 66144421Skarels return (copyout(domainname, uap->domainname, uap->len)); 66241486Smckusick } 66341486Smckusick 66443452Shibler hpuxsetdomainname(p, uap, retval) 66543452Shibler struct proc *p; 66643452Shibler register struct args { 66741486Smckusick char *domainname; 66841486Smckusick u_int len; 66943452Shibler } *uap; 67043452Shibler int *retval; 67143452Shibler { 67243452Shibler int error; 67341486Smckusick 67443452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 67544421Skarels return (error); 67643452Shibler if (uap->len > sizeof (domainname) - 1) 67744421Skarels return (EINVAL); 67841486Smckusick domainnamelen = uap->len; 67943452Shibler error = copyin(uap->domainname, domainname, uap->len); 68041486Smckusick domainname[domainnamelen] = 0; 68144421Skarels return (error); 68241486Smckusick } 68341486Smckusick 68441486Smckusick #ifdef SYSVSHM 68543452Shibler hpuxshmat(p, uap, retval) 68643452Shibler struct proc *p; 68743452Shibler int *uap, *retval; 68841486Smckusick { 68944421Skarels return (shmat(p, uap, retval)); 69041486Smckusick } 69141486Smckusick 69243452Shibler hpuxshmctl(p, uap, retval) 69343452Shibler struct proc *p; 69443452Shibler int *uap, *retval; 69541486Smckusick { 69644421Skarels return (shmctl(p, uap, retval)); 69741486Smckusick } 69841486Smckusick 69943452Shibler hpuxshmdt(p, uap, retval) 70043452Shibler struct proc *p; 70143452Shibler int *uap, *retval; 70241486Smckusick { 70344421Skarels return (shmdt(p, uap, retval)); 70441486Smckusick } 70541486Smckusick 70643452Shibler hpuxshmget(p, uap, retval) 70743452Shibler struct proc *p; 70843452Shibler int *uap, *retval; 70941486Smckusick { 71044421Skarels return (shmget(p, uap, retval)); 71141486Smckusick } 71241486Smckusick #endif 71341486Smckusick 71441486Smckusick /* 71541486Smckusick * Fake semaphore routines, just don't return an error. 71641486Smckusick * Should be adequate for starbase to run. 71741486Smckusick */ 71843452Shibler hpuxsemctl(p, uap, retval) 71943452Shibler struct proc *p; 72043452Shibler struct args { 72141486Smckusick int semid; 72241486Smckusick u_int semnum; 72341486Smckusick int cmd; 72441486Smckusick int arg; 72543452Shibler } *uap; 72643452Shibler int *retval; 72743452Shibler { 72841486Smckusick /* XXX: should do something here */ 72944421Skarels return (0); 73041486Smckusick } 73141486Smckusick 73243452Shibler hpuxsemget(p, uap, retval) 73343452Shibler struct proc *p; 73443452Shibler struct args { 73541486Smckusick key_t key; 73641486Smckusick int nsems; 73741486Smckusick int semflg; 73843452Shibler } *uap; 73943452Shibler int *retval; 74043452Shibler { 74141486Smckusick /* XXX: should do something here */ 74244421Skarels return (0); 74341486Smckusick } 74441486Smckusick 74543452Shibler hpuxsemop(p, uap, retval) 74643452Shibler struct proc *p; 74743452Shibler struct args { 74841486Smckusick int semid; 74941486Smckusick struct sembuf *sops; 75041486Smckusick u_int nsops; 75143452Shibler } *uap; 75243452Shibler int *retval; 75343452Shibler { 75441486Smckusick /* XXX: should do something here */ 75544421Skarels return (0); 75641486Smckusick } 75741486Smckusick 75841486Smckusick /* convert from BSD to HPUX errno */ 75941486Smckusick bsdtohpuxerrno(err) 76041486Smckusick int err; 76141486Smckusick { 76241486Smckusick if (err < 0 || err >= NERR) 76341486Smckusick return(BERR); 76441486Smckusick return((int)bsdtohpuxerrnomap[err]); 76541486Smckusick } 76641486Smckusick 76741486Smckusick hpuxstat1(fname, hsb, follow) 76841486Smckusick char *fname; 76941486Smckusick struct hpuxstat *hsb; 77041486Smckusick int follow; 77141486Smckusick { 77241486Smckusick register struct nameidata *ndp = &u.u_nd; 77341486Smckusick struct stat sb; 77441486Smckusick int error; 77541486Smckusick 77641486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 77741486Smckusick ndp->ni_segflg = UIO_USERSPACE; 77841486Smckusick ndp->ni_dirp = fname; 77941486Smckusick if (error = namei(ndp)) 78041486Smckusick return (error); 78141486Smckusick error = vn_stat(ndp->ni_vp, &sb); 78241486Smckusick vput(ndp->ni_vp); 78341486Smckusick if (error == 0) 78441486Smckusick error = bsdtohpuxstat(&sb, hsb); 78541486Smckusick return (error); 78641486Smckusick } 78741486Smckusick 78841486Smckusick #include "grf.h" 78941486Smckusick 79041486Smckusick bsdtohpuxstat(sb, hsb) 79141486Smckusick struct stat *sb; 79241486Smckusick struct hpuxstat *hsb; 79341486Smckusick { 79441486Smckusick struct hpuxstat ds; 79541486Smckusick 79641486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 79741486Smckusick ds.hst_dev = sb->st_dev; 79841486Smckusick ds.hst_ino = (u_long)sb->st_ino; 79941486Smckusick ds.hst_mode = sb->st_mode; 80041486Smckusick ds.hst_nlink = sb->st_nlink; 80141486Smckusick ds.hst_uid = (u_short)sb->st_uid; 80241486Smckusick ds.hst_gid = (u_short)sb->st_gid; 80341486Smckusick #if NGRF > 0 80441486Smckusick /* XXX: I don't want to talk about it... */ 80541486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 80641486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 80741486Smckusick else 80841486Smckusick #endif 80941486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 81041486Smckusick ds.hst_size = sb->st_size; 81141486Smckusick ds.hst_atime = sb->st_atime; 81241486Smckusick ds.hst_mtime = sb->st_mtime; 81341486Smckusick ds.hst_ctime = sb->st_ctime; 81441486Smckusick ds.hst_blksize = sb->st_blksize; 81541486Smckusick ds.hst_blocks = sb->st_blocks; 81641486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 81741486Smckusick } 81841486Smckusick 81941486Smckusick hpuxtobsdioctl(com) 82041486Smckusick int com; 82141486Smckusick { 82241486Smckusick switch (com) { 82341486Smckusick case HPUXTIOCSLTC: 82441486Smckusick com = TIOCSLTC; break; 82541486Smckusick case HPUXTIOCGLTC: 82641486Smckusick com = TIOCGLTC; break; 82741486Smckusick case HPUXTIOCSPGRP: 82841486Smckusick com = TIOCSPGRP; break; 82941486Smckusick case HPUXTIOCGPGRP: 83041486Smckusick com = TIOCGPGRP; break; 83141486Smckusick case HPUXTIOCLBIS: 83241486Smckusick com = TIOCLBIS; break; 83341486Smckusick case HPUXTIOCLBIC: 83441486Smckusick com = TIOCLBIC; break; 83541486Smckusick case HPUXTIOCLSET: 83641486Smckusick com = TIOCLSET; break; 83741486Smckusick case HPUXTIOCLGET: 83841486Smckusick com = TIOCLGET; break; 83941486Smckusick } 84041486Smckusick return(com); 84141486Smckusick } 84241486Smckusick 84341486Smckusick /* 84441486Smckusick * HPUX ioctl system call. The differences here are: 84541486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 84641486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 84741486Smckusick * the sgttyb struct is 2 bytes longer 84841486Smckusick */ 84943452Shibler hpuxioctl(p, uap, retval) 85043452Shibler struct proc *p; 85143452Shibler register struct args { 85241486Smckusick int fdes; 85341486Smckusick int cmd; 85441486Smckusick caddr_t cmarg; 85543452Shibler } *uap; 85643452Shibler int *retval; 85743452Shibler { 858*45923Smckusick register struct filedesc *fdp = p->p_fd; 85943452Shibler register struct file *fp; 86043452Shibler register int com, error; 86141486Smckusick register u_int size; 86241486Smckusick caddr_t memp = 0; 86341486Smckusick #define STK_PARAMS 128 86441486Smckusick char stkbuf[STK_PARAMS]; 86541486Smckusick caddr_t data = stkbuf; 86641486Smckusick 86741486Smckusick com = uap->cmd; 86841486Smckusick 86941486Smckusick /* XXX */ 87043452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 871*45923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 87241486Smckusick 873*45923Smckusick if (((unsigned)uap->fdes) >= fdp->fd_maxfiles || 874*45923Smckusick (fp = OFILE(fdp, uap->fdes)) == NULL) 87544421Skarels return (EBADF); 87643452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 87744421Skarels return (EBADF); 87841486Smckusick 87941486Smckusick /* 88041486Smckusick * Interpret high order word to find 88141486Smckusick * amount of data to be copied to/from the 88241486Smckusick * user's address space. 88341486Smckusick */ 88441486Smckusick size = IOCPARM_LEN(com); 88543452Shibler if (size > IOCPARM_MAX) 88644421Skarels return (ENOTTY); 88741486Smckusick if (size > sizeof (stkbuf)) { 88843452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 88941486Smckusick data = memp; 89041486Smckusick } 89141486Smckusick if (com&IOC_IN) { 89241486Smckusick if (size) { 89343452Shibler error = copyin(uap->cmarg, data, (u_int)size); 89443452Shibler if (error) { 89541486Smckusick if (memp) 89641486Smckusick free(memp, M_IOCTLOPS); 89744421Skarels return (error); 89841486Smckusick } 89941486Smckusick } else 90041486Smckusick *(caddr_t *)data = uap->cmarg; 90141486Smckusick } else if ((com&IOC_OUT) && size) 90241486Smckusick /* 90343452Shibler * Zero the buffer so the user always 90443452Shibler * gets back something deterministic. 90541486Smckusick */ 90641486Smckusick bzero(data, size); 90741486Smckusick else if (com&IOC_VOID) 90841486Smckusick *(caddr_t *)data = uap->cmarg; 90941486Smckusick 91041486Smckusick switch (com) { 91141486Smckusick 91241486Smckusick case HPUXTIOCCONS: 91341486Smckusick *(int *)data = 1; 91443452Shibler error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data); 91541486Smckusick break; 91641486Smckusick 91741486Smckusick /* BSD-style job control ioctls */ 91841486Smckusick case HPUXTIOCLBIS: 91941486Smckusick case HPUXTIOCLBIC: 92041486Smckusick case HPUXTIOCLSET: 92141486Smckusick *(int *)data &= HPUXLTOSTOP; 92241486Smckusick if (*(int *)data & HPUXLTOSTOP) 92341486Smckusick *(int *)data = LTOSTOP; 92441486Smckusick /* fall into */ 92541486Smckusick case HPUXTIOCLGET: 92641486Smckusick case HPUXTIOCSLTC: 92741486Smckusick case HPUXTIOCGLTC: 92841486Smckusick case HPUXTIOCSPGRP: 92941486Smckusick case HPUXTIOCGPGRP: 93043452Shibler error = (*fp->f_ops->fo_ioctl)(fp, hpuxtobsdioctl(com), data); 93143452Shibler if (error == 0 && com == HPUXTIOCLGET) { 93241486Smckusick *(int *)data &= LTOSTOP; 93341486Smckusick if (*(int *)data & LTOSTOP) 93441486Smckusick *(int *)data = HPUXLTOSTOP; 93541486Smckusick } 93641486Smckusick break; 93741486Smckusick 93841486Smckusick /* SYS 5 termio */ 93941486Smckusick case HPUXTCGETA: 94041486Smckusick case HPUXTCSETA: 94141486Smckusick case HPUXTCSETAW: 94241486Smckusick case HPUXTCSETAF: 94343452Shibler error = hpuxtermio(fp, com, data); 94441486Smckusick break; 94541486Smckusick 94641486Smckusick default: 94743452Shibler error = (*fp->f_ops->fo_ioctl)(fp, com, data); 94841486Smckusick break; 94941486Smckusick } 95041486Smckusick /* 95141486Smckusick * Copy any data to user, size was 95241486Smckusick * already set and checked above. 95341486Smckusick */ 95443452Shibler if (error == 0 && (com&IOC_OUT) && size) 95543452Shibler error = copyout(data, uap->cmarg, (u_int)size); 95641486Smckusick if (memp) 95741486Smckusick free(memp, M_IOCTLOPS); 95844421Skarels return (error); 95941486Smckusick } 96041486Smckusick 96141486Smckusick /* 96241486Smckusick * Man page lies, behaviour here is based on observed behaviour. 96341486Smckusick */ 96443452Shibler hpuxgetcontext(p, uap, retval) 96543452Shibler struct proc *p; 96643452Shibler struct args { 96741486Smckusick char *buf; 96841486Smckusick int len; 96943452Shibler } *uap; 97043452Shibler int *retval; 97143452Shibler { 97241486Smckusick int error = 0; 97341486Smckusick register int len; 97441486Smckusick 97541486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 97641486Smckusick if (len) 97741486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 97843452Shibler if (error == 0) 97943452Shibler *retval = sizeof(hpuxcontext); 98044421Skarels return (error); 98141486Smckusick } 98241486Smckusick 98341486Smckusick /* 98441486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 98541486Smckusick * Note we do not check the real uid or "saved" uid. 98641486Smckusick */ 98743452Shibler hpuxgetpgrp2(cp, uap, retval) 98843452Shibler struct proc *cp; 98943452Shibler register struct args { 99043452Shibler int pid; 99143452Shibler } *uap; 99243452Shibler int *retval; 99341486Smckusick { 99441486Smckusick register struct proc *p; 99541486Smckusick 99641486Smckusick if (uap->pid == 0) 99743452Shibler uap->pid = cp->p_pid; 99841486Smckusick p = pfind(uap->pid); 99943452Shibler if (p == 0) 100044421Skarels return (ESRCH); 100143452Shibler if (u.u_uid && p->p_uid != u.u_uid && !inferior(p)) 100244421Skarels return (EPERM); 100343452Shibler *retval = p->p_pgid; 100444421Skarels return (0); 100541486Smckusick } 100641486Smckusick 100741486Smckusick /* 100841486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 100941486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 101041486Smckusick */ 101143452Shibler hpuxsetpgrp2(p, uap, retval) 101243452Shibler struct proc *p; 101343452Shibler struct args { 101441486Smckusick int pid; 101541486Smckusick int pgrp; 101643452Shibler } *uap; 101743452Shibler int *retval; 101843452Shibler { 101941486Smckusick /* empirically determined */ 102043452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 102144421Skarels return (EINVAL); 102244421Skarels return (setpgrp(p, uap, retval)); 102341486Smckusick } 102441486Smckusick 102541486Smckusick /* 102645753Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 102745753Smckusick */ 102845753Smckusick hpuxsetresuid(p, uap, retval) 102945753Smckusick struct proc *p; 103045753Smckusick struct args { 103145753Smckusick int ruid; 103245753Smckusick int euid; 103345753Smckusick int suid; 103445753Smckusick } *uap; 103545753Smckusick int *retval; 103645753Smckusick { 103745753Smckusick return (osetreuid(p, uap, retval)); 103845753Smckusick } 103945753Smckusick 104045753Smckusick hpuxsetresgid(p, uap, retval) 104145753Smckusick struct proc *p; 104245753Smckusick struct args { 104345753Smckusick int rgid; 104445753Smckusick int egid; 104545753Smckusick int sgid; 104645753Smckusick } *uap; 104745753Smckusick int *retval; 104845753Smckusick { 104945753Smckusick return (osetregid(p, uap, retval)); 105045753Smckusick } 105145753Smckusick 105245753Smckusick /* 105345753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 105445753Smckusick */ 105545753Smckusick hpuxlockf(p, uap, retval) 105645753Smckusick struct proc *p; 105745753Smckusick struct args { 105845753Smckusick int fd; 105945753Smckusick int func; 106045753Smckusick long size; 106145753Smckusick } *uap; 106245753Smckusick int *retval; 106345753Smckusick { 106445753Smckusick #ifdef DEBUG 106545753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 106645753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 106745753Smckusick #endif 106845753Smckusick return (0); 106945753Smckusick } 107045753Smckusick 107145753Smckusick hpuxgetaccess(p, uap, retval) 107245753Smckusick register struct proc *p; 107345753Smckusick register struct args { 107445753Smckusick char *path; 107545753Smckusick int uid; 107645753Smckusick int ngroups; 107745753Smckusick int *gidset; 107845753Smckusick void *label; 107945753Smckusick void *privs; 108045753Smckusick } *uap; 108145753Smckusick int *retval; 108245753Smckusick { 108345753Smckusick struct nameidata *ndp = &u.u_nd; 108445753Smckusick int lgroups[NGROUPS]; 108545753Smckusick int error = 0; 108645753Smckusick register struct ucred *cred; 108745753Smckusick register struct vnode *vp; 108845753Smckusick 108945753Smckusick /* 109045753Smckusick * Build an appropriate credential structure 109145753Smckusick */ 109245753Smckusick cred = crdup(ndp->ni_cred); 109345753Smckusick switch (uap->uid) { 109445753Smckusick case 65502: /* UID_EUID */ 109545753Smckusick break; 109645753Smckusick case 65503: /* UID_RUID */ 109745753Smckusick cred->cr_uid = p->p_ruid; 109845753Smckusick break; 109945753Smckusick case 65504: /* UID_SUID */ 110045753Smckusick error = EINVAL; 110145753Smckusick break; 110245753Smckusick default: 110345753Smckusick if (uap->uid > 65504) 110445753Smckusick error = EINVAL; 110545753Smckusick cred->cr_uid = uap->uid; 110645753Smckusick break; 110745753Smckusick } 110845753Smckusick switch (uap->ngroups) { 110945753Smckusick case -1: /* NGROUPS_EGID */ 111045753Smckusick cred->cr_ngroups = 1; 111145753Smckusick break; 111245753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 111345753Smckusick break; 111445753Smckusick case -2: /* NGROUPS_RGID */ 111545753Smckusick cred->cr_ngroups = 1; 111645753Smckusick cred->cr_gid = p->p_rgid; 111745753Smckusick break; 111845753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 111945753Smckusick cred->cr_gid = p->p_rgid; 112045753Smckusick break; 112145753Smckusick case -3: /* NGROUPS_SGID */ 112245753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 112345753Smckusick error = EINVAL; 112445753Smckusick break; 112545753Smckusick case -4: /* NGROUPS_SUPP */ 112645753Smckusick if (cred->cr_ngroups > 1) 112745753Smckusick cred->cr_gid = cred->cr_groups[1]; 112845753Smckusick else 112945753Smckusick error = EINVAL; 113045753Smckusick break; 113145753Smckusick default: 113245753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 113345753Smckusick error = copyin((caddr_t)uap->gidset, 113445753Smckusick (caddr_t)&lgroups[0], 113545753Smckusick uap->ngroups * sizeof(lgroups[0])); 113645753Smckusick else 113745753Smckusick error = EINVAL; 113845753Smckusick if (error == 0) { 113945753Smckusick int gid; 114045753Smckusick 114145753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 114245753Smckusick cred->cr_groups[gid] = lgroups[gid]; 114345753Smckusick cred->cr_ngroups = uap->ngroups; 114445753Smckusick } 114545753Smckusick break; 114645753Smckusick } 114745753Smckusick /* 114845753Smckusick * Lookup file using caller's effective IDs. 114945753Smckusick */ 115045753Smckusick if (error == 0) { 115145753Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 115245753Smckusick ndp->ni_segflg = UIO_USERSPACE; 115345753Smckusick ndp->ni_dirp = uap->path; 115445753Smckusick error = namei(ndp); 115545753Smckusick } 115645753Smckusick if (error) { 115745753Smckusick crfree(cred); 115845753Smckusick return (error); 115945753Smckusick } 116045753Smckusick /* 116145753Smckusick * Use the constructed credentials for access checks. 116245753Smckusick */ 116345753Smckusick vp = ndp->ni_vp; 116445753Smckusick *retval = 0; 116545753Smckusick if (VOP_ACCESS(vp, VREAD, cred) == 0) 116645753Smckusick *retval |= R_OK; 116745753Smckusick if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred) == 0) 116845753Smckusick *retval |= W_OK; 116945753Smckusick /* XXX we return X_OK for root on VREG even if not */ 117045753Smckusick if (VOP_ACCESS(vp, VEXEC, cred) == 0) 117145753Smckusick *retval |= X_OK; 117245753Smckusick vput(vp); 117345753Smckusick crfree(cred); 117445753Smckusick return (error); 117545753Smckusick } 117645753Smckusick 117745753Smckusick /* 117841486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 117941486Smckusick * No apologies offered, if you don't like it, rewrite it! 118041486Smckusick */ 118141486Smckusick 118241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 118341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 118441486Smckusick 118541486Smckusick /* simplified FP structure */ 118641486Smckusick struct bsdfp { 118741486Smckusick int save[54]; 118841486Smckusick int reg[24]; 118941486Smckusick int ctrl[3]; 119041486Smckusick }; 119141486Smckusick 119241486Smckusick hpuxtobsduoff(off) 119341486Smckusick int *off; 119441486Smckusick { 119541486Smckusick struct hpuxfp *hp; 119641486Smckusick struct bsdfp *bp; 119741486Smckusick register u_int raddr; 119841486Smckusick 119941486Smckusick /* u_ar0 field */ 120041486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 120141486Smckusick return(UOFF(u_ar0)); 120241486Smckusick 120341486Smckusick #ifdef FPCOPROC 120441486Smckusick /* 68881 registers from PCB */ 120541486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 120641486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 120741486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 120841486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 120941486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 121041486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 121141486Smckusick #endif 121241486Smckusick 121341486Smckusick /* 121441486Smckusick * Everything else we recognize comes from the kernel stack, 121541486Smckusick * so we convert off to an absolute address (if not already) 121641486Smckusick * for simplicity. 121741486Smckusick */ 121841486Smckusick if (off < (int *)ctob(UPAGES)) 121941486Smckusick off = (int *)((u_int)off + (u_int)&u); 122041486Smckusick 122141486Smckusick /* 122241486Smckusick * 68020 registers. 122341486Smckusick * We know that the HPUX registers are in the same order as ours. 122441486Smckusick * The only difference is that their PS is 2 bytes instead of a 122541486Smckusick * padded 4 like ours throwing the alignment off. 122641486Smckusick */ 122741486Smckusick if (off >= u.u_ar0 && off < &u.u_ar0[18]) { 122841486Smckusick /* 122941486Smckusick * PS: return low word and high word of PC as HP-UX would 123041486Smckusick * (e.g. &u.u_ar0[16.5]). 123141486Smckusick */ 123241486Smckusick if (off == &u.u_ar0[PS]) 123341486Smckusick raddr = (u_int) &((short *)u.u_ar0)[PS*2+1]; 123441486Smckusick /* 123541486Smckusick * PC: off will be &u.u_ar0[16.5] 123641486Smckusick */ 123741486Smckusick else if (off == (int *)&(((short *)u.u_ar0)[PS*2+1])) 123841486Smckusick raddr = (u_int) &u.u_ar0[PC]; 123941486Smckusick /* 124041486Smckusick * D0-D7, A0-A7: easy 124141486Smckusick */ 124241486Smckusick else 124341486Smckusick raddr = (u_int) &u.u_ar0[(int)(off - u.u_ar0)]; 124441486Smckusick return((int)(raddr - (u_int)&u)); 124541486Smckusick } 124641486Smckusick 124741486Smckusick /* everything else */ 124841486Smckusick return(-1); 124941486Smckusick } 125041486Smckusick 125141486Smckusick /* 125241486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 125341486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 125441486Smckusick * convert the entire user struct. 125541486Smckusick */ 125641486Smckusick hpuxdumpu(vp, cred) 125741486Smckusick struct vnode *vp; 125841486Smckusick struct ucred *cred; 125941486Smckusick { 126041486Smckusick int error; 126141486Smckusick struct hpuxuser *faku; 126241486Smckusick struct bsdfp *bp; 126341486Smckusick short *foop; 126441486Smckusick 126541486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 126641486Smckusick /* 126741486Smckusick * Make sure there is no mistake about this 126841486Smckusick * being a real user structure. 126941486Smckusick */ 127041486Smckusick bzero((caddr_t)faku, ctob(1)); 127141486Smckusick /* 127241486Smckusick * Fill in the process sizes. 127341486Smckusick */ 127441486Smckusick faku->hpuxu_tsize = u.u_tsize; 127541486Smckusick faku->hpuxu_dsize = u.u_dsize; 127641486Smckusick faku->hpuxu_ssize = u.u_ssize; 127741486Smckusick /* 127841486Smckusick * Fill in the exec header for CDB. 127941486Smckusick * This was saved back in exec(). As far as I can tell CDB 128041486Smckusick * only uses this information to verify that a particular 128141486Smckusick * core file goes with a particular binary. 128241486Smckusick */ 128341486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 128441486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 128541486Smckusick /* 128641486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 128741486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 128841486Smckusick * so we have to move it up. 128941486Smckusick */ 129041486Smckusick faku->hpuxu_ar0 = u.u_ar0; 129141486Smckusick foop = (short *) u.u_ar0; 129241486Smckusick foop[32] = foop[33]; 129341486Smckusick foop[33] = foop[34]; 129441486Smckusick foop[34] = foop[35]; 129541486Smckusick #ifdef FPCOPROC 129641486Smckusick /* 129741486Smckusick * Copy 68881 registers from our PCB format to HPUX format 129841486Smckusick */ 129941486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 130041486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 130141486Smckusick sizeof(bp->save)); 130241486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 130341486Smckusick sizeof(bp->ctrl)); 130441486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 130541486Smckusick sizeof(bp->reg)); 130641486Smckusick #endif 130741486Smckusick /* 130841486Smckusick * Slay the dragon 130941486Smckusick */ 131041486Smckusick faku->hpuxu_dragon = -1; 131141486Smckusick /* 131241486Smckusick * Dump this artfully constructed page in place of the 131341486Smckusick * user struct page. 131441486Smckusick */ 131541486Smckusick error = vn_rdwr(UIO_WRITE, vp, 131641486Smckusick (caddr_t)faku, ctob(1), (off_t)0, 131741486Smckusick UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)0); 131841486Smckusick /* 131941486Smckusick * Dump the remaining UPAGES-1 pages normally 132041486Smckusick */ 132141486Smckusick if (!error) 132241486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 132341486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 132441486Smckusick IO_NODELOCKED|IO_UNIT, cred, (int *)0); 132541486Smckusick free((caddr_t)faku, M_TEMP); 132641486Smckusick return(error); 132741486Smckusick } 132841486Smckusick 132941486Smckusick /* 133041486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 133141486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 133241486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 133341486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 133441486Smckusick */ 133541486Smckusick /* #ifdef COMPAT */ 133641486Smckusick 133745753Smckusick #define HPUX_HZ 50 133845753Smckusick 133945788Sbostic #include "sys/times.h" 134041486Smckusick 134141486Smckusick /* from old timeb.h */ 134241486Smckusick struct hpuxtimeb { 134341486Smckusick time_t time; 134441486Smckusick u_short millitm; 134541486Smckusick short timezone; 134641486Smckusick short dstflag; 134741486Smckusick }; 134841486Smckusick 134941486Smckusick /* ye ole stat structure */ 135041486Smckusick struct ohpuxstat { 135141486Smckusick dev_t ohst_dev; 135241486Smckusick u_short ohst_ino; 135341486Smckusick u_short ohst_mode; 135441486Smckusick short ohst_nlink; 135541486Smckusick short ohst_uid; 135641486Smckusick short ohst_gid; 135741486Smckusick dev_t ohst_rdev; 135841486Smckusick int ohst_size; 135941486Smckusick int ohst_atime; 136041486Smckusick int ohst_mtime; 136141486Smckusick int ohst_ctime; 136241486Smckusick }; 136341486Smckusick 136441486Smckusick /* 136541486Smckusick * SYS V style setpgrp() 136641486Smckusick */ 136743452Shibler ohpuxsetpgrp(p, uap, retval) 136843452Shibler register struct proc *p; 136943452Shibler int *uap, *retval; 137041486Smckusick { 137141486Smckusick if (p->p_pid != p->p_pgid) 137241486Smckusick pgmv(p, p->p_pid, 0); 137343452Shibler *retval = p->p_pgid; 137445753Smckusick return (0); 137541486Smckusick } 137641486Smckusick 137743452Shibler ohpuxtime(p, uap, retval) 137843452Shibler struct proc *p; 137943452Shibler register struct args { 138043452Shibler long *tp; 138143452Shibler } *uap; 138243713Smckusick time_t *retval; 138341486Smckusick { 138445753Smckusick int error = 0; 138541486Smckusick 138641486Smckusick if (uap->tp) 138743452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 138843452Shibler sizeof (long)); 138945753Smckusick *retval = time.tv_sec; 139044421Skarels return (error); 139141486Smckusick } 139241486Smckusick 139343452Shibler ohpuxstime(p, uap, retval) 139443452Shibler struct proc *p; 139543452Shibler register struct args { 139643452Shibler int time; 139743452Shibler } *uap; 139843452Shibler int *retval; 139941486Smckusick { 140041486Smckusick struct timeval tv; 140143452Shibler int s, error; 140241486Smckusick 140341486Smckusick tv.tv_sec = uap->time; 140441486Smckusick tv.tv_usec = 0; 140543452Shibler if (error = suser(u.u_cred, &u.u_acflag)) 140644421Skarels return (error); 140741486Smckusick 140841486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 140941486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 141041486Smckusick s = splhigh(); time = tv; splx(s); 141141486Smckusick resettodr(); 141244421Skarels return (0); 141341486Smckusick } 141441486Smckusick 141543452Shibler ohpuxftime(p, uap, retval) 141643452Shibler struct proc *p; 141743452Shibler register struct args { 141841486Smckusick struct hpuxtimeb *tp; 141941486Smckusick } *uap; 142043452Shibler int *retval; 142143452Shibler { 142241486Smckusick struct hpuxtimeb tb; 142341486Smckusick int s; 142441486Smckusick 142541486Smckusick s = splhigh(); 142641486Smckusick tb.time = time.tv_sec; 142741486Smckusick tb.millitm = time.tv_usec / 1000; 142841486Smckusick splx(s); 142941486Smckusick tb.timezone = tz.tz_minuteswest; 143041486Smckusick tb.dstflag = tz.tz_dsttime; 143144421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 143241486Smckusick } 143341486Smckusick 143443452Shibler ohpuxalarm(p, uap, retval) 143543452Shibler register struct proc *p; 143643452Shibler register struct args { 143743452Shibler int deltat; 143843452Shibler } *uap; 143943452Shibler int *retval; 144041486Smckusick { 144141486Smckusick int s = splhigh(); 144241486Smckusick 144341486Smckusick untimeout(realitexpire, (caddr_t)p); 144441486Smckusick timerclear(&p->p_realtimer.it_interval); 144543452Shibler *retval = 0; 144641486Smckusick if (timerisset(&p->p_realtimer.it_value) && 144741486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 144843452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 144941486Smckusick if (uap->deltat == 0) { 145041486Smckusick timerclear(&p->p_realtimer.it_value); 145141486Smckusick splx(s); 145244421Skarels return (0); 145341486Smckusick } 145441486Smckusick p->p_realtimer.it_value = time; 145541486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 145641486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 145741486Smckusick splx(s); 145844421Skarels return (0); 145941486Smckusick } 146041486Smckusick 146143452Shibler ohpuxnice(p, uap, retval) 146243452Shibler register struct proc *p; 146343452Shibler register struct args { 146443452Shibler int niceness; 146543452Shibler } *uap; 146643452Shibler int *retval; 146741486Smckusick { 146843452Shibler int error; 146941486Smckusick 147043452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 147143452Shibler if (error == 0) 147243452Shibler *retval = p->p_nice - NZERO; 147344421Skarels return (error); 147441486Smckusick } 147541486Smckusick 147643452Shibler ohpuxtimes(p, uap, retval) 147743452Shibler struct proc *p; 147843452Shibler register struct args { 147943452Shibler struct tms *tmsb; 148043452Shibler } *uap; 148143713Smckusick time_t *retval; 148241486Smckusick { 148341486Smckusick struct tms atms; 148443452Shibler int error; 148541486Smckusick 148645753Smckusick atms.tms_utime = hpuxscale(&u.u_ru.ru_utime); 148745753Smckusick atms.tms_stime = hpuxscale(&u.u_ru.ru_stime); 148845753Smckusick atms.tms_cutime = hpuxscale(&u.u_cru.ru_utime); 148945753Smckusick atms.tms_cstime = hpuxscale(&u.u_cru.ru_stime); 149043452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 149143452Shibler if (error == 0) 149245753Smckusick *retval = hpuxscale(&time) - hpuxscale(&boottime); 149344421Skarels return (error); 149441486Smckusick } 149541486Smckusick 149645753Smckusick /* 149745753Smckusick * Doesn't exactly do what the documentation says. 149845753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 149945753Smckusick * is what HP-UX returns. 150045753Smckusick */ 150145753Smckusick hpuxscale(tvp) 150241486Smckusick register struct timeval *tvp; 150341486Smckusick { 150445753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 150541486Smckusick } 150641486Smckusick 150741486Smckusick /* 150841486Smckusick * Set IUPD and IACC times on file. 150941486Smckusick * Can't set ICHG. 151041486Smckusick */ 151143452Shibler ohpuxutime(p, uap, retval) 151243452Shibler struct proc *p; 151341486Smckusick register struct a { 151441486Smckusick char *fname; 151541486Smckusick time_t *tptr; 151643452Shibler } *uap; 151743452Shibler int *retval; 151843452Shibler { 151941486Smckusick struct vattr vattr; 152041486Smckusick time_t tv[2]; 152141486Smckusick register struct vnode *vp; 152241486Smckusick register struct nameidata *ndp = &u.u_nd; 152343452Shibler int error; 152441486Smckusick 152541486Smckusick if (uap->tptr) { 152643452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 152743452Shibler if (error) 152844421Skarels return (error); 152941486Smckusick } else 153041486Smckusick tv[0] = tv[1] = time.tv_sec; 153141486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 153241486Smckusick ndp->ni_segflg = UIO_USERSPACE; 153341486Smckusick ndp->ni_dirp = uap->fname; 153441486Smckusick vattr_null(&vattr); 153541486Smckusick vattr.va_atime.tv_sec = tv[0]; 153641486Smckusick vattr.va_atime.tv_usec = 0; 153741486Smckusick vattr.va_mtime.tv_sec = tv[1]; 153841486Smckusick vattr.va_mtime.tv_usec = 0; 153943452Shibler if (error = namei(ndp)) 154044421Skarels return (error); 154141486Smckusick vp = ndp->ni_vp; 154242154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 154343452Shibler error = EROFS; 154441486Smckusick else 154543452Shibler error = VOP_SETATTR(vp, &vattr, ndp->ni_cred); 154641486Smckusick vput(vp); 154744421Skarels return (error); 154841486Smckusick } 154941486Smckusick 155043452Shibler ohpuxpause(p, uap, retval) 155143452Shibler struct proc *p; 155243452Shibler int *uap, *retval; 155341486Smckusick { 155442155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 155542155Skarels /* always return EINTR rather than ERESTART... */ 155644421Skarels return (EINTR); 155741486Smckusick } 155841486Smckusick 155941486Smckusick /* 156041486Smckusick * The old fstat system call. 156141486Smckusick */ 156243452Shibler ohpuxfstat(p, uap, retval) 156343452Shibler struct proc *p; 156443452Shibler register struct args { 156541486Smckusick int fd; 156641486Smckusick struct ohpuxstat *sb; 156743452Shibler } *uap; 156843452Shibler int *retval; 156943452Shibler { 1570*45923Smckusick register struct filedesc *fdp = p->p_fd; 157141486Smckusick struct file *fp; 157241486Smckusick 1573*45923Smckusick if (((unsigned)uap->fd) >= fdp->fd_maxfiles || 1574*45923Smckusick (fp = OFILE(fdp, uap->fd)) == NULL) 157544421Skarels return (EBADF); 157643452Shibler if (fp->f_type != DTYPE_VNODE) 157744421Skarels return (EINVAL); 157844421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 157941486Smckusick } 158041486Smckusick 158141486Smckusick /* 158241486Smckusick * Old stat system call. This version follows links. 158341486Smckusick */ 158443452Shibler ohpuxstat(p, uap, retval) 158543452Shibler struct proc *p; 158643452Shibler register struct args { 158741486Smckusick char *fname; 158841486Smckusick struct ohpuxstat *sb; 158943452Shibler } *uap; 159043452Shibler int *retval; 159143452Shibler { 159241486Smckusick register struct nameidata *ndp = &u.u_nd; 159343452Shibler int error; 159441486Smckusick 159541486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 159641486Smckusick ndp->ni_segflg = UIO_USERSPACE; 159741486Smckusick ndp->ni_dirp = uap->fname; 159843452Shibler if (error = namei(ndp)) 159944421Skarels return (error); 160043452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 160141486Smckusick vput(ndp->ni_vp); 160244421Skarels return (error); 160341486Smckusick } 160441486Smckusick 160541486Smckusick int 160641486Smckusick ohpuxstat1(vp, ub) 160741486Smckusick register struct vnode *vp; 160841486Smckusick struct ohpuxstat *ub; 160941486Smckusick { 161041486Smckusick struct ohpuxstat ds; 161141486Smckusick struct vattr vattr; 161241486Smckusick register int error; 161341486Smckusick 161441486Smckusick error = VOP_GETATTR(vp, &vattr, u.u_cred); 161541486Smckusick if (error) 161641486Smckusick return(error); 161741486Smckusick /* 161841486Smckusick * Copy from inode table 161941486Smckusick */ 162041486Smckusick ds.ohst_dev = vattr.va_fsid; 162141486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 162241486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 162341486Smckusick ds.ohst_nlink = vattr.va_nlink; 162441486Smckusick ds.ohst_uid = (short)vattr.va_uid; 162541486Smckusick ds.ohst_gid = (short)vattr.va_gid; 162641486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 162741486Smckusick ds.ohst_size = (int)vattr.va_size; 162841486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 162941486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 163041486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 163141486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 163241486Smckusick } 163341486Smckusick /* #endif */ 163441486Smckusick 163541486Smckusick #endif 1636