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*48478Skarels * @(#)hpux_compat.c 7.13 (Berkeley) 04/20/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" 25*48478Skarels #include "sys/signalvar.h" 2645788Sbostic #include "sys/kernel.h" 2745923Smckusick #include "sys/filedesc.h" 2845788Sbostic #include "sys/proc.h" 2945788Sbostic #include "sys/buf.h" 3045788Sbostic #include "sys/wait.h" 3145788Sbostic #include "sys/file.h" 32*48478Skarels #include "sys/namei.h" 3345788Sbostic #include "sys/vnode.h" 3445788Sbostic #include "sys/ioctl.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" 41*48478Skarels #include "sys/user.h" 4241486Smckusick 43*48478Skarels #include "machine/cpu.h" 44*48478Skarels #include "machine/reg.h" 45*48478Skarels #include "machine/psl.h" 46*48478Skarels #include "machine/vmparam.h" 4741486Smckusick #include "hpux.h" 4841486Smckusick #include "hpux_termio.h" 4941486Smckusick 5041486Smckusick #ifdef DEBUG 5141486Smckusick int unimpresponse = 0; 5241486Smckusick #endif 5341486Smckusick 5441486Smckusick /* SYS5 style UTSNAME info */ 5541486Smckusick struct hpuxutsname protoutsname = { 5641486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5741486Smckusick }; 5841486Smckusick 5941486Smckusick /* 6.0 and later style context */ 6041486Smckusick #ifdef FPCOPROC 6141486Smckusick char hpuxcontext[] = 6241486Smckusick "standalone HP-MC68881 HP-MC68020 HP-MC68010 localroot default"; 6341486Smckusick #else 6441486Smckusick char hpuxcontext[] = 6541486Smckusick "standalone HP-MC68020 HP-MC68010 localroot default"; 6641486Smckusick #endif 6741486Smckusick 6841486Smckusick /* YP domainname */ 6941486Smckusick char domainname[MAXHOSTNAMELEN] = "unknown"; 7041486Smckusick int domainnamelen = 7; 7141486Smckusick 7241486Smckusick #define NERR 79 7341486Smckusick #define BERR 1000 7441486Smckusick 7541486Smckusick /* indexed by BSD errno */ 7641486Smckusick short bsdtohpuxerrnomap[NERR] = { 7741486Smckusick /*00*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 7841486Smckusick /*10*/ 10, 45, 12, 13, 14, 15, 16, 17, 18, 19, 7941486Smckusick /*20*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 8041486Smckusick /*30*/ 30, 31, 32, 33, 34, 246, 245, 244, 216, 217, 8141486Smckusick /*40*/ 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 8241486Smckusick /*50*/ 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 8341486Smckusick /*60*/ 238, 239, 249, 248, 241, 242, 247,BERR,BERR,BERR, 8441486Smckusick /*70*/ 70, 71,BERR,BERR,BERR,BERR,BERR, 46,BERR 8541486Smckusick }; 8641486Smckusick 8743452Shibler notimp(p, uap, retval, code, nargs) 8843452Shibler struct proc *p; 8943452Shibler int *uap, *retval; 9043452Shibler int code, nargs; 9141486Smckusick { 9243452Shibler int error = 0; 9341486Smckusick #ifdef DEBUG 9443452Shibler register int *argp = uap; 9541486Smckusick extern char *hpuxsyscallnames[]; 9641486Smckusick 9741486Smckusick printf("HPUX %s(", hpuxsyscallnames[code]); 9841486Smckusick if (nargs) 9941486Smckusick while (nargs--) 10041486Smckusick printf("%x%c", *argp++, nargs? ',' : ')'); 10141486Smckusick else 10241486Smckusick printf(")"); 10341486Smckusick printf("\n"); 10441486Smckusick switch (unimpresponse) { 10541486Smckusick case 0: 10643452Shibler error = nosys(p, uap, retval); 10741486Smckusick break; 10841486Smckusick case 1: 10943452Shibler error = EINVAL; 11041486Smckusick break; 11141486Smckusick } 11241486Smckusick #else 11343452Shibler error = nosys(p, uap, retval); 11441486Smckusick #endif 11543452Shibler uprintf("HP-UX system call %d not implemented\n", code); 11644421Skarels return (error); 11741486Smckusick } 11841486Smckusick 119*48478Skarels hpuxexecv(p, uap, retval) 120*48478Skarels struct proc *p; 121*48478Skarels struct args { 122*48478Skarels char *fname; 123*48478Skarels char **argp; 124*48478Skarels char **envp; 125*48478Skarels } *uap; 126*48478Skarels int *retval; 127*48478Skarels { 128*48478Skarels extern int execve(); 129*48478Skarels 130*48478Skarels uap->envp = NULL; 131*48478Skarels return (execve(p, uap, retval)); 132*48478Skarels } 133*48478Skarels 13441486Smckusick /* 13541486Smckusick * HPUX versions of wait and wait3 actually pass the parameters 13641486Smckusick * (status pointer, options, rusage) into the kernel rather than 13742352Smckusick * handling it in the C library stub. We also need to map any 13842352Smckusick * termination signal from BSD to HPUX. 13941486Smckusick */ 14043452Shibler hpuxwait3(p, uap, retval) 14143452Shibler struct proc *p; 14243452Shibler struct args { 14341486Smckusick int *status; 14441486Smckusick int options; 14541486Smckusick int rusage; 14643452Shibler } *uap; 14743452Shibler int *retval; 14843452Shibler { 14941486Smckusick /* rusage pointer must be zero */ 15043452Shibler if (uap->rusage) 15144421Skarels return (EINVAL); 152*48478Skarels p->p_regs[PS] = PSL_ALLCC; 153*48478Skarels p->p_regs[R0] = uap->options; 154*48478Skarels p->p_regs[R1] = uap->rusage; 15544421Skarels return (hpuxwait(p, uap, retval)); 15641486Smckusick } 15741486Smckusick 15843452Shibler hpuxwait(p, uap, retval) 15943452Shibler struct proc *p; 16043452Shibler struct args { 16143452Shibler int *status; 16243452Shibler } *uap; 16343452Shibler int *retval; 16441486Smckusick { 16543452Shibler int sig, *statp, error; 16641486Smckusick 16741486Smckusick statp = uap->status; /* owait clobbers first arg */ 16843452Shibler error = owait(p, uap, retval); 16941486Smckusick /* 17041486Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 17141486Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 17241486Smckusick */ 17343452Shibler if (error == ERESTART) 17443452Shibler error = EINTR; 17543452Shibler if (error) 17644421Skarels return (error); 17743452Shibler sig = retval[1] & 0xFF; 17841486Smckusick if (sig == WSTOPPED) { 17943452Shibler sig = (retval[1] >> 8) & 0xFF; 18043452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 18141486Smckusick } else if (sig) 18243452Shibler retval[1] = (retval[1] & 0xFF00) | 18341486Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 18441486Smckusick if (statp) 18543452Shibler if (suword((caddr_t)statp, retval[1])) 18643452Shibler error = EFAULT; 18744421Skarels return (error); 18841486Smckusick } 18941486Smckusick 19043452Shibler hpuxwaitpid(p, uap, retval) 19143452Shibler struct proc *p; 19243452Shibler struct args { 19342352Smckusick int pid; 19442352Smckusick int *status; 19542352Smckusick int options; 19642352Smckusick struct rusage *rusage; /* wait4 arg */ 19743452Shibler } *uap; 19843452Shibler int *retval; 19943452Shibler { 20043452Shibler int sig, *statp, error; 20142352Smckusick 20242352Smckusick uap->rusage = 0; 20343452Shibler error = wait4(p, uap, retval); 20442352Smckusick /* 20542352Smckusick * HP-UX wait always returns EINTR when interrupted by a signal 20642352Smckusick * (well, unless its emulating a BSD process, but we don't bother...) 20742352Smckusick */ 20843452Shibler if (error == ERESTART) 20943452Shibler error = EINTR; 21043452Shibler if (error) 21144421Skarels return (error); 21243452Shibler sig = retval[1] & 0xFF; 21342352Smckusick if (sig == WSTOPPED) { 21443452Shibler sig = (retval[1] >> 8) & 0xFF; 21543452Shibler retval[1] = (bsdtohpuxsig(sig) << 8) | WSTOPPED; 21642352Smckusick } else if (sig) 21743452Shibler retval[1] = (retval[1] & 0xFF00) | 21842352Smckusick bsdtohpuxsig(sig & 0x7F) | (sig & 0x80); 21942352Smckusick if (statp) 22043452Shibler if (suword((caddr_t)statp, retval[1])) 22143452Shibler error = EFAULT; 22244421Skarels return (error); 22342352Smckusick } 22442352Smckusick 22541486Smckusick /* 22641486Smckusick * Must remap some bits in the mode mask. 22741486Smckusick * O_CREAT, O_TRUNC, and O_EXCL must be remapped, 22841486Smckusick * O_SYNCIO (0100000) is removed entirely. 22941486Smckusick */ 23043067Skarels hpuxopen(p, uap, retval) 23143067Skarels struct proc *p; 23243452Shibler register struct args { 23341486Smckusick char *fname; 23441486Smckusick int mode; 23541486Smckusick int crtmode; 23643067Skarels } *uap; 23743067Skarels int *retval; 23843067Skarels { 23941486Smckusick int mode; 24041486Smckusick 24141486Smckusick mode = uap->mode; 24241486Smckusick uap->mode &= ~(HPUXFSYNCIO|HPUXFEXCL|HPUXFTRUNC|HPUXFCREAT); 24341486Smckusick if (mode & HPUXFCREAT) { 24441486Smckusick /* 24541486Smckusick * simulate the pre-NFS behavior that opening a 24641486Smckusick * file for READ+CREATE ignores the CREATE (unless 24741486Smckusick * EXCL is set in which case we will return the 24841486Smckusick * proper error). 24941486Smckusick */ 250*48478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 25141486Smckusick uap->mode |= FCREAT; 25241486Smckusick } 25341486Smckusick if (mode & HPUXFTRUNC) 25441486Smckusick uap->mode |= FTRUNC; 25541486Smckusick if (mode & HPUXFEXCL) 25641486Smckusick uap->mode |= FEXCL; 25744421Skarels return (open(p, uap, retval)); 25841486Smckusick } 25941486Smckusick 26043452Shibler hpuxfcntl(p, uap, retval) 26143452Shibler struct proc *p; 26243452Shibler register struct args { 26341486Smckusick int fdes; 26441486Smckusick int cmd; 26541486Smckusick int arg; 26643452Shibler } *uap; 26743452Shibler int *retval; 26843452Shibler { 26943452Shibler int mode, error; 27041486Smckusick 27141486Smckusick switch (uap->cmd) { 27241486Smckusick case F_SETFL: 27341486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 27441486Smckusick break; 27541486Smckusick case F_GETFL: 27641486Smckusick case F_DUPFD: 27741486Smckusick case F_GETFD: 27841486Smckusick case F_SETFD: 27941486Smckusick break; 28041486Smckusick default: 28144421Skarels return (EINVAL); 28241486Smckusick } 28343452Shibler error = fcntl(p, uap, retval); 28443452Shibler if (error == 0 && uap->arg == F_GETFL) { 28543452Shibler mode = *retval; 28643452Shibler *retval &= ~(FCREAT|FTRUNC|FEXCL|FUSECACHE); 28741486Smckusick if (mode & FCREAT) 28843452Shibler *retval |= HPUXFCREAT; 28941486Smckusick if (mode & FTRUNC) 29043452Shibler *retval |= HPUXFTRUNC; 29141486Smckusick if (mode & FEXCL) 29243452Shibler *retval |= HPUXFEXCL; 29341486Smckusick } 29444421Skarels return (error); 29541486Smckusick } 29641486Smckusick 29741486Smckusick /* 29841486Smckusick * Read and write should return a 0 count when an operation 29941486Smckusick * on a VNODE would block, not an error. Sockets appear to 30041486Smckusick * return EWOULDBLOCK (at least in 6.2). This is probably 30141486Smckusick * not entirely correct, since the behavior is only defined 30241486Smckusick * for pipes and tty type devices. 30341486Smckusick */ 30443452Shibler hpuxread(p, uap, retval) 30543452Shibler struct proc *p; 30643452Shibler struct args { 30743452Shibler int fd; 30843452Shibler } *uap; 30943452Shibler int *retval; 31041486Smckusick { 31143452Shibler int error; 31241486Smckusick 31343452Shibler error = read(p, uap, retval); 31443452Shibler if (error == EWOULDBLOCK && 315*48478Skarels p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE) { 31643452Shibler error = 0; 31743452Shibler *retval = 0; 31841486Smckusick } 31944421Skarels return (error); 32041486Smckusick } 32141486Smckusick 32243452Shibler hpuxwrite(p, uap, retval) 32343452Shibler struct proc *p; 32443452Shibler struct args { 32543452Shibler int fd; 32643452Shibler } *uap; 32743452Shibler int *retval; 32841486Smckusick { 32943452Shibler int error; 33041486Smckusick 33143452Shibler error = write(p, uap, retval); 33243452Shibler if (error == EWOULDBLOCK && 333*48478Skarels p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE) { 33443452Shibler error = 0; 33543452Shibler *retval = 0; 33641486Smckusick } 33744421Skarels return (error); 33841486Smckusick } 33941486Smckusick 34043452Shibler hpuxreadv(p, uap, retval) 34143452Shibler struct proc *p; 34243452Shibler struct args { 34343452Shibler int fd; 34443452Shibler } *uap; 34543452Shibler int *retval; 34641486Smckusick { 34743452Shibler int error; 34841486Smckusick 34943452Shibler error = readv(p, uap, retval); 35043452Shibler if (error == EWOULDBLOCK && 351*48478Skarels p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE) { 35243452Shibler error = 0; 35343452Shibler *retval = 0; 35441486Smckusick } 35544421Skarels return (error); 35641486Smckusick } 35741486Smckusick 35843452Shibler hpuxwritev(p, uap, retval) 35943452Shibler struct proc *p; 36043452Shibler struct args { 36143452Shibler int fd; 36243452Shibler } *uap; 36343452Shibler int *retval; 36441486Smckusick { 36543452Shibler int error; 36641486Smckusick 36743452Shibler error = writev(p, uap, retval); 36843452Shibler if (error == EWOULDBLOCK && 369*48478Skarels p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE) { 37043452Shibler error = 0; 37143452Shibler *retval = 0; 37241486Smckusick } 37344421Skarels return (error); 37441486Smckusick } 37541486Smckusick 37641486Smckusick /* 37741486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 37841486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 37941486Smckusick */ 38043452Shibler hpuxdup(p, uap, retval) 38143452Shibler struct proc *p; 38243452Shibler register struct args { 38343452Shibler int i; 38443452Shibler } *uap; 38543452Shibler int *retval; 38641486Smckusick { 38745923Smckusick register struct filedesc *fdp = p->p_fd; 38841486Smckusick struct file *fp; 38943452Shibler int fd, error; 39041486Smckusick 391*48478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 392*48478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 39344421Skarels return (EBADF); 394*48478Skarels if (error = fdalloc(p, 0, &fd)) 39544421Skarels return (error); 396*48478Skarels fdp->fd_ofiles[fd] = fp; 397*48478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 39845923Smckusick fp->f_count++; 39945923Smckusick if (fd > fdp->fd_lastfile) 40045923Smckusick fdp->fd_lastfile = fd; 40143452Shibler *retval = fd; 40244421Skarels return (0); 40341486Smckusick } 40441486Smckusick 40545753Smckusick hpuxutssys(p, uap, retval) 40643452Shibler struct proc *p; 40743452Shibler register struct args { 40841486Smckusick struct hpuxutsname *uts; 40941486Smckusick int dev; 41041486Smckusick int request; 41143452Shibler } *uap; 41243452Shibler int *retval; 41343452Shibler { 41441486Smckusick register int i; 41543452Shibler int error; 41641486Smckusick 41741486Smckusick switch (uap->request) { 41841486Smckusick /* uname */ 41941486Smckusick case 0: 42041486Smckusick /* fill in machine type */ 42141486Smckusick switch (machineid) { 42241486Smckusick case HP_320: 42341486Smckusick protoutsname.machine[6] = '2'; 42441486Smckusick break; 42541486Smckusick /* includes 318 and 319 */ 42641486Smckusick case HP_330: 42741486Smckusick protoutsname.machine[6] = '3'; 42841486Smckusick break; 42941486Smckusick case HP_340: 43041486Smckusick protoutsname.machine[6] = '4'; 43141486Smckusick break; 43241486Smckusick case HP_350: 43341486Smckusick protoutsname.machine[6] = '5'; 43441486Smckusick break; 43541486Smckusick case HP_360: 43641486Smckusick protoutsname.machine[6] = '6'; 43741486Smckusick break; 43841486Smckusick case HP_370: 43941486Smckusick protoutsname.machine[6] = '7'; 44041486Smckusick break; 44143452Shibler /* includes 345 */ 44243452Shibler case HP_375: 44343452Shibler protoutsname.machine[6] = '7'; 44443452Shibler protoutsname.machine[7] = '5'; 44543452Shibler break; 44641486Smckusick } 44741486Smckusick /* copy hostname (sans domain) to nodename */ 44841486Smckusick for (i = 0; i < 9 && hostname[i] != '.'; i++) 44941486Smckusick protoutsname.nodename[i] = hostname[i]; 45043452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 45143452Shibler sizeof(struct hpuxutsname)); 45241486Smckusick break; 45345753Smckusick 45445753Smckusick /* gethostname */ 45545753Smckusick case 5: 45645753Smckusick /* uap->dev is length */ 45745753Smckusick if (uap->dev > hostnamelen + 1) 45845753Smckusick uap->dev = hostnamelen + 1; 45945753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 46045753Smckusick uap->dev); 46145753Smckusick break; 46245753Smckusick 46345753Smckusick case 1: /* ?? */ 46445753Smckusick case 2: /* ustat */ 46545753Smckusick case 3: /* ?? */ 46645753Smckusick case 4: /* sethostname */ 46741486Smckusick default: 46843452Shibler error = EINVAL; 46941486Smckusick break; 47041486Smckusick } 47144421Skarels return (error); 47241486Smckusick } 47341486Smckusick 47443452Shibler hpuxstat(p, uap, retval) 47543452Shibler struct proc *p; 47643452Shibler struct args { 47741486Smckusick char *fname; 47841486Smckusick struct hpuxstat *hsb; 47943452Shibler } *uap; 48043452Shibler int *retval; 48143452Shibler { 48244421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 48341486Smckusick } 48441486Smckusick 48543452Shibler hpuxlstat(p, uap, retval) 48643452Shibler struct proc *p; 48743452Shibler struct args { 48843452Shibler char *fname; 48943452Shibler struct hpuxstat *hsb; 49043452Shibler } *uap; 49143452Shibler int *retval; 49241486Smckusick { 49344421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 49441486Smckusick } 49541486Smckusick 49643452Shibler hpuxfstat(p, uap, retval) 49743452Shibler struct proc *p; 49843452Shibler register struct args { 49943452Shibler int fdes; 50043452Shibler struct hpuxstat *hsb; 50143452Shibler } *uap; 50243452Shibler int *retval; 50341486Smckusick { 50445923Smckusick register struct filedesc *fdp = p->p_fd; 50541486Smckusick register struct file *fp; 50641486Smckusick struct stat sb; 50743452Shibler int error; 50841486Smckusick 509*48478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 510*48478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 51144421Skarels return (EBADF); 51243452Shibler 51341486Smckusick switch (fp->f_type) { 51441486Smckusick 51541486Smckusick case DTYPE_VNODE: 51643452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 51741486Smckusick break; 51841486Smckusick 51941486Smckusick case DTYPE_SOCKET: 52043452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 52141486Smckusick break; 52241486Smckusick 52341486Smckusick default: 52441486Smckusick panic("fstat"); 52541486Smckusick /*NOTREACHED*/ 52641486Smckusick } 52741486Smckusick /* is this right for sockets?? */ 52843452Shibler if (error == 0) 52943452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 53044421Skarels return (error); 53141486Smckusick } 53241486Smckusick 53343452Shibler hpuxulimit(p, uap, retval) 53443452Shibler struct proc *p; 53543452Shibler register struct args { 53641486Smckusick int cmd; 53741486Smckusick long newlimit; 53843452Shibler } *uap; 53943713Smckusick off_t *retval; 54043452Shibler { 54141486Smckusick struct rlimit *limp; 54243452Shibler int error = 0; 54341486Smckusick 544*48478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 54541486Smckusick switch (uap->cmd) { 54641486Smckusick case 2: 54741486Smckusick uap->newlimit *= 512; 54841486Smckusick if (uap->newlimit > limp->rlim_max && 549*48478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 55041486Smckusick break; 55141486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 55241486Smckusick /* else fall into... */ 55341486Smckusick 55441486Smckusick case 1: 55545753Smckusick *retval = limp->rlim_max / 512; 55641486Smckusick break; 55741486Smckusick 55841486Smckusick case 3: 559*48478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 560*48478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 56141486Smckusick break; 56241486Smckusick 56341486Smckusick default: 56443452Shibler error = EINVAL; 56541486Smckusick break; 56641486Smckusick } 56744421Skarels return (error); 56841486Smckusick } 56941486Smckusick 57041486Smckusick /* 57141486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 57241486Smckusick * values -16 (high) thru -1 (low). 57341486Smckusick */ 57443452Shibler hpuxrtprio(cp, uap, retval) 57543452Shibler struct proc *cp; 57643452Shibler register struct args { 57741486Smckusick int pid; 57841486Smckusick int prio; 57943452Shibler } *uap; 58043452Shibler int *retval; 58143452Shibler { 58241486Smckusick struct proc *p; 58343452Shibler int nice, error; 58441486Smckusick 58541486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 58643452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 58744421Skarels return (EINVAL); 58841486Smckusick if (uap->pid == 0) 58943452Shibler p = cp; 59043452Shibler else if ((p = pfind(uap->pid)) == 0) 59144421Skarels return (ESRCH); 59241486Smckusick nice = p->p_nice; 59341486Smckusick if (nice < NZERO) 59443452Shibler *retval = (nice + 16) << 3; 59541486Smckusick else 59643452Shibler *retval = RTPRIO_RTOFF; 59741486Smckusick switch (uap->prio) { 59841486Smckusick 59941486Smckusick case RTPRIO_NOCHG: 60044421Skarels return (0); 60141486Smckusick 60241486Smckusick case RTPRIO_RTOFF: 60341486Smckusick if (nice >= NZERO) 60444421Skarels return (0); 60541486Smckusick nice = NZERO; 60641486Smckusick break; 60741486Smckusick 60841486Smckusick default: 60941486Smckusick nice = (uap->prio >> 3) - 16; 61041486Smckusick break; 61141486Smckusick } 61243452Shibler error = donice(cp, p, nice); 61343452Shibler if (error == EACCES) 61443452Shibler error = EPERM; 61544421Skarels return (error); 61641486Smckusick } 61741486Smckusick 61843452Shibler hpuxadvise(p, uap, retval) 61943452Shibler struct proc *p; 62043452Shibler struct args { 62143452Shibler int arg; 62243452Shibler } *uap; 62343452Shibler int *retval; 62441486Smckusick { 62543452Shibler int error = 0; 62641486Smckusick 62741486Smckusick switch (uap->arg) { 62841486Smckusick case 0: 62941486Smckusick u.u_pcb.pcb_flags |= PCB_HPUXMMAP; 63041486Smckusick break; 63141486Smckusick case 1: 63241486Smckusick ICIA(); 63341486Smckusick break; 63441486Smckusick case 2: 63541486Smckusick DCIA(); 63641486Smckusick break; 63741486Smckusick default: 63843452Shibler error = EINVAL; 63941486Smckusick break; 64041486Smckusick } 64144421Skarels return (error); 64241486Smckusick } 64341486Smckusick 64443452Shibler hpuxptrace(p, uap, retval) 64543452Shibler struct proc *p; 64643452Shibler struct args { 64741486Smckusick int req; 64841486Smckusick int pid; 64941486Smckusick int *addr; 65041486Smckusick int data; 65143452Shibler } *uap; 65243452Shibler int *retval; 65343452Shibler { 65443452Shibler int error; 65541486Smckusick 65641486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 65741486Smckusick if (uap->data) { 65841486Smckusick uap->data = hpuxtobsdsig(uap->data); 65941486Smckusick if (uap->data == 0) 66041486Smckusick uap->data = NSIG; 66141486Smckusick } 66241486Smckusick } 66343452Shibler error = ptrace(p, uap, retval); 66444421Skarels return (error); 66541486Smckusick } 66641486Smckusick 66743452Shibler hpuxgetdomainname(p, uap, retval) 66843452Shibler struct proc *p; 66943452Shibler register struct args { 67041486Smckusick char *domainname; 67141486Smckusick u_int len; 67243452Shibler } *uap; 67343452Shibler int *retval; 67443452Shibler { 67541486Smckusick if (uap->len > domainnamelen + 1) 67641486Smckusick uap->len = domainnamelen + 1; 67744421Skarels return (copyout(domainname, uap->domainname, uap->len)); 67841486Smckusick } 67941486Smckusick 68043452Shibler hpuxsetdomainname(p, uap, retval) 68143452Shibler struct proc *p; 68243452Shibler register struct args { 68341486Smckusick char *domainname; 68441486Smckusick u_int len; 68543452Shibler } *uap; 68643452Shibler int *retval; 68743452Shibler { 68843452Shibler int error; 68941486Smckusick 690*48478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 69144421Skarels return (error); 69243452Shibler if (uap->len > sizeof (domainname) - 1) 69344421Skarels return (EINVAL); 69441486Smckusick domainnamelen = uap->len; 69543452Shibler error = copyin(uap->domainname, domainname, uap->len); 69641486Smckusick domainname[domainnamelen] = 0; 69744421Skarels return (error); 69841486Smckusick } 69941486Smckusick 70041486Smckusick #ifdef SYSVSHM 70143452Shibler hpuxshmat(p, uap, retval) 70243452Shibler struct proc *p; 70343452Shibler int *uap, *retval; 70441486Smckusick { 70544421Skarels return (shmat(p, uap, retval)); 70641486Smckusick } 70741486Smckusick 70843452Shibler hpuxshmctl(p, uap, retval) 70943452Shibler struct proc *p; 71043452Shibler int *uap, *retval; 71141486Smckusick { 71244421Skarels return (shmctl(p, uap, retval)); 71341486Smckusick } 71441486Smckusick 71543452Shibler hpuxshmdt(p, uap, retval) 71643452Shibler struct proc *p; 71743452Shibler int *uap, *retval; 71841486Smckusick { 71944421Skarels return (shmdt(p, uap, retval)); 72041486Smckusick } 72141486Smckusick 72243452Shibler hpuxshmget(p, uap, retval) 72343452Shibler struct proc *p; 72443452Shibler int *uap, *retval; 72541486Smckusick { 72644421Skarels return (shmget(p, uap, retval)); 72741486Smckusick } 72841486Smckusick #endif 72941486Smckusick 73041486Smckusick /* 73141486Smckusick * Fake semaphore routines, just don't return an error. 73241486Smckusick * Should be adequate for starbase to run. 73341486Smckusick */ 73443452Shibler hpuxsemctl(p, uap, retval) 73543452Shibler struct proc *p; 73643452Shibler struct args { 73741486Smckusick int semid; 73841486Smckusick u_int semnum; 73941486Smckusick int cmd; 74041486Smckusick int arg; 74143452Shibler } *uap; 74243452Shibler int *retval; 74343452Shibler { 74441486Smckusick /* XXX: should do something here */ 74544421Skarels return (0); 74641486Smckusick } 74741486Smckusick 74843452Shibler hpuxsemget(p, uap, retval) 74943452Shibler struct proc *p; 75043452Shibler struct args { 75141486Smckusick key_t key; 75241486Smckusick int nsems; 75341486Smckusick int semflg; 75443452Shibler } *uap; 75543452Shibler int *retval; 75643452Shibler { 75741486Smckusick /* XXX: should do something here */ 75844421Skarels return (0); 75941486Smckusick } 76041486Smckusick 76143452Shibler hpuxsemop(p, uap, retval) 76243452Shibler struct proc *p; 76343452Shibler struct args { 76441486Smckusick int semid; 76541486Smckusick struct sembuf *sops; 76641486Smckusick u_int nsops; 76743452Shibler } *uap; 76843452Shibler int *retval; 76943452Shibler { 77041486Smckusick /* XXX: should do something here */ 77144421Skarels return (0); 77241486Smckusick } 77341486Smckusick 77441486Smckusick /* convert from BSD to HPUX errno */ 77541486Smckusick bsdtohpuxerrno(err) 77641486Smckusick int err; 77741486Smckusick { 77841486Smckusick if (err < 0 || err >= NERR) 77941486Smckusick return(BERR); 78041486Smckusick return((int)bsdtohpuxerrnomap[err]); 78141486Smckusick } 78241486Smckusick 78341486Smckusick hpuxstat1(fname, hsb, follow) 78441486Smckusick char *fname; 78541486Smckusick struct hpuxstat *hsb; 78641486Smckusick int follow; 78741486Smckusick { 788*48478Skarels register struct nameidata *ndp; 789*48478Skarels int error; 79041486Smckusick struct stat sb; 791*48478Skarels struct nameidata nd; 79241486Smckusick 793*48478Skarels ndp = &nd; 79441486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 79541486Smckusick ndp->ni_segflg = UIO_USERSPACE; 79641486Smckusick ndp->ni_dirp = fname; 797*48478Skarels if (error = namei(ndp, curproc)) 79841486Smckusick return (error); 79941486Smckusick error = vn_stat(ndp->ni_vp, &sb); 80041486Smckusick vput(ndp->ni_vp); 80141486Smckusick if (error == 0) 80241486Smckusick error = bsdtohpuxstat(&sb, hsb); 80341486Smckusick return (error); 80441486Smckusick } 80541486Smckusick 80641486Smckusick #include "grf.h" 80741486Smckusick 80841486Smckusick bsdtohpuxstat(sb, hsb) 80941486Smckusick struct stat *sb; 81041486Smckusick struct hpuxstat *hsb; 81141486Smckusick { 81241486Smckusick struct hpuxstat ds; 81341486Smckusick 81441486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 81541486Smckusick ds.hst_dev = sb->st_dev; 81641486Smckusick ds.hst_ino = (u_long)sb->st_ino; 81741486Smckusick ds.hst_mode = sb->st_mode; 81841486Smckusick ds.hst_nlink = sb->st_nlink; 81941486Smckusick ds.hst_uid = (u_short)sb->st_uid; 82041486Smckusick ds.hst_gid = (u_short)sb->st_gid; 82141486Smckusick #if NGRF > 0 82241486Smckusick /* XXX: I don't want to talk about it... */ 82341486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 82441486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 82541486Smckusick else 82641486Smckusick #endif 82741486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 82841486Smckusick ds.hst_size = sb->st_size; 82941486Smckusick ds.hst_atime = sb->st_atime; 83041486Smckusick ds.hst_mtime = sb->st_mtime; 83141486Smckusick ds.hst_ctime = sb->st_ctime; 83241486Smckusick ds.hst_blksize = sb->st_blksize; 83341486Smckusick ds.hst_blocks = sb->st_blocks; 83441486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 83541486Smckusick } 83641486Smckusick 83741486Smckusick hpuxtobsdioctl(com) 83841486Smckusick int com; 83941486Smckusick { 84041486Smckusick switch (com) { 84141486Smckusick case HPUXTIOCSLTC: 84241486Smckusick com = TIOCSLTC; break; 84341486Smckusick case HPUXTIOCGLTC: 84441486Smckusick com = TIOCGLTC; break; 84541486Smckusick case HPUXTIOCSPGRP: 84641486Smckusick com = TIOCSPGRP; break; 84741486Smckusick case HPUXTIOCGPGRP: 84841486Smckusick com = TIOCGPGRP; break; 84941486Smckusick case HPUXTIOCLBIS: 85041486Smckusick com = TIOCLBIS; break; 85141486Smckusick case HPUXTIOCLBIC: 85241486Smckusick com = TIOCLBIC; break; 85341486Smckusick case HPUXTIOCLSET: 85441486Smckusick com = TIOCLSET; break; 85541486Smckusick case HPUXTIOCLGET: 85641486Smckusick com = TIOCLGET; break; 85741486Smckusick } 85841486Smckusick return(com); 85941486Smckusick } 86041486Smckusick 86141486Smckusick /* 86241486Smckusick * HPUX ioctl system call. The differences here are: 86341486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 86441486Smckusick * no FIOCLEX/FIONCLEX/FIONBIO/FIOASYNC/FIOGETOWN/FIOSETOWN 86541486Smckusick * the sgttyb struct is 2 bytes longer 86641486Smckusick */ 86743452Shibler hpuxioctl(p, uap, retval) 86843452Shibler struct proc *p; 86943452Shibler register struct args { 87041486Smckusick int fdes; 87141486Smckusick int cmd; 87241486Smckusick caddr_t cmarg; 87343452Shibler } *uap; 87443452Shibler int *retval; 87543452Shibler { 87645923Smckusick register struct filedesc *fdp = p->p_fd; 87743452Shibler register struct file *fp; 87843452Shibler register int com, error; 87941486Smckusick register u_int size; 88041486Smckusick caddr_t memp = 0; 88141486Smckusick #define STK_PARAMS 128 88241486Smckusick char stkbuf[STK_PARAMS]; 88341486Smckusick caddr_t data = stkbuf; 88441486Smckusick 88541486Smckusick com = uap->cmd; 88641486Smckusick 88741486Smckusick /* XXX */ 88843452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 88945923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 89041486Smckusick 891*48478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 892*48478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 89344421Skarels return (EBADF); 89443452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 89544421Skarels return (EBADF); 89641486Smckusick 89741486Smckusick /* 89841486Smckusick * Interpret high order word to find 89941486Smckusick * amount of data to be copied to/from the 90041486Smckusick * user's address space. 90141486Smckusick */ 90241486Smckusick size = IOCPARM_LEN(com); 90343452Shibler if (size > IOCPARM_MAX) 90444421Skarels return (ENOTTY); 90541486Smckusick if (size > sizeof (stkbuf)) { 90643452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 90741486Smckusick data = memp; 90841486Smckusick } 90941486Smckusick if (com&IOC_IN) { 91041486Smckusick if (size) { 91143452Shibler error = copyin(uap->cmarg, data, (u_int)size); 91243452Shibler if (error) { 91341486Smckusick if (memp) 91441486Smckusick free(memp, M_IOCTLOPS); 91544421Skarels return (error); 91641486Smckusick } 91741486Smckusick } else 91841486Smckusick *(caddr_t *)data = uap->cmarg; 91941486Smckusick } else if ((com&IOC_OUT) && size) 92041486Smckusick /* 92143452Shibler * Zero the buffer so the user always 92243452Shibler * gets back something deterministic. 92341486Smckusick */ 92441486Smckusick bzero(data, size); 92541486Smckusick else if (com&IOC_VOID) 92641486Smckusick *(caddr_t *)data = uap->cmarg; 92741486Smckusick 92841486Smckusick switch (com) { 92941486Smckusick 93041486Smckusick case HPUXTIOCCONS: 93141486Smckusick *(int *)data = 1; 932*48478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 93341486Smckusick break; 93441486Smckusick 93541486Smckusick /* BSD-style job control ioctls */ 93641486Smckusick case HPUXTIOCLBIS: 93741486Smckusick case HPUXTIOCLBIC: 93841486Smckusick case HPUXTIOCLSET: 93941486Smckusick *(int *)data &= HPUXLTOSTOP; 94041486Smckusick if (*(int *)data & HPUXLTOSTOP) 94141486Smckusick *(int *)data = LTOSTOP; 94241486Smckusick /* fall into */ 94341486Smckusick case HPUXTIOCLGET: 94441486Smckusick case HPUXTIOCSLTC: 94541486Smckusick case HPUXTIOCGLTC: 94641486Smckusick case HPUXTIOCSPGRP: 94741486Smckusick case HPUXTIOCGPGRP: 948*48478Skarels error = (*fp->f_ops->fo_ioctl) 949*48478Skarels (fp, hpuxtobsdioctl(com), data, p); 95043452Shibler if (error == 0 && com == HPUXTIOCLGET) { 95141486Smckusick *(int *)data &= LTOSTOP; 95241486Smckusick if (*(int *)data & LTOSTOP) 95341486Smckusick *(int *)data = HPUXLTOSTOP; 95441486Smckusick } 95541486Smckusick break; 95641486Smckusick 95741486Smckusick /* SYS 5 termio */ 95841486Smckusick case HPUXTCGETA: 95941486Smckusick case HPUXTCSETA: 96041486Smckusick case HPUXTCSETAW: 96141486Smckusick case HPUXTCSETAF: 962*48478Skarels error = hpuxtermio(fp, com, data, p); 96341486Smckusick break; 96441486Smckusick 96541486Smckusick default: 966*48478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 96741486Smckusick break; 96841486Smckusick } 96941486Smckusick /* 97041486Smckusick * Copy any data to user, size was 97141486Smckusick * already set and checked above. 97241486Smckusick */ 97343452Shibler if (error == 0 && (com&IOC_OUT) && size) 97443452Shibler error = copyout(data, uap->cmarg, (u_int)size); 97541486Smckusick if (memp) 97641486Smckusick free(memp, M_IOCTLOPS); 97744421Skarels return (error); 97841486Smckusick } 97941486Smckusick 98041486Smckusick /* 98141486Smckusick * Man page lies, behaviour here is based on observed behaviour. 98241486Smckusick */ 98343452Shibler hpuxgetcontext(p, uap, retval) 98443452Shibler struct proc *p; 98543452Shibler struct args { 98641486Smckusick char *buf; 98741486Smckusick int len; 98843452Shibler } *uap; 98943452Shibler int *retval; 99043452Shibler { 99141486Smckusick int error = 0; 99241486Smckusick register int len; 99341486Smckusick 99441486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 99541486Smckusick if (len) 99641486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 99743452Shibler if (error == 0) 99843452Shibler *retval = sizeof(hpuxcontext); 99944421Skarels return (error); 100041486Smckusick } 100141486Smckusick 100241486Smckusick /* 100341486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 100441486Smckusick * Note we do not check the real uid or "saved" uid. 100541486Smckusick */ 100643452Shibler hpuxgetpgrp2(cp, uap, retval) 100743452Shibler struct proc *cp; 100843452Shibler register struct args { 100943452Shibler int pid; 101043452Shibler } *uap; 101143452Shibler int *retval; 101241486Smckusick { 101341486Smckusick register struct proc *p; 101441486Smckusick 101541486Smckusick if (uap->pid == 0) 101643452Shibler uap->pid = cp->p_pid; 101741486Smckusick p = pfind(uap->pid); 101843452Shibler if (p == 0) 101944421Skarels return (ESRCH); 1020*48478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 1021*48478Skarels !inferior(p)) 102244421Skarels return (EPERM); 102343452Shibler *retval = p->p_pgid; 102444421Skarels return (0); 102541486Smckusick } 102641486Smckusick 102741486Smckusick /* 102841486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 102941486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 103041486Smckusick */ 103143452Shibler hpuxsetpgrp2(p, uap, retval) 103243452Shibler struct proc *p; 103343452Shibler struct args { 103441486Smckusick int pid; 103541486Smckusick int pgrp; 103643452Shibler } *uap; 103743452Shibler int *retval; 103843452Shibler { 103941486Smckusick /* empirically determined */ 104043452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 104144421Skarels return (EINVAL); 1042*48478Skarels return (setpgid(p, uap, retval)); 104341486Smckusick } 104441486Smckusick 104541486Smckusick /* 104645753Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 104745753Smckusick */ 104845753Smckusick hpuxsetresuid(p, uap, retval) 104945753Smckusick struct proc *p; 105045753Smckusick struct args { 105145753Smckusick int ruid; 105245753Smckusick int euid; 105345753Smckusick int suid; 105445753Smckusick } *uap; 105545753Smckusick int *retval; 105645753Smckusick { 105745753Smckusick return (osetreuid(p, uap, retval)); 105845753Smckusick } 105945753Smckusick 106045753Smckusick hpuxsetresgid(p, uap, retval) 106145753Smckusick struct proc *p; 106245753Smckusick struct args { 106345753Smckusick int rgid; 106445753Smckusick int egid; 106545753Smckusick int sgid; 106645753Smckusick } *uap; 106745753Smckusick int *retval; 106845753Smckusick { 106945753Smckusick return (osetregid(p, uap, retval)); 107045753Smckusick } 107145753Smckusick 107245753Smckusick /* 107345753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 107445753Smckusick */ 107545753Smckusick hpuxlockf(p, uap, retval) 107645753Smckusick struct proc *p; 107745753Smckusick struct args { 107845753Smckusick int fd; 107945753Smckusick int func; 108045753Smckusick long size; 108145753Smckusick } *uap; 108245753Smckusick int *retval; 108345753Smckusick { 108445753Smckusick #ifdef DEBUG 108545753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 108645753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 108745753Smckusick #endif 108845753Smckusick return (0); 108945753Smckusick } 109045753Smckusick 109145753Smckusick hpuxgetaccess(p, uap, retval) 109245753Smckusick register struct proc *p; 109345753Smckusick register struct args { 109445753Smckusick char *path; 109545753Smckusick int uid; 109645753Smckusick int ngroups; 109745753Smckusick int *gidset; 109845753Smckusick void *label; 109945753Smckusick void *privs; 110045753Smckusick } *uap; 110145753Smckusick int *retval; 110245753Smckusick { 1103*48478Skarels struct nameidata *ndp; 110445753Smckusick int lgroups[NGROUPS]; 110545753Smckusick int error = 0; 110645753Smckusick register struct ucred *cred; 110745753Smckusick register struct vnode *vp; 110845753Smckusick 110945753Smckusick /* 111045753Smckusick * Build an appropriate credential structure 111145753Smckusick */ 1112*48478Skarels cred = crdup(p->p_ucred); 111345753Smckusick switch (uap->uid) { 111445753Smckusick case 65502: /* UID_EUID */ 111545753Smckusick break; 111645753Smckusick case 65503: /* UID_RUID */ 1117*48478Skarels cred->cr_uid = p->p_cred->p_ruid; 111845753Smckusick break; 111945753Smckusick case 65504: /* UID_SUID */ 112045753Smckusick error = EINVAL; 112145753Smckusick break; 112245753Smckusick default: 112345753Smckusick if (uap->uid > 65504) 112445753Smckusick error = EINVAL; 112545753Smckusick cred->cr_uid = uap->uid; 112645753Smckusick break; 112745753Smckusick } 112845753Smckusick switch (uap->ngroups) { 112945753Smckusick case -1: /* NGROUPS_EGID */ 113045753Smckusick cred->cr_ngroups = 1; 113145753Smckusick break; 113245753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 113345753Smckusick break; 113445753Smckusick case -2: /* NGROUPS_RGID */ 113545753Smckusick cred->cr_ngroups = 1; 1136*48478Skarels cred->cr_gid = p->p_cred->p_rgid; 113745753Smckusick break; 113845753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 1139*48478Skarels cred->cr_gid = p->p_cred->p_rgid; 114045753Smckusick break; 114145753Smckusick case -3: /* NGROUPS_SGID */ 114245753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 114345753Smckusick error = EINVAL; 114445753Smckusick break; 114545753Smckusick case -4: /* NGROUPS_SUPP */ 114645753Smckusick if (cred->cr_ngroups > 1) 114745753Smckusick cred->cr_gid = cred->cr_groups[1]; 114845753Smckusick else 114945753Smckusick error = EINVAL; 115045753Smckusick break; 115145753Smckusick default: 115245753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 115345753Smckusick error = copyin((caddr_t)uap->gidset, 115445753Smckusick (caddr_t)&lgroups[0], 115545753Smckusick uap->ngroups * sizeof(lgroups[0])); 115645753Smckusick else 115745753Smckusick error = EINVAL; 115845753Smckusick if (error == 0) { 115945753Smckusick int gid; 116045753Smckusick 116145753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 116245753Smckusick cred->cr_groups[gid] = lgroups[gid]; 116345753Smckusick cred->cr_ngroups = uap->ngroups; 116445753Smckusick } 116545753Smckusick break; 116645753Smckusick } 116745753Smckusick /* 116845753Smckusick * Lookup file using caller's effective IDs. 116945753Smckusick */ 117045753Smckusick if (error == 0) { 117145753Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 117245753Smckusick ndp->ni_segflg = UIO_USERSPACE; 117345753Smckusick ndp->ni_dirp = uap->path; 1174*48478Skarels error = namei(ndp, p); 117545753Smckusick } 117645753Smckusick if (error) { 117745753Smckusick crfree(cred); 117845753Smckusick return (error); 117945753Smckusick } 118045753Smckusick /* 118145753Smckusick * Use the constructed credentials for access checks. 118245753Smckusick */ 118345753Smckusick vp = ndp->ni_vp; 118445753Smckusick *retval = 0; 1185*48478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 118645753Smckusick *retval |= R_OK; 1187*48478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 118845753Smckusick *retval |= W_OK; 118945753Smckusick /* XXX we return X_OK for root on VREG even if not */ 1190*48478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 119145753Smckusick *retval |= X_OK; 119245753Smckusick vput(vp); 119345753Smckusick crfree(cred); 119445753Smckusick return (error); 119545753Smckusick } 119645753Smckusick 119745753Smckusick /* 119841486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 119941486Smckusick * No apologies offered, if you don't like it, rewrite it! 120041486Smckusick */ 120141486Smckusick 120241486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 120341486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 120441486Smckusick 120541486Smckusick /* simplified FP structure */ 120641486Smckusick struct bsdfp { 120741486Smckusick int save[54]; 120841486Smckusick int reg[24]; 120941486Smckusick int ctrl[3]; 121041486Smckusick }; 121141486Smckusick 121241486Smckusick hpuxtobsduoff(off) 121341486Smckusick int *off; 121441486Smckusick { 1215*48478Skarels register int *ar0 = curproc->p_regs; 121641486Smckusick struct hpuxfp *hp; 121741486Smckusick struct bsdfp *bp; 121841486Smckusick register u_int raddr; 121941486Smckusick 1220*48478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 122141486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 1222*48478Skarels return(UOFF(U_ar0)); 122341486Smckusick 122441486Smckusick #ifdef FPCOPROC 122541486Smckusick /* 68881 registers from PCB */ 122641486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 122741486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 122841486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 122941486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 123041486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 123141486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 123241486Smckusick #endif 123341486Smckusick 123441486Smckusick /* 123541486Smckusick * Everything else we recognize comes from the kernel stack, 123641486Smckusick * so we convert off to an absolute address (if not already) 123741486Smckusick * for simplicity. 123841486Smckusick */ 123941486Smckusick if (off < (int *)ctob(UPAGES)) 124041486Smckusick off = (int *)((u_int)off + (u_int)&u); 124141486Smckusick 124241486Smckusick /* 124341486Smckusick * 68020 registers. 124441486Smckusick * We know that the HPUX registers are in the same order as ours. 124541486Smckusick * The only difference is that their PS is 2 bytes instead of a 124641486Smckusick * padded 4 like ours throwing the alignment off. 124741486Smckusick */ 1248*48478Skarels if (off >= ar0 && off < &ar0[18]) { 124941486Smckusick /* 125041486Smckusick * PS: return low word and high word of PC as HP-UX would 125141486Smckusick * (e.g. &u.u_ar0[16.5]). 125241486Smckusick */ 1253*48478Skarels if (off == &ar0[PS]) 1254*48478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 125541486Smckusick /* 125641486Smckusick * PC: off will be &u.u_ar0[16.5] 125741486Smckusick */ 1258*48478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 1259*48478Skarels raddr = (u_int) &ar0[PC]; 126041486Smckusick /* 126141486Smckusick * D0-D7, A0-A7: easy 126241486Smckusick */ 126341486Smckusick else 1264*48478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 126541486Smckusick return((int)(raddr - (u_int)&u)); 126641486Smckusick } 126741486Smckusick 126841486Smckusick /* everything else */ 126941486Smckusick return(-1); 127041486Smckusick } 127141486Smckusick 127241486Smckusick /* 127341486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 127441486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 127541486Smckusick * convert the entire user struct. 127641486Smckusick */ 127741486Smckusick hpuxdumpu(vp, cred) 127841486Smckusick struct vnode *vp; 127941486Smckusick struct ucred *cred; 128041486Smckusick { 1281*48478Skarels struct proc *p = curproc; 128241486Smckusick int error; 128341486Smckusick struct hpuxuser *faku; 128441486Smckusick struct bsdfp *bp; 128541486Smckusick short *foop; 128641486Smckusick 128741486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 128841486Smckusick /* 128941486Smckusick * Make sure there is no mistake about this 129041486Smckusick * being a real user structure. 129141486Smckusick */ 129241486Smckusick bzero((caddr_t)faku, ctob(1)); 129341486Smckusick /* 129441486Smckusick * Fill in the process sizes. 129541486Smckusick */ 1296*48478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 1297*48478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 1298*48478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 129941486Smckusick /* 130041486Smckusick * Fill in the exec header for CDB. 130141486Smckusick * This was saved back in exec(). As far as I can tell CDB 130241486Smckusick * only uses this information to verify that a particular 130341486Smckusick * core file goes with a particular binary. 130441486Smckusick */ 130541486Smckusick bcopy((caddr_t)u.u_pcb.pcb_exec, 130641486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 130741486Smckusick /* 130841486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 130941486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 131041486Smckusick * so we have to move it up. 131141486Smckusick */ 1312*48478Skarels faku->hpuxu_ar0 = p->p_regs; 1313*48478Skarels foop = (short *) p->p_regs; 131441486Smckusick foop[32] = foop[33]; 131541486Smckusick foop[33] = foop[34]; 131641486Smckusick foop[34] = foop[35]; 131741486Smckusick #ifdef FPCOPROC 131841486Smckusick /* 131941486Smckusick * Copy 68881 registers from our PCB format to HPUX format 132041486Smckusick */ 132141486Smckusick bp = (struct bsdfp *) &u.u_pcb.pcb_fpregs; 132241486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 132341486Smckusick sizeof(bp->save)); 132441486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 132541486Smckusick sizeof(bp->ctrl)); 132641486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 132741486Smckusick sizeof(bp->reg)); 132841486Smckusick #endif 132941486Smckusick /* 133041486Smckusick * Slay the dragon 133141486Smckusick */ 133241486Smckusick faku->hpuxu_dragon = -1; 133341486Smckusick /* 133441486Smckusick * Dump this artfully constructed page in place of the 133541486Smckusick * user struct page. 133641486Smckusick */ 1337*48478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 1338*48478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 1339*48478Skarels (int *)0, (struct proc *)0); 134041486Smckusick /* 134141486Smckusick * Dump the remaining UPAGES-1 pages normally 134241486Smckusick */ 134341486Smckusick if (!error) 134441486Smckusick error = vn_rdwr(UIO_WRITE, vp, ((caddr_t)&u)+ctob(1), 134541486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 1346*48478Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)0, 1347*48478Skarels (struct proc *)0); 134841486Smckusick free((caddr_t)faku, M_TEMP); 134941486Smckusick return(error); 135041486Smckusick } 135141486Smckusick 135241486Smckusick /* 135341486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 135441486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 135541486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 135641486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 135741486Smckusick */ 135841486Smckusick /* #ifdef COMPAT */ 135941486Smckusick 136045753Smckusick #define HPUX_HZ 50 136145753Smckusick 136245788Sbostic #include "sys/times.h" 136341486Smckusick 136441486Smckusick /* from old timeb.h */ 136541486Smckusick struct hpuxtimeb { 136641486Smckusick time_t time; 136741486Smckusick u_short millitm; 136841486Smckusick short timezone; 136941486Smckusick short dstflag; 137041486Smckusick }; 137141486Smckusick 137241486Smckusick /* ye ole stat structure */ 137341486Smckusick struct ohpuxstat { 137441486Smckusick dev_t ohst_dev; 137541486Smckusick u_short ohst_ino; 137641486Smckusick u_short ohst_mode; 137741486Smckusick short ohst_nlink; 137841486Smckusick short ohst_uid; 137941486Smckusick short ohst_gid; 138041486Smckusick dev_t ohst_rdev; 138141486Smckusick int ohst_size; 138241486Smckusick int ohst_atime; 138341486Smckusick int ohst_mtime; 138441486Smckusick int ohst_ctime; 138541486Smckusick }; 138641486Smckusick 138741486Smckusick /* 138841486Smckusick * SYS V style setpgrp() 138941486Smckusick */ 139043452Shibler ohpuxsetpgrp(p, uap, retval) 139143452Shibler register struct proc *p; 139243452Shibler int *uap, *retval; 139341486Smckusick { 139441486Smckusick if (p->p_pid != p->p_pgid) 1395*48478Skarels enterpgrp(p, p->p_pid, 0); 139643452Shibler *retval = p->p_pgid; 139745753Smckusick return (0); 139841486Smckusick } 139941486Smckusick 140043452Shibler ohpuxtime(p, uap, retval) 140143452Shibler struct proc *p; 140243452Shibler register struct args { 140343452Shibler long *tp; 140443452Shibler } *uap; 140543713Smckusick time_t *retval; 140641486Smckusick { 140745753Smckusick int error = 0; 140841486Smckusick 140941486Smckusick if (uap->tp) 141043452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 141143452Shibler sizeof (long)); 141245753Smckusick *retval = time.tv_sec; 141344421Skarels return (error); 141441486Smckusick } 141541486Smckusick 141643452Shibler ohpuxstime(p, uap, retval) 141743452Shibler struct proc *p; 141843452Shibler register struct args { 141943452Shibler int time; 142043452Shibler } *uap; 142143452Shibler int *retval; 142241486Smckusick { 142341486Smckusick struct timeval tv; 142443452Shibler int s, error; 142541486Smckusick 142641486Smckusick tv.tv_sec = uap->time; 142741486Smckusick tv.tv_usec = 0; 1428*48478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 142944421Skarels return (error); 143041486Smckusick 143141486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 143241486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 143341486Smckusick s = splhigh(); time = tv; splx(s); 143441486Smckusick resettodr(); 143544421Skarels return (0); 143641486Smckusick } 143741486Smckusick 143843452Shibler ohpuxftime(p, uap, retval) 143943452Shibler struct proc *p; 144043452Shibler register struct args { 144141486Smckusick struct hpuxtimeb *tp; 144241486Smckusick } *uap; 144343452Shibler int *retval; 144443452Shibler { 144541486Smckusick struct hpuxtimeb tb; 144641486Smckusick int s; 144741486Smckusick 144841486Smckusick s = splhigh(); 144941486Smckusick tb.time = time.tv_sec; 145041486Smckusick tb.millitm = time.tv_usec / 1000; 145141486Smckusick splx(s); 145241486Smckusick tb.timezone = tz.tz_minuteswest; 145341486Smckusick tb.dstflag = tz.tz_dsttime; 145444421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 145541486Smckusick } 145641486Smckusick 145743452Shibler ohpuxalarm(p, uap, retval) 145843452Shibler register struct proc *p; 145943452Shibler register struct args { 146043452Shibler int deltat; 146143452Shibler } *uap; 146243452Shibler int *retval; 146341486Smckusick { 146441486Smckusick int s = splhigh(); 146541486Smckusick 146641486Smckusick untimeout(realitexpire, (caddr_t)p); 146741486Smckusick timerclear(&p->p_realtimer.it_interval); 146843452Shibler *retval = 0; 146941486Smckusick if (timerisset(&p->p_realtimer.it_value) && 147041486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 147143452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 147241486Smckusick if (uap->deltat == 0) { 147341486Smckusick timerclear(&p->p_realtimer.it_value); 147441486Smckusick splx(s); 147544421Skarels return (0); 147641486Smckusick } 147741486Smckusick p->p_realtimer.it_value = time; 147841486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 147941486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 148041486Smckusick splx(s); 148144421Skarels return (0); 148241486Smckusick } 148341486Smckusick 148443452Shibler ohpuxnice(p, uap, retval) 148543452Shibler register struct proc *p; 148643452Shibler register struct args { 148743452Shibler int niceness; 148843452Shibler } *uap; 148943452Shibler int *retval; 149041486Smckusick { 149143452Shibler int error; 149241486Smckusick 149343452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 149443452Shibler if (error == 0) 149543452Shibler *retval = p->p_nice - NZERO; 149644421Skarels return (error); 149741486Smckusick } 149841486Smckusick 149943452Shibler ohpuxtimes(p, uap, retval) 150043452Shibler struct proc *p; 150143452Shibler register struct args { 150243452Shibler struct tms *tmsb; 150343452Shibler } *uap; 150443713Smckusick time_t *retval; 150541486Smckusick { 150641486Smckusick struct tms atms; 150743452Shibler int error; 150841486Smckusick 1509*48478Skarels atms.tms_utime = hpuxscale(&p->p_utime); 1510*48478Skarels atms.tms_stime = hpuxscale(&p->p_stime); 1511*48478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 1512*48478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 151343452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 151443452Shibler if (error == 0) 151545753Smckusick *retval = hpuxscale(&time) - hpuxscale(&boottime); 151644421Skarels return (error); 151741486Smckusick } 151841486Smckusick 151945753Smckusick /* 152045753Smckusick * Doesn't exactly do what the documentation says. 152145753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 152245753Smckusick * is what HP-UX returns. 152345753Smckusick */ 152445753Smckusick hpuxscale(tvp) 152541486Smckusick register struct timeval *tvp; 152641486Smckusick { 152745753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 152841486Smckusick } 152941486Smckusick 153041486Smckusick /* 153141486Smckusick * Set IUPD and IACC times on file. 153241486Smckusick * Can't set ICHG. 153341486Smckusick */ 153443452Shibler ohpuxutime(p, uap, retval) 153543452Shibler struct proc *p; 153641486Smckusick register struct a { 153741486Smckusick char *fname; 153841486Smckusick time_t *tptr; 153943452Shibler } *uap; 154043452Shibler int *retval; 154143452Shibler { 1542*48478Skarels register struct vnode *vp; 1543*48478Skarels register struct nameidata *ndp; 154441486Smckusick struct vattr vattr; 154541486Smckusick time_t tv[2]; 154643452Shibler int error; 1547*48478Skarels struct nameidata nd; 154841486Smckusick 1549*48478Skarels ndp = &nd; 155041486Smckusick if (uap->tptr) { 155143452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 155243452Shibler if (error) 155344421Skarels return (error); 155441486Smckusick } else 155541486Smckusick tv[0] = tv[1] = time.tv_sec; 155641486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 155741486Smckusick ndp->ni_segflg = UIO_USERSPACE; 155841486Smckusick ndp->ni_dirp = uap->fname; 155941486Smckusick vattr_null(&vattr); 156041486Smckusick vattr.va_atime.tv_sec = tv[0]; 156141486Smckusick vattr.va_atime.tv_usec = 0; 156241486Smckusick vattr.va_mtime.tv_sec = tv[1]; 156341486Smckusick vattr.va_mtime.tv_usec = 0; 1564*48478Skarels if (error = namei(ndp, p)) 156544421Skarels return (error); 156641486Smckusick vp = ndp->ni_vp; 156742154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 156843452Shibler error = EROFS; 156941486Smckusick else 1570*48478Skarels error = VOP_SETATTR(vp, &vattr, ndp->ni_cred, p); 157141486Smckusick vput(vp); 157244421Skarels return (error); 157341486Smckusick } 157441486Smckusick 157543452Shibler ohpuxpause(p, uap, retval) 157643452Shibler struct proc *p; 157743452Shibler int *uap, *retval; 157841486Smckusick { 157942155Skarels (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); 158042155Skarels /* always return EINTR rather than ERESTART... */ 158144421Skarels return (EINTR); 158241486Smckusick } 158341486Smckusick 158441486Smckusick /* 158541486Smckusick * The old fstat system call. 158641486Smckusick */ 158743452Shibler ohpuxfstat(p, uap, retval) 158843452Shibler struct proc *p; 158943452Shibler register struct args { 159041486Smckusick int fd; 159141486Smckusick struct ohpuxstat *sb; 159243452Shibler } *uap; 159343452Shibler int *retval; 159443452Shibler { 159545923Smckusick register struct filedesc *fdp = p->p_fd; 159641486Smckusick struct file *fp; 159741486Smckusick 1598*48478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 1599*48478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 160044421Skarels return (EBADF); 160143452Shibler if (fp->f_type != DTYPE_VNODE) 160244421Skarels return (EINVAL); 160344421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 160441486Smckusick } 160541486Smckusick 160641486Smckusick /* 160741486Smckusick * Old stat system call. This version follows links. 160841486Smckusick */ 160943452Shibler ohpuxstat(p, uap, retval) 161043452Shibler struct proc *p; 161143452Shibler register struct args { 161241486Smckusick char *fname; 161341486Smckusick struct ohpuxstat *sb; 161443452Shibler } *uap; 161543452Shibler int *retval; 161643452Shibler { 1617*48478Skarels register struct nameidata *ndp; 161843452Shibler int error; 1619*48478Skarels struct nameidata nd; 162041486Smckusick 1621*48478Skarels ndp = &nd; 162241486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 162341486Smckusick ndp->ni_segflg = UIO_USERSPACE; 162441486Smckusick ndp->ni_dirp = uap->fname; 1625*48478Skarels if (error = namei(ndp, p)) 162644421Skarels return (error); 162743452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 162841486Smckusick vput(ndp->ni_vp); 162944421Skarels return (error); 163041486Smckusick } 163141486Smckusick 163241486Smckusick int 163341486Smckusick ohpuxstat1(vp, ub) 163441486Smckusick register struct vnode *vp; 163541486Smckusick struct ohpuxstat *ub; 163641486Smckusick { 163741486Smckusick struct ohpuxstat ds; 163841486Smckusick struct vattr vattr; 163941486Smckusick register int error; 164041486Smckusick 1641*48478Skarels error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 164241486Smckusick if (error) 164341486Smckusick return(error); 164441486Smckusick /* 164541486Smckusick * Copy from inode table 164641486Smckusick */ 164741486Smckusick ds.ohst_dev = vattr.va_fsid; 164841486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 164941486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 165041486Smckusick ds.ohst_nlink = vattr.va_nlink; 165141486Smckusick ds.ohst_uid = (short)vattr.va_uid; 165241486Smckusick ds.ohst_gid = (short)vattr.va_gid; 165341486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 165441486Smckusick ds.ohst_size = (int)vattr.va_size; 165541486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 165641486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 165741486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 165841486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 165941486Smckusick } 166041486Smckusick /* #endif */ 166141486Smckusick 166241486Smckusick #endif 1663