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 * 1249329Shibler * from: Utah $Hdr: hpux_compat.c 1.41 91/04/06$ 1341486Smckusick * 14*49950Smckusick * @(#)hpux_compat.c 7.16 (Berkeley) 05/30/91 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Various HPUX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2349134Skarels #include "param.h" 2449134Skarels #include "systm.h" 2549134Skarels #include "signalvar.h" 2649134Skarels #include "kernel.h" 2749134Skarels #include "filedesc.h" 2849134Skarels #include "proc.h" 2949134Skarels #include "buf.h" 3049134Skarels #include "wait.h" 3149134Skarels #include "file.h" 3249134Skarels #include "namei.h" 3349134Skarels #include "vnode.h" 3449134Skarels #include "ioctl.h" 3549134Skarels #include "ptrace.h" 3649134Skarels #include "stat.h" 3749134Skarels #include "syslog.h" 3849134Skarels #include "malloc.h" 3949134Skarels #include "mount.h" 4049134Skarels #include "ipc.h" 4149134Skarels #include "user.h" 4241486Smckusick 4348478Skarels #include "machine/cpu.h" 4448478Skarels #include "machine/reg.h" 4548478Skarels #include "machine/psl.h" 4648478Skarels #include "machine/vmparam.h" 4741486Smckusick #include "hpux.h" 4841486Smckusick #include "hpux_termio.h" 4941486Smckusick 5041486Smckusick #ifdef DEBUG 5141486Smckusick int unimpresponse = 0; 5241486Smckusick #endif 5341486Smckusick 5441486Smckusick /* SYS5 style UTSNAME info */ 5541486Smckusick struct hpuxutsname protoutsname = { 5641486Smckusick "4.4bsd", "", "2.0", "B", "9000/3?0", "" 5741486Smckusick }; 5841486Smckusick 5941486Smckusick /* 6.0 and later style context */ 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 11948478Skarels hpuxexecv(p, uap, retval) 12048478Skarels struct proc *p; 12148478Skarels struct args { 12248478Skarels char *fname; 12348478Skarels char **argp; 12448478Skarels char **envp; 12548478Skarels } *uap; 12648478Skarels int *retval; 12748478Skarels { 12848478Skarels extern int execve(); 12948478Skarels 13048478Skarels uap->envp = NULL; 13148478Skarels return (execve(p, uap, retval)); 13248478Skarels } 13348478Skarels 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); 15248478Skarels p->p_regs[PS] = PSL_ALLCC; 15348478Skarels p->p_regs[R0] = uap->options; 15448478Skarels 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 */ 25048478Skarels if ((mode & HPUXFEXCL) || (FFLAGS(mode) & FWRITE)) 251*49950Smckusick uap->mode |= O_CREAT; 25241486Smckusick } 25341486Smckusick if (mode & HPUXFTRUNC) 254*49950Smckusick uap->mode |= O_TRUNC; 25541486Smckusick if (mode & HPUXFEXCL) 256*49950Smckusick uap->mode |= O_EXCL; 25744421Skarels return (open(p, uap, retval)); 25841486Smckusick } 25941486Smckusick 26049329Shibler /* XXX */ 26149329Shibler #define UF_FNDELAY_ON 0x20 26249329Shibler #define UF_FIONBIO_ON 0x40 26349329Shibler /* XXX */ 26449329Shibler 26543452Shibler hpuxfcntl(p, uap, retval) 26643452Shibler struct proc *p; 26743452Shibler register struct args { 26841486Smckusick int fdes; 26941486Smckusick int cmd; 27041486Smckusick int arg; 27143452Shibler } *uap; 27243452Shibler int *retval; 27343452Shibler { 27443452Shibler int mode, error; 27549329Shibler char *fp; 27641486Smckusick 27749329Shibler if (uap->cmd == F_GETFL || uap->cmd == F_SETFL) { 27849329Shibler if ((unsigned)uap->fdes >= p->p_fd->fd_nfiles || 27949329Shibler p->p_fd->fd_ofiles[uap->fdes] == NULL) 28049329Shibler return (EBADF); 28149329Shibler fp = &p->p_fd->fd_ofileflags[uap->fdes]; 28249329Shibler } 28341486Smckusick switch (uap->cmd) { 28441486Smckusick case F_SETFL: 285*49950Smckusick if (uap->arg & FNONBLOCK) 28649329Shibler *fp |= UF_FNDELAY_ON; 28749329Shibler else { 28849329Shibler *fp &= ~UF_FNDELAY_ON; 28949329Shibler if (*fp & UF_FIONBIO_ON) 290*49950Smckusick uap->arg |= FNONBLOCK; 29149329Shibler } 29241486Smckusick uap->arg &= ~(HPUXFSYNCIO|HPUXFREMOTE|FUSECACHE); 29341486Smckusick break; 29441486Smckusick case F_GETFL: 29541486Smckusick case F_DUPFD: 29641486Smckusick case F_GETFD: 29741486Smckusick case F_SETFD: 29841486Smckusick break; 29941486Smckusick default: 30044421Skarels return (EINVAL); 30141486Smckusick } 30243452Shibler error = fcntl(p, uap, retval); 30349329Shibler if (error == 0 && uap->cmd == F_GETFL) { 30443452Shibler mode = *retval; 305*49950Smckusick *retval &= ~(O_CREAT|O_TRUNC|O_EXCL|FUSECACHE); 306*49950Smckusick if ((mode & FNONBLOCK) && (*fp & UF_FNDELAY_ON) == 0) 307*49950Smckusick *retval &= ~FNONBLOCK; 308*49950Smckusick if (mode & O_CREAT) 30943452Shibler *retval |= HPUXFCREAT; 310*49950Smckusick if (mode & O_TRUNC) 31143452Shibler *retval |= HPUXFTRUNC; 312*49950Smckusick if (mode & O_EXCL) 31343452Shibler *retval |= HPUXFEXCL; 31441486Smckusick } 31544421Skarels return (error); 31641486Smckusick } 31741486Smckusick 31841486Smckusick /* 31941486Smckusick * Read and write should return a 0 count when an operation 32049329Shibler * on a VNODE would block, not an error. 32149329Shibler * 32249329Shibler * In 6.2 and 6.5 sockets appear to return EWOULDBLOCK. 323*49950Smckusick * In 7.0 the behavior for sockets depends on whether FNONBLOCK is in effect. 32441486Smckusick */ 32543452Shibler hpuxread(p, uap, retval) 32643452Shibler struct proc *p; 32743452Shibler struct args { 32843452Shibler int fd; 32943452Shibler } *uap; 33043452Shibler int *retval; 33141486Smckusick { 33243452Shibler int error; 33341486Smckusick 33443452Shibler error = read(p, uap, retval); 33543452Shibler if (error == EWOULDBLOCK && 33649329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 33749329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 33843452Shibler error = 0; 33943452Shibler *retval = 0; 34041486Smckusick } 34144421Skarels return (error); 34241486Smckusick } 34341486Smckusick 34443452Shibler hpuxwrite(p, uap, retval) 34543452Shibler struct proc *p; 34643452Shibler struct args { 34743452Shibler int fd; 34843452Shibler } *uap; 34943452Shibler int *retval; 35041486Smckusick { 35143452Shibler int error; 35241486Smckusick 35343452Shibler error = write(p, uap, retval); 35443452Shibler if (error == EWOULDBLOCK && 35549329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 35649329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 35743452Shibler error = 0; 35843452Shibler *retval = 0; 35941486Smckusick } 36044421Skarels return (error); 36141486Smckusick } 36241486Smckusick 36343452Shibler hpuxreadv(p, uap, retval) 36443452Shibler struct proc *p; 36543452Shibler struct args { 36643452Shibler int fd; 36743452Shibler } *uap; 36843452Shibler int *retval; 36941486Smckusick { 37043452Shibler int error; 37141486Smckusick 37243452Shibler error = readv(p, uap, retval); 37343452Shibler if (error == EWOULDBLOCK && 37449329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 37549329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 37643452Shibler error = 0; 37743452Shibler *retval = 0; 37841486Smckusick } 37944421Skarels return (error); 38041486Smckusick } 38141486Smckusick 38243452Shibler hpuxwritev(p, uap, retval) 38343452Shibler struct proc *p; 38443452Shibler struct args { 38543452Shibler int fd; 38643452Shibler } *uap; 38743452Shibler int *retval; 38841486Smckusick { 38943452Shibler int error; 39041486Smckusick 39143452Shibler error = writev(p, uap, retval); 39243452Shibler if (error == EWOULDBLOCK && 39349329Shibler (p->p_fd->fd_ofiles[uap->fd]->f_type == DTYPE_VNODE || 39449329Shibler p->p_fd->fd_ofileflags[uap->fd] & UF_FNDELAY_ON)) { 39543452Shibler error = 0; 39643452Shibler *retval = 0; 39741486Smckusick } 39844421Skarels return (error); 39941486Smckusick } 40041486Smckusick 40141486Smckusick /* 40241486Smckusick * 4.3bsd dup allows dup2 to come in on the same syscall entry 40341486Smckusick * and hence allows two arguments. HPUX dup has only one arg. 40441486Smckusick */ 40543452Shibler hpuxdup(p, uap, retval) 40643452Shibler struct proc *p; 40743452Shibler register struct args { 40843452Shibler int i; 40943452Shibler } *uap; 41043452Shibler int *retval; 41141486Smckusick { 41245923Smckusick register struct filedesc *fdp = p->p_fd; 41341486Smckusick struct file *fp; 41443452Shibler int fd, error; 41541486Smckusick 41648478Skarels if (((unsigned)uap->i) >= fdp->fd_nfiles || 41748478Skarels (fp = fdp->fd_ofiles[uap->i]) == NULL) 41844421Skarels return (EBADF); 41948478Skarels if (error = fdalloc(p, 0, &fd)) 42044421Skarels return (error); 42148478Skarels fdp->fd_ofiles[fd] = fp; 42248478Skarels fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; 42345923Smckusick fp->f_count++; 42445923Smckusick if (fd > fdp->fd_lastfile) 42545923Smckusick fdp->fd_lastfile = fd; 42643452Shibler *retval = fd; 42744421Skarels return (0); 42841486Smckusick } 42941486Smckusick 43045753Smckusick hpuxutssys(p, uap, retval) 43143452Shibler struct proc *p; 43243452Shibler register struct args { 43341486Smckusick struct hpuxutsname *uts; 43441486Smckusick int dev; 43541486Smckusick int request; 43643452Shibler } *uap; 43743452Shibler int *retval; 43843452Shibler { 43941486Smckusick register int i; 44043452Shibler int error; 44141486Smckusick 44241486Smckusick switch (uap->request) { 44341486Smckusick /* uname */ 44441486Smckusick case 0: 44541486Smckusick /* fill in machine type */ 44641486Smckusick switch (machineid) { 44741486Smckusick case HP_320: 44841486Smckusick protoutsname.machine[6] = '2'; 44941486Smckusick break; 45041486Smckusick /* includes 318 and 319 */ 45141486Smckusick case HP_330: 45241486Smckusick protoutsname.machine[6] = '3'; 45341486Smckusick break; 45441486Smckusick case HP_340: 45541486Smckusick protoutsname.machine[6] = '4'; 45641486Smckusick break; 45741486Smckusick case HP_350: 45841486Smckusick protoutsname.machine[6] = '5'; 45941486Smckusick break; 46041486Smckusick case HP_360: 46141486Smckusick protoutsname.machine[6] = '6'; 46241486Smckusick break; 46341486Smckusick case HP_370: 46441486Smckusick protoutsname.machine[6] = '7'; 46541486Smckusick break; 46643452Shibler /* includes 345 */ 46743452Shibler case HP_375: 46843452Shibler protoutsname.machine[6] = '7'; 46943452Shibler protoutsname.machine[7] = '5'; 47043452Shibler break; 47141486Smckusick } 47241486Smckusick /* copy hostname (sans domain) to nodename */ 47349329Shibler for (i = 0; i < 8 && hostname[i] != '.'; i++) 47441486Smckusick protoutsname.nodename[i] = hostname[i]; 47549329Shibler protoutsname.nodename[i] = '\0'; 47643452Shibler error = copyout((caddr_t)&protoutsname, (caddr_t)uap->uts, 47743452Shibler sizeof(struct hpuxutsname)); 47841486Smckusick break; 47945753Smckusick 48045753Smckusick /* gethostname */ 48145753Smckusick case 5: 48245753Smckusick /* uap->dev is length */ 48345753Smckusick if (uap->dev > hostnamelen + 1) 48445753Smckusick uap->dev = hostnamelen + 1; 48545753Smckusick error = copyout((caddr_t)hostname, (caddr_t)uap->uts, 48645753Smckusick uap->dev); 48745753Smckusick break; 48845753Smckusick 48945753Smckusick case 1: /* ?? */ 49045753Smckusick case 2: /* ustat */ 49145753Smckusick case 3: /* ?? */ 49245753Smckusick case 4: /* sethostname */ 49341486Smckusick default: 49443452Shibler error = EINVAL; 49541486Smckusick break; 49641486Smckusick } 49744421Skarels return (error); 49841486Smckusick } 49941486Smckusick 50043452Shibler hpuxstat(p, uap, retval) 50143452Shibler struct proc *p; 50243452Shibler struct args { 50341486Smckusick char *fname; 50441486Smckusick struct hpuxstat *hsb; 50543452Shibler } *uap; 50643452Shibler int *retval; 50743452Shibler { 50844421Skarels return (hpuxstat1(uap->fname, uap->hsb, FOLLOW)); 50941486Smckusick } 51041486Smckusick 51143452Shibler hpuxlstat(p, uap, retval) 51243452Shibler struct proc *p; 51343452Shibler struct args { 51443452Shibler char *fname; 51543452Shibler struct hpuxstat *hsb; 51643452Shibler } *uap; 51743452Shibler int *retval; 51841486Smckusick { 51944421Skarels return (hpuxstat1(uap->fname, uap->hsb, NOFOLLOW)); 52041486Smckusick } 52141486Smckusick 52243452Shibler hpuxfstat(p, uap, retval) 52343452Shibler struct proc *p; 52443452Shibler register struct args { 52543452Shibler int fdes; 52643452Shibler struct hpuxstat *hsb; 52743452Shibler } *uap; 52843452Shibler int *retval; 52941486Smckusick { 53045923Smckusick register struct filedesc *fdp = p->p_fd; 53141486Smckusick register struct file *fp; 53241486Smckusick struct stat sb; 53343452Shibler int error; 53441486Smckusick 53548478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 53648478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 53744421Skarels return (EBADF); 53843452Shibler 53941486Smckusick switch (fp->f_type) { 54041486Smckusick 54141486Smckusick case DTYPE_VNODE: 54243452Shibler error = vn_stat((struct vnode *)fp->f_data, &sb); 54341486Smckusick break; 54441486Smckusick 54541486Smckusick case DTYPE_SOCKET: 54643452Shibler error = soo_stat((struct socket *)fp->f_data, &sb); 54741486Smckusick break; 54841486Smckusick 54941486Smckusick default: 55041486Smckusick panic("fstat"); 55141486Smckusick /*NOTREACHED*/ 55241486Smckusick } 55341486Smckusick /* is this right for sockets?? */ 55443452Shibler if (error == 0) 55543452Shibler error = bsdtohpuxstat(&sb, uap->hsb); 55644421Skarels return (error); 55741486Smckusick } 55841486Smckusick 55943452Shibler hpuxulimit(p, uap, retval) 56043452Shibler struct proc *p; 56143452Shibler register struct args { 56241486Smckusick int cmd; 56341486Smckusick long newlimit; 56443452Shibler } *uap; 56543713Smckusick off_t *retval; 56643452Shibler { 56741486Smckusick struct rlimit *limp; 56843452Shibler int error = 0; 56941486Smckusick 57048478Skarels limp = &p->p_rlimit[RLIMIT_FSIZE]; 57141486Smckusick switch (uap->cmd) { 57241486Smckusick case 2: 57341486Smckusick uap->newlimit *= 512; 57441486Smckusick if (uap->newlimit > limp->rlim_max && 57548478Skarels (error = suser(p->p_ucred, &p->p_acflag))) 57641486Smckusick break; 57741486Smckusick limp->rlim_cur = limp->rlim_max = uap->newlimit; 57841486Smckusick /* else fall into... */ 57941486Smckusick 58041486Smckusick case 1: 58145753Smckusick *retval = limp->rlim_max / 512; 58241486Smckusick break; 58341486Smckusick 58441486Smckusick case 3: 58548478Skarels limp = &p->p_rlimit[RLIMIT_DATA]; 58648478Skarels *retval = ctob(p->p_vmspace->vm_tsize) + limp->rlim_max; 58741486Smckusick break; 58841486Smckusick 58941486Smckusick default: 59043452Shibler error = EINVAL; 59141486Smckusick break; 59241486Smckusick } 59344421Skarels return (error); 59441486Smckusick } 59541486Smckusick 59641486Smckusick /* 59741486Smckusick * Map "real time" priorities 0 (high) thru 127 (low) into nice 59841486Smckusick * values -16 (high) thru -1 (low). 59941486Smckusick */ 60043452Shibler hpuxrtprio(cp, uap, retval) 60143452Shibler struct proc *cp; 60243452Shibler register struct args { 60341486Smckusick int pid; 60441486Smckusick int prio; 60543452Shibler } *uap; 60643452Shibler int *retval; 60743452Shibler { 60841486Smckusick struct proc *p; 60943452Shibler int nice, error; 61041486Smckusick 61141486Smckusick if (uap->prio < RTPRIO_MIN && uap->prio > RTPRIO_MAX && 61243452Shibler uap->prio != RTPRIO_NOCHG && uap->prio != RTPRIO_RTOFF) 61344421Skarels return (EINVAL); 61441486Smckusick if (uap->pid == 0) 61543452Shibler p = cp; 61643452Shibler else if ((p = pfind(uap->pid)) == 0) 61744421Skarels return (ESRCH); 61841486Smckusick nice = p->p_nice; 61941486Smckusick if (nice < NZERO) 62043452Shibler *retval = (nice + 16) << 3; 62141486Smckusick else 62243452Shibler *retval = RTPRIO_RTOFF; 62341486Smckusick switch (uap->prio) { 62441486Smckusick 62541486Smckusick case RTPRIO_NOCHG: 62644421Skarels return (0); 62741486Smckusick 62841486Smckusick case RTPRIO_RTOFF: 62941486Smckusick if (nice >= NZERO) 63044421Skarels return (0); 63141486Smckusick nice = NZERO; 63241486Smckusick break; 63341486Smckusick 63441486Smckusick default: 63541486Smckusick nice = (uap->prio >> 3) - 16; 63641486Smckusick break; 63741486Smckusick } 63843452Shibler error = donice(cp, p, nice); 63943452Shibler if (error == EACCES) 64043452Shibler error = EPERM; 64144421Skarels return (error); 64241486Smckusick } 64341486Smckusick 64443452Shibler hpuxadvise(p, uap, retval) 64543452Shibler struct proc *p; 64643452Shibler struct args { 64743452Shibler int arg; 64843452Shibler } *uap; 64943452Shibler int *retval; 65041486Smckusick { 65143452Shibler int error = 0; 65241486Smckusick 65341486Smckusick switch (uap->arg) { 65441486Smckusick case 0: 65549134Skarels p->p_addr->u_pcb.pcb_flags |= PCB_HPUXMMAP; 65641486Smckusick break; 65741486Smckusick case 1: 65841486Smckusick ICIA(); 65941486Smckusick break; 66041486Smckusick case 2: 66141486Smckusick DCIA(); 66241486Smckusick break; 66341486Smckusick default: 66443452Shibler error = EINVAL; 66541486Smckusick break; 66641486Smckusick } 66744421Skarels return (error); 66841486Smckusick } 66941486Smckusick 67043452Shibler hpuxptrace(p, uap, retval) 67143452Shibler struct proc *p; 67243452Shibler struct args { 67341486Smckusick int req; 67441486Smckusick int pid; 67541486Smckusick int *addr; 67641486Smckusick int data; 67743452Shibler } *uap; 67843452Shibler int *retval; 67943452Shibler { 68043452Shibler int error; 68141486Smckusick 68241486Smckusick if (uap->req == PT_STEP || uap->req == PT_CONTINUE) { 68341486Smckusick if (uap->data) { 68441486Smckusick uap->data = hpuxtobsdsig(uap->data); 68541486Smckusick if (uap->data == 0) 68641486Smckusick uap->data = NSIG; 68741486Smckusick } 68841486Smckusick } 68943452Shibler error = ptrace(p, uap, retval); 69044421Skarels return (error); 69141486Smckusick } 69241486Smckusick 69343452Shibler hpuxgetdomainname(p, uap, retval) 69443452Shibler struct proc *p; 69543452Shibler register struct args { 69641486Smckusick char *domainname; 69741486Smckusick u_int len; 69843452Shibler } *uap; 69943452Shibler int *retval; 70043452Shibler { 70141486Smckusick if (uap->len > domainnamelen + 1) 70241486Smckusick uap->len = domainnamelen + 1; 70344421Skarels return (copyout(domainname, uap->domainname, uap->len)); 70441486Smckusick } 70541486Smckusick 70643452Shibler hpuxsetdomainname(p, uap, retval) 70743452Shibler struct proc *p; 70843452Shibler register struct args { 70941486Smckusick char *domainname; 71041486Smckusick u_int len; 71143452Shibler } *uap; 71243452Shibler int *retval; 71343452Shibler { 71443452Shibler int error; 71541486Smckusick 71648478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 71744421Skarels return (error); 71843452Shibler if (uap->len > sizeof (domainname) - 1) 71944421Skarels return (EINVAL); 72041486Smckusick domainnamelen = uap->len; 72143452Shibler error = copyin(uap->domainname, domainname, uap->len); 72241486Smckusick domainname[domainnamelen] = 0; 72344421Skarels return (error); 72441486Smckusick } 72541486Smckusick 72641486Smckusick #ifdef SYSVSHM 72743452Shibler hpuxshmat(p, uap, retval) 72843452Shibler struct proc *p; 72943452Shibler int *uap, *retval; 73041486Smckusick { 73144421Skarels return (shmat(p, uap, retval)); 73241486Smckusick } 73341486Smckusick 73443452Shibler hpuxshmctl(p, uap, retval) 73543452Shibler struct proc *p; 73643452Shibler int *uap, *retval; 73741486Smckusick { 73844421Skarels return (shmctl(p, uap, retval)); 73941486Smckusick } 74041486Smckusick 74143452Shibler hpuxshmdt(p, uap, retval) 74243452Shibler struct proc *p; 74343452Shibler int *uap, *retval; 74441486Smckusick { 74544421Skarels return (shmdt(p, uap, retval)); 74641486Smckusick } 74741486Smckusick 74843452Shibler hpuxshmget(p, uap, retval) 74943452Shibler struct proc *p; 75043452Shibler int *uap, *retval; 75141486Smckusick { 75244421Skarels return (shmget(p, uap, retval)); 75341486Smckusick } 75441486Smckusick #endif 75541486Smckusick 75641486Smckusick /* 75741486Smckusick * Fake semaphore routines, just don't return an error. 75841486Smckusick * Should be adequate for starbase to run. 75941486Smckusick */ 76043452Shibler hpuxsemctl(p, uap, retval) 76143452Shibler struct proc *p; 76243452Shibler struct args { 76341486Smckusick int semid; 76441486Smckusick u_int semnum; 76541486Smckusick int cmd; 76641486Smckusick int arg; 76743452Shibler } *uap; 76843452Shibler int *retval; 76943452Shibler { 77041486Smckusick /* XXX: should do something here */ 77144421Skarels return (0); 77241486Smckusick } 77341486Smckusick 77443452Shibler hpuxsemget(p, uap, retval) 77543452Shibler struct proc *p; 77643452Shibler struct args { 77741486Smckusick key_t key; 77841486Smckusick int nsems; 77941486Smckusick int semflg; 78043452Shibler } *uap; 78143452Shibler int *retval; 78243452Shibler { 78341486Smckusick /* XXX: should do something here */ 78444421Skarels return (0); 78541486Smckusick } 78641486Smckusick 78743452Shibler hpuxsemop(p, uap, retval) 78843452Shibler struct proc *p; 78943452Shibler struct args { 79041486Smckusick int semid; 79141486Smckusick struct sembuf *sops; 79241486Smckusick u_int nsops; 79343452Shibler } *uap; 79443452Shibler int *retval; 79543452Shibler { 79641486Smckusick /* XXX: should do something here */ 79744421Skarels return (0); 79841486Smckusick } 79941486Smckusick 80041486Smckusick /* convert from BSD to HPUX errno */ 80141486Smckusick bsdtohpuxerrno(err) 80241486Smckusick int err; 80341486Smckusick { 80441486Smckusick if (err < 0 || err >= NERR) 80541486Smckusick return(BERR); 80641486Smckusick return((int)bsdtohpuxerrnomap[err]); 80741486Smckusick } 80841486Smckusick 80941486Smckusick hpuxstat1(fname, hsb, follow) 81041486Smckusick char *fname; 81141486Smckusick struct hpuxstat *hsb; 81241486Smckusick int follow; 81341486Smckusick { 81448478Skarels register struct nameidata *ndp; 81548478Skarels int error; 81641486Smckusick struct stat sb; 81748478Skarels struct nameidata nd; 81841486Smckusick 81948478Skarels ndp = &nd; 82041486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | follow; 82141486Smckusick ndp->ni_segflg = UIO_USERSPACE; 82241486Smckusick ndp->ni_dirp = fname; 82348478Skarels if (error = namei(ndp, curproc)) 82441486Smckusick return (error); 82541486Smckusick error = vn_stat(ndp->ni_vp, &sb); 82641486Smckusick vput(ndp->ni_vp); 82741486Smckusick if (error == 0) 82841486Smckusick error = bsdtohpuxstat(&sb, hsb); 82941486Smckusick return (error); 83041486Smckusick } 83141486Smckusick 83241486Smckusick #include "grf.h" 83341486Smckusick 83441486Smckusick bsdtohpuxstat(sb, hsb) 83541486Smckusick struct stat *sb; 83641486Smckusick struct hpuxstat *hsb; 83741486Smckusick { 83841486Smckusick struct hpuxstat ds; 83941486Smckusick 84041486Smckusick bzero((caddr_t)&ds, sizeof(ds)); 84141486Smckusick ds.hst_dev = sb->st_dev; 84241486Smckusick ds.hst_ino = (u_long)sb->st_ino; 84341486Smckusick ds.hst_mode = sb->st_mode; 84441486Smckusick ds.hst_nlink = sb->st_nlink; 84541486Smckusick ds.hst_uid = (u_short)sb->st_uid; 84641486Smckusick ds.hst_gid = (u_short)sb->st_gid; 84741486Smckusick #if NGRF > 0 84841486Smckusick /* XXX: I don't want to talk about it... */ 84941486Smckusick if ((sb->st_mode & S_IFMT) == S_IFCHR && major(sb->st_rdev) == 10) 85041486Smckusick ds.hst_rdev = grfdevno(sb->st_rdev); 85141486Smckusick else 85241486Smckusick #endif 85341486Smckusick ds.hst_rdev = bsdtohpuxdev(sb->st_rdev); 85441486Smckusick ds.hst_size = sb->st_size; 85541486Smckusick ds.hst_atime = sb->st_atime; 85641486Smckusick ds.hst_mtime = sb->st_mtime; 85741486Smckusick ds.hst_ctime = sb->st_ctime; 85841486Smckusick ds.hst_blksize = sb->st_blksize; 85941486Smckusick ds.hst_blocks = sb->st_blocks; 86041486Smckusick return(copyout((caddr_t)&ds, (caddr_t)hsb, sizeof(ds))); 86141486Smckusick } 86241486Smckusick 86341486Smckusick hpuxtobsdioctl(com) 86441486Smckusick int com; 86541486Smckusick { 86641486Smckusick switch (com) { 86741486Smckusick case HPUXTIOCSLTC: 86841486Smckusick com = TIOCSLTC; break; 86941486Smckusick case HPUXTIOCGLTC: 87041486Smckusick com = TIOCGLTC; break; 87141486Smckusick case HPUXTIOCSPGRP: 87241486Smckusick com = TIOCSPGRP; break; 87341486Smckusick case HPUXTIOCGPGRP: 87441486Smckusick com = TIOCGPGRP; break; 87541486Smckusick case HPUXTIOCLBIS: 87641486Smckusick com = TIOCLBIS; break; 87741486Smckusick case HPUXTIOCLBIC: 87841486Smckusick com = TIOCLBIC; break; 87941486Smckusick case HPUXTIOCLSET: 88041486Smckusick com = TIOCLSET; break; 88141486Smckusick case HPUXTIOCLGET: 88241486Smckusick com = TIOCLGET; break; 88341486Smckusick } 88441486Smckusick return(com); 88541486Smckusick } 88641486Smckusick 88741486Smckusick /* 88841486Smckusick * HPUX ioctl system call. The differences here are: 88941486Smckusick * IOC_IN also means IOC_VOID if the size portion is zero. 89049329Shibler * no FIOCLEX/FIONCLEX/FIOASYNC/FIOGETOWN/FIOSETOWN 89141486Smckusick * the sgttyb struct is 2 bytes longer 89241486Smckusick */ 89343452Shibler hpuxioctl(p, uap, retval) 89443452Shibler struct proc *p; 89543452Shibler register struct args { 89641486Smckusick int fdes; 89741486Smckusick int cmd; 89841486Smckusick caddr_t cmarg; 89943452Shibler } *uap; 90043452Shibler int *retval; 90143452Shibler { 90245923Smckusick register struct filedesc *fdp = p->p_fd; 90343452Shibler register struct file *fp; 90443452Shibler register int com, error; 90541486Smckusick register u_int size; 90641486Smckusick caddr_t memp = 0; 90741486Smckusick #define STK_PARAMS 128 90841486Smckusick char stkbuf[STK_PARAMS]; 90941486Smckusick caddr_t data = stkbuf; 91041486Smckusick 91141486Smckusick com = uap->cmd; 91241486Smckusick 91341486Smckusick /* XXX */ 91443452Shibler if (com == HPUXTIOCGETP || com == HPUXTIOCSETP) 91545923Smckusick return (getsettty(p, uap->fdes, com, uap->cmarg)); 91641486Smckusick 91748478Skarels if (((unsigned)uap->fdes) >= fdp->fd_nfiles || 91848478Skarels (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 91944421Skarels return (EBADF); 92043452Shibler if ((fp->f_flag & (FREAD|FWRITE)) == 0) 92144421Skarels return (EBADF); 92241486Smckusick 92341486Smckusick /* 92441486Smckusick * Interpret high order word to find 92541486Smckusick * amount of data to be copied to/from the 92641486Smckusick * user's address space. 92741486Smckusick */ 92841486Smckusick size = IOCPARM_LEN(com); 92943452Shibler if (size > IOCPARM_MAX) 93044421Skarels return (ENOTTY); 93141486Smckusick if (size > sizeof (stkbuf)) { 93243452Shibler memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 93341486Smckusick data = memp; 93441486Smckusick } 93541486Smckusick if (com&IOC_IN) { 93641486Smckusick if (size) { 93743452Shibler error = copyin(uap->cmarg, data, (u_int)size); 93843452Shibler if (error) { 93941486Smckusick if (memp) 94041486Smckusick free(memp, M_IOCTLOPS); 94144421Skarels return (error); 94241486Smckusick } 94341486Smckusick } else 94441486Smckusick *(caddr_t *)data = uap->cmarg; 94541486Smckusick } else if ((com&IOC_OUT) && size) 94641486Smckusick /* 94743452Shibler * Zero the buffer so the user always 94843452Shibler * gets back something deterministic. 94941486Smckusick */ 95041486Smckusick bzero(data, size); 95141486Smckusick else if (com&IOC_VOID) 95241486Smckusick *(caddr_t *)data = uap->cmarg; 95341486Smckusick 95441486Smckusick switch (com) { 95541486Smckusick 95649329Shibler case HPUXFIOSNBIO: 95749329Shibler { 95849329Shibler char *ofp = &fdp->fd_ofileflags[uap->fdes]; 95949329Shibler int tmp; 96049329Shibler 96149329Shibler if (*(int *)data) 96249329Shibler *ofp |= UF_FIONBIO_ON; 96349329Shibler else 96449329Shibler *ofp &= ~UF_FIONBIO_ON; 96549329Shibler /* 966*49950Smckusick * Only set/clear if FNONBLOCK not in effect 96749329Shibler */ 96849329Shibler if ((*ofp & UF_FNDELAY_ON) == 0) { 969*49950Smckusick tmp = fp->f_flag & FNONBLOCK; 97049329Shibler error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, 97149329Shibler (caddr_t)&tmp, p); 97249329Shibler } 97349329Shibler break; 97449329Shibler } 97549329Shibler 97641486Smckusick case HPUXTIOCCONS: 97741486Smckusick *(int *)data = 1; 97848478Skarels error = (*fp->f_ops->fo_ioctl)(fp, TIOCCONS, data, p); 97941486Smckusick break; 98041486Smckusick 98141486Smckusick /* BSD-style job control ioctls */ 98241486Smckusick case HPUXTIOCLBIS: 98341486Smckusick case HPUXTIOCLBIC: 98441486Smckusick case HPUXTIOCLSET: 98541486Smckusick *(int *)data &= HPUXLTOSTOP; 98641486Smckusick if (*(int *)data & HPUXLTOSTOP) 98741486Smckusick *(int *)data = LTOSTOP; 98841486Smckusick /* fall into */ 98941486Smckusick case HPUXTIOCLGET: 99041486Smckusick case HPUXTIOCSLTC: 99141486Smckusick case HPUXTIOCGLTC: 99241486Smckusick case HPUXTIOCSPGRP: 99341486Smckusick case HPUXTIOCGPGRP: 99448478Skarels error = (*fp->f_ops->fo_ioctl) 99548478Skarels (fp, hpuxtobsdioctl(com), data, p); 99643452Shibler if (error == 0 && com == HPUXTIOCLGET) { 99741486Smckusick *(int *)data &= LTOSTOP; 99841486Smckusick if (*(int *)data & LTOSTOP) 99941486Smckusick *(int *)data = HPUXLTOSTOP; 100041486Smckusick } 100141486Smckusick break; 100241486Smckusick 100341486Smckusick /* SYS 5 termio */ 100441486Smckusick case HPUXTCGETA: 100541486Smckusick case HPUXTCSETA: 100641486Smckusick case HPUXTCSETAW: 100741486Smckusick case HPUXTCSETAF: 100848478Skarels error = hpuxtermio(fp, com, data, p); 100941486Smckusick break; 101041486Smckusick 101141486Smckusick default: 101248478Skarels error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 101341486Smckusick break; 101441486Smckusick } 101541486Smckusick /* 101641486Smckusick * Copy any data to user, size was 101741486Smckusick * already set and checked above. 101841486Smckusick */ 101943452Shibler if (error == 0 && (com&IOC_OUT) && size) 102043452Shibler error = copyout(data, uap->cmarg, (u_int)size); 102141486Smckusick if (memp) 102241486Smckusick free(memp, M_IOCTLOPS); 102344421Skarels return (error); 102441486Smckusick } 102541486Smckusick 102641486Smckusick /* 102741486Smckusick * Man page lies, behaviour here is based on observed behaviour. 102841486Smckusick */ 102943452Shibler hpuxgetcontext(p, uap, retval) 103043452Shibler struct proc *p; 103143452Shibler struct args { 103241486Smckusick char *buf; 103341486Smckusick int len; 103443452Shibler } *uap; 103543452Shibler int *retval; 103643452Shibler { 103741486Smckusick int error = 0; 103841486Smckusick register int len; 103941486Smckusick 104041486Smckusick len = MIN(uap->len, sizeof(hpuxcontext)); 104141486Smckusick if (len) 104241486Smckusick error = copyout(hpuxcontext, uap->buf, (u_int)len); 104343452Shibler if (error == 0) 104443452Shibler *retval = sizeof(hpuxcontext); 104544421Skarels return (error); 104641486Smckusick } 104741486Smckusick 104841486Smckusick /* 104941486Smckusick * This is the equivalent of BSD getpgrp but with more restrictions. 105041486Smckusick * Note we do not check the real uid or "saved" uid. 105141486Smckusick */ 105243452Shibler hpuxgetpgrp2(cp, uap, retval) 105343452Shibler struct proc *cp; 105443452Shibler register struct args { 105543452Shibler int pid; 105643452Shibler } *uap; 105743452Shibler int *retval; 105841486Smckusick { 105941486Smckusick register struct proc *p; 106041486Smckusick 106141486Smckusick if (uap->pid == 0) 106243452Shibler uap->pid = cp->p_pid; 106341486Smckusick p = pfind(uap->pid); 106443452Shibler if (p == 0) 106544421Skarels return (ESRCH); 106648478Skarels if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && 106748478Skarels !inferior(p)) 106844421Skarels return (EPERM); 106943452Shibler *retval = p->p_pgid; 107044421Skarels return (0); 107141486Smckusick } 107241486Smckusick 107341486Smckusick /* 107441486Smckusick * This is the equivalent of BSD setpgrp but with more restrictions. 107541486Smckusick * Note we do not check the real uid or "saved" uid or pgrp. 107641486Smckusick */ 107743452Shibler hpuxsetpgrp2(p, uap, retval) 107843452Shibler struct proc *p; 107943452Shibler struct args { 108041486Smckusick int pid; 108141486Smckusick int pgrp; 108243452Shibler } *uap; 108343452Shibler int *retval; 108443452Shibler { 108541486Smckusick /* empirically determined */ 108643452Shibler if (uap->pgrp < 0 || uap->pgrp >= 30000) 108744421Skarels return (EINVAL); 108848478Skarels return (setpgid(p, uap, retval)); 108941486Smckusick } 109041486Smckusick 109141486Smckusick /* 109245753Smckusick * XXX Same as BSD setre[ug]id right now. Need to consider saved ids. 109345753Smckusick */ 109445753Smckusick hpuxsetresuid(p, uap, retval) 109545753Smckusick struct proc *p; 109645753Smckusick struct args { 109745753Smckusick int ruid; 109845753Smckusick int euid; 109945753Smckusick int suid; 110045753Smckusick } *uap; 110145753Smckusick int *retval; 110245753Smckusick { 110345753Smckusick return (osetreuid(p, uap, retval)); 110445753Smckusick } 110545753Smckusick 110645753Smckusick hpuxsetresgid(p, uap, retval) 110745753Smckusick struct proc *p; 110845753Smckusick struct args { 110945753Smckusick int rgid; 111045753Smckusick int egid; 111145753Smckusick int sgid; 111245753Smckusick } *uap; 111345753Smckusick int *retval; 111445753Smckusick { 111545753Smckusick return (osetregid(p, uap, retval)); 111645753Smckusick } 111745753Smckusick 111845753Smckusick /* 111945753Smckusick * XXX: simple recognition hack to see if we can make grmd work. 112045753Smckusick */ 112145753Smckusick hpuxlockf(p, uap, retval) 112245753Smckusick struct proc *p; 112345753Smckusick struct args { 112445753Smckusick int fd; 112545753Smckusick int func; 112645753Smckusick long size; 112745753Smckusick } *uap; 112845753Smckusick int *retval; 112945753Smckusick { 113045753Smckusick #ifdef DEBUG 113145753Smckusick log(LOG_DEBUG, "%d: lockf(%d, %d, %d)\n", 113245753Smckusick p->p_pid, uap->fd, uap->func, uap->size); 113345753Smckusick #endif 113445753Smckusick return (0); 113545753Smckusick } 113645753Smckusick 113745753Smckusick hpuxgetaccess(p, uap, retval) 113845753Smckusick register struct proc *p; 113945753Smckusick register struct args { 114045753Smckusick char *path; 114145753Smckusick int uid; 114245753Smckusick int ngroups; 114345753Smckusick int *gidset; 114445753Smckusick void *label; 114545753Smckusick void *privs; 114645753Smckusick } *uap; 114745753Smckusick int *retval; 114845753Smckusick { 114948478Skarels struct nameidata *ndp; 115045753Smckusick int lgroups[NGROUPS]; 115145753Smckusick int error = 0; 115245753Smckusick register struct ucred *cred; 115345753Smckusick register struct vnode *vp; 115445753Smckusick 115545753Smckusick /* 115645753Smckusick * Build an appropriate credential structure 115745753Smckusick */ 115848478Skarels cred = crdup(p->p_ucred); 115945753Smckusick switch (uap->uid) { 116045753Smckusick case 65502: /* UID_EUID */ 116145753Smckusick break; 116245753Smckusick case 65503: /* UID_RUID */ 116348478Skarels cred->cr_uid = p->p_cred->p_ruid; 116445753Smckusick break; 116545753Smckusick case 65504: /* UID_SUID */ 116645753Smckusick error = EINVAL; 116745753Smckusick break; 116845753Smckusick default: 116945753Smckusick if (uap->uid > 65504) 117045753Smckusick error = EINVAL; 117145753Smckusick cred->cr_uid = uap->uid; 117245753Smckusick break; 117345753Smckusick } 117445753Smckusick switch (uap->ngroups) { 117545753Smckusick case -1: /* NGROUPS_EGID */ 117645753Smckusick cred->cr_ngroups = 1; 117745753Smckusick break; 117845753Smckusick case -5: /* NGROUPS_EGID_SUPP */ 117945753Smckusick break; 118045753Smckusick case -2: /* NGROUPS_RGID */ 118145753Smckusick cred->cr_ngroups = 1; 118248478Skarels cred->cr_gid = p->p_cred->p_rgid; 118345753Smckusick break; 118445753Smckusick case -6: /* NGROUPS_RGID_SUPP */ 118548478Skarels cred->cr_gid = p->p_cred->p_rgid; 118645753Smckusick break; 118745753Smckusick case -3: /* NGROUPS_SGID */ 118845753Smckusick case -7: /* NGROUPS_SGID_SUPP */ 118945753Smckusick error = EINVAL; 119045753Smckusick break; 119145753Smckusick case -4: /* NGROUPS_SUPP */ 119245753Smckusick if (cred->cr_ngroups > 1) 119345753Smckusick cred->cr_gid = cred->cr_groups[1]; 119445753Smckusick else 119545753Smckusick error = EINVAL; 119645753Smckusick break; 119745753Smckusick default: 119845753Smckusick if (uap->ngroups > 0 && uap->ngroups <= NGROUPS) 119945753Smckusick error = copyin((caddr_t)uap->gidset, 120045753Smckusick (caddr_t)&lgroups[0], 120145753Smckusick uap->ngroups * sizeof(lgroups[0])); 120245753Smckusick else 120345753Smckusick error = EINVAL; 120445753Smckusick if (error == 0) { 120545753Smckusick int gid; 120645753Smckusick 120745753Smckusick for (gid = 0; gid < uap->ngroups; gid++) 120845753Smckusick cred->cr_groups[gid] = lgroups[gid]; 120945753Smckusick cred->cr_ngroups = uap->ngroups; 121045753Smckusick } 121145753Smckusick break; 121245753Smckusick } 121345753Smckusick /* 121445753Smckusick * Lookup file using caller's effective IDs. 121545753Smckusick */ 121645753Smckusick if (error == 0) { 121745753Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 121845753Smckusick ndp->ni_segflg = UIO_USERSPACE; 121945753Smckusick ndp->ni_dirp = uap->path; 122048478Skarels error = namei(ndp, p); 122145753Smckusick } 122245753Smckusick if (error) { 122345753Smckusick crfree(cred); 122445753Smckusick return (error); 122545753Smckusick } 122645753Smckusick /* 122745753Smckusick * Use the constructed credentials for access checks. 122845753Smckusick */ 122945753Smckusick vp = ndp->ni_vp; 123045753Smckusick *retval = 0; 123148478Skarels if (VOP_ACCESS(vp, VREAD, cred, p) == 0) 123245753Smckusick *retval |= R_OK; 123348478Skarels if (vn_writechk(vp) == 0 && VOP_ACCESS(vp, VWRITE, cred, p) == 0) 123445753Smckusick *retval |= W_OK; 123545753Smckusick /* XXX we return X_OK for root on VREG even if not */ 123648478Skarels if (VOP_ACCESS(vp, VEXEC, cred, p) == 0) 123745753Smckusick *retval |= X_OK; 123845753Smckusick vput(vp); 123945753Smckusick crfree(cred); 124045753Smckusick return (error); 124145753Smckusick } 124245753Smckusick 124345753Smckusick /* 124441486Smckusick * Brutal hack! Map HPUX u-area offsets into BSD u offsets. 124541486Smckusick * No apologies offered, if you don't like it, rewrite it! 124641486Smckusick */ 124741486Smckusick 124849134Skarels extern char kstack[]; 124941486Smckusick #define UOFF(f) ((int)&((struct user *)0)->f) 125041486Smckusick #define HPUOFF(f) ((int)&((struct hpuxuser *)0)->f) 125141486Smckusick 125241486Smckusick /* simplified FP structure */ 125341486Smckusick struct bsdfp { 125441486Smckusick int save[54]; 125541486Smckusick int reg[24]; 125641486Smckusick int ctrl[3]; 125741486Smckusick }; 125841486Smckusick 125941486Smckusick hpuxtobsduoff(off) 126041486Smckusick int *off; 126141486Smckusick { 126248478Skarels register int *ar0 = curproc->p_regs; 126341486Smckusick struct hpuxfp *hp; 126441486Smckusick struct bsdfp *bp; 126541486Smckusick register u_int raddr; 126641486Smckusick 126748478Skarels /* u_ar0 field; procxmt puts in U_ar0 */ 126841486Smckusick if ((int)off == HPUOFF(hpuxu_ar0)) 126948478Skarels return(UOFF(U_ar0)); 127041486Smckusick 127141486Smckusick #ifdef FPCOPROC 127241486Smckusick /* 68881 registers from PCB */ 127341486Smckusick hp = (struct hpuxfp *)HPUOFF(hpuxu_fp); 127441486Smckusick bp = (struct bsdfp *)UOFF(u_pcb.pcb_fpregs); 127541486Smckusick if (off >= hp->hpfp_ctrl && off < &hp->hpfp_ctrl[3]) 127641486Smckusick return((int)&bp->ctrl[off - hp->hpfp_ctrl]); 127741486Smckusick if (off >= hp->hpfp_reg && off < &hp->hpfp_reg[24]) 127841486Smckusick return((int)&bp->reg[off - hp->hpfp_reg]); 127941486Smckusick #endif 128041486Smckusick 128141486Smckusick /* 128241486Smckusick * Everything else we recognize comes from the kernel stack, 128341486Smckusick * so we convert off to an absolute address (if not already) 128441486Smckusick * for simplicity. 128541486Smckusick */ 128641486Smckusick if (off < (int *)ctob(UPAGES)) 128749134Skarels off = (int *)((u_int)off + (u_int)kstack); 128841486Smckusick 128941486Smckusick /* 129041486Smckusick * 68020 registers. 129141486Smckusick * We know that the HPUX registers are in the same order as ours. 129241486Smckusick * The only difference is that their PS is 2 bytes instead of a 129341486Smckusick * padded 4 like ours throwing the alignment off. 129441486Smckusick */ 129548478Skarels if (off >= ar0 && off < &ar0[18]) { 129641486Smckusick /* 129741486Smckusick * PS: return low word and high word of PC as HP-UX would 129841486Smckusick * (e.g. &u.u_ar0[16.5]). 129941486Smckusick */ 130048478Skarels if (off == &ar0[PS]) 130148478Skarels raddr = (u_int) &((short *)ar0)[PS*2+1]; 130241486Smckusick /* 130341486Smckusick * PC: off will be &u.u_ar0[16.5] 130441486Smckusick */ 130548478Skarels else if (off == (int *)&(((short *)ar0)[PS*2+1])) 130648478Skarels raddr = (u_int) &ar0[PC]; 130741486Smckusick /* 130841486Smckusick * D0-D7, A0-A7: easy 130941486Smckusick */ 131041486Smckusick else 131148478Skarels raddr = (u_int) &ar0[(int)(off - ar0)]; 131249134Skarels return((int)(raddr - (u_int)kstack)); 131341486Smckusick } 131441486Smckusick 131541486Smckusick /* everything else */ 131641486Smckusick return(-1); 131741486Smckusick } 131841486Smckusick 131941486Smckusick /* 132041486Smckusick * Kludge up a uarea dump so that HPUX debuggers can find out 132141486Smckusick * what they need. IMPORTANT NOTE: we do not EVEN attempt to 132241486Smckusick * convert the entire user struct. 132341486Smckusick */ 132441486Smckusick hpuxdumpu(vp, cred) 132541486Smckusick struct vnode *vp; 132641486Smckusick struct ucred *cred; 132741486Smckusick { 132848478Skarels struct proc *p = curproc; 132941486Smckusick int error; 133041486Smckusick struct hpuxuser *faku; 133141486Smckusick struct bsdfp *bp; 133241486Smckusick short *foop; 133341486Smckusick 133441486Smckusick faku = (struct hpuxuser *)malloc((u_long)ctob(1), M_TEMP, M_WAITOK); 133541486Smckusick /* 133641486Smckusick * Make sure there is no mistake about this 133741486Smckusick * being a real user structure. 133841486Smckusick */ 133941486Smckusick bzero((caddr_t)faku, ctob(1)); 134041486Smckusick /* 134141486Smckusick * Fill in the process sizes. 134241486Smckusick */ 134348478Skarels faku->hpuxu_tsize = p->p_vmspace->vm_tsize; 134448478Skarels faku->hpuxu_dsize = p->p_vmspace->vm_dsize; 134548478Skarels faku->hpuxu_ssize = p->p_vmspace->vm_ssize; 134641486Smckusick /* 134741486Smckusick * Fill in the exec header for CDB. 134841486Smckusick * This was saved back in exec(). As far as I can tell CDB 134941486Smckusick * only uses this information to verify that a particular 135041486Smckusick * core file goes with a particular binary. 135141486Smckusick */ 135249134Skarels bcopy((caddr_t)p->p_addr->u_pcb.pcb_exec, 135341486Smckusick (caddr_t)&faku->hpuxu_exdata, sizeof (struct hpux_exec)); 135441486Smckusick /* 135541486Smckusick * Adjust user's saved registers (on kernel stack) to reflect 135641486Smckusick * HPUX order. Note that HPUX saves the SR as 2 bytes not 4 135741486Smckusick * so we have to move it up. 135841486Smckusick */ 135948478Skarels faku->hpuxu_ar0 = p->p_regs; 136048478Skarels foop = (short *) p->p_regs; 136141486Smckusick foop[32] = foop[33]; 136241486Smckusick foop[33] = foop[34]; 136341486Smckusick foop[34] = foop[35]; 136441486Smckusick #ifdef FPCOPROC 136541486Smckusick /* 136641486Smckusick * Copy 68881 registers from our PCB format to HPUX format 136741486Smckusick */ 136849134Skarels bp = (struct bsdfp *) &p->p_addr->u_pcb.pcb_fpregs; 136941486Smckusick bcopy((caddr_t)bp->save, (caddr_t)faku->hpuxu_fp.hpfp_save, 137041486Smckusick sizeof(bp->save)); 137141486Smckusick bcopy((caddr_t)bp->ctrl, (caddr_t)faku->hpuxu_fp.hpfp_ctrl, 137241486Smckusick sizeof(bp->ctrl)); 137341486Smckusick bcopy((caddr_t)bp->reg, (caddr_t)faku->hpuxu_fp.hpfp_reg, 137441486Smckusick sizeof(bp->reg)); 137541486Smckusick #endif 137641486Smckusick /* 137741486Smckusick * Slay the dragon 137841486Smckusick */ 137941486Smckusick faku->hpuxu_dragon = -1; 138041486Smckusick /* 138141486Smckusick * Dump this artfully constructed page in place of the 138241486Smckusick * user struct page. 138341486Smckusick */ 138448478Skarels error = vn_rdwr(UIO_WRITE, vp, (caddr_t)faku, ctob(1), (off_t)0, 138548478Skarels UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, 138649134Skarels (int *)NULL, p); 138741486Smckusick /* 138841486Smckusick * Dump the remaining UPAGES-1 pages normally 138941486Smckusick */ 139041486Smckusick if (!error) 139149134Skarels error = vn_rdwr(UIO_WRITE, vp, kstack + ctob(1), 139241486Smckusick ctob(UPAGES-1), (off_t)ctob(1), UIO_SYSSPACE, 139349134Skarels IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, p); 139441486Smckusick free((caddr_t)faku, M_TEMP); 139541486Smckusick return(error); 139641486Smckusick } 139741486Smckusick 139841486Smckusick /* 139941486Smckusick * The remaining routines are essentially the same as those in kern_xxx.c 140041486Smckusick * and vfs_xxx.c as defined under "#ifdef COMPAT". We replicate them here 140141486Smckusick * to avoid HPUXCOMPAT dependencies in those files and to make sure that 140241486Smckusick * HP-UX compatibility still works even when COMPAT is not defined. 140341486Smckusick */ 140441486Smckusick /* #ifdef COMPAT */ 140541486Smckusick 140645753Smckusick #define HPUX_HZ 50 140745753Smckusick 140845788Sbostic #include "sys/times.h" 140941486Smckusick 141041486Smckusick /* from old timeb.h */ 141141486Smckusick struct hpuxtimeb { 141241486Smckusick time_t time; 141341486Smckusick u_short millitm; 141441486Smckusick short timezone; 141541486Smckusick short dstflag; 141641486Smckusick }; 141741486Smckusick 141841486Smckusick /* ye ole stat structure */ 141941486Smckusick struct ohpuxstat { 142041486Smckusick dev_t ohst_dev; 142141486Smckusick u_short ohst_ino; 142241486Smckusick u_short ohst_mode; 142341486Smckusick short ohst_nlink; 142441486Smckusick short ohst_uid; 142541486Smckusick short ohst_gid; 142641486Smckusick dev_t ohst_rdev; 142741486Smckusick int ohst_size; 142841486Smckusick int ohst_atime; 142941486Smckusick int ohst_mtime; 143041486Smckusick int ohst_ctime; 143141486Smckusick }; 143241486Smckusick 143341486Smckusick /* 143441486Smckusick * SYS V style setpgrp() 143541486Smckusick */ 143643452Shibler ohpuxsetpgrp(p, uap, retval) 143743452Shibler register struct proc *p; 143843452Shibler int *uap, *retval; 143941486Smckusick { 144041486Smckusick if (p->p_pid != p->p_pgid) 144148478Skarels enterpgrp(p, p->p_pid, 0); 144243452Shibler *retval = p->p_pgid; 144345753Smckusick return (0); 144441486Smckusick } 144541486Smckusick 144643452Shibler ohpuxtime(p, uap, retval) 144743452Shibler struct proc *p; 144843452Shibler register struct args { 144943452Shibler long *tp; 145043452Shibler } *uap; 145143713Smckusick time_t *retval; 145241486Smckusick { 145345753Smckusick int error = 0; 145441486Smckusick 145541486Smckusick if (uap->tp) 145643452Shibler error = copyout((caddr_t)&time.tv_sec, (caddr_t)uap->tp, 145743452Shibler sizeof (long)); 145845753Smckusick *retval = time.tv_sec; 145944421Skarels return (error); 146041486Smckusick } 146141486Smckusick 146243452Shibler ohpuxstime(p, uap, retval) 146343452Shibler struct proc *p; 146443452Shibler register struct args { 146543452Shibler int time; 146643452Shibler } *uap; 146743452Shibler int *retval; 146841486Smckusick { 146941486Smckusick struct timeval tv; 147043452Shibler int s, error; 147141486Smckusick 147241486Smckusick tv.tv_sec = uap->time; 147341486Smckusick tv.tv_usec = 0; 147448478Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 147544421Skarels return (error); 147641486Smckusick 147741486Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 147841486Smckusick boottime.tv_sec += tv.tv_sec - time.tv_sec; 147941486Smckusick s = splhigh(); time = tv; splx(s); 148041486Smckusick resettodr(); 148144421Skarels return (0); 148241486Smckusick } 148341486Smckusick 148443452Shibler ohpuxftime(p, uap, retval) 148543452Shibler struct proc *p; 148643452Shibler register struct args { 148741486Smckusick struct hpuxtimeb *tp; 148841486Smckusick } *uap; 148943452Shibler int *retval; 149043452Shibler { 149141486Smckusick struct hpuxtimeb tb; 149241486Smckusick int s; 149341486Smckusick 149441486Smckusick s = splhigh(); 149541486Smckusick tb.time = time.tv_sec; 149641486Smckusick tb.millitm = time.tv_usec / 1000; 149741486Smckusick splx(s); 149841486Smckusick tb.timezone = tz.tz_minuteswest; 149941486Smckusick tb.dstflag = tz.tz_dsttime; 150044421Skarels return (copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb))); 150141486Smckusick } 150241486Smckusick 150343452Shibler ohpuxalarm(p, uap, retval) 150443452Shibler register struct proc *p; 150543452Shibler register struct args { 150643452Shibler int deltat; 150743452Shibler } *uap; 150843452Shibler int *retval; 150941486Smckusick { 151041486Smckusick int s = splhigh(); 151141486Smckusick 151241486Smckusick untimeout(realitexpire, (caddr_t)p); 151341486Smckusick timerclear(&p->p_realtimer.it_interval); 151443452Shibler *retval = 0; 151541486Smckusick if (timerisset(&p->p_realtimer.it_value) && 151641486Smckusick timercmp(&p->p_realtimer.it_value, &time, >)) 151743452Shibler *retval = p->p_realtimer.it_value.tv_sec - time.tv_sec; 151841486Smckusick if (uap->deltat == 0) { 151941486Smckusick timerclear(&p->p_realtimer.it_value); 152041486Smckusick splx(s); 152144421Skarels return (0); 152241486Smckusick } 152341486Smckusick p->p_realtimer.it_value = time; 152441486Smckusick p->p_realtimer.it_value.tv_sec += uap->deltat; 152541486Smckusick timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); 152641486Smckusick splx(s); 152744421Skarels return (0); 152841486Smckusick } 152941486Smckusick 153043452Shibler ohpuxnice(p, uap, retval) 153143452Shibler register struct proc *p; 153243452Shibler register struct args { 153343452Shibler int niceness; 153443452Shibler } *uap; 153543452Shibler int *retval; 153641486Smckusick { 153743452Shibler int error; 153841486Smckusick 153943452Shibler error = donice(p, p, (p->p_nice-NZERO)+uap->niceness); 154043452Shibler if (error == 0) 154143452Shibler *retval = p->p_nice - NZERO; 154244421Skarels return (error); 154341486Smckusick } 154441486Smckusick 154543452Shibler ohpuxtimes(p, uap, retval) 154643452Shibler struct proc *p; 154743452Shibler register struct args { 154843452Shibler struct tms *tmsb; 154943452Shibler } *uap; 155043713Smckusick time_t *retval; 155141486Smckusick { 155241486Smckusick struct tms atms; 155343452Shibler int error; 155441486Smckusick 155548478Skarels atms.tms_utime = hpuxscale(&p->p_utime); 155648478Skarels atms.tms_stime = hpuxscale(&p->p_stime); 155748478Skarels atms.tms_cutime = hpuxscale(&p->p_stats->p_cru.ru_utime); 155848478Skarels atms.tms_cstime = hpuxscale(&p->p_stats->p_cru.ru_stime); 155943452Shibler error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); 156043452Shibler if (error == 0) 156145753Smckusick *retval = hpuxscale(&time) - hpuxscale(&boottime); 156244421Skarels return (error); 156341486Smckusick } 156441486Smckusick 156545753Smckusick /* 156645753Smckusick * Doesn't exactly do what the documentation says. 156745753Smckusick * What we really do is return 1/HPUX_HZ-th of a second since that 156845753Smckusick * is what HP-UX returns. 156945753Smckusick */ 157045753Smckusick hpuxscale(tvp) 157141486Smckusick register struct timeval *tvp; 157241486Smckusick { 157345753Smckusick return (tvp->tv_sec * HPUX_HZ + tvp->tv_usec * HPUX_HZ / 1000000); 157441486Smckusick } 157541486Smckusick 157641486Smckusick /* 157741486Smckusick * Set IUPD and IACC times on file. 157841486Smckusick * Can't set ICHG. 157941486Smckusick */ 158043452Shibler ohpuxutime(p, uap, retval) 158143452Shibler struct proc *p; 158241486Smckusick register struct a { 158341486Smckusick char *fname; 158441486Smckusick time_t *tptr; 158543452Shibler } *uap; 158643452Shibler int *retval; 158743452Shibler { 158848478Skarels register struct vnode *vp; 158948478Skarels register struct nameidata *ndp; 159041486Smckusick struct vattr vattr; 159141486Smckusick time_t tv[2]; 159243452Shibler int error; 159348478Skarels struct nameidata nd; 159441486Smckusick 159548478Skarels ndp = &nd; 159641486Smckusick if (uap->tptr) { 159743452Shibler error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)); 159843452Shibler if (error) 159944421Skarels return (error); 160041486Smckusick } else 160141486Smckusick tv[0] = tv[1] = time.tv_sec; 160241486Smckusick ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF; 160341486Smckusick ndp->ni_segflg = UIO_USERSPACE; 160441486Smckusick ndp->ni_dirp = uap->fname; 160541486Smckusick vattr_null(&vattr); 160641486Smckusick vattr.va_atime.tv_sec = tv[0]; 160741486Smckusick vattr.va_atime.tv_usec = 0; 160841486Smckusick vattr.va_mtime.tv_sec = tv[1]; 160941486Smckusick vattr.va_mtime.tv_usec = 0; 161048478Skarels if (error = namei(ndp, p)) 161144421Skarels return (error); 161241486Smckusick vp = ndp->ni_vp; 161342154Smckusick if (vp->v_mount->mnt_flag & MNT_RDONLY) 161443452Shibler error = EROFS; 161541486Smckusick else 161648478Skarels error = VOP_SETATTR(vp, &vattr, ndp->ni_cred, p); 161741486Smckusick vput(vp); 161844421Skarels return (error); 161941486Smckusick } 162041486Smckusick 162143452Shibler ohpuxpause(p, uap, retval) 162243452Shibler struct proc *p; 162343452Shibler int *uap, *retval; 162441486Smckusick { 162549134Skarels (void) tsleep(kstack, PPAUSE | PCATCH, "pause", 0); 162642155Skarels /* always return EINTR rather than ERESTART... */ 162744421Skarels return (EINTR); 162841486Smckusick } 162941486Smckusick 163041486Smckusick /* 163141486Smckusick * The old fstat system call. 163241486Smckusick */ 163343452Shibler ohpuxfstat(p, uap, retval) 163443452Shibler struct proc *p; 163543452Shibler register struct args { 163641486Smckusick int fd; 163741486Smckusick struct ohpuxstat *sb; 163843452Shibler } *uap; 163943452Shibler int *retval; 164043452Shibler { 164145923Smckusick register struct filedesc *fdp = p->p_fd; 164241486Smckusick struct file *fp; 164341486Smckusick 164448478Skarels if (((unsigned)uap->fd) >= fdp->fd_nfiles || 164548478Skarels (fp = fdp->fd_ofiles[uap->fd]) == NULL) 164644421Skarels return (EBADF); 164743452Shibler if (fp->f_type != DTYPE_VNODE) 164844421Skarels return (EINVAL); 164944421Skarels return (ohpuxstat1((struct vnode *)fp->f_data, uap->sb)); 165041486Smckusick } 165141486Smckusick 165241486Smckusick /* 165341486Smckusick * Old stat system call. This version follows links. 165441486Smckusick */ 165543452Shibler ohpuxstat(p, uap, retval) 165643452Shibler struct proc *p; 165743452Shibler register struct args { 165841486Smckusick char *fname; 165941486Smckusick struct ohpuxstat *sb; 166043452Shibler } *uap; 166143452Shibler int *retval; 166243452Shibler { 166348478Skarels register struct nameidata *ndp; 166443452Shibler int error; 166548478Skarels struct nameidata nd; 166641486Smckusick 166748478Skarels ndp = &nd; 166841486Smckusick ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 166941486Smckusick ndp->ni_segflg = UIO_USERSPACE; 167041486Smckusick ndp->ni_dirp = uap->fname; 167148478Skarels if (error = namei(ndp, p)) 167244421Skarels return (error); 167343452Shibler error = ohpuxstat1(ndp->ni_vp, uap->sb); 167441486Smckusick vput(ndp->ni_vp); 167544421Skarels return (error); 167641486Smckusick } 167741486Smckusick 167841486Smckusick int 167941486Smckusick ohpuxstat1(vp, ub) 168041486Smckusick register struct vnode *vp; 168141486Smckusick struct ohpuxstat *ub; 168241486Smckusick { 168341486Smckusick struct ohpuxstat ds; 168441486Smckusick struct vattr vattr; 168541486Smckusick register int error; 168641486Smckusick 168748478Skarels error = VOP_GETATTR(vp, &vattr, curproc->p_ucred, curproc); 168841486Smckusick if (error) 168941486Smckusick return(error); 169041486Smckusick /* 169141486Smckusick * Copy from inode table 169241486Smckusick */ 169341486Smckusick ds.ohst_dev = vattr.va_fsid; 169441486Smckusick ds.ohst_ino = (short)vattr.va_fileid; 169541486Smckusick ds.ohst_mode = (u_short)vattr.va_mode; 169641486Smckusick ds.ohst_nlink = vattr.va_nlink; 169741486Smckusick ds.ohst_uid = (short)vattr.va_uid; 169841486Smckusick ds.ohst_gid = (short)vattr.va_gid; 169941486Smckusick ds.ohst_rdev = (dev_t)vattr.va_rdev; 170041486Smckusick ds.ohst_size = (int)vattr.va_size; 170141486Smckusick ds.ohst_atime = (int)vattr.va_atime.tv_sec; 170241486Smckusick ds.ohst_mtime = (int)vattr.va_mtime.tv_sec; 170341486Smckusick ds.ohst_ctime = (int)vattr.va_ctime.tv_sec; 170441486Smckusick return (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))); 170541486Smckusick } 170641486Smckusick /* #endif */ 170741486Smckusick 170841486Smckusick #endif 1709